blob: bd9847ce467bcf340aa6682c0fbd452f81d9125c [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* ====================================================================
2 * Copyright (c) 2001-2011 The OpenSSL Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 *
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgment:
18 * "This product includes software developed by the OpenSSL Project
19 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20 *
21 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22 * endorse or promote products derived from this software without
23 * prior written permission. For written permission, please contact
24 * openssl-core@openssl.org.
25 *
26 * 5. Products derived from this software may not be called "OpenSSL"
27 * nor may "OpenSSL" appear in their names without prior written
28 * permission of the OpenSSL Project.
29 *
30 * 6. Redistributions of any form whatsoever must retain the following
31 * acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34 *
35 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46 * OF THE POSSIBILITY OF SUCH DAMAGE.
47 * ==================================================================== */
48
49#include <string.h>
50
51#include <openssl/aead.h>
52#include <openssl/aes.h>
53#include <openssl/cipher.h>
54#include <openssl/cpu.h>
55#include <openssl/err.h>
56#include <openssl/mem.h>
David Benjamin4969cc92016-04-22 15:02:23 -040057#include <openssl/nid.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080058#include <openssl/rand.h>
59
60#include "internal.h"
Robert Sloan8ff03552017-06-14 12:40:58 -070061#include "../../internal.h"
62#include "../aes/internal.h"
63#include "../modes/internal.h"
64#include "../delocate.h"
Adam Langleyd9e397b2015-01-22 14:27:53 -080065
66#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
Kenny Rootb8494592015-09-25 02:29:14 +000067#include <openssl/arm_arch.h>
Adam Langleyd9e397b2015-01-22 14:27:53 -080068#endif
69
70
Robert Sloan8f860b12017-08-28 07:37:06 -070071OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) // Unreachable code.
David Benjamin4969cc92016-04-22 15:02:23 -040072
Adam Langleyd9e397b2015-01-22 14:27:53 -080073typedef struct {
74 union {
75 double align;
76 AES_KEY ks;
77 } ks;
78 block128_f block;
79 union {
80 cbc128_f cbc;
81 ctr128_f ctr;
82 } stream;
83} EVP_AES_KEY;
84
85typedef struct {
86 union {
87 double align;
88 AES_KEY ks;
Robert Sloan8f860b12017-08-28 07:37:06 -070089 } ks; // AES key schedule to use
90 int key_set; // Set if key initialised
91 int iv_set; // Set if an iv is set
Adam Langleyd9e397b2015-01-22 14:27:53 -080092 GCM128_CONTEXT gcm;
Robert Sloan8f860b12017-08-28 07:37:06 -070093 uint8_t *iv; // Temporary IV store
94 int ivlen; // IV length
Adam Langleyd9e397b2015-01-22 14:27:53 -080095 int taglen;
Robert Sloan8f860b12017-08-28 07:37:06 -070096 int iv_gen; // It is OK to generate IVs
Adam Langleyd9e397b2015-01-22 14:27:53 -080097 ctr128_f ctr;
98} EVP_AES_GCM_CTX;
99
100#if !defined(OPENSSL_NO_ASM) && \
101 (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
102#define VPAES
Adam Langleyd9e397b2015-01-22 14:27:53 -0800103static char vpaes_capable(void) {
104 return (OPENSSL_ia32cap_P[1] & (1 << (41 - 32))) != 0;
105}
106
107#if defined(OPENSSL_X86_64)
108#define BSAES
109static char bsaes_capable(void) {
110 return vpaes_capable();
111}
112#endif
113
114#elif !defined(OPENSSL_NO_ASM) && \
115 (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
Adam Langleyd9e397b2015-01-22 14:27:53 -0800116
Adam Langleyf4e42722015-06-04 17:45:09 -0700117#if defined(OPENSSL_ARM) && __ARM_MAX_ARCH__ >= 7
Adam Langleyd9e397b2015-01-22 14:27:53 -0800118#define BSAES
119static char bsaes_capable(void) {
120 return CRYPTO_is_NEON_capable();
121}
122#endif
123
Robert Sloan8ff03552017-06-14 12:40:58 -0700124#endif
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400125
Adam Langleyd9e397b2015-01-22 14:27:53 -0800126
127#if defined(BSAES)
Robert Sloan8f860b12017-08-28 07:37:06 -0700128// On platforms where BSAES gets defined (just above), then these functions are
129// provided by asm.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800130void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
131 const AES_KEY *key, uint8_t ivec[16], int enc);
132void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
133 const AES_KEY *key, const uint8_t ivec[16]);
134#else
135static char bsaes_capable(void) {
136 return 0;
137}
138
Robert Sloan8f860b12017-08-28 07:37:06 -0700139// On other platforms, bsaes_capable() will always return false and so the
140// following will never be called.
Kenny Roote99801b2015-11-06 15:31:15 -0800141static void bsaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
142 const AES_KEY *key, uint8_t ivec[16], int enc) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800143 abort();
144}
145
Kenny Roote99801b2015-11-06 15:31:15 -0800146static void bsaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
147 size_t len, const AES_KEY *key,
148 const uint8_t ivec[16]) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800149 abort();
150}
151#endif
152
153#if defined(VPAES)
Robert Sloan8f860b12017-08-28 07:37:06 -0700154// On platforms where VPAES gets defined (just above), then these functions are
155// provided by asm.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800156int vpaes_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
157int vpaes_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
158
159void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
160void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
161
162void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
163 const AES_KEY *key, uint8_t *ivec, int enc);
164#else
165static char vpaes_capable(void) {
166 return 0;
167}
168
Robert Sloan8f860b12017-08-28 07:37:06 -0700169// On other platforms, vpaes_capable() will always return false and so the
170// following will never be called.
Kenny Roote99801b2015-11-06 15:31:15 -0800171static int vpaes_set_encrypt_key(const uint8_t *userKey, int bits,
172 AES_KEY *key) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800173 abort();
174}
Kenny Roote99801b2015-11-06 15:31:15 -0800175static int vpaes_set_decrypt_key(const uint8_t *userKey, int bits,
176 AES_KEY *key) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800177 abort();
178}
Kenny Roote99801b2015-11-06 15:31:15 -0800179static void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800180 abort();
181}
Kenny Roote99801b2015-11-06 15:31:15 -0800182static void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800183 abort();
184}
Kenny Roote99801b2015-11-06 15:31:15 -0800185static void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
186 const AES_KEY *key, uint8_t *ivec, int enc) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800187 abort();
188}
189#endif
190
Adam Langleyd9e397b2015-01-22 14:27:53 -0800191#if !defined(OPENSSL_NO_ASM) && \
192 (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
193int aesni_set_encrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
194int aesni_set_decrypt_key(const uint8_t *userKey, int bits, AES_KEY *key);
195
196void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
197void aesni_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
198
199void aesni_ecb_encrypt(const uint8_t *in, uint8_t *out, size_t length,
200 const AES_KEY *key, int enc);
201void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
202 const AES_KEY *key, uint8_t *ivec, int enc);
203
Adam Langleyd9e397b2015-01-22 14:27:53 -0800204#else
205
Robert Sloan8f860b12017-08-28 07:37:06 -0700206// On other platforms, aesni_capable() will always return false and so the
207// following will never be called.
Kenny Roote99801b2015-11-06 15:31:15 -0800208static void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800209 abort();
210}
Kenny Roote99801b2015-11-06 15:31:15 -0800211static int aesni_set_encrypt_key(const uint8_t *userKey, int bits,
212 AES_KEY *key) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800213 abort();
214}
Kenny Roote99801b2015-11-06 15:31:15 -0800215static void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
216 size_t blocks, const void *key,
217 const uint8_t *ivec) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800218 abort();
219}
220
221#endif
222
223static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
David Benjamin4969cc92016-04-22 15:02:23 -0400224 const uint8_t *iv, int enc) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800225 int ret, mode;
226 EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
227
228 mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
229 if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) {
230 if (hwaes_capable()) {
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400231 ret = aes_hw_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
232 dat->block = (block128_f)aes_hw_decrypt;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800233 dat->stream.cbc = NULL;
234 if (mode == EVP_CIPH_CBC_MODE) {
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400235 dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800236 }
237 } else if (bsaes_capable() && mode == EVP_CIPH_CBC_MODE) {
238 ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
239 dat->block = (block128_f)AES_decrypt;
240 dat->stream.cbc = (cbc128_f)bsaes_cbc_encrypt;
241 } else if (vpaes_capable()) {
242 ret = vpaes_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
243 dat->block = (block128_f)vpaes_decrypt;
244 dat->stream.cbc =
245 mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
246 } else {
247 ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
248 dat->block = (block128_f)AES_decrypt;
249 dat->stream.cbc =
250 mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
251 }
252 } else if (hwaes_capable()) {
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400253 ret = aes_hw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
254 dat->block = (block128_f)aes_hw_encrypt;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800255 dat->stream.cbc = NULL;
256 if (mode == EVP_CIPH_CBC_MODE) {
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400257 dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800258 } else if (mode == EVP_CIPH_CTR_MODE) {
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400259 dat->stream.ctr = (ctr128_f)aes_hw_ctr32_encrypt_blocks;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800260 }
261 } else if (bsaes_capable() && mode == EVP_CIPH_CTR_MODE) {
262 ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
263 dat->block = (block128_f)AES_encrypt;
264 dat->stream.ctr = (ctr128_f)bsaes_ctr32_encrypt_blocks;
265 } else if (vpaes_capable()) {
266 ret = vpaes_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
267 dat->block = (block128_f)vpaes_encrypt;
268 dat->stream.cbc =
269 mode == EVP_CIPH_CBC_MODE ? (cbc128_f)vpaes_cbc_encrypt : NULL;
270 } else {
271 ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
272 dat->block = (block128_f)AES_encrypt;
273 dat->stream.cbc =
274 mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
275 }
276
277 if (ret < 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000278 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800279 return 0;
280 }
281
282 return 1;
283}
284
Adam Langleye9ada862015-05-11 17:20:37 -0700285static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
286 size_t len) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800287 EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
288
289 if (dat->stream.cbc) {
290 (*dat->stream.cbc)(in, out, len, &dat->ks, ctx->iv, ctx->encrypt);
291 } else if (ctx->encrypt) {
292 CRYPTO_cbc128_encrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
293 } else {
294 CRYPTO_cbc128_decrypt(in, out, len, &dat->ks, ctx->iv, dat->block);
295 }
296
297 return 1;
298}
299
Adam Langleye9ada862015-05-11 17:20:37 -0700300static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
301 size_t len) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800302 size_t bl = ctx->cipher->block_size;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800303 EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
304
305 if (len < bl) {
306 return 1;
307 }
308
David Benjamin7c0d06c2016-08-11 13:26:41 -0400309 len -= bl;
310 for (size_t i = 0; i <= len; i += bl) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800311 (*dat->block)(in + i, out + i, &dat->ks);
312 }
313
314 return 1;
315}
316
Adam Langleye9ada862015-05-11 17:20:37 -0700317static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
318 size_t len) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800319 EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
320
321 if (dat->stream.ctr) {
David Benjamin4969cc92016-04-22 15:02:23 -0400322 CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf,
323 &ctx->num, dat->stream.ctr);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800324 } else {
David Benjamin4969cc92016-04-22 15:02:23 -0400325 CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num,
Adam Langleyd9e397b2015-01-22 14:27:53 -0800326 dat->block);
327 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800328 return 1;
329}
330
Adam Langleye9ada862015-05-11 17:20:37 -0700331static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
332 size_t len) {
333 EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
334
335 CRYPTO_ofb128_encrypt(in, out, len, &dat->ks, ctx->iv, &ctx->num, dat->block);
336 return 1;
337}
338
339static char aesni_capable(void);
340
Robert Sloan572a4e22017-04-17 10:52:19 -0700341ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
342 block128_f *out_block, const uint8_t *key,
343 size_t key_bytes) {
Adam Langleye9ada862015-05-11 17:20:37 -0700344 if (aesni_capable()) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700345 aesni_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langleye9ada862015-05-11 17:20:37 -0700346 if (gcm_ctx != NULL) {
Robert Sloan9254e682017-04-24 09:42:06 -0700347 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aesni_encrypt, 1);
Adam Langleye9ada862015-05-11 17:20:37 -0700348 }
349 if (out_block) {
350 *out_block = (block128_f) aesni_encrypt;
351 }
352 return (ctr128_f)aesni_ctr32_encrypt_blocks;
353 }
354
Adam Langleyd9e397b2015-01-22 14:27:53 -0800355 if (hwaes_capable()) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700356 aes_hw_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langleye9ada862015-05-11 17:20:37 -0700357 if (gcm_ctx != NULL) {
Robert Sloan9254e682017-04-24 09:42:06 -0700358 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_hw_encrypt, 0);
Adam Langleye9ada862015-05-11 17:20:37 -0700359 }
360 if (out_block) {
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400361 *out_block = (block128_f) aes_hw_encrypt;
Adam Langleye9ada862015-05-11 17:20:37 -0700362 }
Steven Valdezbb1ceac2016-10-07 10:34:51 -0400363 return (ctr128_f)aes_hw_ctr32_encrypt_blocks;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800364 }
365
366 if (bsaes_capable()) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700367 AES_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langleye9ada862015-05-11 17:20:37 -0700368 if (gcm_ctx != NULL) {
Robert Sloan9254e682017-04-24 09:42:06 -0700369 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0);
Adam Langleye9ada862015-05-11 17:20:37 -0700370 }
371 if (out_block) {
372 *out_block = (block128_f) AES_encrypt;
373 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800374 return (ctr128_f)bsaes_ctr32_encrypt_blocks;
375 }
376
377 if (vpaes_capable()) {
Robert Sloan572a4e22017-04-17 10:52:19 -0700378 vpaes_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langleye9ada862015-05-11 17:20:37 -0700379 if (out_block) {
380 *out_block = (block128_f) vpaes_encrypt;
381 }
382 if (gcm_ctx != NULL) {
Robert Sloan9254e682017-04-24 09:42:06 -0700383 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt, 0);
Adam Langleye9ada862015-05-11 17:20:37 -0700384 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800385 return NULL;
386 }
387
Robert Sloan572a4e22017-04-17 10:52:19 -0700388 AES_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langleye9ada862015-05-11 17:20:37 -0700389 if (gcm_ctx != NULL) {
Robert Sloan9254e682017-04-24 09:42:06 -0700390 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0);
Adam Langleye9ada862015-05-11 17:20:37 -0700391 }
392 if (out_block) {
393 *out_block = (block128_f) AES_encrypt;
394 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800395 return NULL;
396}
397
398static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
399 const uint8_t *iv, int enc) {
400 EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
401 if (!iv && !key) {
402 return 1;
403 }
404 if (key) {
Adam Langleye9ada862015-05-11 17:20:37 -0700405 gctx->ctr =
406 aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm, NULL, key, ctx->key_len);
Robert Sloan8f860b12017-08-28 07:37:06 -0700407 // If we have an iv can set it directly, otherwise use saved IV.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800408 if (iv == NULL && gctx->iv_set) {
409 iv = gctx->iv;
410 }
411 if (iv) {
Kenny Roote99801b2015-11-06 15:31:15 -0800412 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800413 gctx->iv_set = 1;
414 }
415 gctx->key_set = 1;
416 } else {
Robert Sloan8f860b12017-08-28 07:37:06 -0700417 // If key set use IV, otherwise copy
Adam Langleyd9e397b2015-01-22 14:27:53 -0800418 if (gctx->key_set) {
Kenny Roote99801b2015-11-06 15:31:15 -0800419 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800420 } else {
Robert Sloan69939df2017-01-09 10:53:07 -0800421 OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800422 }
423 gctx->iv_set = 1;
424 gctx->iv_gen = 0;
425 }
426 return 1;
427}
428
Adam Langleye9ada862015-05-11 17:20:37 -0700429static void aes_gcm_cleanup(EVP_CIPHER_CTX *c) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800430 EVP_AES_GCM_CTX *gctx = c->cipher_data;
431 OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
432 if (gctx->iv != c->iv) {
433 OPENSSL_free(gctx->iv);
434 }
Adam Langleyd9e397b2015-01-22 14:27:53 -0800435}
436
Robert Sloan8f860b12017-08-28 07:37:06 -0700437// increment counter (64-bit int) by 1
Adam Langleyd9e397b2015-01-22 14:27:53 -0800438static void ctr64_inc(uint8_t *counter) {
439 int n = 8;
440 uint8_t c;
441
442 do {
443 --n;
444 c = counter[n];
445 ++c;
446 counter[n] = c;
447 if (c) {
448 return;
449 }
450 } while (n);
451}
452
453static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) {
454 EVP_AES_GCM_CTX *gctx = c->cipher_data;
455 switch (type) {
456 case EVP_CTRL_INIT:
457 gctx->key_set = 0;
458 gctx->iv_set = 0;
459 gctx->ivlen = c->cipher->iv_len;
460 gctx->iv = c->iv;
461 gctx->taglen = -1;
462 gctx->iv_gen = 0;
463 return 1;
464
465 case EVP_CTRL_GCM_SET_IVLEN:
466 if (arg <= 0) {
467 return 0;
468 }
469
Robert Sloan8f860b12017-08-28 07:37:06 -0700470 // Allocate memory for IV if needed
Adam Langleyd9e397b2015-01-22 14:27:53 -0800471 if (arg > EVP_MAX_IV_LENGTH && arg > gctx->ivlen) {
472 if (gctx->iv != c->iv) {
473 OPENSSL_free(gctx->iv);
474 }
475 gctx->iv = OPENSSL_malloc(arg);
476 if (!gctx->iv) {
477 return 0;
478 }
479 }
480 gctx->ivlen = arg;
481 return 1;
482
483 case EVP_CTRL_GCM_SET_TAG:
484 if (arg <= 0 || arg > 16 || c->encrypt) {
485 return 0;
486 }
Robert Sloan69939df2017-01-09 10:53:07 -0800487 OPENSSL_memcpy(c->buf, ptr, arg);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800488 gctx->taglen = arg;
489 return 1;
490
491 case EVP_CTRL_GCM_GET_TAG:
492 if (arg <= 0 || arg > 16 || !c->encrypt || gctx->taglen < 0) {
493 return 0;
494 }
Robert Sloan69939df2017-01-09 10:53:07 -0800495 OPENSSL_memcpy(ptr, c->buf, arg);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800496 return 1;
497
498 case EVP_CTRL_GCM_SET_IV_FIXED:
Robert Sloan8f860b12017-08-28 07:37:06 -0700499 // Special case: -1 length restores whole IV
Adam Langleyd9e397b2015-01-22 14:27:53 -0800500 if (arg == -1) {
Robert Sloan69939df2017-01-09 10:53:07 -0800501 OPENSSL_memcpy(gctx->iv, ptr, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800502 gctx->iv_gen = 1;
503 return 1;
504 }
Robert Sloan8f860b12017-08-28 07:37:06 -0700505 // Fixed field must be at least 4 bytes and invocation field
506 // at least 8.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800507 if (arg < 4 || (gctx->ivlen - arg) < 8) {
508 return 0;
509 }
510 if (arg) {
Robert Sloan69939df2017-01-09 10:53:07 -0800511 OPENSSL_memcpy(gctx->iv, ptr, arg);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800512 }
513 if (c->encrypt && !RAND_bytes(gctx->iv + arg, gctx->ivlen - arg)) {
514 return 0;
515 }
516 gctx->iv_gen = 1;
517 return 1;
518
519 case EVP_CTRL_GCM_IV_GEN:
520 if (gctx->iv_gen == 0 || gctx->key_set == 0) {
521 return 0;
522 }
Kenny Roote99801b2015-11-06 15:31:15 -0800523 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800524 if (arg <= 0 || arg > gctx->ivlen) {
525 arg = gctx->ivlen;
526 }
Robert Sloan69939df2017-01-09 10:53:07 -0800527 OPENSSL_memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
Robert Sloan8f860b12017-08-28 07:37:06 -0700528 // Invocation field will be at least 8 bytes in size and
529 // so no need to check wrap around or increment more than
530 // last 8 bytes.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800531 ctr64_inc(gctx->iv + gctx->ivlen - 8);
532 gctx->iv_set = 1;
533 return 1;
534
535 case EVP_CTRL_GCM_SET_IV_INV:
536 if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt) {
537 return 0;
538 }
Robert Sloan69939df2017-01-09 10:53:07 -0800539 OPENSSL_memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
Kenny Roote99801b2015-11-06 15:31:15 -0800540 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800541 gctx->iv_set = 1;
542 return 1;
543
544 case EVP_CTRL_COPY: {
545 EVP_CIPHER_CTX *out = ptr;
546 EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
Adam Langleyd9e397b2015-01-22 14:27:53 -0800547 if (gctx->iv == c->iv) {
548 gctx_out->iv = out->iv;
549 } else {
550 gctx_out->iv = OPENSSL_malloc(gctx->ivlen);
551 if (!gctx_out->iv) {
552 return 0;
553 }
Robert Sloan69939df2017-01-09 10:53:07 -0800554 OPENSSL_memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800555 }
556 return 1;
557 }
558
559 default:
560 return -1;
561 }
562}
563
564static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
565 size_t len) {
566 EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
567
Robert Sloan8f860b12017-08-28 07:37:06 -0700568 // If not set up, return error
Adam Langleyd9e397b2015-01-22 14:27:53 -0800569 if (!gctx->key_set) {
570 return -1;
571 }
572 if (!gctx->iv_set) {
573 return -1;
574 }
575
576 if (in) {
577 if (out == NULL) {
578 if (!CRYPTO_gcm128_aad(&gctx->gcm, in, len)) {
579 return -1;
580 }
581 } else if (ctx->encrypt) {
582 if (gctx->ctr) {
David Benjamin4969cc92016-04-22 15:02:23 -0400583 if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
584 gctx->ctr)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800585 return -1;
586 }
587 } else {
David Benjamin4969cc92016-04-22 15:02:23 -0400588 if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800589 return -1;
590 }
591 }
592 } else {
593 if (gctx->ctr) {
David Benjamin4969cc92016-04-22 15:02:23 -0400594 if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
595 gctx->ctr)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800596 return -1;
597 }
598 } else {
David Benjamin4969cc92016-04-22 15:02:23 -0400599 if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800600 return -1;
601 }
602 }
603 }
604 return len;
605 } else {
606 if (!ctx->encrypt) {
607 if (gctx->taglen < 0 ||
Kenny Rootb8494592015-09-25 02:29:14 +0000608 !CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -0800609 return -1;
610 }
611 gctx->iv_set = 0;
612 return 0;
613 }
614 CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
615 gctx->taglen = 16;
Robert Sloan8f860b12017-08-28 07:37:06 -0700616 // Don't reuse the IV
Adam Langleyd9e397b2015-01-22 14:27:53 -0800617 gctx->iv_set = 0;
618 return 0;
619 }
620}
621
Robert Sloan8ff03552017-06-14 12:40:58 -0700622DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_cbc_generic) {
623 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800624
Robert Sloan8ff03552017-06-14 12:40:58 -0700625 out->nid = NID_aes_128_cbc;
626 out->block_size = 16;
627 out->key_len = 16;
628 out->iv_len = 16;
629 out->ctx_size = sizeof(EVP_AES_KEY);
630 out->flags = EVP_CIPH_CBC_MODE;
631 out->init = aes_init_key;
632 out->cipher = aes_cbc_cipher;
633}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800634
Robert Sloan8ff03552017-06-14 12:40:58 -0700635DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_ctr_generic) {
636 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800637
Robert Sloan8ff03552017-06-14 12:40:58 -0700638 out->nid = NID_aes_128_ctr;
639 out->block_size = 1;
640 out->key_len = 16;
641 out->iv_len = 16;
642 out->ctx_size = sizeof(EVP_AES_KEY);
643 out->flags = EVP_CIPH_CTR_MODE;
644 out->init = aes_init_key;
645 out->cipher = aes_ctr_cipher;
646}
Adam Langleye9ada862015-05-11 17:20:37 -0700647
Robert Sloan8ff03552017-06-14 12:40:58 -0700648DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_ecb_generic) {
649 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800650
Robert Sloan8ff03552017-06-14 12:40:58 -0700651 out->nid = NID_aes_128_ecb;
652 out->block_size = 16;
653 out->key_len = 16;
654 out->ctx_size = sizeof(EVP_AES_KEY);
655 out->flags = EVP_CIPH_ECB_MODE;
656 out->init = aes_init_key;
657 out->cipher = aes_ecb_cipher;
658}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800659
Robert Sloan8ff03552017-06-14 12:40:58 -0700660DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_ofb_generic) {
661 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley13d393e2015-04-08 11:18:53 -0700662
Robert Sloan8ff03552017-06-14 12:40:58 -0700663 out->nid = NID_aes_128_ofb128;
664 out->block_size = 1;
665 out->key_len = 16;
666 out->iv_len = 16;
667 out->ctx_size = sizeof(EVP_AES_KEY);
668 out->flags = EVP_CIPH_OFB_MODE;
669 out->init = aes_init_key;
670 out->cipher = aes_ofb_cipher;
671}
Adam Langley13d393e2015-04-08 11:18:53 -0700672
Robert Sloan8ff03552017-06-14 12:40:58 -0700673DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_gcm_generic) {
674 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley13d393e2015-04-08 11:18:53 -0700675
Robert Sloan8ff03552017-06-14 12:40:58 -0700676 out->nid = NID_aes_128_gcm;
677 out->block_size = 1;
678 out->key_len = 16;
679 out->iv_len = 12;
680 out->ctx_size = sizeof(EVP_AES_GCM_CTX);
681 out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
682 EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
683 EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER;
684 out->init = aes_gcm_init_key;
685 out->cipher = aes_gcm_cipher;
686 out->cleanup = aes_gcm_cleanup;
687 out->ctrl = aes_gcm_ctrl;
688}
Adam Langley13d393e2015-04-08 11:18:53 -0700689
Robert Sloan8ff03552017-06-14 12:40:58 -0700690DEFINE_LOCAL_DATA(EVP_CIPHER, aes_192_cbc_generic) {
691 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley13d393e2015-04-08 11:18:53 -0700692
Robert Sloan8ff03552017-06-14 12:40:58 -0700693 out->nid = NID_aes_192_cbc;
694 out->block_size = 16;
695 out->key_len = 24;
696 out->iv_len = 16;
697 out->ctx_size = sizeof(EVP_AES_KEY);
698 out->flags = EVP_CIPH_CBC_MODE;
699 out->init = aes_init_key;
700 out->cipher = aes_cbc_cipher;
701}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800702
Robert Sloan8ff03552017-06-14 12:40:58 -0700703DEFINE_LOCAL_DATA(EVP_CIPHER, aes_192_ctr_generic) {
704 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800705
Robert Sloan8ff03552017-06-14 12:40:58 -0700706 out->nid = NID_aes_192_ctr;
707 out->block_size = 1;
708 out->key_len = 24;
709 out->iv_len = 16;
710 out->ctx_size = sizeof(EVP_AES_KEY);
711 out->flags = EVP_CIPH_CTR_MODE;
712 out->init = aes_init_key;
713 out->cipher = aes_ctr_cipher;
714}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800715
Robert Sloan8ff03552017-06-14 12:40:58 -0700716DEFINE_LOCAL_DATA(EVP_CIPHER, aes_192_ecb_generic) {
717 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleye9ada862015-05-11 17:20:37 -0700718
Robert Sloan8ff03552017-06-14 12:40:58 -0700719 out->nid = NID_aes_192_ecb;
720 out->block_size = 16;
721 out->key_len = 24;
722 out->ctx_size = sizeof(EVP_AES_KEY);
723 out->flags = EVP_CIPH_ECB_MODE;
724 out->init = aes_init_key;
725 out->cipher = aes_ecb_cipher;
726}
727
728DEFINE_LOCAL_DATA(EVP_CIPHER, aes_192_gcm_generic) {
729 memset(out, 0, sizeof(EVP_CIPHER));
730
731 out->nid = NID_aes_192_gcm;
732 out->block_size = 1;
733 out->key_len = 24;
734 out->iv_len = 12;
735 out->ctx_size = sizeof(EVP_AES_GCM_CTX);
736 out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
737 EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
738 EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER;
739 out->init = aes_gcm_init_key;
740 out->cipher = aes_gcm_cipher;
741 out->cleanup = aes_gcm_cleanup;
742 out->ctrl = aes_gcm_ctrl;
743}
744
745DEFINE_LOCAL_DATA(EVP_CIPHER, aes_256_cbc_generic) {
746 memset(out, 0, sizeof(EVP_CIPHER));
747
748 out->nid = NID_aes_256_cbc;
749 out->block_size = 16;
750 out->key_len = 32;
751 out->iv_len = 16;
752 out->ctx_size = sizeof(EVP_AES_KEY);
753 out->flags = EVP_CIPH_CBC_MODE;
754 out->init = aes_init_key;
755 out->cipher = aes_cbc_cipher;
756}
757
758DEFINE_LOCAL_DATA(EVP_CIPHER, aes_256_ctr_generic) {
759 memset(out, 0, sizeof(EVP_CIPHER));
760
761 out->nid = NID_aes_256_ctr;
762 out->block_size = 1;
763 out->key_len = 32;
764 out->iv_len = 16;
765 out->ctx_size = sizeof(EVP_AES_KEY);
766 out->flags = EVP_CIPH_CTR_MODE;
767 out->init = aes_init_key;
768 out->cipher = aes_ctr_cipher;
769}
770
771DEFINE_LOCAL_DATA(EVP_CIPHER, aes_256_ecb_generic) {
772 memset(out, 0, sizeof(EVP_CIPHER));
773
774 out->nid = NID_aes_256_ecb;
775 out->block_size = 16;
776 out->key_len = 32;
777 out->ctx_size = sizeof(EVP_AES_KEY);
778 out->flags = EVP_CIPH_ECB_MODE;
779 out->init = aes_init_key;
780 out->cipher = aes_ecb_cipher;
781}
782
783DEFINE_LOCAL_DATA(EVP_CIPHER, aes_256_ofb_generic) {
784 memset(out, 0, sizeof(EVP_CIPHER));
785
786 out->nid = NID_aes_256_ofb128;
787 out->block_size = 1;
788 out->key_len = 32;
789 out->iv_len = 16;
790 out->ctx_size = sizeof(EVP_AES_KEY);
791 out->flags = EVP_CIPH_OFB_MODE;
792 out->init = aes_init_key;
793 out->cipher = aes_ofb_cipher;
794}
795
796DEFINE_LOCAL_DATA(EVP_CIPHER, aes_256_gcm_generic) {
797 memset(out, 0, sizeof(EVP_CIPHER));
798
799 out->nid = NID_aes_256_gcm;
800 out->block_size = 1;
801 out->key_len = 32;
802 out->iv_len = 12;
803 out->ctx_size = sizeof(EVP_AES_GCM_CTX);
804 out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
805 EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
806 EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER;
807 out->init = aes_gcm_init_key;
808 out->cipher = aes_gcm_cipher;
809 out->cleanup = aes_gcm_cleanup;
810 out->ctrl = aes_gcm_ctrl;
811}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800812
813#if !defined(OPENSSL_NO_ASM) && \
814 (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
815
Robert Sloan8f860b12017-08-28 07:37:06 -0700816// AES-NI section.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800817
818static char aesni_capable(void) {
819 return (OPENSSL_ia32cap_P[1] & (1 << (57 - 32))) != 0;
820}
821
822static int aesni_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
823 const uint8_t *iv, int enc) {
824 int ret, mode;
825 EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
826
827 mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
828 if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) {
829 ret = aesni_set_decrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
830 dat->block = (block128_f)aesni_decrypt;
831 dat->stream.cbc =
832 mode == EVP_CIPH_CBC_MODE ? (cbc128_f)aesni_cbc_encrypt : NULL;
833 } else {
834 ret = aesni_set_encrypt_key(key, ctx->key_len * 8, ctx->cipher_data);
835 dat->block = (block128_f)aesni_encrypt;
836 if (mode == EVP_CIPH_CBC_MODE) {
837 dat->stream.cbc = (cbc128_f)aesni_cbc_encrypt;
838 } else if (mode == EVP_CIPH_CTR_MODE) {
839 dat->stream.ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
840 } else {
841 dat->stream.cbc = NULL;
842 }
843 }
844
845 if (ret < 0) {
Kenny Rootb8494592015-09-25 02:29:14 +0000846 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800847 return 0;
848 }
849
850 return 1;
851}
852
853static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
854 const uint8_t *in, size_t len) {
855 aesni_cbc_encrypt(in, out, len, ctx->cipher_data, ctx->iv, ctx->encrypt);
856
857 return 1;
858}
859
860static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
861 const uint8_t *in, size_t len) {
862 size_t bl = ctx->cipher->block_size;
863
864 if (len < bl) {
865 return 1;
866 }
867
868 aesni_ecb_encrypt(in, out, len, ctx->cipher_data, ctx->encrypt);
869
870 return 1;
871}
872
873static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
874 const uint8_t *iv, int enc) {
875 EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
876 if (!iv && !key) {
877 return 1;
878 }
879 if (key) {
880 aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
Robert Sloan9254e682017-04-24 09:42:06 -0700881 CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)aesni_encrypt, 1);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800882 gctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
Robert Sloan8f860b12017-08-28 07:37:06 -0700883 // If we have an iv can set it directly, otherwise use
884 // saved IV.
Adam Langleyd9e397b2015-01-22 14:27:53 -0800885 if (iv == NULL && gctx->iv_set) {
886 iv = gctx->iv;
887 }
888 if (iv) {
Kenny Roote99801b2015-11-06 15:31:15 -0800889 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800890 gctx->iv_set = 1;
891 }
892 gctx->key_set = 1;
893 } else {
Robert Sloan8f860b12017-08-28 07:37:06 -0700894 // If key set use IV, otherwise copy
Adam Langleyd9e397b2015-01-22 14:27:53 -0800895 if (gctx->key_set) {
Kenny Roote99801b2015-11-06 15:31:15 -0800896 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800897 } else {
Robert Sloan69939df2017-01-09 10:53:07 -0800898 OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800899 }
900 gctx->iv_set = 1;
901 gctx->iv_gen = 0;
902 }
903 return 1;
904}
905
Robert Sloan8ff03552017-06-14 12:40:58 -0700906DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_cbc) {
907 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800908
Robert Sloan8ff03552017-06-14 12:40:58 -0700909 out->nid = NID_aes_128_cbc;
910 out->block_size = 16;
911 out->key_len = 16;
912 out->iv_len = 16;
913 out->ctx_size = sizeof(EVP_AES_KEY);
914 out->flags = EVP_CIPH_CBC_MODE;
915 out->init = aesni_init_key;
916 out->cipher = aesni_cbc_cipher;
917}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800918
Robert Sloan8ff03552017-06-14 12:40:58 -0700919DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_ctr) {
920 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800921
Robert Sloan8ff03552017-06-14 12:40:58 -0700922 out->nid = NID_aes_128_ctr;
923 out->block_size = 1;
924 out->key_len = 16;
925 out->iv_len = 16;
926 out->ctx_size = sizeof(EVP_AES_KEY);
927 out->flags = EVP_CIPH_CTR_MODE;
928 out->init = aesni_init_key;
929 out->cipher = aes_ctr_cipher;
930}
Adam Langleye9ada862015-05-11 17:20:37 -0700931
Robert Sloan8ff03552017-06-14 12:40:58 -0700932DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_ecb) {
933 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800934
Robert Sloan8ff03552017-06-14 12:40:58 -0700935 out->nid = NID_aes_128_ecb;
936 out->block_size = 16;
937 out->key_len = 16;
938 out->ctx_size = sizeof(EVP_AES_KEY);
939 out->flags = EVP_CIPH_ECB_MODE;
940 out->init = aesni_init_key;
941 out->cipher = aesni_ecb_cipher;
942}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800943
Robert Sloan8ff03552017-06-14 12:40:58 -0700944DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_ofb) {
945 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley13d393e2015-04-08 11:18:53 -0700946
Robert Sloan8ff03552017-06-14 12:40:58 -0700947 out->nid = NID_aes_128_ofb128;
948 out->block_size = 1;
949 out->key_len = 16;
950 out->iv_len = 16;
951 out->ctx_size = sizeof(EVP_AES_KEY);
952 out->flags = EVP_CIPH_OFB_MODE;
953 out->init = aesni_init_key;
954 out->cipher = aes_ofb_cipher;
955}
Adam Langley13d393e2015-04-08 11:18:53 -0700956
Robert Sloan8ff03552017-06-14 12:40:58 -0700957DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_gcm) {
958 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley13d393e2015-04-08 11:18:53 -0700959
Robert Sloan8ff03552017-06-14 12:40:58 -0700960 out->nid = NID_aes_128_gcm;
961 out->block_size = 1;
962 out->key_len = 16;
963 out->iv_len = 12;
964 out->ctx_size = sizeof(EVP_AES_GCM_CTX);
965 out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
966 EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
967 EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER;
968 out->init = aesni_gcm_init_key;
969 out->cipher = aes_gcm_cipher;
970 out->cleanup = aes_gcm_cleanup;
971 out->ctrl = aes_gcm_ctrl;
972}
Adam Langley13d393e2015-04-08 11:18:53 -0700973
Robert Sloan8ff03552017-06-14 12:40:58 -0700974DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_192_cbc) {
975 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley13d393e2015-04-08 11:18:53 -0700976
Robert Sloan8ff03552017-06-14 12:40:58 -0700977 out->nid = NID_aes_192_cbc;
978 out->block_size = 16;
979 out->key_len = 24;
980 out->iv_len = 16;
981 out->ctx_size = sizeof(EVP_AES_KEY);
982 out->flags = EVP_CIPH_CBC_MODE;
983 out->init = aesni_init_key;
984 out->cipher = aesni_cbc_cipher;
985}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800986
Robert Sloan8ff03552017-06-14 12:40:58 -0700987DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_192_ctr) {
988 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleyd9e397b2015-01-22 14:27:53 -0800989
Robert Sloan8ff03552017-06-14 12:40:58 -0700990 out->nid = NID_aes_192_ctr;
991 out->block_size = 1;
992 out->key_len = 24;
993 out->iv_len = 16;
994 out->ctx_size = sizeof(EVP_AES_KEY);
995 out->flags = EVP_CIPH_CTR_MODE;
996 out->init = aesni_init_key;
997 out->cipher = aes_ctr_cipher;
998}
Adam Langleyd9e397b2015-01-22 14:27:53 -0800999
Robert Sloan8ff03552017-06-14 12:40:58 -07001000DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_192_ecb) {
1001 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langleye9ada862015-05-11 17:20:37 -07001002
Robert Sloan8ff03552017-06-14 12:40:58 -07001003 out->nid = NID_aes_192_ecb;
1004 out->block_size = 16;
1005 out->key_len = 24;
1006 out->ctx_size = sizeof(EVP_AES_KEY);
1007 out->flags = EVP_CIPH_ECB_MODE;
1008 out->init = aesni_init_key;
1009 out->cipher = aesni_ecb_cipher;
1010}
1011
1012DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_192_gcm) {
1013 memset(out, 0, sizeof(EVP_CIPHER));
1014
1015 out->nid = NID_aes_192_gcm;
1016 out->block_size = 1;
1017 out->key_len = 24;
1018 out->iv_len = 12;
1019 out->ctx_size = sizeof(EVP_AES_GCM_CTX);
1020 out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
1021 EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
1022 EVP_CIPH_CTRL_INIT | EVP_CIPH_FLAG_AEAD_CIPHER;
1023 out->init = aesni_gcm_init_key;
1024 out->cipher = aes_gcm_cipher;
1025 out->cleanup = aes_gcm_cleanup;
1026 out->ctrl = aes_gcm_ctrl;
1027}
1028
1029DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_256_cbc) {
1030 memset(out, 0, sizeof(EVP_CIPHER));
1031
1032 out->nid = NID_aes_256_cbc;
1033 out->block_size = 16;
1034 out->key_len = 32;
1035 out->iv_len = 16;
1036 out->ctx_size = sizeof(EVP_AES_KEY);
1037 out->flags = EVP_CIPH_CBC_MODE;
1038 out->init = aesni_init_key;
1039 out->cipher = aesni_cbc_cipher;
1040}
1041
1042DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_256_ctr) {
1043 memset(out, 0, sizeof(EVP_CIPHER));
1044
1045 out->nid = NID_aes_256_ctr;
1046 out->block_size = 1;
1047 out->key_len = 32;
1048 out->iv_len = 16;
1049 out->ctx_size = sizeof(EVP_AES_KEY);
1050 out->flags = EVP_CIPH_CTR_MODE;
1051 out->init = aesni_init_key;
1052 out->cipher = aes_ctr_cipher;
1053}
1054
1055DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_256_ecb) {
1056 memset(out, 0, sizeof(EVP_CIPHER));
1057
1058 out->nid = NID_aes_256_ecb;
1059 out->block_size = 16;
1060 out->key_len = 32;
1061 out->ctx_size = sizeof(EVP_AES_KEY);
1062 out->flags = EVP_CIPH_ECB_MODE;
1063 out->init = aesni_init_key;
1064 out->cipher = aesni_ecb_cipher;
1065}
1066
1067DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_256_ofb) {
1068 memset(out, 0, sizeof(EVP_CIPHER));
1069
1070 out->nid = NID_aes_256_ofb128;
1071 out->block_size = 1;
1072 out->key_len = 32;
1073 out->iv_len = 16;
1074 out->ctx_size = sizeof(EVP_AES_KEY);
1075 out->flags = EVP_CIPH_OFB_MODE;
1076 out->init = aesni_init_key;
1077 out->cipher = aes_ofb_cipher;
1078}
1079
1080DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_256_gcm) {
1081 memset(out, 0, sizeof(EVP_CIPHER));
1082
1083 out->nid = NID_aes_256_gcm;
1084 out->block_size = 1;
1085 out->key_len = 32;
1086 out->iv_len = 12;
1087 out->ctx_size = sizeof(EVP_AES_GCM_CTX);
1088 out->flags = EVP_CIPH_GCM_MODE | EVP_CIPH_CUSTOM_IV |
1089 EVP_CIPH_FLAG_CUSTOM_CIPHER | EVP_CIPH_ALWAYS_CALL_INIT |
1090 EVP_CIPH_CTRL_INIT | EVP_CIPH_CUSTOM_COPY |
1091 EVP_CIPH_FLAG_AEAD_CIPHER;
1092 out->init = aesni_gcm_init_key;
1093 out->cipher = aes_gcm_cipher;
1094 out->cleanup = aes_gcm_cleanup;
1095 out->ctrl = aes_gcm_ctrl;
1096}
Adam Langleyd9e397b2015-01-22 14:27:53 -08001097
1098#define EVP_CIPHER_FUNCTION(keybits, mode) \
1099 const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
1100 if (aesni_capable()) { \
Robert Sloan8ff03552017-06-14 12:40:58 -07001101 return aesni_##keybits##_##mode(); \
Adam Langleyd9e397b2015-01-22 14:27:53 -08001102 } else { \
Robert Sloan8ff03552017-06-14 12:40:58 -07001103 return aes_##keybits##_##mode##_generic(); \
Adam Langleyd9e397b2015-01-22 14:27:53 -08001104 } \
1105 }
1106
Robert Sloan8f860b12017-08-28 07:37:06 -07001107#else // ^^^ OPENSSL_X86_64 || OPENSSL_X86
Adam Langleyd9e397b2015-01-22 14:27:53 -08001108
1109static char aesni_capable(void) {
1110 return 0;
1111}
1112
1113#define EVP_CIPHER_FUNCTION(keybits, mode) \
1114 const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
Robert Sloan8ff03552017-06-14 12:40:58 -07001115 return aes_##keybits##_##mode##_generic(); \
Adam Langleyd9e397b2015-01-22 14:27:53 -08001116 }
1117
1118#endif
1119
1120EVP_CIPHER_FUNCTION(128, cbc)
1121EVP_CIPHER_FUNCTION(128, ctr)
1122EVP_CIPHER_FUNCTION(128, ecb)
Adam Langleye9ada862015-05-11 17:20:37 -07001123EVP_CIPHER_FUNCTION(128, ofb)
Adam Langleyd9e397b2015-01-22 14:27:53 -08001124EVP_CIPHER_FUNCTION(128, gcm)
1125
Adam Langley13d393e2015-04-08 11:18:53 -07001126EVP_CIPHER_FUNCTION(192, cbc)
1127EVP_CIPHER_FUNCTION(192, ctr)
1128EVP_CIPHER_FUNCTION(192, ecb)
1129EVP_CIPHER_FUNCTION(192, gcm)
1130
Adam Langleyd9e397b2015-01-22 14:27:53 -08001131EVP_CIPHER_FUNCTION(256, cbc)
1132EVP_CIPHER_FUNCTION(256, ctr)
1133EVP_CIPHER_FUNCTION(256, ecb)
Adam Langleye9ada862015-05-11 17:20:37 -07001134EVP_CIPHER_FUNCTION(256, ofb)
Adam Langleyd9e397b2015-01-22 14:27:53 -08001135EVP_CIPHER_FUNCTION(256, gcm)
1136
1137
1138#define EVP_AEAD_AES_GCM_TAG_LEN 16
1139
1140struct aead_aes_gcm_ctx {
1141 union {
1142 double align;
1143 AES_KEY ks;
1144 } ks;
1145 GCM128_CONTEXT gcm;
1146 ctr128_f ctr;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001147};
1148
Robert Sloan8ff03552017-06-14 12:40:58 -07001149struct aead_aes_gcm_tls12_ctx {
1150 struct aead_aes_gcm_ctx gcm_ctx;
1151 uint64_t counter;
1152};
1153
1154static int aead_aes_gcm_init_impl(struct aead_aes_gcm_ctx *gcm_ctx,
Robert Sloan927a4952017-07-03 11:25:09 -07001155 size_t *out_tag_len, const uint8_t *key,
1156 size_t key_len, size_t tag_len) {
Adam Langleyd9e397b2015-01-22 14:27:53 -08001157 const size_t key_bits = key_len * 8;
1158
1159 if (key_bits != 128 && key_bits != 256) {
Kenny Rootb8494592015-09-25 02:29:14 +00001160 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
Robert Sloan8f860b12017-08-28 07:37:06 -07001161 return 0; // EVP_AEAD_CTX_init should catch this.
Adam Langleyd9e397b2015-01-22 14:27:53 -08001162 }
1163
1164 if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
1165 tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
1166 }
1167
1168 if (tag_len > EVP_AEAD_AES_GCM_TAG_LEN) {
Kenny Rootb8494592015-09-25 02:29:14 +00001169 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001170 return 0;
1171 }
1172
Robert Sloan8ff03552017-06-14 12:40:58 -07001173 gcm_ctx->ctr =
1174 aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, NULL, key, key_len);
Robert Sloan927a4952017-07-03 11:25:09 -07001175 *out_tag_len = tag_len;
Robert Sloan8ff03552017-06-14 12:40:58 -07001176 return 1;
1177}
1178
1179static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
Robert Sloan927a4952017-07-03 11:25:09 -07001180 size_t key_len, size_t requested_tag_len) {
Robert Sloan8ff03552017-06-14 12:40:58 -07001181 struct aead_aes_gcm_ctx *gcm_ctx;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001182 gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_ctx));
1183 if (gcm_ctx == NULL) {
1184 return 0;
1185 }
1186
Robert Sloan927a4952017-07-03 11:25:09 -07001187 size_t actual_tag_len;
1188 if (!aead_aes_gcm_init_impl(gcm_ctx, &actual_tag_len, key, key_len,
1189 requested_tag_len)) {
Robert Sloan8ff03552017-06-14 12:40:58 -07001190 OPENSSL_free(gcm_ctx);
1191 return 0;
1192 }
Adam Langleyd9e397b2015-01-22 14:27:53 -08001193
Robert Sloan8ff03552017-06-14 12:40:58 -07001194 ctx->aead_state = gcm_ctx;
Robert Sloan927a4952017-07-03 11:25:09 -07001195 ctx->tag_len = actual_tag_len;
Adam Langleyd9e397b2015-01-22 14:27:53 -08001196 return 1;
1197}
1198
1199static void aead_aes_gcm_cleanup(EVP_AEAD_CTX *ctx) {
1200 struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
1201 OPENSSL_cleanse(gcm_ctx, sizeof(struct aead_aes_gcm_ctx));
1202 OPENSSL_free(gcm_ctx);
1203}
1204
Robert Sloan8ff03552017-06-14 12:40:58 -07001205static int aead_aes_gcm_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
1206 uint8_t *out_tag, size_t *out_tag_len,
1207 size_t max_out_tag_len,
1208 const uint8_t *nonce, size_t nonce_len,
1209 const uint8_t *in, size_t in_len,
Robert Sloan927a4952017-07-03 11:25:09 -07001210 const uint8_t *extra_in,
1211 size_t extra_in_len,
Robert Sloan8ff03552017-06-14 12:40:58 -07001212 const uint8_t *ad, size_t ad_len) {
Adam Langleyd9e397b2015-01-22 14:27:53 -08001213 const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
1214 GCM128_CONTEXT gcm;
1215
Robert Sloan927a4952017-07-03 11:25:09 -07001216 if (extra_in_len + ctx->tag_len < ctx->tag_len) {
1217 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
1218 return 0;
1219 }
Robert Sloanfe7cd212017-08-07 09:03:39 -07001220 if (max_out_tag_len < extra_in_len + ctx->tag_len) {
Robert Sloan927a4952017-07-03 11:25:09 -07001221 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
1222 return 0;
1223 }
Robert Sloan8ff03552017-06-14 12:40:58 -07001224 if (nonce_len == 0) {
1225 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001226 return 0;
1227 }
1228
Kenny Roote99801b2015-11-06 15:31:15 -08001229 const AES_KEY *key = &gcm_ctx->ks.ks;
1230
Robert Sloan69939df2017-01-09 10:53:07 -08001231 OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
Kenny Roote99801b2015-11-06 15:31:15 -08001232 CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001233
1234 if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
1235 return 0;
1236 }
1237
1238 if (gcm_ctx->ctr) {
Kenny Roote99801b2015-11-06 15:31:15 -08001239 if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, in, out, in_len,
Adam Langleyd9e397b2015-01-22 14:27:53 -08001240 gcm_ctx->ctr)) {
1241 return 0;
1242 }
1243 } else {
Kenny Roote99801b2015-11-06 15:31:15 -08001244 if (!CRYPTO_gcm128_encrypt(&gcm, key, in, out, in_len)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -08001245 return 0;
1246 }
1247 }
1248
Robert Sloan927a4952017-07-03 11:25:09 -07001249 if (extra_in_len) {
1250 if (gcm_ctx->ctr) {
1251 if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, extra_in, out_tag,
1252 extra_in_len, gcm_ctx->ctr)) {
1253 return 0;
1254 }
1255 } else {
1256 if (!CRYPTO_gcm128_encrypt(&gcm, key, extra_in, out_tag, extra_in_len)) {
1257 return 0;
1258 }
1259 }
1260 }
1261
1262 CRYPTO_gcm128_tag(&gcm, out_tag + extra_in_len, ctx->tag_len);
1263 *out_tag_len = ctx->tag_len + extra_in_len;
1264
Adam Langleyd9e397b2015-01-22 14:27:53 -08001265 return 1;
1266}
1267
Robert Sloan8ff03552017-06-14 12:40:58 -07001268static int aead_aes_gcm_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
1269 const uint8_t *nonce, size_t nonce_len,
1270 const uint8_t *in, size_t in_len,
1271 const uint8_t *in_tag, size_t in_tag_len,
1272 const uint8_t *ad, size_t ad_len) {
Adam Langleyd9e397b2015-01-22 14:27:53 -08001273 const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
1274 uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN];
Adam Langleyd9e397b2015-01-22 14:27:53 -08001275 GCM128_CONTEXT gcm;
1276
Robert Sloan8ff03552017-06-14 12:40:58 -07001277 if (nonce_len == 0) {
1278 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001279 return 0;
1280 }
1281
Robert Sloan927a4952017-07-03 11:25:09 -07001282 if (in_tag_len != ctx->tag_len) {
Robert Sloan8ff03552017-06-14 12:40:58 -07001283 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001284 return 0;
1285 }
1286
Kenny Roote99801b2015-11-06 15:31:15 -08001287 const AES_KEY *key = &gcm_ctx->ks.ks;
1288
Robert Sloan69939df2017-01-09 10:53:07 -08001289 OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
Kenny Roote99801b2015-11-06 15:31:15 -08001290 CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001291
1292 if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
1293 return 0;
1294 }
1295
1296 if (gcm_ctx->ctr) {
Robert Sloan8ff03552017-06-14 12:40:58 -07001297 if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out, in_len,
1298 gcm_ctx->ctr)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -08001299 return 0;
1300 }
1301 } else {
Robert Sloan8ff03552017-06-14 12:40:58 -07001302 if (!CRYPTO_gcm128_decrypt(&gcm, key, in, out, in_len)) {
Adam Langleyd9e397b2015-01-22 14:27:53 -08001303 return 0;
1304 }
1305 }
1306
Robert Sloan927a4952017-07-03 11:25:09 -07001307 CRYPTO_gcm128_tag(&gcm, tag, ctx->tag_len);
1308 if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) {
Kenny Rootb8494592015-09-25 02:29:14 +00001309 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
Adam Langleyd9e397b2015-01-22 14:27:53 -08001310 return 0;
1311 }
1312
Adam Langleyd9e397b2015-01-22 14:27:53 -08001313 return 1;
1314}
1315
Robert Sloan8ff03552017-06-14 12:40:58 -07001316DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm) {
1317 memset(out, 0, sizeof(EVP_AEAD));
Adam Langleyd9e397b2015-01-22 14:27:53 -08001318
Robert Sloan8ff03552017-06-14 12:40:58 -07001319 out->key_len = 16;
1320 out->nonce_len = 12;
1321 out->overhead = EVP_AEAD_AES_GCM_TAG_LEN;
1322 out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
Robert Sloan927a4952017-07-03 11:25:09 -07001323 out->seal_scatter_supports_extra_in = 1;
1324
Robert Sloan8ff03552017-06-14 12:40:58 -07001325 out->init = aead_aes_gcm_init;
1326 out->cleanup = aead_aes_gcm_cleanup;
1327 out->seal_scatter = aead_aes_gcm_seal_scatter;
1328 out->open_gather = aead_aes_gcm_open_gather;
1329}
Adam Langleyd9e397b2015-01-22 14:27:53 -08001330
Robert Sloan8ff03552017-06-14 12:40:58 -07001331DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm) {
1332 memset(out, 0, sizeof(EVP_AEAD));
Adam Langleyd9e397b2015-01-22 14:27:53 -08001333
Robert Sloan8ff03552017-06-14 12:40:58 -07001334 out->key_len = 32;
1335 out->nonce_len = 12;
1336 out->overhead = EVP_AEAD_AES_GCM_TAG_LEN;
1337 out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
Robert Sloan927a4952017-07-03 11:25:09 -07001338 out->seal_scatter_supports_extra_in = 1;
1339
Robert Sloan8ff03552017-06-14 12:40:58 -07001340 out->init = aead_aes_gcm_init;
1341 out->cleanup = aead_aes_gcm_cleanup;
1342 out->seal_scatter = aead_aes_gcm_seal_scatter;
1343 out->open_gather = aead_aes_gcm_open_gather;
1344}
Adam Langleyd9e397b2015-01-22 14:27:53 -08001345
Robert Sloan8ff03552017-06-14 12:40:58 -07001346static int aead_aes_gcm_tls12_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
Robert Sloan927a4952017-07-03 11:25:09 -07001347 size_t key_len, size_t requested_tag_len) {
Robert Sloan8ff03552017-06-14 12:40:58 -07001348 struct aead_aes_gcm_tls12_ctx *gcm_ctx;
1349 gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_tls12_ctx));
1350 if (gcm_ctx == NULL) {
1351 return 0;
1352 }
Robert Sloan9254e682017-04-24 09:42:06 -07001353
Robert Sloan8ff03552017-06-14 12:40:58 -07001354 gcm_ctx->counter = 0;
1355
Robert Sloan927a4952017-07-03 11:25:09 -07001356 size_t actual_tag_len;
1357 if (!aead_aes_gcm_init_impl(&gcm_ctx->gcm_ctx, &actual_tag_len, key, key_len,
1358 requested_tag_len)) {
Robert Sloan8ff03552017-06-14 12:40:58 -07001359 OPENSSL_free(gcm_ctx);
1360 return 0;
1361 }
1362
1363 ctx->aead_state = gcm_ctx;
Robert Sloan927a4952017-07-03 11:25:09 -07001364 ctx->tag_len = actual_tag_len;
Robert Sloan8ff03552017-06-14 12:40:58 -07001365 return 1;
1366}
1367
1368static void aead_aes_gcm_tls12_cleanup(EVP_AEAD_CTX *ctx) {
1369 struct aead_aes_gcm_tls12_ctx *gcm_ctx = ctx->aead_state;
1370 OPENSSL_cleanse(gcm_ctx, sizeof(struct aead_aes_gcm_tls12_ctx));
1371 OPENSSL_free(gcm_ctx);
1372}
1373
1374static int aead_aes_gcm_tls12_seal_scatter(
1375 const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
1376 size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
Robert Sloan927a4952017-07-03 11:25:09 -07001377 size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
1378 size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
Robert Sloan8ff03552017-06-14 12:40:58 -07001379 struct aead_aes_gcm_tls12_ctx *gcm_ctx = ctx->aead_state;
1380 if (gcm_ctx->counter == UINT64_MAX) {
1381 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE);
1382 return 0;
1383 }
1384
1385 if (nonce_len != 12) {
Robert Sloan9254e682017-04-24 09:42:06 -07001386 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
1387 return 0;
1388 }
Robert Sloan8ff03552017-06-14 12:40:58 -07001389
1390 const uint64_t be_counter = CRYPTO_bswap8(gcm_ctx->counter);
1391 if (OPENSSL_memcmp((uint8_t *)&be_counter, nonce + nonce_len - 8, 8) != 0) {
1392 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE);
Robert Sloan9254e682017-04-24 09:42:06 -07001393 return 0;
1394 }
1395
Robert Sloan8ff03552017-06-14 12:40:58 -07001396 gcm_ctx->counter++;
Robert Sloan9254e682017-04-24 09:42:06 -07001397
Robert Sloan8ff03552017-06-14 12:40:58 -07001398 return aead_aes_gcm_seal_scatter(ctx, out, out_tag, out_tag_len,
1399 max_out_tag_len, nonce, nonce_len, in,
Robert Sloan927a4952017-07-03 11:25:09 -07001400 in_len, extra_in, extra_in_len, ad, ad_len);
Robert Sloan9254e682017-04-24 09:42:06 -07001401}
1402
Robert Sloan8ff03552017-06-14 12:40:58 -07001403DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm_tls12) {
1404 memset(out, 0, sizeof(EVP_AEAD));
Robert Sloan9254e682017-04-24 09:42:06 -07001405
Robert Sloan8ff03552017-06-14 12:40:58 -07001406 out->key_len = 16;
1407 out->nonce_len = 12;
1408 out->overhead = EVP_AEAD_AES_GCM_TAG_LEN;
1409 out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
Robert Sloan927a4952017-07-03 11:25:09 -07001410 out->seal_scatter_supports_extra_in = 1;
1411
Robert Sloan8ff03552017-06-14 12:40:58 -07001412 out->init = aead_aes_gcm_tls12_init;
1413 out->cleanup = aead_aes_gcm_tls12_cleanup;
1414 out->seal_scatter = aead_aes_gcm_tls12_seal_scatter;
1415 out->open_gather = aead_aes_gcm_open_gather;
Robert Sloan9254e682017-04-24 09:42:06 -07001416}
1417
Robert Sloan8ff03552017-06-14 12:40:58 -07001418DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm_tls12) {
1419 memset(out, 0, sizeof(EVP_AEAD));
Robert Sloan9254e682017-04-24 09:42:06 -07001420
Robert Sloan8ff03552017-06-14 12:40:58 -07001421 out->key_len = 32;
1422 out->nonce_len = 12;
1423 out->overhead = EVP_AEAD_AES_GCM_TAG_LEN;
1424 out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
Robert Sloan927a4952017-07-03 11:25:09 -07001425 out->seal_scatter_supports_extra_in = 1;
1426
Robert Sloan8ff03552017-06-14 12:40:58 -07001427 out->init = aead_aes_gcm_tls12_init;
1428 out->cleanup = aead_aes_gcm_tls12_cleanup;
1429 out->seal_scatter = aead_aes_gcm_tls12_seal_scatter;
1430 out->open_gather = aead_aes_gcm_open_gather;
Robert Sloan9254e682017-04-24 09:42:06 -07001431}
1432
Adam Langleyd9e397b2015-01-22 14:27:53 -08001433int EVP_has_aes_hardware(void) {
1434#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
1435 return aesni_capable() && crypto_gcm_clmul_enabled();
1436#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
Kenny Roote99801b2015-11-06 15:31:15 -08001437 return hwaes_capable() && CRYPTO_is_ARMv8_PMULL_capable();
Adam Langleyd9e397b2015-01-22 14:27:53 -08001438#else
1439 return 0;
1440#endif
1441}