1/*
2 * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10/* Dispatch functions for gcm mode */
11
12#include "prov/ciphercommon.h"
13#include "prov/ciphercommon_gcm.h"
14#include "prov/providercommonerr.h"
15#include "crypto/rand.h"
16#include "prov/provider_ctx.h"
17
18static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len);
19static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
20 size_t len);
21static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
22 const unsigned char *in, size_t len);
23static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
24 size_t *padlen, const unsigned char *in,
25 size_t len);
26
27void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits,
28 const PROV_GCM_HW *hw, size_t ivlen_min)
29{
30 ctx->pad = 1;
31 ctx->mode = EVP_CIPH_GCM_MODE;
32 ctx->taglen = UNINITIALISED_SIZET;
33 ctx->tls_aad_len = UNINITIALISED_SIZET;
34 ctx->ivlen_min = ivlen_min;
35 ctx->ivlen = (EVP_GCM_TLS_FIXED_IV_LEN + EVP_GCM_TLS_EXPLICIT_IV_LEN);
36 ctx->keylen = keybits / 8;
37 ctx->hw = hw;
38 ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
39}
40
41static int gcm_init(void *vctx, const unsigned char *key, size_t keylen,
42 const unsigned char *iv, size_t ivlen, int enc)
43{
44 PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
45
46 ctx->enc = enc;
47
48 if (iv != NULL) {
49 if (ivlen < ctx->ivlen_min || ivlen > sizeof(ctx->iv)) {
50 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
51 return 0;
52 }
53 ctx->ivlen = ivlen;
54 memcpy(ctx->iv, iv, ivlen);
55 ctx->iv_state = IV_STATE_BUFFERED;
56 }
57
58 if (key != NULL) {
59 if (keylen != ctx->keylen) {
60 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
61 return 0;
62 }
63 return ctx->hw->setkey(ctx, key, ctx->keylen);
64 }
65 return 1;
66}
67
68int gcm_einit(void *vctx, const unsigned char *key, size_t keylen,
69 const unsigned char *iv, size_t ivlen)
70{
71 return gcm_init(vctx, key, keylen, iv, ivlen, 1);
72}
73
74int gcm_dinit(void *vctx, const unsigned char *key, size_t keylen,
75 const unsigned char *iv, size_t ivlen)
76{
77 return gcm_init(vctx, key, keylen, iv, ivlen, 0);
78}
79
80int gcm_get_ctx_params(void *vctx, OSSL_PARAM params[])
81{
82 PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
83 OSSL_PARAM *p;
84 size_t sz;
85
86 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IVLEN);
87 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->ivlen)) {
88 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
89 return 0;
90 }
91 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_KEYLEN);
92 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->keylen)) {
93 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
94 return 0;
95 }
96 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAGLEN);
97 if (p != NULL) {
98 size_t taglen = (ctx->taglen != UNINITIALISED_SIZET) ? ctx->taglen :
99 GCM_TAG_MAX_SIZE;
100
101 if (!OSSL_PARAM_set_size_t(p, taglen)) {
102 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
103 return 0;
104 }
105 }
106
107 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV);
108 if (p != NULL) {
109 if (ctx->iv_gen != 1 && ctx->iv_gen_rand != 1)
110 return 0;
111 if (ctx->ivlen != p->data_size) {
112 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
113 return 0;
114 }
115 if (!OSSL_PARAM_set_octet_string(p, ctx->iv, ctx->ivlen)) {
116 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
117 return 0;
118 }
119 }
120
121 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD_PAD);
122 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->tls_aad_pad_sz)) {
123 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
124 return 0;
125 }
126 p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_AEAD_TAG);
127 if (p != NULL) {
128 sz = p->data_size;
129 if (sz == 0
130 || sz > EVP_GCM_TLS_TAG_LEN
131 || !ctx->enc
132 || ctx->taglen == UNINITIALISED_SIZET) {
133 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
134 return 0;
135 }
136 if (!OSSL_PARAM_set_octet_string(p, ctx->buf, sz)) {
137 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER);
138 return 0;
139 }
140 }
141
142 return 1;
143}
144
145int gcm_set_ctx_params(void *vctx, const OSSL_PARAM params[])
146{
147 PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
148 const OSSL_PARAM *p;
149 size_t sz;
150 void *vp;
151
152 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TAG);
153 if (p != NULL) {
154 vp = ctx->buf;
155 if (!OSSL_PARAM_get_octet_string(p, &vp, EVP_GCM_TLS_TAG_LEN, &sz)) {
156 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
157 return 0;
158 }
159 if (sz == 0 || ctx->enc) {
160 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_TAG);
161 return 0;
162 }
163 ctx->taglen = sz;
164 }
165
166 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_IVLEN);
167 if (p != NULL) {
168 if (!OSSL_PARAM_get_size_t(p, &sz)) {
169 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
170 return 0;
171 }
172 if (sz == 0 || sz > sizeof(ctx->iv)) {
173 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH);
174 return 0;
175 }
176 ctx->ivlen = sz;
177 }
178
179 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_AAD);
180 if (p != NULL) {
181 if (p->data_type != OSSL_PARAM_OCTET_STRING) {
182 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
183 return 0;
184 }
185 sz = gcm_tls_init(ctx, p->data, p->data_size);
186 if (sz == 0) {
187 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_AAD);
188 return 0;
189 }
190 ctx->tls_aad_pad_sz = sz;
191 }
192
193 p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_AEAD_TLS1_IV_FIXED);
194 if (p != NULL) {
195 if (p->data_type != OSSL_PARAM_OCTET_STRING) {
196 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
197 return 0;
198 }
199 if (gcm_tls_iv_set_fixed(ctx, p->data, p->data_size) == 0) {
200 ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER);
201 return 0;
202 }
203 }
204
205 return 1;
206}
207
208int gcm_stream_update(void *vctx, unsigned char *out, size_t *outl,
209 size_t outsize, const unsigned char *in, size_t inl)
210{
211 PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
212
213 if (inl == 0) {
214 *outl = 0;
215 return 1;
216 }
217
218 if (outsize < inl) {
219 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
220 return -1;
221 }
222
223 if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0) {
224 ERR_raise(ERR_LIB_PROV, PROV_R_CIPHER_OPERATION_FAILED);
225 return -1;
226 }
227 return 1;
228}
229
230int gcm_stream_final(void *vctx, unsigned char *out, size_t *outl,
231 size_t outsize)
232{
233 PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
234 int i;
235
236 i = gcm_cipher_internal(ctx, out, outl, NULL, 0);
237 if (i <= 0)
238 return 0;
239
240 *outl = 0;
241 return 1;
242}
243
244int gcm_cipher(void *vctx,
245 unsigned char *out, size_t *outl, size_t outsize,
246 const unsigned char *in, size_t inl)
247{
248 PROV_GCM_CTX *ctx = (PROV_GCM_CTX *)vctx;
249
250 if (outsize < inl) {
251 ERR_raise(ERR_LIB_PROV, PROV_R_OUTPUT_BUFFER_TOO_SMALL);
252 return 0;
253 }
254
255 if (gcm_cipher_internal(ctx, out, outl, in, inl) <= 0)
256 return 0;
257
258 *outl = inl;
259 return 1;
260}
261
262/*
263 * See SP800-38D (GCM) Section 8 "Uniqueness requirement on IVS and keys"
264 *
265 * See also 8.2.2 RBG-based construction.
266 * Random construction consists of a free field (which can be NULL) and a
267 * random field which will use a DRBG that can return at least 96 bits of
268 * entropy strength. (The DRBG must be seeded by the FIPS module).
269 */
270static int gcm_iv_generate(PROV_GCM_CTX *ctx, int offset)
271{
272 int sz = ctx->ivlen - offset;
273
274 /* Must be at least 96 bits */
275 if (sz <= 0 || ctx->ivlen < GCM_IV_DEFAULT_SIZE)
276 return 0;
277
278 /* Use DRBG to generate random iv */
279 if (rand_bytes_ex(ctx->libctx, ctx->iv + offset, sz) <= 0)
280 return 0;
281 ctx->iv_state = IV_STATE_BUFFERED;
282 ctx->iv_gen_rand = 1;
283 return 1;
284}
285
286static int gcm_cipher_internal(PROV_GCM_CTX *ctx, unsigned char *out,
287 size_t *padlen, const unsigned char *in,
288 size_t len)
289{
290 size_t olen = 0;
291 int rv = 0;
292 const PROV_GCM_HW *hw = ctx->hw;
293
294 if (ctx->tls_aad_len != UNINITIALISED_SIZET)
295 return gcm_tls_cipher(ctx, out, padlen, in, len);
296
297 if (!ctx->key_set || ctx->iv_state == IV_STATE_FINISHED)
298 goto err;
299
300 /*
301 * FIPS requires generation of AES-GCM IV's inside the FIPS module.
302 * The IV can still be set externally (the security policy will state that
303 * this is not FIPS compliant). There are some applications
304 * where setting the IV externally is the only option available.
305 */
306 if (ctx->iv_state == IV_STATE_UNINITIALISED) {
307 if (!ctx->enc || !gcm_iv_generate(ctx, 0))
308 goto err;
309 }
310
311 if (ctx->iv_state == IV_STATE_BUFFERED) {
312 if (!hw->setiv(ctx, ctx->iv, ctx->ivlen))
313 goto err;
314 ctx->iv_state = IV_STATE_COPIED;
315 }
316
317 if (in != NULL) {
318 /* The input is AAD if out is NULL */
319 if (out == NULL) {
320 if (!hw->aadupdate(ctx, in, len))
321 goto err;
322 } else {
323 /* The input is ciphertext OR plaintext */
324 if (!hw->cipherupdate(ctx, in, len, out))
325 goto err;
326 }
327 } else {
328 /* The tag must be set before actually decrypting data */
329 if (!ctx->enc && ctx->taglen == UNINITIALISED_SIZET)
330 goto err;
331 if (!hw->cipherfinal(ctx, ctx->buf))
332 goto err;
333 ctx->iv_state = IV_STATE_FINISHED; /* Don't reuse the IV */
334 goto finish;
335 }
336 olen = len;
337finish:
338 rv = 1;
339err:
340 *padlen = olen;
341 return rv;
342}
343
344static int gcm_tls_init(PROV_GCM_CTX *dat, unsigned char *aad, size_t aad_len)
345{
346 unsigned char *buf;
347 size_t len;
348
349 if (aad_len != EVP_AEAD_TLS1_AAD_LEN)
350 return 0;
351
352 /* Save the aad for later use. */
353 buf = dat->buf;
354 memcpy(buf, aad, aad_len);
355 dat->tls_aad_len = aad_len;
356 dat->tls_enc_records = 0;
357
358 len = buf[aad_len - 2] << 8 | buf[aad_len - 1];
359 /* Correct length for explicit iv. */
360 if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
361 return 0;
362 len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
363
364 /* If decrypting correct for tag too. */
365 if (!dat->enc) {
366 if (len < EVP_GCM_TLS_TAG_LEN)
367 return 0;
368 len -= EVP_GCM_TLS_TAG_LEN;
369 }
370 buf[aad_len - 2] = (unsigned char)(len >> 8);
371 buf[aad_len - 1] = (unsigned char)(len & 0xff);
372 /* Extra padding: tag appended to record. */
373 return EVP_GCM_TLS_TAG_LEN;
374}
375
376static int gcm_tls_iv_set_fixed(PROV_GCM_CTX *ctx, unsigned char *iv,
377 size_t len)
378{
379 /* Special case: -1 length restores whole IV */
380 if (len == (size_t)-1) {
381 memcpy(ctx->iv, iv, ctx->ivlen);
382 ctx->iv_gen = 1;
383 ctx->iv_state = IV_STATE_BUFFERED;
384 return 1;
385 }
386 /* Fixed field must be at least 4 bytes and invocation field at least 8 */
387 if ((len < EVP_GCM_TLS_FIXED_IV_LEN)
388 || (ctx->ivlen - (int)len) < EVP_GCM_TLS_EXPLICIT_IV_LEN)
389 return 0;
390 if (len > 0)
391 memcpy(ctx->iv, iv, len);
392 if (ctx->enc
393 && rand_bytes_ex(ctx->libctx, ctx->iv + len, ctx->ivlen - len) <= 0)
394 return 0;
395 ctx->iv_gen = 1;
396 ctx->iv_state = IV_STATE_BUFFERED;
397 return 1;
398}
399
400/* increment counter (64-bit int) by 1 */
401static void ctr64_inc(unsigned char *counter)
402{
403 int n = 8;
404 unsigned char c;
405
406 do {
407 --n;
408 c = counter[n];
409 ++c;
410 counter[n] = c;
411 if (c > 0)
412 return;
413 } while (n > 0);
414}
415
416/*
417 * Handle TLS GCM packet format. This consists of the last portion of the IV
418 * followed by the payload and finally the tag. On encrypt generate IV,
419 * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
420 * and verify tag.
421 */
422static int gcm_tls_cipher(PROV_GCM_CTX *ctx, unsigned char *out, size_t *padlen,
423 const unsigned char *in, size_t len)
424{
425 int rv = 0;
426 size_t arg = EVP_GCM_TLS_EXPLICIT_IV_LEN;
427 size_t plen = 0;
428 unsigned char *tag = NULL;
429
430 if (!ctx->key_set)
431 goto err;
432
433 /* Encrypt/decrypt must be performed in place */
434 if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
435 goto err;
436
437 /*
438 * Check for too many keys as per FIPS 140-2 IG A.5 "Key/IV Pair Uniqueness
439 * Requirements from SP 800-38D". The requirements is for one party to the
440 * communication to fail after 2^64 - 1 keys. We do this on the encrypting
441 * side only.
442 */
443 if (ctx->enc && ++ctx->tls_enc_records == 0) {
444 ERR_raise(ERR_LIB_PROV, EVP_R_TOO_MANY_RECORDS);
445 goto err;
446 }
447
448 if (ctx->iv_gen == 0)
449 goto err;
450 /*
451 * Set IV from start of buffer or generate IV and write to start of
452 * buffer.
453 */
454 if (ctx->enc) {
455 if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
456 goto err;
457 if (arg > ctx->ivlen)
458 arg = ctx->ivlen;
459 memcpy(out, ctx->iv + ctx->ivlen - arg, arg);
460 /*
461 * Invocation field will be at least 8 bytes in size and so no need
462 * to check wrap around or increment more than last 8 bytes.
463 */
464 ctr64_inc(ctx->iv + ctx->ivlen - 8);
465 } else {
466 memcpy(ctx->iv + ctx->ivlen - arg, out, arg);
467 if (!ctx->hw->setiv(ctx, ctx->iv, ctx->ivlen))
468 goto err;
469 }
470 ctx->iv_state = IV_STATE_COPIED;
471
472 /* Fix buffer and length to point to payload */
473 in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
474 out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
475 len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
476
477 tag = ctx->enc ? out + len : (unsigned char *)in + len;
478 if (!ctx->hw->oneshot(ctx, ctx->buf, ctx->tls_aad_len, in, len, out, tag,
479 EVP_GCM_TLS_TAG_LEN)) {
480 if (!ctx->enc)
481 OPENSSL_cleanse(out, len);
482 goto err;
483 }
484 if (ctx->enc)
485 plen = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
486 else
487 plen = len;
488
489 rv = 1;
490err:
491 ctx->iv_state = IV_STATE_FINISHED;
492 ctx->tls_aad_len = UNINITIALISED_SIZET;
493 *padlen = plen;
494 return rv;
495}
496