A simple library to support serving https.
Dependents: oldheating gps motorhome heating
aes-gcm/gcm.h@6:819c17738dc2, 2019-09-01 (annotated)
- Committer:
- andrewboyson
- Date:
- Sun Sep 01 18:15:12 2019 +0000
- Revision:
- 6:819c17738dc2
Making progress - now have decryption working.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 6:819c17738dc2 | 1 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 2 | * |
andrewboyson | 6:819c17738dc2 | 3 | * THIS SOURCE CODE IS HEREBY PLACED INTO THE PUBLIC DOMAIN FOR THE GOOD OF ALL |
andrewboyson | 6:819c17738dc2 | 4 | * |
andrewboyson | 6:819c17738dc2 | 5 | * This is a simple and straightforward implementation of AES-GCM authenticated |
andrewboyson | 6:819c17738dc2 | 6 | * encryption. The focus of this work was correctness & accuracy. It is written |
andrewboyson | 6:819c17738dc2 | 7 | * in straight 'C' without any particular focus upon optimization or speed. It |
andrewboyson | 6:819c17738dc2 | 8 | * should be endian (memory byte order) neutral since the few places that care |
andrewboyson | 6:819c17738dc2 | 9 | * are handled explicitly. |
andrewboyson | 6:819c17738dc2 | 10 | * |
andrewboyson | 6:819c17738dc2 | 11 | * This implementation of AES-GCM was created by Steven M. Gibson of GRC.com. |
andrewboyson | 6:819c17738dc2 | 12 | * |
andrewboyson | 6:819c17738dc2 | 13 | * It is intended for general purpose use, but was written in support of GRC's |
andrewboyson | 6:819c17738dc2 | 14 | * reference implementation of the SQRL (Secure Quick Reliable Login) client. |
andrewboyson | 6:819c17738dc2 | 15 | * |
andrewboyson | 6:819c17738dc2 | 16 | * See: http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf |
andrewboyson | 6:819c17738dc2 | 17 | * http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/ \ |
andrewboyson | 6:819c17738dc2 | 18 | * gcm/gcm-revised-spec.pdf |
andrewboyson | 6:819c17738dc2 | 19 | * |
andrewboyson | 6:819c17738dc2 | 20 | * NO COPYRIGHT IS CLAIMED IN THIS WORK, HOWEVER, NEITHER IS ANY WARRANTY MADE |
andrewboyson | 6:819c17738dc2 | 21 | * REGARDING ITS FITNESS FOR ANY PARTICULAR PURPOSE. USE IT AT YOUR OWN RISK. |
andrewboyson | 6:819c17738dc2 | 22 | * |
andrewboyson | 6:819c17738dc2 | 23 | *******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 24 | #ifndef GCM_HEADER |
andrewboyson | 6:819c17738dc2 | 25 | #define GCM_HEADER |
andrewboyson | 6:819c17738dc2 | 26 | |
andrewboyson | 6:819c17738dc2 | 27 | #define GCM_AUTH_FAILURE 0x55555555 // authentication failure |
andrewboyson | 6:819c17738dc2 | 28 | |
andrewboyson | 6:819c17738dc2 | 29 | #include "aes.h" // gcm_context includes aes_context |
andrewboyson | 6:819c17738dc2 | 30 | |
andrewboyson | 6:819c17738dc2 | 31 | #if defined(_MSC_VER) |
andrewboyson | 6:819c17738dc2 | 32 | #include <basetsd.h> |
andrewboyson | 6:819c17738dc2 | 33 | typedef unsigned int size_t;// use the right type for length declarations |
andrewboyson | 6:819c17738dc2 | 34 | typedef UINT32 uint32_t; |
andrewboyson | 6:819c17738dc2 | 35 | typedef UINT64 uint64_t; |
andrewboyson | 6:819c17738dc2 | 36 | #else |
andrewboyson | 6:819c17738dc2 | 37 | #include <stdint.h> |
andrewboyson | 6:819c17738dc2 | 38 | #endif |
andrewboyson | 6:819c17738dc2 | 39 | |
andrewboyson | 6:819c17738dc2 | 40 | |
andrewboyson | 6:819c17738dc2 | 41 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 42 | * GCM_CONTEXT : GCM context / holds keytables, instance data, and AES ctx |
andrewboyson | 6:819c17738dc2 | 43 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 44 | typedef struct { |
andrewboyson | 6:819c17738dc2 | 45 | int mode; // cipher direction: encrypt/decrypt |
andrewboyson | 6:819c17738dc2 | 46 | uint64_t len; // cipher data length processed so far |
andrewboyson | 6:819c17738dc2 | 47 | uint64_t add_len; // total add data length |
andrewboyson | 6:819c17738dc2 | 48 | uint64_t HL[16]; // precalculated lo-half HTable |
andrewboyson | 6:819c17738dc2 | 49 | uint64_t HH[16]; // precalculated hi-half HTable |
andrewboyson | 6:819c17738dc2 | 50 | uchar base_ectr[16]; // first counter-mode cipher output for tag |
andrewboyson | 6:819c17738dc2 | 51 | uchar y[16]; // the current cipher-input IV|Counter value |
andrewboyson | 6:819c17738dc2 | 52 | uchar buf[16]; // buf working value |
andrewboyson | 6:819c17738dc2 | 53 | aes_context aes_ctx; // cipher context used |
andrewboyson | 6:819c17738dc2 | 54 | } gcm_context; |
andrewboyson | 6:819c17738dc2 | 55 | |
andrewboyson | 6:819c17738dc2 | 56 | |
andrewboyson | 6:819c17738dc2 | 57 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 58 | * GCM_CONTEXT : MUST be called once before ANY use of this library |
andrewboyson | 6:819c17738dc2 | 59 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 60 | int gcm_initialize( void ); |
andrewboyson | 6:819c17738dc2 | 61 | |
andrewboyson | 6:819c17738dc2 | 62 | |
andrewboyson | 6:819c17738dc2 | 63 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 64 | * GCM_SETKEY : sets the GCM (and AES) keying material for use |
andrewboyson | 6:819c17738dc2 | 65 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 66 | int gcm_setkey( gcm_context *ctx, // caller-provided context ptr |
andrewboyson | 6:819c17738dc2 | 67 | const uchar *key, // pointer to cipher key |
andrewboyson | 6:819c17738dc2 | 68 | const uint keysize // must be 128, 192 or 256 |
andrewboyson | 6:819c17738dc2 | 69 | ); // returns 0 for success |
andrewboyson | 6:819c17738dc2 | 70 | |
andrewboyson | 6:819c17738dc2 | 71 | |
andrewboyson | 6:819c17738dc2 | 72 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 73 | * |
andrewboyson | 6:819c17738dc2 | 74 | * GCM_CRYPT_AND_TAG |
andrewboyson | 6:819c17738dc2 | 75 | * |
andrewboyson | 6:819c17738dc2 | 76 | * This either encrypts or decrypts the user-provided data and, either |
andrewboyson | 6:819c17738dc2 | 77 | * way, generates an authentication tag of the requested length. It must be |
andrewboyson | 6:819c17738dc2 | 78 | * called with a GCM context whose key has already been set with GCM_SETKEY. |
andrewboyson | 6:819c17738dc2 | 79 | * |
andrewboyson | 6:819c17738dc2 | 80 | * The user would typically call this explicitly to ENCRYPT a buffer of data |
andrewboyson | 6:819c17738dc2 | 81 | * and optional associated data, and produce its an authentication tag. |
andrewboyson | 6:819c17738dc2 | 82 | * |
andrewboyson | 6:819c17738dc2 | 83 | * To reverse the process the user would typically call the companion |
andrewboyson | 6:819c17738dc2 | 84 | * GCM_AUTH_DECRYPT function to decrypt data and verify a user-provided |
andrewboyson | 6:819c17738dc2 | 85 | * authentication tag. The GCM_AUTH_DECRYPT function calls this function |
andrewboyson | 6:819c17738dc2 | 86 | * to perform its decryption and tag generation, which it then compares. |
andrewboyson | 6:819c17738dc2 | 87 | * |
andrewboyson | 6:819c17738dc2 | 88 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 89 | int gcm_crypt_and_tag( |
andrewboyson | 6:819c17738dc2 | 90 | gcm_context *ctx, // gcm context with key already setup |
andrewboyson | 6:819c17738dc2 | 91 | int mode, // cipher direction: GCM_ENCRYPT or GCM_DECRYPT |
andrewboyson | 6:819c17738dc2 | 92 | const uchar *iv, // pointer to the 12-byte initialization vector |
andrewboyson | 6:819c17738dc2 | 93 | size_t iv_len, // byte length if the IV. should always be 12 |
andrewboyson | 6:819c17738dc2 | 94 | const uchar *add, // pointer to the non-ciphered additional data |
andrewboyson | 6:819c17738dc2 | 95 | size_t add_len, // byte length of the additional AEAD data |
andrewboyson | 6:819c17738dc2 | 96 | const uchar *input, // pointer to the cipher data source |
andrewboyson | 6:819c17738dc2 | 97 | uchar *output, // pointer to the cipher data destination |
andrewboyson | 6:819c17738dc2 | 98 | size_t length, // byte length of the cipher data |
andrewboyson | 6:819c17738dc2 | 99 | uchar *tag, // pointer to the tag to be generated |
andrewboyson | 6:819c17738dc2 | 100 | size_t tag_len ); // byte length of the tag to be generated |
andrewboyson | 6:819c17738dc2 | 101 | |
andrewboyson | 6:819c17738dc2 | 102 | |
andrewboyson | 6:819c17738dc2 | 103 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 104 | * |
andrewboyson | 6:819c17738dc2 | 105 | * GCM_AUTH_DECRYPT |
andrewboyson | 6:819c17738dc2 | 106 | * |
andrewboyson | 6:819c17738dc2 | 107 | * This DECRYPTS a user-provided data buffer with optional associated data. |
andrewboyson | 6:819c17738dc2 | 108 | * It then verifies a user-supplied authentication tag against the tag just |
andrewboyson | 6:819c17738dc2 | 109 | * re-created during decryption to verify that the data has not been altered. |
andrewboyson | 6:819c17738dc2 | 110 | * |
andrewboyson | 6:819c17738dc2 | 111 | * This function calls GCM_CRYPT_AND_TAG (above) to perform the decryption |
andrewboyson | 6:819c17738dc2 | 112 | * and authentication tag generation. |
andrewboyson | 6:819c17738dc2 | 113 | * |
andrewboyson | 6:819c17738dc2 | 114 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 115 | int gcm_auth_decrypt( |
andrewboyson | 6:819c17738dc2 | 116 | gcm_context *ctx, // gcm context with key already setup |
andrewboyson | 6:819c17738dc2 | 117 | const uchar *iv, // pointer to the 12-byte initialization vector |
andrewboyson | 6:819c17738dc2 | 118 | size_t iv_len, // byte length if the IV. should always be 12 |
andrewboyson | 6:819c17738dc2 | 119 | const uchar *add, // pointer to the non-ciphered additional data |
andrewboyson | 6:819c17738dc2 | 120 | size_t add_len, // byte length of the additional AEAD data |
andrewboyson | 6:819c17738dc2 | 121 | const uchar *input, // pointer to the cipher data source |
andrewboyson | 6:819c17738dc2 | 122 | uchar *output, // pointer to the cipher data destination |
andrewboyson | 6:819c17738dc2 | 123 | size_t length, // byte length of the cipher data |
andrewboyson | 6:819c17738dc2 | 124 | const uchar *tag, // pointer to the tag to be authenticated |
andrewboyson | 6:819c17738dc2 | 125 | size_t tag_len ); // byte length of the tag <= 16 |
andrewboyson | 6:819c17738dc2 | 126 | |
andrewboyson | 6:819c17738dc2 | 127 | |
andrewboyson | 6:819c17738dc2 | 128 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 129 | * |
andrewboyson | 6:819c17738dc2 | 130 | * GCM_START |
andrewboyson | 6:819c17738dc2 | 131 | * |
andrewboyson | 6:819c17738dc2 | 132 | * Given a user-provided GCM context, this initializes it, sets the encryption |
andrewboyson | 6:819c17738dc2 | 133 | * mode, and preprocesses the initialization vector and additional AEAD data. |
andrewboyson | 6:819c17738dc2 | 134 | * |
andrewboyson | 6:819c17738dc2 | 135 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 136 | int gcm_start( gcm_context *ctx, // pointer to user-provided GCM context |
andrewboyson | 6:819c17738dc2 | 137 | int mode, // GCM_ENCRYPT or GCM_DECRYPT |
andrewboyson | 6:819c17738dc2 | 138 | const uchar *iv, // pointer to initialization vector |
andrewboyson | 6:819c17738dc2 | 139 | size_t iv_len, // IV length in bytes (should == 12) |
andrewboyson | 6:819c17738dc2 | 140 | const uchar *add, // pointer to additional AEAD data (NULL if none) |
andrewboyson | 6:819c17738dc2 | 141 | size_t add_len ); // length of additional AEAD data (bytes) |
andrewboyson | 6:819c17738dc2 | 142 | |
andrewboyson | 6:819c17738dc2 | 143 | |
andrewboyson | 6:819c17738dc2 | 144 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 145 | * |
andrewboyson | 6:819c17738dc2 | 146 | * GCM_UPDATE |
andrewboyson | 6:819c17738dc2 | 147 | * |
andrewboyson | 6:819c17738dc2 | 148 | * This is called once or more to process bulk plaintext or ciphertext data. |
andrewboyson | 6:819c17738dc2 | 149 | * We give this some number of bytes of input and it returns the same number |
andrewboyson | 6:819c17738dc2 | 150 | * of output bytes. If called multiple times (which is fine) all but the final |
andrewboyson | 6:819c17738dc2 | 151 | * invocation MUST be called with length mod 16 == 0. (Only the final call can |
andrewboyson | 6:819c17738dc2 | 152 | * have a partial block length of < 128 bits.) |
andrewboyson | 6:819c17738dc2 | 153 | * |
andrewboyson | 6:819c17738dc2 | 154 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 155 | int gcm_update( gcm_context *ctx, // pointer to user-provided GCM context |
andrewboyson | 6:819c17738dc2 | 156 | size_t length, // length, in bytes, of data to process |
andrewboyson | 6:819c17738dc2 | 157 | const uchar *input, // pointer to source data |
andrewboyson | 6:819c17738dc2 | 158 | uchar *output ); // pointer to destination data |
andrewboyson | 6:819c17738dc2 | 159 | |
andrewboyson | 6:819c17738dc2 | 160 | |
andrewboyson | 6:819c17738dc2 | 161 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 162 | * |
andrewboyson | 6:819c17738dc2 | 163 | * GCM_FINISH |
andrewboyson | 6:819c17738dc2 | 164 | * |
andrewboyson | 6:819c17738dc2 | 165 | * This is called once after all calls to GCM_UPDATE to finalize the GCM. |
andrewboyson | 6:819c17738dc2 | 166 | * It performs the final GHASH to produce the resulting authentication TAG. |
andrewboyson | 6:819c17738dc2 | 167 | * |
andrewboyson | 6:819c17738dc2 | 168 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 169 | int gcm_finish( gcm_context *ctx, // pointer to user-provided GCM context |
andrewboyson | 6:819c17738dc2 | 170 | uchar *tag, // ptr to tag buffer - NULL if tag_len = 0 |
andrewboyson | 6:819c17738dc2 | 171 | size_t tag_len ); // length, in bytes, of the tag-receiving buf |
andrewboyson | 6:819c17738dc2 | 172 | |
andrewboyson | 6:819c17738dc2 | 173 | |
andrewboyson | 6:819c17738dc2 | 174 | /****************************************************************************** |
andrewboyson | 6:819c17738dc2 | 175 | * |
andrewboyson | 6:819c17738dc2 | 176 | * GCM_ZERO_CTX |
andrewboyson | 6:819c17738dc2 | 177 | * |
andrewboyson | 6:819c17738dc2 | 178 | * The GCM context contains both the GCM context and the AES context. |
andrewboyson | 6:819c17738dc2 | 179 | * This includes keying and key-related material which is security- |
andrewboyson | 6:819c17738dc2 | 180 | * sensitive, so it MUST be zeroed after use. This function does that. |
andrewboyson | 6:819c17738dc2 | 181 | * |
andrewboyson | 6:819c17738dc2 | 182 | ******************************************************************************/ |
andrewboyson | 6:819c17738dc2 | 183 | void gcm_zero_ctx( gcm_context *ctx ); |
andrewboyson | 6:819c17738dc2 | 184 | |
andrewboyson | 6:819c17738dc2 | 185 | |
andrewboyson | 6:819c17738dc2 | 186 | #endif /* GCM_HEADER */ |