blob: 2c6fc4173f6f76508108dc3ca97b2313cc6adad5 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* ====================================================================
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
Adam Langley2b2d66d2015-01-30 17:08:37 -080049#include <string.h>
50
Adam Langleyfd772a52014-06-20 12:00:00 -070051#include <openssl/aead.h>
Adam Langley95c29f32014-06-20 12:00:00 -070052#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 Benjamin98193672016-03-25 18:07:11 -040057#include <openssl/nid.h>
Adam Langleyfd772a52014-06-20 12:00:00 -070058#include <openssl/rand.h>
Adam Langley95c29f32014-06-20 12:00:00 -070059
60#include "internal.h"
Adam Langley2e2a2262017-05-03 13:23:37 -070061#include "../../internal.h"
62#include "../aes/internal.h"
63#include "../modes/internal.h"
Matthew Braithwaite894e2002017-05-19 18:11:20 -070064#include "../delocate.h"
Adam Langley95c29f32014-06-20 12:00:00 -070065
Adam Langleye49da742015-01-16 14:06:22 -080066#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
Adam Langley73415b62015-08-24 18:03:17 -070067#include <openssl/arm_arch.h>
Adam Langleye49da742015-01-16 14:06:22 -080068#endif
69
Adam Langley95c29f32014-06-20 12:00:00 -070070
David Benjamina353cdb2016-06-09 16:48:33 -040071OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) /* Unreachable code. */
Brian Smithdc6c1b82016-01-17 22:21:42 -100072
Adam Langley95c29f32014-06-20 12:00:00 -070073typedef 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;
89 } ks; /* AES key schedule to use */
90 int key_set; /* Set if key initialised */
91 int iv_set; /* Set if an iv is set */
92 GCM128_CONTEXT gcm;
93 uint8_t *iv; /* Temporary IV store */
94 int ivlen; /* IV length */
95 int taglen;
96 int iv_gen; /* It is OK to generate IVs */
Adam Langley95c29f32014-06-20 12:00:00 -070097 ctr128_f ctr;
98} EVP_AES_GCM_CTX;
99
Adam Langley95c29f32014-06-20 12:00:00 -0700100#if !defined(OPENSSL_NO_ASM) && \
101 (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
102#define VPAES
David Benjaminc44d2f42014-08-20 16:24:00 -0400103static char vpaes_capable(void) {
Adam Langley95c29f32014-06-20 12:00:00 -0700104 return (OPENSSL_ia32cap_P[1] & (1 << (41 - 32))) != 0;
105}
106
107#if defined(OPENSSL_X86_64)
108#define BSAES
David Benjaminc44d2f42014-08-20 16:24:00 -0400109static char bsaes_capable(void) {
Adam Langley95c29f32014-06-20 12:00:00 -0700110 return vpaes_capable();
111}
112#endif
113
Adam Langley3e652652015-01-09 15:44:37 -0800114#elif !defined(OPENSSL_NO_ASM) && \
115 (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
Adam Langley3e652652015-01-09 15:44:37 -0800116
Joel Klinghed485a50a2015-05-29 15:02:09 +0200117#if defined(OPENSSL_ARM) && __ARM_MAX_ARCH__ >= 7
Adam Langley95c29f32014-06-20 12:00:00 -0700118#define BSAES
David Benjaminc44d2f42014-08-20 16:24:00 -0400119static char bsaes_capable(void) {
Adam Langley95c29f32014-06-20 12:00:00 -0700120 return CRYPTO_is_NEON_capable();
121}
Adam Langley3e652652015-01-09 15:44:37 -0800122#endif
123
Adam Langley2e2a2262017-05-03 13:23:37 -0700124#endif
Adam Langley4467e592016-09-23 12:47:24 -0700125
Adam Langley95c29f32014-06-20 12:00:00 -0700126
127#if defined(BSAES)
128/* On platforms where BSAES gets defined (just above), then these functions are
129 * provided by asm. */
130void 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
David Benjaminc44d2f42014-08-20 16:24:00 -0400135static char bsaes_capable(void) {
Adam Langley95c29f32014-06-20 12:00:00 -0700136 return 0;
137}
138
139/* On other platforms, bsaes_capable() will always return false and so the
140 * following will never be called. */
Adam Langley5f005cc2015-09-24 19:14:04 -0700141static 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 Langley95c29f32014-06-20 12:00:00 -0700143 abort();
144}
145
Adam Langley5f005cc2015-09-24 19:14:04 -0700146static 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 Langley95c29f32014-06-20 12:00:00 -0700149 abort();
150}
151#endif
152
153#if defined(VPAES)
Adam Langleyfd772a52014-06-20 12:00:00 -0700154/* On platforms where VPAES gets defined (just above), then these functions are
Adam Langley95c29f32014-06-20 12:00:00 -0700155 * provided by asm. */
156int 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
David Benjaminc44d2f42014-08-20 16:24:00 -0400165static char vpaes_capable(void) {
Adam Langley95c29f32014-06-20 12:00:00 -0700166 return 0;
167}
168
169/* On other platforms, vpaes_capable() will always return false and so the
170 * following will never be called. */
Adam Langley5f005cc2015-09-24 19:14:04 -0700171static int vpaes_set_encrypt_key(const uint8_t *userKey, int bits,
172 AES_KEY *key) {
Adam Langley95c29f32014-06-20 12:00:00 -0700173 abort();
174}
Adam Langley5f005cc2015-09-24 19:14:04 -0700175static int vpaes_set_decrypt_key(const uint8_t *userKey, int bits,
176 AES_KEY *key) {
Adam Langley95c29f32014-06-20 12:00:00 -0700177 abort();
178}
Adam Langley5f005cc2015-09-24 19:14:04 -0700179static void vpaes_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
Adam Langley95c29f32014-06-20 12:00:00 -0700180 abort();
181}
Adam Langley5f005cc2015-09-24 19:14:04 -0700182static void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
Adam Langley95c29f32014-06-20 12:00:00 -0700183 abort();
184}
Adam Langley5f005cc2015-09-24 19:14:04 -0700185static 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 Langley95c29f32014-06-20 12:00:00 -0700187 abort();
188}
189#endif
190
191#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 Langley95c29f32014-06-20 12:00:00 -0700204#else
205
206/* On other platforms, aesni_capable() will always return false and so the
207 * following will never be called. */
Adam Langley5f005cc2015-09-24 19:14:04 -0700208static void aesni_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
Adam Langley95c29f32014-06-20 12:00:00 -0700209 abort();
210}
Adam Langley5f005cc2015-09-24 19:14:04 -0700211static int aesni_set_encrypt_key(const uint8_t *userKey, int bits,
212 AES_KEY *key) {
Adam Langley95c29f32014-06-20 12:00:00 -0700213 abort();
214}
Adam Langley5f005cc2015-09-24 19:14:04 -0700215static 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 Langley95c29f32014-06-20 12:00:00 -0700218 abort();
219}
220
221#endif
222
223static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
Brian Smithdc6c1b82016-01-17 22:21:42 -1000224 const uint8_t *iv, int enc) {
Adam Langley95c29f32014-06-20 12:00:00 -0700225 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) {
Adam Langley3e652652015-01-09 15:44:37 -0800230 if (hwaes_capable()) {
Adam Langley4467e592016-09-23 12:47:24 -0700231 ret = aes_hw_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
232 dat->block = (block128_f)aes_hw_decrypt;
Adam Langley3e652652015-01-09 15:44:37 -0800233 dat->stream.cbc = NULL;
234 if (mode == EVP_CIPH_CBC_MODE) {
Adam Langley4467e592016-09-23 12:47:24 -0700235 dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
Adam Langley3e652652015-01-09 15:44:37 -0800236 }
237 } else if (bsaes_capable() && mode == EVP_CIPH_CBC_MODE) {
Adam Langley95c29f32014-06-20 12:00:00 -0700238 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 }
Adam Langley3e652652015-01-09 15:44:37 -0800252 } else if (hwaes_capable()) {
Adam Langley4467e592016-09-23 12:47:24 -0700253 ret = aes_hw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
254 dat->block = (block128_f)aes_hw_encrypt;
Adam Langley3e652652015-01-09 15:44:37 -0800255 dat->stream.cbc = NULL;
256 if (mode == EVP_CIPH_CBC_MODE) {
Adam Langley4467e592016-09-23 12:47:24 -0700257 dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
Adam Langley3e652652015-01-09 15:44:37 -0800258 } else if (mode == EVP_CIPH_CTR_MODE) {
Adam Langley4467e592016-09-23 12:47:24 -0700259 dat->stream.ctr = (ctr128_f)aes_hw_ctr32_encrypt_blocks;
Adam Langley3e652652015-01-09 15:44:37 -0800260 }
Adam Langley95c29f32014-06-20 12:00:00 -0700261 } 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) {
David Benjamin3570d732015-06-29 00:28:17 -0400278 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
Adam Langley95c29f32014-06-20 12:00:00 -0700279 return 0;
280 }
281
282 return 1;
283}
284
Adam Langley087930f2015-02-24 12:44:40 -0800285static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
286 size_t len) {
Adam Langley95c29f32014-06-20 12:00:00 -0700287 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 Langley087930f2015-02-24 12:44:40 -0800300static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
301 size_t len) {
Adam Langley95c29f32014-06-20 12:00:00 -0700302 size_t bl = ctx->cipher->block_size;
Adam Langley95c29f32014-06-20 12:00:00 -0700303 EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
304
305 if (len < bl) {
306 return 1;
307 }
308
David Benjamin54091232016-09-05 12:47:25 -0400309 len -= bl;
310 for (size_t i = 0; i <= len; i += bl) {
Adam Langley95c29f32014-06-20 12:00:00 -0700311 (*dat->block)(in + i, out + i, &dat->ks);
312 }
313
314 return 1;
315}
316
Adam Langley087930f2015-02-24 12:44:40 -0800317static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
318 size_t len) {
Adam Langley95c29f32014-06-20 12:00:00 -0700319 EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
320
321 if (dat->stream.ctr) {
David Benjamin0e21f412016-04-16 15:20:07 -0400322 CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf,
323 &ctx->num, dat->stream.ctr);
Adam Langley95c29f32014-06-20 12:00:00 -0700324 } else {
David Benjamin0e21f412016-04-16 15:20:07 -0400325 CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num,
Adam Langley95c29f32014-06-20 12:00:00 -0700326 dat->block);
327 }
Adam Langley95c29f32014-06-20 12:00:00 -0700328 return 1;
329}
330
Adam Langley087930f2015-02-24 12:44:40 -0800331static 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
Adam Langley52f9f622015-03-13 11:49:22 -0700339static char aesni_capable(void);
340
Adam Langley20422532017-04-07 11:46:13 -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 Langley52f9f622015-03-13 11:49:22 -0700344 if (aesni_capable()) {
Adam Langley20422532017-04-07 11:46:13 -0700345 aesni_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langley52f9f622015-03-13 11:49:22 -0700346 if (gcm_ctx != NULL) {
David Benjamin1997ef22017-04-21 14:29:57 -0400347 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aesni_encrypt, 1);
Adam Langley52f9f622015-03-13 11:49:22 -0700348 }
349 if (out_block) {
350 *out_block = (block128_f) aesni_encrypt;
351 }
352 return (ctr128_f)aesni_ctr32_encrypt_blocks;
353 }
354
Adam Langley3e652652015-01-09 15:44:37 -0800355 if (hwaes_capable()) {
Adam Langley20422532017-04-07 11:46:13 -0700356 aes_hw_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langley52f9f622015-03-13 11:49:22 -0700357 if (gcm_ctx != NULL) {
David Benjamin1997ef22017-04-21 14:29:57 -0400358 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_hw_encrypt, 0);
Adam Langley52f9f622015-03-13 11:49:22 -0700359 }
360 if (out_block) {
Adam Langley4467e592016-09-23 12:47:24 -0700361 *out_block = (block128_f) aes_hw_encrypt;
Adam Langley52f9f622015-03-13 11:49:22 -0700362 }
Adam Langley4467e592016-09-23 12:47:24 -0700363 return (ctr128_f)aes_hw_ctr32_encrypt_blocks;
Adam Langley3e652652015-01-09 15:44:37 -0800364 }
365
Adam Langleyfd772a52014-06-20 12:00:00 -0700366 if (bsaes_capable()) {
Adam Langley20422532017-04-07 11:46:13 -0700367 AES_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langley52f9f622015-03-13 11:49:22 -0700368 if (gcm_ctx != NULL) {
David Benjamin1997ef22017-04-21 14:29:57 -0400369 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0);
Adam Langley52f9f622015-03-13 11:49:22 -0700370 }
371 if (out_block) {
372 *out_block = (block128_f) AES_encrypt;
373 }
Adam Langleyfd772a52014-06-20 12:00:00 -0700374 return (ctr128_f)bsaes_ctr32_encrypt_blocks;
375 }
376
377 if (vpaes_capable()) {
Adam Langley20422532017-04-07 11:46:13 -0700378 vpaes_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langley52f9f622015-03-13 11:49:22 -0700379 if (out_block) {
380 *out_block = (block128_f) vpaes_encrypt;
381 }
382 if (gcm_ctx != NULL) {
David Benjamin1997ef22017-04-21 14:29:57 -0400383 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)vpaes_encrypt, 0);
Adam Langley52f9f622015-03-13 11:49:22 -0700384 }
Adam Langleyfd772a52014-06-20 12:00:00 -0700385 return NULL;
386 }
387
Adam Langley20422532017-04-07 11:46:13 -0700388 AES_set_encrypt_key(key, key_bytes * 8, aes_key);
Adam Langley52f9f622015-03-13 11:49:22 -0700389 if (gcm_ctx != NULL) {
David Benjamin1997ef22017-04-21 14:29:57 -0400390 CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)AES_encrypt, 0);
Adam Langley52f9f622015-03-13 11:49:22 -0700391 }
392 if (out_block) {
393 *out_block = (block128_f) AES_encrypt;
394 }
Adam Langleyfd772a52014-06-20 12:00:00 -0700395 return NULL;
396}
397
Adam Langley95c29f32014-06-20 12:00:00 -0700398static 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 }
Adam Langley95c29f32014-06-20 12:00:00 -0700404 if (key) {
Adam Langley52f9f622015-03-13 11:49:22 -0700405 gctx->ctr =
406 aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm, NULL, key, ctx->key_len);
Adam Langleyfd772a52014-06-20 12:00:00 -0700407 /* If we have an iv can set it directly, otherwise use saved IV. */
Adam Langley95c29f32014-06-20 12:00:00 -0700408 if (iv == NULL && gctx->iv_set) {
409 iv = gctx->iv;
410 }
411 if (iv) {
Brian Smith0f8bfde2015-09-26 20:12:01 -1000412 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700413 gctx->iv_set = 1;
414 }
415 gctx->key_set = 1;
416 } else {
417 /* If key set use IV, otherwise copy */
418 if (gctx->key_set) {
Brian Smith0f8bfde2015-09-26 20:12:01 -1000419 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700420 } else {
David Benjamin17cf2cb2016-12-13 01:07:13 -0500421 OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700422 }
423 gctx->iv_set = 1;
424 gctx->iv_gen = 0;
425 }
426 return 1;
427}
428
David Benjamin3f5917f2015-02-23 02:15:50 -0500429static void aes_gcm_cleanup(EVP_CIPHER_CTX *c) {
Adam Langley95c29f32014-06-20 12:00:00 -0700430 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 Langley95c29f32014-06-20 12:00:00 -0700435}
436
437/* increment counter (64-bit int) by 1 */
438static 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;
Adam Langley95c29f32014-06-20 12:00:00 -0700463 return 1;
464
465 case EVP_CTRL_GCM_SET_IVLEN:
466 if (arg <= 0) {
467 return 0;
468 }
469
470 /* Allocate memory for IV if needed */
471 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 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500487 OPENSSL_memcpy(c->buf, ptr, arg);
Adam Langley95c29f32014-06-20 12:00:00 -0700488 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 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500495 OPENSSL_memcpy(ptr, c->buf, arg);
Adam Langley95c29f32014-06-20 12:00:00 -0700496 return 1;
497
498 case EVP_CTRL_GCM_SET_IV_FIXED:
499 /* Special case: -1 length restores whole IV */
500 if (arg == -1) {
David Benjamin17cf2cb2016-12-13 01:07:13 -0500501 OPENSSL_memcpy(gctx->iv, ptr, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700502 gctx->iv_gen = 1;
503 return 1;
504 }
505 /* Fixed field must be at least 4 bytes and invocation field
506 * at least 8. */
507 if (arg < 4 || (gctx->ivlen - arg) < 8) {
508 return 0;
509 }
510 if (arg) {
David Benjamin17cf2cb2016-12-13 01:07:13 -0500511 OPENSSL_memcpy(gctx->iv, ptr, arg);
Adam Langley95c29f32014-06-20 12:00:00 -0700512 }
David Benjamina6d81012014-12-16 07:48:10 -0500513 if (c->encrypt && !RAND_bytes(gctx->iv + arg, gctx->ivlen - arg)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700514 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 }
Brian Smith0f8bfde2015-09-26 20:12:01 -1000523 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700524 if (arg <= 0 || arg > gctx->ivlen) {
525 arg = gctx->ivlen;
526 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500527 OPENSSL_memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
Adam Langley95c29f32014-06-20 12:00:00 -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. */
531 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 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500539 OPENSSL_memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
Brian Smith0f8bfde2015-09-26 20:12:01 -1000540 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700541 gctx->iv_set = 1;
542 return 1;
543
Adam Langley7578f3f2014-07-24 17:42:11 -0700544 case EVP_CTRL_COPY: {
545 EVP_CIPHER_CTX *out = ptr;
546 EVP_AES_GCM_CTX *gctx_out = out->cipher_data;
Adam Langley7578f3f2014-07-24 17:42:11 -0700547 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 }
David Benjamin17cf2cb2016-12-13 01:07:13 -0500554 OPENSSL_memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
Adam Langley7578f3f2014-07-24 17:42:11 -0700555 }
556 return 1;
557 }
558
Adam Langley95c29f32014-06-20 12:00:00 -0700559 default:
560 return -1;
561 }
562}
563
Adam Langley95c29f32014-06-20 12:00:00 -0700564static 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;
Adam Langleyfd772a52014-06-20 12:00:00 -0700567
Adam Langley95c29f32014-06-20 12:00:00 -0700568 /* If not set up, return error */
Adam Langleyfd772a52014-06-20 12:00:00 -0700569 if (!gctx->key_set) {
Adam Langley95c29f32014-06-20 12:00:00 -0700570 return -1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700571 }
Adam Langleyfd772a52014-06-20 12:00:00 -0700572 if (!gctx->iv_set) {
Adam Langley95c29f32014-06-20 12:00:00 -0700573 return -1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700574 }
575
Adam Langley95c29f32014-06-20 12:00:00 -0700576 if (in) {
577 if (out == NULL) {
Adam Langleyfd772a52014-06-20 12:00:00 -0700578 if (!CRYPTO_gcm128_aad(&gctx->gcm, in, len)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700579 return -1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700580 }
Adam Langley95c29f32014-06-20 12:00:00 -0700581 } else if (ctx->encrypt) {
582 if (gctx->ctr) {
Brian Smitha3d95282016-02-17 18:59:19 -1000583 if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
584 gctx->ctr)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700585 return -1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700586 }
Adam Langley95c29f32014-06-20 12:00:00 -0700587 } else {
Brian Smitha3d95282016-02-17 18:59:19 -1000588 if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700589 return -1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700590 }
Adam Langley95c29f32014-06-20 12:00:00 -0700591 }
592 } else {
593 if (gctx->ctr) {
Brian Smitha3d95282016-02-17 18:59:19 -1000594 if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
595 gctx->ctr)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700596 return -1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700597 }
Adam Langley95c29f32014-06-20 12:00:00 -0700598 } else {
Brian Smitha3d95282016-02-17 18:59:19 -1000599 if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700600 return -1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700601 }
Adam Langley95c29f32014-06-20 12:00:00 -0700602 }
603 }
604 return len;
605 } else {
606 if (!ctx->encrypt) {
Adam Langleyfd772a52014-06-20 12:00:00 -0700607 if (gctx->taglen < 0 ||
Adam Langley048d4ad2015-08-14 13:05:21 -0700608 !CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen)) {
Adam Langley95c29f32014-06-20 12:00:00 -0700609 return -1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700610 }
Adam Langley95c29f32014-06-20 12:00:00 -0700611 gctx->iv_set = 0;
612 return 0;
613 }
614 CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
615 gctx->taglen = 16;
616 /* Don't reuse the IV */
617 gctx->iv_set = 0;
618 return 0;
619 }
620}
621
Adam Langley2e2a2262017-05-03 13:23:37 -0700622DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_cbc_generic) {
623 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley95c29f32014-06-20 12:00:00 -0700624
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700634
Adam Langley2e2a2262017-05-03 13:23:37 -0700635DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_ctr_generic) {
636 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley95c29f32014-06-20 12:00:00 -0700637
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley087930f2015-02-24 12:44:40 -0800647
Adam Langley2e2a2262017-05-03 13:23:37 -0700648DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_ecb_generic) {
649 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley95c29f32014-06-20 12:00:00 -0700650
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700659
Adam Langley2e2a2262017-05-03 13:23:37 -0700660DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_ofb_generic) {
661 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley1049e262015-04-02 13:09:01 -0700662
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley1049e262015-04-02 13:09:01 -0700672
Adam Langley2e2a2262017-05-03 13:23:37 -0700673DEFINE_LOCAL_DATA(EVP_CIPHER, aes_128_gcm_generic) {
674 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley5dca0312015-05-04 17:41:23 -0700675
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley1049e262015-04-02 13:09:01 -0700689
Adam Langley2e2a2262017-05-03 13:23:37 -0700690DEFINE_LOCAL_DATA(EVP_CIPHER, aes_192_cbc_generic) {
691 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley1049e262015-04-02 13:09:01 -0700692
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700702
Adam Langley2e2a2262017-05-03 13:23:37 -0700703DEFINE_LOCAL_DATA(EVP_CIPHER, aes_192_ctr_generic) {
704 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley95c29f32014-06-20 12:00:00 -0700705
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700715
Adam Langley2e2a2262017-05-03 13:23:37 -0700716DEFINE_LOCAL_DATA(EVP_CIPHER, aes_192_ecb_generic) {
717 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley087930f2015-02-24 12:44:40 -0800718
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700812
813#if !defined(OPENSSL_NO_ASM) && \
814 (defined(OPENSSL_X86_64) || defined(OPENSSL_X86))
815
816/* AES-NI section. */
817
David Benjaminc44d2f42014-08-20 16:24:00 -0400818static char aesni_capable(void) {
Adam Langley95c29f32014-06-20 12:00:00 -0700819 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) {
David Benjamin3570d732015-06-29 00:28:17 -0400846 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
Adam Langley95c29f32014-06-20 12:00:00 -0700847 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;
Adam Langleyfd772a52014-06-20 12:00:00 -0700876 if (!iv && !key) {
Adam Langley95c29f32014-06-20 12:00:00 -0700877 return 1;
Adam Langleyfd772a52014-06-20 12:00:00 -0700878 }
Adam Langley95c29f32014-06-20 12:00:00 -0700879 if (key) {
880 aesni_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
David Benjamin1997ef22017-04-21 14:29:57 -0400881 CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f)aesni_encrypt, 1);
Adam Langley95c29f32014-06-20 12:00:00 -0700882 gctx->ctr = (ctr128_f)aesni_ctr32_encrypt_blocks;
883 /* If we have an iv can set it directly, otherwise use
884 * saved IV. */
885 if (iv == NULL && gctx->iv_set) {
886 iv = gctx->iv;
887 }
888 if (iv) {
Brian Smith0f8bfde2015-09-26 20:12:01 -1000889 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700890 gctx->iv_set = 1;
891 }
892 gctx->key_set = 1;
893 } else {
894 /* If key set use IV, otherwise copy */
895 if (gctx->key_set) {
Brian Smith0f8bfde2015-09-26 20:12:01 -1000896 CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700897 } else {
David Benjamin17cf2cb2016-12-13 01:07:13 -0500898 OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen);
Adam Langley95c29f32014-06-20 12:00:00 -0700899 }
900 gctx->iv_set = 1;
901 gctx->iv_gen = 0;
902 }
903 return 1;
904}
905
Adam Langley2e2a2262017-05-03 13:23:37 -0700906DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_cbc) {
907 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley95c29f32014-06-20 12:00:00 -0700908
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700918
Adam Langley2e2a2262017-05-03 13:23:37 -0700919DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_ctr) {
920 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley95c29f32014-06-20 12:00:00 -0700921
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley087930f2015-02-24 12:44:40 -0800931
Adam Langley2e2a2262017-05-03 13:23:37 -0700932DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_ecb) {
933 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley95c29f32014-06-20 12:00:00 -0700934
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700943
Adam Langley2e2a2262017-05-03 13:23:37 -0700944DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_ofb) {
945 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley1049e262015-04-02 13:09:01 -0700946
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley1049e262015-04-02 13:09:01 -0700956
Adam Langley2e2a2262017-05-03 13:23:37 -0700957DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_128_gcm) {
958 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley5dca0312015-05-04 17:41:23 -0700959
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley1049e262015-04-02 13:09:01 -0700973
Adam Langley2e2a2262017-05-03 13:23:37 -0700974DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_192_cbc) {
975 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley1049e262015-04-02 13:09:01 -0700976
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700986
Adam Langley2e2a2262017-05-03 13:23:37 -0700987DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_192_ctr) {
988 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley95c29f32014-06-20 12:00:00 -0700989
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -0700999
Adam Langley2e2a2262017-05-03 13:23:37 -07001000DEFINE_LOCAL_DATA(EVP_CIPHER, aesni_192_ecb) {
1001 memset(out, 0, sizeof(EVP_CIPHER));
Adam Langley087930f2015-02-24 12:44:40 -08001002
Adam Langley2e2a2262017-05-03 13:23:37 -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 Langley95c29f32014-06-20 12:00:00 -07001097
1098#define EVP_CIPHER_FUNCTION(keybits, mode) \
1099 const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
1100 if (aesni_capable()) { \
Adam Langley2e2a2262017-05-03 13:23:37 -07001101 return aesni_##keybits##_##mode(); \
Adam Langley95c29f32014-06-20 12:00:00 -07001102 } else { \
Adam Langley2e2a2262017-05-03 13:23:37 -07001103 return aes_##keybits##_##mode##_generic(); \
Adam Langley95c29f32014-06-20 12:00:00 -07001104 } \
1105 }
1106
1107#else /* ^^^ OPENSSL_X86_64 || OPENSSL_X86 */
1108
David Benjaminc44d2f42014-08-20 16:24:00 -04001109static char aesni_capable(void) {
Adam Langleyfd772a52014-06-20 12:00:00 -07001110 return 0;
1111}
1112
Adam Langley95c29f32014-06-20 12:00:00 -07001113#define EVP_CIPHER_FUNCTION(keybits, mode) \
1114 const EVP_CIPHER *EVP_aes_##keybits##_##mode(void) { \
Adam Langley2e2a2262017-05-03 13:23:37 -07001115 return aes_##keybits##_##mode##_generic(); \
Adam Langley95c29f32014-06-20 12:00:00 -07001116 }
1117
1118#endif
1119
1120EVP_CIPHER_FUNCTION(128, cbc)
1121EVP_CIPHER_FUNCTION(128, ctr)
1122EVP_CIPHER_FUNCTION(128, ecb)
Adam Langley087930f2015-02-24 12:44:40 -08001123EVP_CIPHER_FUNCTION(128, ofb)
Adam Langley95c29f32014-06-20 12:00:00 -07001124EVP_CIPHER_FUNCTION(128, gcm)
1125
Adam Langley1049e262015-04-02 13:09:01 -07001126EVP_CIPHER_FUNCTION(192, cbc)
1127EVP_CIPHER_FUNCTION(192, ctr)
Adam Langley5dca0312015-05-04 17:41:23 -07001128EVP_CIPHER_FUNCTION(192, ecb)
Adam Langley1049e262015-04-02 13:09:01 -07001129EVP_CIPHER_FUNCTION(192, gcm)
1130
Adam Langley95c29f32014-06-20 12:00:00 -07001131EVP_CIPHER_FUNCTION(256, cbc)
1132EVP_CIPHER_FUNCTION(256, ctr)
1133EVP_CIPHER_FUNCTION(256, ecb)
Adam Langley087930f2015-02-24 12:44:40 -08001134EVP_CIPHER_FUNCTION(256, ofb)
Adam Langley95c29f32014-06-20 12:00:00 -07001135EVP_CIPHER_FUNCTION(256, gcm)
Adam Langleyfd772a52014-06-20 12:00:00 -07001136
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 Langleyfd772a52014-06-20 12:00:00 -07001147};
1148
Steven Valdez2f3404b2017-05-24 16:54:35 -04001149struct 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,
Adam Langley946dd622017-06-27 15:49:40 -07001155 size_t *out_tag_len, const uint8_t *key,
1156 size_t key_len, size_t tag_len) {
Adam Langleyfd772a52014-06-20 12:00:00 -07001157 const size_t key_bits = key_len * 8;
1158
1159 if (key_bits != 128 && key_bits != 256) {
David Benjamin3570d732015-06-29 00:28:17 -04001160 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
Adam Langleyfd772a52014-06-20 12:00:00 -07001161 return 0; /* EVP_AEAD_CTX_init should catch this. */
1162 }
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) {
David Benjamin3570d732015-06-29 00:28:17 -04001169 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
Adam Langleyfd772a52014-06-20 12:00:00 -07001170 return 0;
1171 }
1172
Steven Valdez2f3404b2017-05-24 16:54:35 -04001173 gcm_ctx->ctr =
1174 aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm, NULL, key, key_len);
Adam Langley946dd622017-06-27 15:49:40 -07001175 *out_tag_len = tag_len;
Steven Valdez2f3404b2017-05-24 16:54:35 -04001176 return 1;
1177}
1178
1179static int aead_aes_gcm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
Adam Langley946dd622017-06-27 15:49:40 -07001180 size_t key_len, size_t requested_tag_len) {
Steven Valdez2f3404b2017-05-24 16:54:35 -04001181 struct aead_aes_gcm_ctx *gcm_ctx;
Adam Langleyfd772a52014-06-20 12:00:00 -07001182 gcm_ctx = OPENSSL_malloc(sizeof(struct aead_aes_gcm_ctx));
1183 if (gcm_ctx == NULL) {
1184 return 0;
1185 }
1186
Adam Langley946dd622017-06-27 15:49:40 -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)) {
Steven Valdez2f3404b2017-05-24 16:54:35 -04001190 OPENSSL_free(gcm_ctx);
1191 return 0;
1192 }
Adam Langleyfd772a52014-06-20 12:00:00 -07001193
Steven Valdez2f3404b2017-05-24 16:54:35 -04001194 ctx->aead_state = gcm_ctx;
Adam Langley946dd622017-06-27 15:49:40 -07001195 ctx->tag_len = actual_tag_len;
Adam Langleyfd772a52014-06-20 12:00:00 -07001196 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
Martin Kreichgauer18d9f282017-06-06 12:29:48 -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,
Martin Kreichgauer74bce292017-06-23 14:49:22 -07001210 const uint8_t *extra_in,
1211 size_t extra_in_len,
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001212 const uint8_t *ad, size_t ad_len) {
Adam Langleyfd772a52014-06-20 12:00:00 -07001213 const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
1214 GCM128_CONTEXT gcm;
1215
Martin Kreichgauerd977eaa2017-06-26 10:16:50 -07001216 if (extra_in_len + ctx->tag_len < ctx->tag_len) {
1217 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
1218 return 0;
1219 }
Martin Kreichgauerabbf3652017-07-21 16:27:54 -07001220 if (max_out_tag_len < extra_in_len + ctx->tag_len) {
Martin Kreichgauerd977eaa2017-06-26 10:16:50 -07001221 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
1222 return 0;
1223 }
David Benjamin03c6fa42017-05-23 12:40:58 -04001224 if (nonce_len == 0) {
1225 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
1226 return 0;
1227 }
1228
Brian Smith0f8bfde2015-09-26 20:12:01 -10001229 const AES_KEY *key = &gcm_ctx->ks.ks;
1230
David Benjamin17cf2cb2016-12-13 01:07:13 -05001231 OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
Brian Smith0f8bfde2015-09-26 20:12:01 -10001232 CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);
Adam Langleyfd772a52014-06-20 12:00:00 -07001233
1234 if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
1235 return 0;
1236 }
1237
1238 if (gcm_ctx->ctr) {
Brian Smith0f8bfde2015-09-26 20:12:01 -10001239 if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, in, out, in_len,
1240 gcm_ctx->ctr)) {
Adam Langleyfd772a52014-06-20 12:00:00 -07001241 return 0;
1242 }
1243 } else {
Brian Smith0f8bfde2015-09-26 20:12:01 -10001244 if (!CRYPTO_gcm128_encrypt(&gcm, key, in, out, in_len)) {
Adam Langleyfd772a52014-06-20 12:00:00 -07001245 return 0;
1246 }
1247 }
1248
Martin Kreichgauerd977eaa2017-06-26 10:16:50 -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 Langleyfd772a52014-06-20 12:00:00 -07001265 return 1;
1266}
1267
Martin Kreichgauer18d9f282017-06-06 12:29:48 -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 Langleyfd772a52014-06-20 12:00:00 -07001273 const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
1274 uint8_t tag[EVP_AEAD_AES_GCM_TAG_LEN];
Adam Langleyfd772a52014-06-20 12:00:00 -07001275 GCM128_CONTEXT gcm;
1276
David Benjamin03c6fa42017-05-23 12:40:58 -04001277 if (nonce_len == 0) {
1278 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
1279 return 0;
1280 }
1281
Adam Langley946dd622017-06-27 15:49:40 -07001282 if (in_tag_len != ctx->tag_len) {
David Benjamin3570d732015-06-29 00:28:17 -04001283 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
Adam Langleyfd772a52014-06-20 12:00:00 -07001284 return 0;
1285 }
1286
Brian Smith0f8bfde2015-09-26 20:12:01 -10001287 const AES_KEY *key = &gcm_ctx->ks.ks;
1288
David Benjamin17cf2cb2016-12-13 01:07:13 -05001289 OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
Brian Smith0f8bfde2015-09-26 20:12:01 -10001290 CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);
Adam Langleyfd772a52014-06-20 12:00:00 -07001291
1292 if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
1293 return 0;
1294 }
1295
1296 if (gcm_ctx->ctr) {
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001297 if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out, in_len,
1298 gcm_ctx->ctr)) {
Adam Langleyfd772a52014-06-20 12:00:00 -07001299 return 0;
1300 }
1301 } else {
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001302 if (!CRYPTO_gcm128_decrypt(&gcm, key, in, out, in_len)) {
Adam Langleyfd772a52014-06-20 12:00:00 -07001303 return 0;
1304 }
1305 }
1306
Adam Langley946dd622017-06-27 15:49:40 -07001307 CRYPTO_gcm128_tag(&gcm, tag, ctx->tag_len);
1308 if (CRYPTO_memcmp(tag, in_tag, ctx->tag_len) != 0) {
David Benjamin3570d732015-06-29 00:28:17 -04001309 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
Adam Langleyfd772a52014-06-20 12:00:00 -07001310 return 0;
1311 }
1312
Adam Langleyfd772a52014-06-20 12:00:00 -07001313 return 1;
1314}
1315
Adam Langley2e2a2262017-05-03 13:23:37 -07001316DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm) {
1317 memset(out, 0, sizeof(EVP_AEAD));
Adam Langleyfd772a52014-06-20 12:00:00 -07001318
Adam Langley2e2a2262017-05-03 13:23:37 -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;
Martin Kreichgauerd977eaa2017-06-26 10:16:50 -07001323 out->seal_scatter_supports_extra_in = 1;
1324
Adam Langley2e2a2262017-05-03 13:23:37 -07001325 out->init = aead_aes_gcm_init;
1326 out->cleanup = aead_aes_gcm_cleanup;
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001327 out->seal_scatter = aead_aes_gcm_seal_scatter;
1328 out->open_gather = aead_aes_gcm_open_gather;
Adam Langley2e2a2262017-05-03 13:23:37 -07001329}
Adam Langleyfd772a52014-06-20 12:00:00 -07001330
Adam Langley2e2a2262017-05-03 13:23:37 -07001331DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm) {
1332 memset(out, 0, sizeof(EVP_AEAD));
Adam Langleyfd772a52014-06-20 12:00:00 -07001333
Adam Langley2e2a2262017-05-03 13:23:37 -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;
Martin Kreichgauerd977eaa2017-06-26 10:16:50 -07001338 out->seal_scatter_supports_extra_in = 1;
1339
Adam Langley2e2a2262017-05-03 13:23:37 -07001340 out->init = aead_aes_gcm_init;
1341 out->cleanup = aead_aes_gcm_cleanup;
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001342 out->seal_scatter = aead_aes_gcm_seal_scatter;
1343 out->open_gather = aead_aes_gcm_open_gather;
Adam Langley2e2a2262017-05-03 13:23:37 -07001344}
Adam Langley93a3dcd2014-07-25 15:40:44 -07001345
Steven Valdez2f3404b2017-05-24 16:54:35 -04001346static int aead_aes_gcm_tls12_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
Adam Langley946dd622017-06-27 15:49:40 -07001347 size_t key_len, size_t requested_tag_len) {
Steven Valdez2f3404b2017-05-24 16:54:35 -04001348 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 }
Steven Valdez1d134ee2017-04-19 16:45:09 -04001353
Steven Valdez2f3404b2017-05-24 16:54:35 -04001354 gcm_ctx->counter = 0;
1355
Adam Langley946dd622017-06-27 15:49:40 -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)) {
Steven Valdez2f3404b2017-05-24 16:54:35 -04001359 OPENSSL_free(gcm_ctx);
1360 return 0;
1361 }
1362
1363 ctx->aead_state = gcm_ctx;
Adam Langley946dd622017-06-27 15:49:40 -07001364 ctx->tag_len = actual_tag_len;
Steven Valdez2f3404b2017-05-24 16:54:35 -04001365 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
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001374static 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,
Martin Kreichgauer74bce292017-06-23 14:49:22 -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) {
Steven Valdez2f3404b2017-05-24 16:54:35 -04001379 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) {
Steven Valdez1d134ee2017-04-19 16:45:09 -04001386 OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
1387 return 0;
1388 }
Steven Valdez2f3404b2017-05-24 16:54:35 -04001389
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);
Steven Valdez1d134ee2017-04-19 16:45:09 -04001393 return 0;
1394 }
1395
Steven Valdez2f3404b2017-05-24 16:54:35 -04001396 gcm_ctx->counter++;
Steven Valdez1d134ee2017-04-19 16:45:09 -04001397
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001398 return aead_aes_gcm_seal_scatter(ctx, out, out_tag, out_tag_len,
1399 max_out_tag_len, nonce, nonce_len, in,
Martin Kreichgauer74bce292017-06-23 14:49:22 -07001400 in_len, extra_in, extra_in_len, ad, ad_len);
Steven Valdez1d134ee2017-04-19 16:45:09 -04001401}
1402
Steven Valdez2f3404b2017-05-24 16:54:35 -04001403DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm_tls12) {
Adam Langley2e2a2262017-05-03 13:23:37 -07001404 memset(out, 0, sizeof(EVP_AEAD));
Steven Valdez1d134ee2017-04-19 16:45:09 -04001405
Adam Langley2e2a2262017-05-03 13:23:37 -07001406 out->key_len = 16;
Steven Valdez2f3404b2017-05-24 16:54:35 -04001407 out->nonce_len = 12;
1408 out->overhead = EVP_AEAD_AES_GCM_TAG_LEN;
Adam Langley2e2a2262017-05-03 13:23:37 -07001409 out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
Martin Kreichgauerd977eaa2017-06-26 10:16:50 -07001410 out->seal_scatter_supports_extra_in = 1;
1411
Steven Valdez2f3404b2017-05-24 16:54:35 -04001412 out->init = aead_aes_gcm_tls12_init;
1413 out->cleanup = aead_aes_gcm_tls12_cleanup;
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001414 out->seal_scatter = aead_aes_gcm_tls12_seal_scatter;
1415 out->open_gather = aead_aes_gcm_open_gather;
Steven Valdez1d134ee2017-04-19 16:45:09 -04001416}
1417
Steven Valdez2f3404b2017-05-24 16:54:35 -04001418DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_256_gcm_tls12) {
Adam Langley2e2a2262017-05-03 13:23:37 -07001419 memset(out, 0, sizeof(EVP_AEAD));
1420
1421 out->key_len = 32;
Steven Valdez2f3404b2017-05-24 16:54:35 -04001422 out->nonce_len = 12;
1423 out->overhead = EVP_AEAD_AES_GCM_TAG_LEN;
Adam Langley2e2a2262017-05-03 13:23:37 -07001424 out->max_tag_len = EVP_AEAD_AES_GCM_TAG_LEN;
Martin Kreichgauerd977eaa2017-06-26 10:16:50 -07001425 out->seal_scatter_supports_extra_in = 1;
1426
Steven Valdez2f3404b2017-05-24 16:54:35 -04001427 out->init = aead_aes_gcm_tls12_init;
1428 out->cleanup = aead_aes_gcm_tls12_cleanup;
Martin Kreichgauer18d9f282017-06-06 12:29:48 -07001429 out->seal_scatter = aead_aes_gcm_tls12_seal_scatter;
1430 out->open_gather = aead_aes_gcm_open_gather;
Steven Valdez1d134ee2017-04-19 16:45:09 -04001431}
Adam Langley2e2a2262017-05-03 13:23:37 -07001432
David Benjamin5213df42014-08-20 14:19:54 -04001433int EVP_has_aes_hardware(void) {
1434#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
1435 return aesni_capable() && crypto_gcm_clmul_enabled();
Adam Langley3e652652015-01-09 15:44:37 -08001436#elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
Adam Langley6a7cfbe2015-10-16 15:46:46 -07001437 return hwaes_capable() && CRYPTO_is_ARMv8_PMULL_capable();
David Benjamin5213df42014-08-20 14:19:54 -04001438#else
1439 return 0;
1440#endif
1441}