Coverage Report

Created: 2025-03-06 06:58

/src/gnutls/lib/crypto-api.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2000-2016 Free Software Foundation, Inc.
3
 * Copyright (C) 2016 Red Hat, Inc.
4
 *
5
 * Author: Nikos Mavrogiannopoulos
6
 *
7
 * This file is part of GnuTLS.
8
 *
9
 * The GnuTLS is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public License
11
 * as published by the Free Software Foundation; either version 2.1 of
12
 * the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful, but
15
 * WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program.  If not, see <https://www.gnu.org/licenses/>
21
 *
22
 */
23
24
#include "gnutls_int.h"
25
#include "errors.h"
26
#include "cipher_int.h"
27
#include "datum.h"
28
#include <gnutls/crypto.h>
29
#include "algorithms.h"
30
#include "random.h"
31
#include "crypto.h"
32
#include "fips.h"
33
#include "crypto-api.h"
34
#include "iov.h"
35
#include "intprops.h"
36
37
typedef struct api_cipher_hd_st {
38
  cipher_hd_st ctx_enc;
39
  cipher_hd_st ctx_dec;
40
} api_cipher_hd_st;
41
42
/**
43
 * gnutls_cipher_init:
44
 * @handle: is a #gnutls_cipher_hd_t type
45
 * @cipher: the encryption algorithm to use
46
 * @key: the key to be used for encryption/decryption
47
 * @iv: the IV to use (if not applicable set NULL)
48
 *
49
 * This function will initialize the @handle context to be usable
50
 * for encryption/decryption of data. This will effectively use the
51
 * current crypto backend in use by gnutls or the cryptographic
52
 * accelerator in use.
53
 *
54
 * Returns: Zero or a negative error code on error.
55
 *
56
 * Since: 2.10.0
57
 **/
58
int gnutls_cipher_init(gnutls_cipher_hd_t *handle,
59
           gnutls_cipher_algorithm_t cipher,
60
           const gnutls_datum_t *key, const gnutls_datum_t *iv)
61
0
{
62
0
  api_cipher_hd_st *h;
63
0
  int ret;
64
0
  const cipher_entry_st *e;
65
0
  bool not_approved = false;
66
67
0
  if (!is_cipher_algo_allowed(cipher)) {
68
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
69
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
70
0
  } else if (!is_cipher_algo_approved_in_fips(cipher)) {
71
0
    not_approved = true;
72
0
  }
73
74
0
  e = cipher_to_entry(cipher);
75
0
  if (e == NULL || (e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD)) {
76
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
77
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
78
0
  }
79
80
0
  h = gnutls_calloc(1, sizeof(api_cipher_hd_st));
81
0
  if (h == NULL) {
82
0
    gnutls_assert();
83
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
84
0
    return GNUTLS_E_MEMORY_ERROR;
85
0
  }
86
87
0
  ret = _gnutls_cipher_init(&h->ctx_enc, e, key, iv, 1);
88
0
  if (ret < 0) {
89
0
    gnutls_free(h);
90
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
91
0
    return ret;
92
0
  }
93
94
0
  if (_gnutls_cipher_type(e) == CIPHER_BLOCK) {
95
0
    ret = _gnutls_cipher_init(&h->ctx_dec, e, key, iv, 0);
96
0
    if (ret < 0) {
97
0
      gnutls_free(h);
98
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
99
0
      return ret;
100
0
    }
101
0
  }
102
103
0
  *handle = h;
104
105
0
  if (not_approved) {
106
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
107
0
  } else {
108
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
109
0
  }
110
111
0
  return ret;
112
0
}
113
114
/**
115
 * gnutls_cipher_tag:
116
 * @handle: is a #gnutls_cipher_hd_t type
117
 * @tag: will hold the tag
118
 * @tag_size: the length of the tag to return
119
 *
120
 * This function operates on authenticated encryption with
121
 * associated data (AEAD) ciphers and will return the
122
 * output tag.
123
 *
124
 * Returns: Zero or a negative error code on error.
125
 *
126
 * Since: 3.0
127
 **/
128
int gnutls_cipher_tag(gnutls_cipher_hd_t handle, void *tag, size_t tag_size)
129
0
{
130
0
  api_cipher_hd_st *h = handle;
131
132
0
  if (_gnutls_cipher_is_aead(&h->ctx_enc) == 0)
133
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
134
135
0
  _gnutls_cipher_tag(&h->ctx_enc, tag, tag_size);
136
137
0
  return 0;
138
0
}
139
140
/**
141
 * gnutls_cipher_add_auth:
142
 * @handle: is a #gnutls_cipher_hd_t type
143
 * @ptext: the data to be authenticated
144
 * @ptext_size: the length of the data
145
 *
146
 * This function operates on authenticated encryption with
147
 * associated data (AEAD) ciphers and authenticate the
148
 * input data. This function can only be called once
149
 * and before any encryption operations.
150
 *
151
 * Returns: Zero or a negative error code on error.
152
 *
153
 * Since: 3.0
154
 **/
155
int gnutls_cipher_add_auth(gnutls_cipher_hd_t handle, const void *ptext,
156
         size_t ptext_size)
157
0
{
158
0
  api_cipher_hd_st *h = handle;
159
0
  int ret;
160
161
0
  if (_gnutls_cipher_is_aead(&h->ctx_enc) == 0) {
162
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
163
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
164
0
  }
165
166
0
  ret = _gnutls_cipher_auth(&h->ctx_enc, ptext, ptext_size);
167
0
  if (ret < 0) {
168
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
169
0
  }
170
0
  return ret;
171
0
}
172
173
/**
174
 * gnutls_cipher_set_iv:
175
 * @handle: is a #gnutls_cipher_hd_t type
176
 * @iv: the IV to set
177
 * @ivlen: the length of the IV
178
 *
179
 * This function will set the IV to be used for the next
180
 * encryption block.
181
 *
182
 * Since: 3.0
183
 **/
184
void gnutls_cipher_set_iv(gnutls_cipher_hd_t handle, void *iv, size_t ivlen)
185
0
{
186
0
  api_cipher_hd_st *h = handle;
187
188
0
  if (_gnutls_cipher_setiv(&h->ctx_enc, iv, ivlen) < 0) {
189
0
    _gnutls_switch_lib_state(LIB_STATE_ERROR);
190
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
191
0
  }
192
193
0
  if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK) {
194
0
    if (_gnutls_cipher_setiv(&h->ctx_dec, iv, ivlen) < 0) {
195
0
      _gnutls_switch_lib_state(LIB_STATE_ERROR);
196
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
197
0
    }
198
0
  }
199
0
}
200
201
/*-
202
 * _gnutls_cipher_get_iv:
203
 * @handle: is a #gnutls_cipher_hd_t type
204
 * @iv: the IV to set
205
 * @ivlen: the length of the IV
206
 *
207
 * This function will retrieve the internally calculated IV value. It is
208
 * intended to be used  for modes like CFB. @iv must have @ivlen length
209
 * at least.
210
 *
211
 * This is solely for validation purposes of our crypto
212
 * implementation.  For other purposes, the IV can be typically
213
 * calculated from the initial IV value and the subsequent ciphertext
214
 * values.  As such, this function only works with the internally
215
 * registered ciphers.
216
 *
217
 * Returns: The length of IV or a negative error code on error.
218
 *
219
 * Since: 3.6.8
220
 -*/
221
int _gnutls_cipher_get_iv(gnutls_cipher_hd_t handle, void *iv, size_t ivlen)
222
0
{
223
0
  api_cipher_hd_st *h = handle;
224
225
0
  return _gnutls_cipher_getiv(&h->ctx_enc, iv, ivlen);
226
0
}
227
228
/*-
229
 * _gnutls_cipher_set_key:
230
 * @handle: is a #gnutls_cipher_hd_t type
231
 * @key: the key to set
232
 * @keylen: the length of the key
233
 *
234
 * This function will set the key used by the cipher
235
 *
236
 * This is solely for validation purposes of our crypto
237
 * implementation.  For other purposes, the key should be set at the time of
238
 * cipher setup.  As such, this function only works with the internally
239
 * registered ciphers.
240
 *
241
 * Returns: Zero or a negative error code on error.
242
 *
243
 * Since: 3.6.14
244
 -*/
245
int _gnutls_cipher_set_key(gnutls_cipher_hd_t handle, void *key, size_t keylen)
246
0
{
247
0
  api_cipher_hd_st *h = handle;
248
0
  int ret;
249
250
0
  ret = _gnutls_cipher_setkey(&h->ctx_enc, key, keylen);
251
252
0
  if (ret < 0) {
253
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
254
0
  }
255
0
  return ret;
256
0
}
257
258
/**
259
 * gnutls_cipher_encrypt:
260
 * @handle: is a #gnutls_cipher_hd_t type
261
 * @ptext: the data to encrypt
262
 * @ptext_len: the length of data to encrypt
263
 *
264
 * This function will encrypt the given data using the algorithm
265
 * specified by the context.
266
 *
267
 * Returns: Zero or a negative error code on error.
268
 *
269
 * Since: 2.10.0
270
 **/
271
int gnutls_cipher_encrypt(gnutls_cipher_hd_t handle, void *ptext,
272
        size_t ptext_len)
273
0
{
274
0
  api_cipher_hd_st *h = handle;
275
0
  int ret;
276
277
0
  ret = _gnutls_cipher_encrypt(&h->ctx_enc, ptext, ptext_len);
278
0
  if (ret < 0) {
279
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
280
0
  } else {
281
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
282
0
  }
283
0
  return ret;
284
0
}
285
286
/**
287
 * gnutls_cipher_decrypt:
288
 * @handle: is a #gnutls_cipher_hd_t type
289
 * @ctext: the data to decrypt
290
 * @ctext_len: the length of data to decrypt
291
 *
292
 * This function will decrypt the given data using the algorithm
293
 * specified by the context.
294
 *
295
 * Note that in AEAD ciphers, this will not check the tag. You will
296
 * need to compare the tag sent with the value returned from gnutls_cipher_tag().
297
 *
298
 * Returns: Zero or a negative error code on error.
299
 *
300
 * Since: 2.10.0
301
 **/
302
int gnutls_cipher_decrypt(gnutls_cipher_hd_t handle, void *ctext,
303
        size_t ctext_len)
304
0
{
305
0
  api_cipher_hd_st *h = handle;
306
0
  int ret;
307
308
0
  if (_gnutls_cipher_type(h->ctx_enc.e) != CIPHER_BLOCK) {
309
0
    ret = _gnutls_cipher_decrypt(&h->ctx_enc, ctext, ctext_len);
310
0
  } else {
311
0
    ret = _gnutls_cipher_decrypt(&h->ctx_dec, ctext, ctext_len);
312
0
  }
313
314
0
  if (ret < 0) {
315
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
316
0
  } else {
317
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
318
0
  }
319
0
  return ret;
320
0
}
321
322
/**
323
 * gnutls_cipher_encrypt2:
324
 * @handle: is a #gnutls_cipher_hd_t type
325
 * @ptext: the data to encrypt
326
 * @ptext_len: the length of data to encrypt
327
 * @ctext: the encrypted data
328
 * @ctext_len: the available length for encrypted data
329
 *
330
 * This function will encrypt the given data using the algorithm
331
 * specified by the context. For block ciphers the @ptext_len must be
332
 * a multiple of the block size. For the supported ciphers the encrypted
333
 * data length will equal the plaintext size.
334
 *
335
 * Returns: Zero or a negative error code on error.
336
 *
337
 * Since: 2.12.0
338
 **/
339
int gnutls_cipher_encrypt2(gnutls_cipher_hd_t handle, const void *ptext,
340
         size_t ptext_len, void *ctext, size_t ctext_len)
341
0
{
342
0
  api_cipher_hd_st *h = handle;
343
0
  int ret;
344
345
0
  ret = _gnutls_cipher_encrypt2(&h->ctx_enc, ptext, ptext_len, ctext,
346
0
              ctext_len);
347
0
  if (ret < 0) {
348
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
349
0
  } else {
350
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
351
0
  }
352
0
  return ret;
353
0
}
354
355
/**
356
 * gnutls_cipher_decrypt2:
357
 * @handle: is a #gnutls_cipher_hd_t type
358
 * @ctext: the data to decrypt
359
 * @ctext_len: the length of data to decrypt
360
 * @ptext: the decrypted data
361
 * @ptext_len: the available length for decrypted data
362
 *
363
 * This function will decrypt the given data using the algorithm
364
 * specified by the context. For block ciphers the @ctext_len must be
365
 * a multiple of the block size. For the supported ciphers the plaintext
366
 * data length will equal the ciphertext size.
367
 *
368
 * Note that in AEAD ciphers, this will not check the tag. You will
369
 * need to compare the tag sent with the value returned from gnutls_cipher_tag().
370
 *
371
 * Returns: Zero or a negative error code on error.
372
 *
373
 * Since: 2.12.0
374
 **/
375
int gnutls_cipher_decrypt2(gnutls_cipher_hd_t handle, const void *ctext,
376
         size_t ctext_len, void *ptext, size_t ptext_len)
377
0
{
378
0
  api_cipher_hd_st *h = handle;
379
0
  int ret;
380
381
0
  if (_gnutls_cipher_type(h->ctx_enc.e) != CIPHER_BLOCK) {
382
0
    ret = _gnutls_cipher_decrypt2(&h->ctx_enc, ctext, ctext_len,
383
0
                ptext, ptext_len);
384
0
  } else {
385
0
    ret = _gnutls_cipher_decrypt2(&h->ctx_dec, ctext, ctext_len,
386
0
                ptext, ptext_len);
387
0
  }
388
389
0
  if (ret < 0) {
390
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
391
0
  } else {
392
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
393
0
  }
394
0
  return ret;
395
0
}
396
397
/**
398
 * gnutls_cipher_encrypt3:
399
 * @handle: is a #gnutls_cipher_hd_t type
400
 * @ptext: the data to encrypt
401
 * @ptext_len: the length of data to encrypt
402
 * @ctext: the encrypted data
403
 * @ctext_len: the length of encrypted data (initially must hold the maximum available size)
404
 * @flags: flags for padding
405
 *
406
 * This function will encrypt the given data using the algorithm
407
 * specified by the context. For block ciphers, @ptext_len is
408
 * typically a multiple of the block size. If not, the caller can
409
 * instruct the function to pad the last block according to @flags.
410
 * Currently, the only available padding scheme is
411
 * %GNUTLS_CIPHER_PADDING_PKCS7.
412
 *
413
 * If @ctext is not %NULL, it must hold enough space to store
414
 * resulting cipher text. To check the required size, this function
415
 * can be called with @ctext set to %NULL. Then @ctext_len will be
416
 * updated without performing actual encryption.
417
 *
418
 * Returns: Zero or a negative error code on error.
419
 *
420
 * Since: 3.7.7
421
 **/
422
int gnutls_cipher_encrypt3(gnutls_cipher_hd_t handle, const void *ptext,
423
         size_t ptext_len, void *ctext, size_t *ctext_len,
424
         unsigned flags)
425
0
{
426
0
  api_cipher_hd_st *h = handle;
427
0
  const cipher_entry_st *e = h->ctx_enc.e;
428
0
  int block_size = _gnutls_cipher_get_block_size(e);
429
0
  int ret = 0;
430
431
0
  if (unlikely(ctext_len == NULL)) {
432
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
433
0
  }
434
435
0
  if (_gnutls_cipher_type(e) == CIPHER_BLOCK &&
436
0
      (flags & GNUTLS_CIPHER_PADDING_PKCS7)) {
437
0
    size_t n, r;
438
0
    uint8_t last_block[MAX_CIPHER_BLOCK_SIZE];
439
0
    const uint8_t *p = ptext;
440
0
    uint8_t *c = ctext;
441
442
0
    if (!INT_ADD_OK(ptext_len, block_size, &n)) {
443
0
      return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
444
0
    }
445
446
0
    n = (n / block_size) * block_size;
447
448
0
    if (!ctext) {
449
0
      *ctext_len = n;
450
0
      return 0;
451
0
    }
452
453
0
    if (*ctext_len < n) {
454
0
      return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
455
0
    }
456
457
    /* Encrypt up to the last complete block */
458
0
    r = ptext_len % block_size;
459
460
0
    ret = _gnutls_cipher_encrypt2(&h->ctx_enc, ptext, ptext_len - r,
461
0
                ctext, ptext_len - r);
462
0
    if (ret < 0) {
463
0
      goto error;
464
0
    }
465
466
    /* Encrypt the last block with padding */
467
0
    gnutls_memset(last_block, block_size - r, sizeof(last_block));
468
0
    if (r > 0) {
469
0
      memcpy(last_block, &p[ptext_len - r], r);
470
0
    }
471
0
    ret = _gnutls_cipher_encrypt2(&h->ctx_enc, last_block,
472
0
                block_size, &c[ptext_len - r],
473
0
                block_size);
474
0
    if (ret < 0) {
475
0
      goto error;
476
0
    }
477
0
    *ctext_len = n;
478
0
  } else {
479
0
    if (!ctext) {
480
0
      *ctext_len = ptext_len;
481
0
      return 0;
482
0
    }
483
484
0
    ret = _gnutls_cipher_encrypt2(&h->ctx_enc, ptext, ptext_len,
485
0
                ctext, *ctext_len);
486
0
    if (ret < 0) {
487
0
      goto error;
488
0
    }
489
0
    *ctext_len = ptext_len;
490
0
  }
491
492
0
error:
493
0
  if (ret < 0) {
494
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
495
0
  } else {
496
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
497
0
  }
498
0
  return ret;
499
0
}
500
501
/**
502
 * gnutls_cipher_decrypt3:
503
 * @handle: is a #gnutls_cipher_hd_t type
504
 * @ctext: the data to decrypt
505
 * @ctext_len: the length of data to decrypt
506
 * @ptext: the decrypted data
507
 * @ptext_len: the available length for decrypted data
508
 * @flags: flags for padding
509
 *
510
 * This function will decrypt the given data using the algorithm
511
 * specified by the context. If @flags is specified, padding for the
512
 * decrypted data will be removed accordingly and @ptext_len will be
513
 * updated.
514
 *
515
 * Returns: Zero or a negative error code on error.
516
 *
517
 * Since: 3.7.7
518
 **/
519
int gnutls_cipher_decrypt3(gnutls_cipher_hd_t handle, const void *ctext,
520
         size_t ctext_len, void *ptext, size_t *ptext_len,
521
         unsigned flags)
522
0
{
523
0
  api_cipher_hd_st *h = handle;
524
0
  int ret;
525
526
0
  ret = gnutls_cipher_decrypt2(handle, ctext, ctext_len, ptext,
527
0
             *ptext_len);
528
0
  if (ret < 0) {
529
0
    return ret;
530
0
  }
531
532
0
  if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK &&
533
0
      (flags & GNUTLS_CIPHER_PADDING_PKCS7)) {
534
0
    uint8_t *p = ptext;
535
0
    uint8_t padding = p[*ptext_len - 1];
536
0
    if (!padding ||
537
0
        padding > _gnutls_cipher_get_block_size(h->ctx_enc.e)) {
538
0
      return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
539
0
    }
540
    /* Check that the prior bytes are all PADDING */
541
0
    for (size_t i = *ptext_len - padding; i < *ptext_len; i++) {
542
0
      if (padding != p[*ptext_len - 1]) {
543
0
        return gnutls_assert_val(
544
0
          GNUTLS_E_DECRYPTION_FAILED);
545
0
      }
546
0
    }
547
0
    *ptext_len -= padding;
548
0
  }
549
550
0
  return 0;
551
0
}
552
553
/**
554
 * gnutls_cipher_deinit:
555
 * @handle: is a #gnutls_cipher_hd_t type
556
 *
557
 * This function will deinitialize all resources occupied by the given
558
 * encryption context.
559
 *
560
 * Since: 2.10.0
561
 **/
562
void gnutls_cipher_deinit(gnutls_cipher_hd_t handle)
563
0
{
564
0
  api_cipher_hd_st *h = handle;
565
566
0
  _gnutls_cipher_deinit(&h->ctx_enc);
567
0
  if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK)
568
0
    _gnutls_cipher_deinit(&h->ctx_dec);
569
0
  gnutls_free(handle);
570
0
}
571
572
/* HMAC */
573
574
/**
575
 * gnutls_hmac_init:
576
 * @dig: is a #gnutls_hmac_hd_t type
577
 * @algorithm: the HMAC algorithm to use
578
 * @key: the key to be used for encryption
579
 * @keylen: the length of the key
580
 *
581
 * This function will initialize an context that can be used to
582
 * produce a Message Authentication Code (MAC) of data.  This will
583
 * effectively use the current crypto backend in use by gnutls or the
584
 * cryptographic accelerator in use.
585
 *
586
 * Note that despite the name of this function, it can be used
587
 * for other MAC algorithms than HMAC.
588
 *
589
 * Returns: Zero or a negative error code on error.
590
 *
591
 * Since: 2.10.0
592
 **/
593
int gnutls_hmac_init(gnutls_hmac_hd_t *dig, gnutls_mac_algorithm_t algorithm,
594
         const void *key, size_t keylen)
595
0
{
596
0
  int ret;
597
0
  bool not_approved = false;
598
599
  /* MD5 is only allowed internally for TLS */
600
0
  if (!is_mac_algo_allowed(algorithm)) {
601
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
602
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
603
0
  } else if (!is_mac_algo_approved_in_fips(algorithm)) {
604
0
    not_approved = true;
605
0
  }
606
607
  /* Key lengths of less than 112 bits are not approved */
608
0
  if (keylen < 14) {
609
0
    not_approved = true;
610
0
  }
611
612
0
  *dig = gnutls_malloc(sizeof(mac_hd_st));
613
0
  if (*dig == NULL) {
614
0
    gnutls_assert();
615
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
616
0
    return GNUTLS_E_MEMORY_ERROR;
617
0
  }
618
619
0
  ret = _gnutls_mac_init(((mac_hd_st *)*dig), mac_to_entry(algorithm),
620
0
             key, keylen);
621
0
  if (ret < 0) {
622
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
623
0
  } else if (not_approved) {
624
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
625
0
  } else {
626
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
627
0
  }
628
0
  return ret;
629
0
}
630
631
/**
632
 * gnutls_hmac_set_nonce:
633
 * @handle: is a #gnutls_hmac_hd_t type
634
 * @nonce: the data to set as nonce
635
 * @nonce_len: the length of data
636
 *
637
 * This function will set the nonce in the MAC algorithm.
638
 *
639
 * Since: 3.2.0
640
 **/
641
void gnutls_hmac_set_nonce(gnutls_hmac_hd_t handle, const void *nonce,
642
         size_t nonce_len)
643
0
{
644
0
  _gnutls_mac_set_nonce((mac_hd_st *)handle, nonce, nonce_len);
645
0
}
646
647
/**
648
 * gnutls_hmac:
649
 * @handle: is a #gnutls_hmac_hd_t type
650
 * @ptext: the data to hash
651
 * @ptext_len: the length of data to hash
652
 *
653
 * This function will hash the given data using the algorithm
654
 * specified by the context.
655
 *
656
 * Returns: Zero or a negative error code on error.
657
 *
658
 * Since: 2.10.0
659
 **/
660
int gnutls_hmac(gnutls_hmac_hd_t handle, const void *ptext, size_t ptext_len)
661
0
{
662
0
  int ret;
663
664
0
  ret = _gnutls_mac((mac_hd_st *)handle, ptext, ptext_len);
665
0
  if (ret < 0) {
666
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
667
0
  } else {
668
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
669
0
  }
670
0
  return ret;
671
0
}
672
673
/**
674
 * gnutls_hmac_output:
675
 * @handle: is a #gnutls_hmac_hd_t type
676
 * @digest: is the output value of the MAC
677
 *
678
 * This function will output the current MAC value
679
 * and reset the state of the MAC.
680
 *
681
 * Since: 2.10.0
682
 **/
683
void gnutls_hmac_output(gnutls_hmac_hd_t handle, void *digest)
684
0
{
685
0
  _gnutls_mac_output((mac_hd_st *)handle, digest);
686
0
}
687
688
/**
689
 * gnutls_hmac_deinit:
690
 * @handle: is a #gnutls_hmac_hd_t type
691
 * @digest: is the output value of the MAC
692
 *
693
 * This function will deinitialize all resources occupied by
694
 * the given hmac context.
695
 *
696
 * Since: 2.10.0
697
 **/
698
void gnutls_hmac_deinit(gnutls_hmac_hd_t handle, void *digest)
699
0
{
700
0
  _gnutls_mac_deinit((mac_hd_st *)handle, digest);
701
0
  gnutls_free(handle);
702
0
}
703
704
/**
705
 * gnutls_hmac_get_len:
706
 * @algorithm: the hmac algorithm to use
707
 *
708
 * This function will return the length of the output data
709
 * of the given hmac algorithm.
710
 *
711
 * Returns: The length or zero on error.
712
 *
713
 * Since: 2.10.0
714
 **/
715
unsigned gnutls_hmac_get_len(gnutls_mac_algorithm_t algorithm)
716
0
{
717
0
  return _gnutls_mac_get_algo_len(mac_to_entry(algorithm));
718
0
}
719
720
/**
721
 * gnutls_hmac_get_key_size:
722
 * @algorithm: the mac algorithm to use
723
 *
724
 * This function will return the size of the key to be used with this
725
 * algorithm. On the algorithms which may accept arbitrary key sizes,
726
 * the returned size is the MAC key size used in the TLS protocol.
727
 *
728
 * Returns: The key size or zero on error.
729
 *
730
 * Since: 3.6.12
731
 **/
732
unsigned gnutls_hmac_get_key_size(gnutls_mac_algorithm_t algorithm)
733
0
{
734
0
  return _gnutls_mac_get_key_size(mac_to_entry(algorithm));
735
0
}
736
737
/**
738
 * gnutls_hmac_fast:
739
 * @algorithm: the hash algorithm to use
740
 * @key: the key to use
741
 * @keylen: the length of the key
742
 * @ptext: the data to hash
743
 * @ptext_len: the length of data to hash
744
 * @digest: is the output value of the hash
745
 *
746
 * This convenience function will hash the given data and return output
747
 * on a single call. Note, this call will not work for MAC algorithms
748
 * that require nonce (like UMAC or GMAC).
749
 *
750
 * Returns: Zero or a negative error code on error.
751
 *
752
 * Since: 2.10.0
753
 **/
754
int gnutls_hmac_fast(gnutls_mac_algorithm_t algorithm, const void *key,
755
         size_t keylen, const void *ptext, size_t ptext_len,
756
         void *digest)
757
0
{
758
0
  int ret;
759
0
  bool not_approved = false;
760
761
0
  if (!is_mac_algo_allowed(algorithm)) {
762
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
763
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
764
0
  } else if (!is_mac_algo_approved_in_fips(algorithm)) {
765
0
    not_approved = true;
766
0
  }
767
768
  /* Key lengths of less than 112 bits are not approved */
769
0
  if (keylen < 14) {
770
0
    not_approved = true;
771
0
  }
772
773
0
  ret = _gnutls_mac_fast(algorithm, key, keylen, ptext, ptext_len,
774
0
             digest);
775
0
  if (ret < 0) {
776
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
777
0
  } else if (not_approved) {
778
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
779
0
  } else {
780
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
781
0
  }
782
0
  return ret;
783
0
}
784
785
/**
786
 * gnutls_hmac_copy:
787
 * @handle: is a #gnutls_hmac_hd_t type
788
 *
789
 * This function will create a copy of MAC context, containing all its current
790
 * state. Copying contexts for MACs registered using
791
 * gnutls_crypto_register_mac() is not supported and will always result in an
792
 * error. In addition to that, some of the MAC implementations do not support
793
 * this operation. Applications should check the return value and provide a
794
 * proper fallback.
795
 *
796
 * Returns: new MAC context or NULL in case of an error.
797
 *
798
 * Since: 3.6.9
799
 */
800
gnutls_hmac_hd_t gnutls_hmac_copy(gnutls_hmac_hd_t handle)
801
0
{
802
0
  gnutls_hmac_hd_t dig;
803
804
0
  dig = gnutls_malloc(sizeof(mac_hd_st));
805
0
  if (dig == NULL) {
806
0
    gnutls_assert();
807
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
808
0
    return NULL;
809
0
  }
810
811
0
  if (_gnutls_mac_copy((const mac_hd_st *)handle, (mac_hd_st *)dig) !=
812
0
      GNUTLS_E_SUCCESS) {
813
0
    gnutls_assert();
814
0
    gnutls_free(dig);
815
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
816
0
    return NULL;
817
0
  }
818
819
0
  return dig;
820
0
}
821
822
/* HASH */
823
824
/**
825
 * gnutls_hash_init:
826
 * @dig: is a #gnutls_hash_hd_t type
827
 * @algorithm: the hash algorithm to use
828
 *
829
 * This function will initialize an context that can be used to
830
 * produce a Message Digest of data.  This will effectively use the
831
 * current crypto backend in use by gnutls or the cryptographic
832
 * accelerator in use.
833
 *
834
 * Returns: Zero or a negative error code on error.
835
 *
836
 * Since: 2.10.0
837
 **/
838
int gnutls_hash_init(gnutls_hash_hd_t *dig, gnutls_digest_algorithm_t algorithm)
839
0
{
840
0
  int ret;
841
0
  bool not_approved = false;
842
843
0
  if (!is_mac_algo_allowed(DIG_TO_MAC(algorithm))) {
844
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
845
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
846
0
  } else if (!is_mac_algo_approved_in_fips(DIG_TO_MAC(algorithm))) {
847
0
    not_approved = true;
848
0
  }
849
850
0
  *dig = gnutls_malloc(sizeof(digest_hd_st));
851
0
  if (*dig == NULL) {
852
0
    gnutls_assert();
853
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
854
0
    return GNUTLS_E_MEMORY_ERROR;
855
0
  }
856
857
0
  ret = _gnutls_hash_init(((digest_hd_st *)*dig),
858
0
        hash_to_entry(algorithm));
859
0
  if (ret < 0) {
860
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
861
0
  } else if (not_approved) {
862
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
863
0
  } else {
864
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
865
0
  }
866
0
  return ret;
867
0
}
868
869
/**
870
 * gnutls_hash:
871
 * @handle: is a #gnutls_hash_hd_t type
872
 * @ptext: the data to hash
873
 * @ptext_len: the length of data to hash
874
 *
875
 * This function will hash the given data using the algorithm
876
 * specified by the context.
877
 *
878
 * Returns: Zero or a negative error code on error.
879
 *
880
 * Since: 2.10.0
881
 **/
882
int gnutls_hash(gnutls_hash_hd_t handle, const void *ptext, size_t ptext_len)
883
0
{
884
0
  int ret;
885
886
0
  ret = _gnutls_hash((digest_hd_st *)handle, ptext, ptext_len);
887
0
  if (ret < 0) {
888
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
889
0
  }
890
0
  return ret;
891
0
}
892
893
/**
894
 * gnutls_hash_output:
895
 * @handle: is a #gnutls_hash_hd_t type
896
 * @digest: is the output value of the hash
897
 *
898
 * This function will output the current hash value and reset the
899
 * state of the hash. If @digest is %NULL, it only resets the state of
900
 * the hash.
901
 *
902
 * Since: 2.10.0
903
 **/
904
void gnutls_hash_output(gnutls_hash_hd_t handle, void *digest)
905
0
{
906
0
  _gnutls_hash_output((digest_hd_st *)handle, digest);
907
0
}
908
909
/**
910
 * gnutls_hash_deinit:
911
 * @handle: is a #gnutls_hash_hd_t type
912
 * @digest: is the output value of the hash
913
 *
914
 * This function will deinitialize all resources occupied by
915
 * the given hash context.
916
 *
917
 * Since: 2.10.0
918
 **/
919
void gnutls_hash_deinit(gnutls_hash_hd_t handle, void *digest)
920
0
{
921
0
  _gnutls_hash_deinit((digest_hd_st *)handle, digest);
922
0
  gnutls_free(handle);
923
0
}
924
925
/**
926
 * gnutls_hash_get_len:
927
 * @algorithm: the hash algorithm to use
928
 *
929
 * This function will return the length of the output data
930
 * of the given hash algorithm.
931
 *
932
 * Returns: The length or zero on error.
933
 *
934
 * Since: 2.10.0
935
 **/
936
unsigned gnutls_hash_get_len(gnutls_digest_algorithm_t algorithm)
937
0
{
938
0
  return _gnutls_hash_get_algo_len(hash_to_entry(algorithm));
939
0
}
940
941
/**
942
 * gnutls_hash_fast:
943
 * @algorithm: the hash algorithm to use
944
 * @ptext: the data to hash
945
 * @ptext_len: the length of data to hash
946
 * @digest: is the output value of the hash
947
 *
948
 * This convenience function will hash the given data and return output
949
 * on a single call.
950
 *
951
 * Returns: Zero or a negative error code on error.
952
 *
953
 * Since: 2.10.0
954
 **/
955
int gnutls_hash_fast(gnutls_digest_algorithm_t algorithm, const void *ptext,
956
         size_t ptext_len, void *digest)
957
0
{
958
0
  int ret;
959
0
  bool not_approved = false;
960
961
0
  if (!is_mac_algo_allowed(DIG_TO_MAC(algorithm))) {
962
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
963
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
964
0
  } else if (!is_mac_algo_approved_in_fips(DIG_TO_MAC(algorithm))) {
965
0
    not_approved = true;
966
0
  }
967
968
0
  ret = _gnutls_hash_fast(algorithm, ptext, ptext_len, digest);
969
0
  if (ret < 0) {
970
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
971
0
  } else if (not_approved) {
972
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
973
0
  } else {
974
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
975
0
  }
976
977
0
  return ret;
978
0
}
979
980
/**
981
 * gnutls_hash_copy:
982
 * @handle: is a #gnutls_hash_hd_t type
983
 *
984
 * This function will create a copy of Message Digest context, containing all
985
 * its current state. Copying contexts for Message Digests registered using
986
 * gnutls_crypto_register_digest() is not supported and will always result in
987
 * an error. In addition to that, some of the Message Digest implementations do
988
 * not support this operation. Applications should check the return value and
989
 * provide a proper fallback.
990
 *
991
 * Returns: new Message Digest context or NULL in case of an error.
992
 *
993
 * Since: 3.6.9
994
 */
995
gnutls_hash_hd_t gnutls_hash_copy(gnutls_hash_hd_t handle)
996
0
{
997
0
  gnutls_hash_hd_t dig;
998
999
0
  dig = gnutls_malloc(sizeof(digest_hd_st));
1000
0
  if (dig == NULL) {
1001
0
    gnutls_assert();
1002
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1003
0
    return NULL;
1004
0
  }
1005
1006
0
  if (_gnutls_hash_copy((const digest_hd_st *)handle,
1007
0
            (digest_hd_st *)dig) != GNUTLS_E_SUCCESS) {
1008
0
    gnutls_assert();
1009
0
    gnutls_free(dig);
1010
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1011
0
    return NULL;
1012
0
  }
1013
1014
0
  return dig;
1015
0
}
1016
1017
/**
1018
 * gnutls_hash_squeeze:
1019
 * @handle: a #gnutls_hash_hd_t
1020
 * @output: destination to store the output; must be equal to or larger than @length
1021
 * @length: length of @output
1022
 *
1023
 * This function will extract digest output of @length bytes. The @handle must
1024
 * be initialized with gnutls_hash_init() as an extended output function (XOF),
1025
 * such as %GNUTLS_DIG_SHAKE_128 or %GNUTLS_DIG_SHAKE_256.
1026
 *
1027
 * This function can be called multiple times. To reset the state of @handle,
1028
 * call gnutls_hash_deinit() with %NULL as the digest argument.
1029
 *
1030
 * Returns: %GNUTLS_E_SUCCESS (0) on success; negative error code otherwise.
1031
 *
1032
 * Since: 3.8.6
1033
 */
1034
int gnutls_hash_squeeze(gnutls_hash_hd_t handle, void *output, size_t length)
1035
0
{
1036
0
  return _gnutls_hash_squeeze((digest_hd_st *)handle, output, length);
1037
0
}
1038
1039
/**
1040
 * gnutls_key_generate:
1041
 * @key: is a pointer to a #gnutls_datum_t which will contain a newly
1042
 * created key
1043
 * @key_size: the number of bytes of the key
1044
 *
1045
 * Generates a random key of @key_size bytes.
1046
 *
1047
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
1048
 * error code.
1049
 *
1050
 * Since: 3.0
1051
 **/
1052
int gnutls_key_generate(gnutls_datum_t *key, unsigned int key_size)
1053
0
{
1054
0
  int ret;
1055
0
  bool not_approved = false;
1056
1057
0
  FAIL_IF_LIB_ERROR;
1058
1059
#ifdef ENABLE_FIPS140
1060
  /* The FIPS140 approved RNGs are not allowed to be used
1061
   * to extract key sizes longer than their original seed.
1062
   */
1063
  if (_gnutls_fips_mode_enabled() != 0 && key_size > FIPS140_RND_KEY_SIZE)
1064
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1065
#endif
1066
1067
0
  key->size = key_size;
1068
0
  key->data = gnutls_malloc(key->size);
1069
0
  if (!key->data) {
1070
0
    gnutls_assert();
1071
0
    ret = GNUTLS_E_MEMORY_ERROR;
1072
0
    goto error;
1073
0
  }
1074
1075
  /* Key lengths of less than 112 bits are not approved */
1076
0
  if (key_size < 14) {
1077
0
    not_approved = true;
1078
0
  }
1079
1080
0
  ret = gnutls_rnd(GNUTLS_RND_RANDOM, key->data, key->size);
1081
0
  if (ret < 0) {
1082
0
    gnutls_assert();
1083
0
    _gnutls_free_datum(key);
1084
0
    goto error;
1085
0
  }
1086
1087
0
error:
1088
0
  if (ret < 0) {
1089
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1090
0
  } else if (not_approved) {
1091
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
1092
0
  } else {
1093
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
1094
0
  }
1095
0
  return ret;
1096
0
}
1097
1098
/* AEAD API */
1099
1100
/**
1101
 * gnutls_aead_cipher_init:
1102
 * @handle: is a #gnutls_aead_cipher_hd_t type.
1103
 * @cipher: the authenticated-encryption algorithm to use
1104
 * @key: The key to be used for encryption
1105
 *
1106
 * This function will initialize an context that can be used for
1107
 * encryption/decryption of data. This will effectively use the
1108
 * current crypto backend in use by gnutls or the cryptographic
1109
 * accelerator in use.
1110
 *
1111
 * Returns: Zero or a negative error code on error.
1112
 *
1113
 * Since: 3.4.0
1114
 **/
1115
int gnutls_aead_cipher_init(gnutls_aead_cipher_hd_t *handle,
1116
          gnutls_cipher_algorithm_t cipher,
1117
          const gnutls_datum_t *key)
1118
0
{
1119
0
  api_aead_cipher_hd_st *h;
1120
0
  const cipher_entry_st *e;
1121
0
  int ret;
1122
0
  bool not_approved = false;
1123
1124
0
  if (!is_cipher_algo_allowed(cipher)) {
1125
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1126
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
1127
0
  } else if (!is_cipher_algo_approved_in_fips(cipher)) {
1128
0
    not_approved = true;
1129
0
  }
1130
1131
0
  e = cipher_to_entry(cipher);
1132
0
  if (e == NULL || e->type != CIPHER_AEAD) {
1133
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1134
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1135
0
  }
1136
1137
0
  h = gnutls_calloc(1, sizeof(api_aead_cipher_hd_st));
1138
0
  if (h == NULL) {
1139
0
    gnutls_assert();
1140
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1141
0
    return GNUTLS_E_MEMORY_ERROR;
1142
0
  }
1143
1144
0
  ret = _gnutls_aead_cipher_init(h, cipher, key);
1145
0
  if (ret < 0) {
1146
0
    gnutls_free(h);
1147
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1148
0
    return ret;
1149
0
  }
1150
1151
0
  *handle = h;
1152
1153
0
  if (not_approved) {
1154
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
1155
0
  } else {
1156
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
1157
0
  }
1158
1159
0
  return ret;
1160
0
}
1161
1162
/**
1163
 * gnutls_aead_cipher_set_key:
1164
 * @handle: is a #gnutls_aead_cipher_hd_t type.
1165
 * @key: The key to be used for encryption
1166
 *
1167
 * This function will set a new key without re-initializing the
1168
 * context.
1169
 *
1170
 * Returns: Zero or a negative error code on error.
1171
 *
1172
 * Since: 3.7.5
1173
 **/
1174
int gnutls_aead_cipher_set_key(gnutls_aead_cipher_hd_t handle,
1175
             const gnutls_datum_t *key)
1176
0
{
1177
0
  const cipher_entry_st *e;
1178
0
  int ret;
1179
1180
0
  e = cipher_to_entry(handle->ctx_enc.e->id);
1181
0
  if (e == NULL || e->type != CIPHER_AEAD) {
1182
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1183
0
  }
1184
1185
0
  ret = handle->ctx_enc.setkey(handle->ctx_enc.handle, key->data,
1186
0
             key->size);
1187
0
  if (ret < 0) {
1188
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1189
0
  }
1190
1191
0
  return ret;
1192
0
}
1193
1194
/**
1195
 * gnutls_aead_cipher_decrypt:
1196
 * @handle: is a #gnutls_aead_cipher_hd_t type.
1197
 * @nonce: the nonce to set
1198
 * @nonce_len: The length of the nonce
1199
 * @auth: additional data to be authenticated
1200
 * @auth_len: The length of the data
1201
 * @tag_size: The size of the tag to use (use zero for the default)
1202
 * @ctext: the data to decrypt (including the authentication tag)
1203
 * @ctext_len: the length of data to decrypt (includes tag size)
1204
 * @ptext: the decrypted data
1205
 * @ptext_len: the length of decrypted data (initially must hold the maximum available size)
1206
 *
1207
 * This function will decrypt the given data using the algorithm
1208
 * specified by the context. This function must be provided the complete
1209
 * data to be decrypted, including the authentication tag. On several
1210
 * AEAD ciphers, the authentication tag is appended to the ciphertext,
1211
 * though this is not a general rule. This function will fail if
1212
 * the tag verification fails.
1213
 *
1214
 * Returns: Zero or a negative error code on verification failure or other error.
1215
 *
1216
 * Since: 3.4.0
1217
 **/
1218
int gnutls_aead_cipher_decrypt(gnutls_aead_cipher_hd_t handle,
1219
             const void *nonce, size_t nonce_len,
1220
             const void *auth, size_t auth_len,
1221
             size_t tag_size, const void *ctext,
1222
             size_t ctext_len, void *ptext, size_t *ptext_len)
1223
0
{
1224
0
  int ret;
1225
0
  api_aead_cipher_hd_st *h = handle;
1226
1227
0
  if (tag_size == 0)
1228
0
    tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
1229
0
  else if (tag_size >
1230
0
     (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e)) {
1231
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1232
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1233
0
  }
1234
1235
0
  if (unlikely(ctext_len < tag_size)) {
1236
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1237
0
    return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1238
0
  }
1239
1240
0
  ret = _gnutls_aead_cipher_decrypt(&h->ctx_enc, nonce, nonce_len, auth,
1241
0
            auth_len, tag_size, ctext, ctext_len,
1242
0
            ptext, *ptext_len);
1243
0
  if (unlikely(ret < 0)) {
1244
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1245
0
    return gnutls_assert_val(ret);
1246
0
  } else {
1247
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
1248
0
  }
1249
1250
  /* That assumes that AEAD ciphers are stream */
1251
0
  *ptext_len = ctext_len - tag_size;
1252
1253
0
  return 0;
1254
0
}
1255
1256
/**
1257
 * gnutls_aead_cipher_encrypt:
1258
 * @handle: is a #gnutls_aead_cipher_hd_t type.
1259
 * @nonce: the nonce to set
1260
 * @nonce_len: The length of the nonce
1261
 * @auth: additional data to be authenticated
1262
 * @auth_len: The length of the data
1263
 * @tag_size: The size of the tag to use (use zero for the default)
1264
 * @ptext: the data to encrypt
1265
 * @ptext_len: The length of data to encrypt
1266
 * @ctext: the encrypted data including authentication tag
1267
 * @ctext_len: the length of encrypted data (initially must hold the maximum available size, including space for tag)
1268
 *
1269
 * This function will encrypt the given data using the algorithm
1270
 * specified by the context. The output data will contain the
1271
 * authentication tag.
1272
 *
1273
 * Returns: Zero or a negative error code on error.
1274
 *
1275
 * Since: 3.4.0
1276
 **/
1277
int gnutls_aead_cipher_encrypt(gnutls_aead_cipher_hd_t handle,
1278
             const void *nonce, size_t nonce_len,
1279
             const void *auth, size_t auth_len,
1280
             size_t tag_size, const void *ptext,
1281
             size_t ptext_len, void *ctext, size_t *ctext_len)
1282
0
{
1283
0
  api_aead_cipher_hd_st *h = handle;
1284
0
  int ret;
1285
1286
0
  if (tag_size == 0)
1287
0
    tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
1288
0
  else if (tag_size >
1289
0
     (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e)) {
1290
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1291
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1292
0
  }
1293
1294
0
  if (unlikely(*ctext_len < ptext_len + tag_size)) {
1295
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1296
0
    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
1297
0
  }
1298
1299
0
  ret = _gnutls_aead_cipher_encrypt(&h->ctx_enc, nonce, nonce_len, auth,
1300
0
            auth_len, tag_size, ptext, ptext_len,
1301
0
            ctext, *ctext_len);
1302
0
  if (unlikely(ret < 0)) {
1303
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1304
0
    return gnutls_assert_val(ret);
1305
0
  } else {
1306
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
1307
0
  }
1308
1309
  /* That assumes that AEAD ciphers are stream */
1310
0
  *ctext_len = ptext_len + tag_size;
1311
1312
0
  return 0;
1313
0
}
1314
1315
struct iov_store_st {
1316
  void *data;
1317
  size_t length;
1318
  size_t capacity;
1319
};
1320
1321
static void iov_store_free(struct iov_store_st *s)
1322
0
{
1323
0
  gnutls_free(s->data);
1324
0
}
1325
1326
static int iov_store_grow(struct iov_store_st *s, size_t length)
1327
0
{
1328
0
  void *new_data;
1329
0
  size_t new_capacity = s->capacity;
1330
1331
0
  if (INT_ADD_OVERFLOW(new_capacity, length)) {
1332
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1333
0
  }
1334
0
  new_capacity += length;
1335
0
  new_data = gnutls_realloc(s->data, new_capacity);
1336
0
  if (!new_data) {
1337
0
    return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1338
0
  }
1339
0
  s->data = new_data;
1340
0
  s->capacity = new_capacity;
1341
0
  return 0;
1342
0
}
1343
1344
static int append_from_iov(struct iov_store_st *dst, const giovec_t *iov,
1345
         int iovcnt)
1346
0
{
1347
0
  if (iovcnt > 0) {
1348
0
    int i;
1349
0
    uint8_t *p;
1350
0
    void *new_data;
1351
0
    size_t new_capacity = dst->capacity;
1352
1353
0
    for (i = 0; i < iovcnt; i++) {
1354
0
      if (INT_ADD_OVERFLOW(new_capacity, iov[i].iov_len)) {
1355
0
        return gnutls_assert_val(
1356
0
          GNUTLS_E_INVALID_REQUEST);
1357
0
      }
1358
0
      new_capacity += iov[i].iov_len;
1359
0
    }
1360
0
    new_data = gnutls_realloc(dst->data, new_capacity);
1361
0
    if (!new_data) {
1362
0
      return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
1363
0
    }
1364
0
    dst->data = new_data;
1365
0
    dst->capacity = new_capacity;
1366
1367
0
    p = (uint8_t *)dst->data + dst->length;
1368
0
    for (i = 0; i < iovcnt; i++) {
1369
0
      if (iov[i].iov_len > 0) {
1370
0
        memcpy(p, iov[i].iov_base, iov[i].iov_len);
1371
0
      }
1372
0
      p += iov[i].iov_len;
1373
0
      dst->length += iov[i].iov_len;
1374
0
    }
1375
0
  }
1376
0
  return 0;
1377
0
}
1378
1379
static int copy_to_iov(const uint8_t *data, size_t size, const giovec_t *iov,
1380
           int iovcnt)
1381
0
{
1382
0
  size_t offset = 0;
1383
0
  int i;
1384
1385
0
  for (i = 0; i < iovcnt && size > 0; i++) {
1386
0
    size_t to_copy = MIN(size, iov[i].iov_len);
1387
0
    memcpy(iov[i].iov_base, (uint8_t *)data + offset, to_copy);
1388
0
    offset += to_copy;
1389
0
    size -= to_copy;
1390
0
  }
1391
0
  if (size > 0)
1392
0
    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
1393
0
  return 0;
1394
0
}
1395
1396
0
#define IOV_STORE_INIT { NULL, 0, 0 }
1397
1398
static int aead_cipher_encryptv_fallback(gnutls_aead_cipher_hd_t handle,
1399
           const void *nonce, size_t nonce_len,
1400
           const giovec_t *auth_iov,
1401
           int auth_iovcnt, size_t tag_size,
1402
           const giovec_t *iov, int iovcnt,
1403
           void *ctext, size_t *ctext_len)
1404
0
{
1405
0
  struct iov_store_st auth = IOV_STORE_INIT;
1406
0
  struct iov_store_st ptext = IOV_STORE_INIT;
1407
0
  int ret;
1408
1409
0
  if (tag_size == 0)
1410
0
    tag_size = _gnutls_cipher_get_tag_size(handle->ctx_enc.e);
1411
0
  else if (tag_size >
1412
0
     (unsigned)_gnutls_cipher_get_tag_size(handle->ctx_enc.e)) {
1413
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1414
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1415
0
  }
1416
1417
0
  ret = append_from_iov(&auth, auth_iov, auth_iovcnt);
1418
0
  if (ret < 0) {
1419
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1420
0
    return gnutls_assert_val(ret);
1421
0
  }
1422
1423
0
  ret = append_from_iov(&ptext, iov, iovcnt);
1424
0
  if (ret < 0) {
1425
0
    iov_store_free(&auth);
1426
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1427
0
    return gnutls_assert_val(ret);
1428
0
  }
1429
1430
0
  ret = gnutls_aead_cipher_encrypt(handle, nonce, nonce_len, auth.data,
1431
0
           auth.length, tag_size, ptext.data,
1432
0
           ptext.length, ctext, ctext_len);
1433
0
  iov_store_free(&auth);
1434
0
  iov_store_free(&ptext);
1435
1436
  /* FIPS operation state is set by gnutls_aead_cipher_encrypt */
1437
0
  return ret;
1438
0
}
1439
1440
static int aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
1441
        const void *nonce, size_t nonce_len,
1442
        const giovec_t *auth_iov, int auth_iovcnt,
1443
        size_t tag_size, const giovec_t *iov,
1444
        int iovcnt, void *ctext, size_t *ctext_len)
1445
0
{
1446
0
  int ret;
1447
0
  uint8_t *dst;
1448
0
  size_t dst_size, total = 0;
1449
0
  uint8_t *p;
1450
0
  size_t len;
1451
0
  size_t blocksize = handle->ctx_enc.e->blocksize;
1452
0
  struct iov_iter_st iter;
1453
1454
0
  if (tag_size == 0)
1455
0
    tag_size = _gnutls_cipher_get_tag_size(handle->ctx_enc.e);
1456
0
  else if (tag_size >
1457
0
     (unsigned)_gnutls_cipher_get_tag_size(handle->ctx_enc.e)) {
1458
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1459
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1460
0
  }
1461
1462
0
  ret = _gnutls_cipher_setiv(&handle->ctx_enc, nonce, nonce_len);
1463
0
  if (unlikely(ret < 0)) {
1464
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1465
0
    return gnutls_assert_val(ret);
1466
0
  }
1467
1468
0
  ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
1469
0
  if (unlikely(ret < 0)) {
1470
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1471
0
    return gnutls_assert_val(ret);
1472
0
  }
1473
0
  while (1) {
1474
0
    ret = _gnutls_iov_iter_next(&iter, &p);
1475
0
    if (unlikely(ret < 0)) {
1476
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1477
0
      return gnutls_assert_val(ret);
1478
0
    }
1479
0
    if (ret == 0)
1480
0
      break;
1481
0
    ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
1482
0
    if (unlikely(ret < 0)) {
1483
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1484
0
      return gnutls_assert_val(ret);
1485
0
    }
1486
0
  }
1487
1488
0
  dst = ctext;
1489
0
  dst_size = *ctext_len;
1490
1491
0
  ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
1492
0
  if (unlikely(ret < 0)) {
1493
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1494
0
    return gnutls_assert_val(ret);
1495
0
  }
1496
0
  while (1) {
1497
0
    ret = _gnutls_iov_iter_next(&iter, &p);
1498
0
    if (unlikely(ret < 0)) {
1499
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1500
0
      return gnutls_assert_val(ret);
1501
0
    }
1502
0
    if (ret == 0)
1503
0
      break;
1504
0
    len = ret;
1505
0
    ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, len, dst,
1506
0
                dst_size);
1507
0
    if (unlikely(ret < 0)) {
1508
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1509
0
      return gnutls_assert_val(ret);
1510
0
    }
1511
1512
0
    DECR_LEN(dst_size, len);
1513
0
    dst += len;
1514
0
    total += len;
1515
0
  }
1516
1517
0
  if (dst_size < tag_size) {
1518
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1519
0
    return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
1520
0
  }
1521
1522
0
  _gnutls_cipher_tag(&handle->ctx_enc, dst, tag_size);
1523
1524
0
  total += tag_size;
1525
0
  *ctext_len = total;
1526
1527
0
  _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
1528
0
  return 0;
1529
0
}
1530
1531
/**
1532
 * gnutls_aead_cipher_encryptv:
1533
 * @handle: is a #gnutls_aead_cipher_hd_t type.
1534
 * @nonce: the nonce to set
1535
 * @nonce_len: The length of the nonce
1536
 * @auth_iov: additional data to be authenticated
1537
 * @auth_iovcnt: The number of buffers in @auth_iov
1538
 * @tag_size: The size of the tag to use (use zero for the default)
1539
 * @iov: the data to be encrypted
1540
 * @iovcnt: The number of buffers in @iov
1541
 * @ctext: the encrypted data including authentication tag
1542
 * @ctext_len: the length of encrypted data (initially must hold the maximum available size, including space for tag)
1543
 *
1544
 * This function will encrypt the provided data buffers using the algorithm
1545
 * specified by the context. The output data will contain the
1546
 * authentication tag.
1547
 *
1548
 * Returns: Zero or a negative error code on error.
1549
 *
1550
 * Since: 3.6.3
1551
 **/
1552
int gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
1553
        const void *nonce, size_t nonce_len,
1554
        const giovec_t *auth_iov, int auth_iovcnt,
1555
        size_t tag_size, const giovec_t *iov,
1556
        int iovcnt, void *ctext, size_t *ctext_len)
1557
0
{
1558
  /* Limitation: this function provides an optimization under the internally registered
1559
   * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
1560
   * then this becomes a convenience function as it missed the lower-level primitives
1561
   * necessary for piecemeal encryption. */
1562
0
  if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) ||
1563
0
      handle->ctx_enc.encrypt == NULL) {
1564
0
    return aead_cipher_encryptv_fallback(handle, nonce, nonce_len,
1565
0
                 auth_iov, auth_iovcnt,
1566
0
                 tag_size, iov, iovcnt,
1567
0
                 ctext, ctext_len);
1568
0
  } else {
1569
0
    return aead_cipher_encryptv(handle, nonce, nonce_len, auth_iov,
1570
0
              auth_iovcnt, tag_size, iov, iovcnt,
1571
0
              ctext, ctext_len);
1572
0
  }
1573
0
}
1574
1575
static int aead_cipher_encryptv2_fallback(gnutls_aead_cipher_hd_t handle,
1576
            const void *nonce, size_t nonce_len,
1577
            const giovec_t *auth_iov,
1578
            int auth_iovcnt, const giovec_t *iov,
1579
            int iovcnt, void *tag,
1580
            size_t *tag_size)
1581
0
{
1582
0
  struct iov_store_st auth = IOV_STORE_INIT;
1583
0
  struct iov_store_st ptext = IOV_STORE_INIT;
1584
0
  uint8_t *ptext_data;
1585
0
  size_t ptext_size;
1586
0
  uint8_t *ctext_data;
1587
0
  size_t ctext_size;
1588
0
  uint8_t *_tag;
1589
0
  size_t _tag_size;
1590
0
  int ret;
1591
1592
0
  if (tag_size == NULL || *tag_size == 0)
1593
0
    _tag_size = _gnutls_cipher_get_tag_size(handle->ctx_enc.e);
1594
0
  else
1595
0
    _tag_size = *tag_size;
1596
1597
0
  if (_tag_size >
1598
0
      (unsigned)_gnutls_cipher_get_tag_size(handle->ctx_enc.e)) {
1599
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1600
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1601
0
  }
1602
1603
0
  ret = append_from_iov(&auth, auth_iov, auth_iovcnt);
1604
0
  if (ret < 0) {
1605
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1606
0
    return gnutls_assert_val(ret);
1607
0
  }
1608
1609
0
  if (handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_TAG_PREFIXED) {
1610
    /* prepend space for tag */
1611
0
    ret = iov_store_grow(&ptext, _tag_size);
1612
0
    if (ret < 0) {
1613
0
      gnutls_assert();
1614
0
      goto error;
1615
0
    }
1616
0
    ptext.length = _tag_size;
1617
1618
0
    ret = append_from_iov(&ptext, iov, iovcnt);
1619
0
    if (ret < 0) {
1620
0
      gnutls_assert();
1621
0
      goto error;
1622
0
    }
1623
1624
    /* We must set ptext_data after the above
1625
     * grow/append operations, otherwise it will point to an invalid pointer after realloc.
1626
     */
1627
0
    ptext_data = (uint8_t *)ptext.data + _tag_size;
1628
0
    ptext_size = ptext.length - _tag_size;
1629
0
  } else {
1630
0
    ret = append_from_iov(&ptext, iov, iovcnt);
1631
0
    if (ret < 0) {
1632
0
      gnutls_assert();
1633
0
      goto error;
1634
0
    }
1635
1636
    /* append space for tag */
1637
0
    ret = iov_store_grow(&ptext, _tag_size);
1638
0
    if (ret < 0) {
1639
0
      gnutls_assert();
1640
0
      goto error;
1641
0
    }
1642
1643
    /* We must set ptext_data after the above
1644
     * grow/append operations, otherwise it will point to an invalid pointer after realloc.
1645
     */
1646
0
    ptext_data = ptext.data;
1647
0
    ptext_size = ptext.length;
1648
0
  }
1649
1650
0
  ctext_size = ptext.capacity;
1651
0
  ret = gnutls_aead_cipher_encrypt(handle, nonce, nonce_len, auth.data,
1652
0
           auth.length, _tag_size, ptext_data,
1653
0
           ptext_size, ptext.data, &ctext_size);
1654
0
  if (ret < 0) {
1655
0
    gnutls_assert();
1656
0
    goto error;
1657
0
  }
1658
1659
0
  if (handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_TAG_PREFIXED) {
1660
0
    ctext_data = (uint8_t *)ptext.data + _tag_size;
1661
0
    _tag = ptext.data;
1662
0
  } else {
1663
0
    ctext_data = ptext.data;
1664
0
    _tag = (uint8_t *)ptext.data + ptext_size;
1665
0
  }
1666
1667
0
  ret = copy_to_iov(ctext_data, ptext_size, iov, iovcnt);
1668
0
  if (ret < 0) {
1669
0
    gnutls_assert();
1670
0
    goto error;
1671
0
  }
1672
1673
0
  if (tag != NULL) {
1674
0
    memcpy(tag, _tag, _tag_size);
1675
0
  }
1676
0
  if (tag_size != NULL) {
1677
0
    *tag_size = _tag_size;
1678
0
  }
1679
1680
0
error:
1681
0
  iov_store_free(&auth);
1682
0
  iov_store_free(&ptext);
1683
1684
0
  if (ret < 0) {
1685
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1686
0
  }
1687
  /* FIPS operation state is set by gnutls_aead_cipher_encrypt */
1688
0
  return ret;
1689
0
}
1690
1691
static int aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
1692
         const void *nonce, size_t nonce_len,
1693
         const giovec_t *auth_iov, int auth_iovcnt,
1694
         const giovec_t *iov, int iovcnt, void *tag,
1695
         size_t *tag_size)
1696
0
{
1697
0
  api_aead_cipher_hd_st *h = handle;
1698
0
  int ret;
1699
0
  uint8_t *p;
1700
0
  size_t len;
1701
0
  size_t blocksize = handle->ctx_enc.e->blocksize;
1702
0
  struct iov_iter_st iter;
1703
0
  size_t _tag_size;
1704
1705
0
  if (tag_size == NULL || *tag_size == 0)
1706
0
    _tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
1707
0
  else
1708
0
    _tag_size = *tag_size;
1709
1710
0
  if (_tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e)) {
1711
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1712
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1713
0
  }
1714
1715
0
  ret = _gnutls_cipher_setiv(&handle->ctx_enc, nonce, nonce_len);
1716
0
  if (unlikely(ret < 0)) {
1717
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1718
0
    return gnutls_assert_val(ret);
1719
0
  }
1720
1721
0
  ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
1722
0
  if (unlikely(ret < 0)) {
1723
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1724
0
    return gnutls_assert_val(ret);
1725
0
  }
1726
0
  while (1) {
1727
0
    ret = _gnutls_iov_iter_next(&iter, &p);
1728
0
    if (unlikely(ret < 0)) {
1729
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1730
0
      return gnutls_assert_val(ret);
1731
0
    }
1732
0
    if (ret == 0)
1733
0
      break;
1734
0
    ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
1735
0
    if (unlikely(ret < 0)) {
1736
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1737
0
      return gnutls_assert_val(ret);
1738
0
    }
1739
0
  }
1740
1741
0
  ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
1742
0
  if (unlikely(ret < 0))
1743
0
    return gnutls_assert_val(ret);
1744
0
  while (1) {
1745
0
    ret = _gnutls_iov_iter_next(&iter, &p);
1746
0
    if (unlikely(ret < 0)) {
1747
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1748
0
      return gnutls_assert_val(ret);
1749
0
    }
1750
0
    if (ret == 0)
1751
0
      break;
1752
1753
0
    len = ret;
1754
0
    ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, len, p, len);
1755
0
    if (unlikely(ret < 0)) {
1756
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1757
0
      return gnutls_assert_val(ret);
1758
0
    }
1759
1760
0
    ret = _gnutls_iov_iter_sync(&iter, p, len);
1761
0
    if (unlikely(ret < 0)) {
1762
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1763
0
      return gnutls_assert_val(ret);
1764
0
    }
1765
0
  }
1766
1767
0
  if (tag != NULL)
1768
0
    _gnutls_cipher_tag(&handle->ctx_enc, tag, _tag_size);
1769
0
  if (tag_size != NULL)
1770
0
    *tag_size = _tag_size;
1771
1772
0
  _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
1773
0
  return 0;
1774
0
}
1775
1776
/**
1777
 * gnutls_aead_cipher_encryptv2:
1778
 * @handle: is a #gnutls_aead_cipher_hd_t type.
1779
 * @nonce: the nonce to set
1780
 * @nonce_len: The length of the nonce
1781
 * @auth_iov: additional data to be authenticated
1782
 * @auth_iovcnt: The number of buffers in @auth_iov
1783
 * @iov: the data to be encrypted
1784
 * @iovcnt: The number of buffers in @iov
1785
 * @tag: The authentication tag
1786
 * @tag_size: The size of the tag to use (use zero for the default)
1787
 *
1788
 * This is similar to gnutls_aead_cipher_encrypt(), but it performs
1789
 * in-place encryption on the provided data buffers.
1790
 *
1791
 * Returns: Zero or a negative error code on error.
1792
 *
1793
 * Since: 3.6.10
1794
 **/
1795
int gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
1796
         const void *nonce, size_t nonce_len,
1797
         const giovec_t *auth_iov, int auth_iovcnt,
1798
         const giovec_t *iov, int iovcnt, void *tag,
1799
         size_t *tag_size)
1800
0
{
1801
  /* Limitation: this function provides an optimization under the internally registered
1802
   * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
1803
   * then this becomes a convenience function as it missed the lower-level primitives
1804
   * necessary for piecemeal encryption. */
1805
0
  if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) ||
1806
0
      handle->ctx_enc.encrypt == NULL) {
1807
0
    return aead_cipher_encryptv2_fallback(handle, nonce, nonce_len,
1808
0
                  auth_iov, auth_iovcnt,
1809
0
                  iov, iovcnt, tag,
1810
0
                  tag_size);
1811
0
  } else {
1812
0
    return aead_cipher_encryptv2(handle, nonce, nonce_len, auth_iov,
1813
0
               auth_iovcnt, iov, iovcnt, tag,
1814
0
               tag_size);
1815
0
  }
1816
0
}
1817
1818
static int aead_cipher_decryptv2_fallback(gnutls_aead_cipher_hd_t handle,
1819
            const void *nonce, size_t nonce_len,
1820
            const giovec_t *auth_iov,
1821
            int auth_iovcnt, const giovec_t *iov,
1822
            int iovcnt, void *tag,
1823
            size_t tag_size)
1824
0
{
1825
0
  struct iov_store_st auth = IOV_STORE_INIT;
1826
0
  struct iov_store_st ctext = IOV_STORE_INIT;
1827
0
  uint8_t *ctext_data;
1828
0
  size_t ptext_size;
1829
0
  int ret;
1830
1831
0
  if (tag_size == 0)
1832
0
    tag_size = _gnutls_cipher_get_tag_size(handle->ctx_enc.e);
1833
0
  else if (tag_size >
1834
0
     (unsigned)_gnutls_cipher_get_tag_size(handle->ctx_enc.e)) {
1835
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1836
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1837
0
  }
1838
1839
0
  ret = append_from_iov(&auth, auth_iov, auth_iovcnt);
1840
0
  if (ret < 0) {
1841
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1842
0
    return gnutls_assert_val(ret);
1843
0
  }
1844
1845
0
  if (handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_TAG_PREFIXED) {
1846
    /* prepend tag */
1847
0
    ret = iov_store_grow(&ctext, tag_size);
1848
0
    if (ret < 0) {
1849
0
      gnutls_assert();
1850
0
      goto error;
1851
0
    }
1852
0
    memcpy(ctext.data, tag, tag_size);
1853
0
    ctext.length += tag_size;
1854
1855
0
    ret = append_from_iov(&ctext, iov, iovcnt);
1856
0
    if (ret < 0) {
1857
0
      gnutls_assert();
1858
0
      goto error;
1859
0
    }
1860
1861
    /* We must set ctext_data after the above
1862
     * grow/append operations, otherwise it will point to an invalid pointer after realloc.
1863
     */
1864
0
    ctext_data = (uint8_t *)ctext.data + tag_size;
1865
0
  } else {
1866
0
    ret = append_from_iov(&ctext, iov, iovcnt);
1867
0
    if (ret < 0) {
1868
0
      gnutls_assert();
1869
0
      goto error;
1870
0
    }
1871
1872
    /* append tag */
1873
0
    ret = iov_store_grow(&ctext, tag_size);
1874
0
    if (ret < 0) {
1875
0
      gnutls_assert();
1876
0
      goto error;
1877
0
    }
1878
0
    memcpy((uint8_t *)ctext.data + ctext.length, tag, tag_size);
1879
0
    ctext.length += tag_size;
1880
1881
    /* We must set ctext_data after the above
1882
     * grow/append operations, otherwise it will point to an invalid pointer after realloc.
1883
     */
1884
0
    ctext_data = ctext.data;
1885
0
  }
1886
1887
0
  ptext_size = ctext.capacity;
1888
0
  ret = gnutls_aead_cipher_decrypt(handle, nonce, nonce_len, auth.data,
1889
0
           auth.length, tag_size, ctext.data,
1890
0
           ctext.length, ctext_data, &ptext_size);
1891
0
  if (ret < 0) {
1892
0
    gnutls_assert();
1893
0
    goto error;
1894
0
  }
1895
1896
0
  ret = copy_to_iov(ctext.data, ptext_size, iov, iovcnt);
1897
0
  if (ret < 0) {
1898
0
    gnutls_assert();
1899
0
    goto error;
1900
0
  }
1901
1902
0
error:
1903
0
  iov_store_free(&auth);
1904
0
  iov_store_free(&ctext);
1905
1906
0
  if (ret < 0) {
1907
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1908
0
  }
1909
  /* FIPS operation state is set by gnutls_aead_cipher_decrypt */
1910
0
  return ret;
1911
0
}
1912
1913
static int aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
1914
         const void *nonce, size_t nonce_len,
1915
         const giovec_t *auth_iov, int auth_iovcnt,
1916
         const giovec_t *iov, int iovcnt, void *tag,
1917
         size_t tag_size)
1918
0
{
1919
0
  int ret;
1920
0
  uint8_t *p;
1921
0
  size_t len;
1922
0
  ssize_t blocksize = handle->ctx_enc.e->blocksize;
1923
0
  struct iov_iter_st iter;
1924
0
  uint8_t _tag[MAX_HASH_SIZE];
1925
1926
0
  if (tag_size == 0)
1927
0
    tag_size = _gnutls_cipher_get_tag_size(handle->ctx_enc.e);
1928
0
  else if (tag_size >
1929
0
     (unsigned)_gnutls_cipher_get_tag_size(handle->ctx_enc.e)) {
1930
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1931
0
    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1932
0
  }
1933
1934
0
  ret = _gnutls_cipher_setiv(&handle->ctx_enc, nonce, nonce_len);
1935
0
  if (unlikely(ret < 0)) {
1936
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1937
0
    return gnutls_assert_val(ret);
1938
0
  }
1939
1940
0
  ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
1941
0
  if (unlikely(ret < 0)) {
1942
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1943
0
    return gnutls_assert_val(ret);
1944
0
  }
1945
0
  while (1) {
1946
0
    ret = _gnutls_iov_iter_next(&iter, &p);
1947
0
    if (unlikely(ret < 0)) {
1948
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1949
0
      return gnutls_assert_val(ret);
1950
0
    }
1951
0
    if (ret == 0)
1952
0
      break;
1953
0
    ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
1954
0
    if (unlikely(ret < 0)) {
1955
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1956
0
      return gnutls_assert_val(ret);
1957
0
    }
1958
0
  }
1959
1960
0
  ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
1961
0
  if (unlikely(ret < 0)) {
1962
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1963
0
    return gnutls_assert_val(ret);
1964
0
  }
1965
0
  while (1) {
1966
0
    ret = _gnutls_iov_iter_next(&iter, &p);
1967
0
    if (unlikely(ret < 0)) {
1968
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1969
0
      return gnutls_assert_val(ret);
1970
0
    }
1971
0
    if (ret == 0)
1972
0
      break;
1973
1974
0
    len = ret;
1975
0
    ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, len, p, len);
1976
0
    if (unlikely(ret < 0)) {
1977
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1978
0
      return gnutls_assert_val(ret);
1979
0
    }
1980
1981
0
    ret = _gnutls_iov_iter_sync(&iter, p, len);
1982
0
    if (unlikely(ret < 0)) {
1983
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1984
0
      return gnutls_assert_val(ret);
1985
0
    }
1986
0
  }
1987
1988
0
  if (tag != NULL) {
1989
0
    _gnutls_cipher_tag(&handle->ctx_enc, _tag, tag_size);
1990
0
    if (gnutls_memcmp(_tag, tag, tag_size) != 0) {
1991
0
      _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
1992
0
      return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1993
0
    }
1994
0
  }
1995
1996
0
  _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
1997
0
  return 0;
1998
0
}
1999
2000
/**
2001
 * gnutls_aead_cipher_decryptv2:
2002
 * @handle: is a #gnutls_aead_cipher_hd_t type.
2003
 * @nonce: the nonce to set
2004
 * @nonce_len: The length of the nonce
2005
 * @auth_iov: additional data to be authenticated
2006
 * @auth_iovcnt: The number of buffers in @auth_iov
2007
 * @iov: the data to decrypt
2008
 * @iovcnt: The number of buffers in @iov
2009
 * @tag: The authentication tag
2010
 * @tag_size: The size of the tag to use (use zero for the default)
2011
 *
2012
 * This is similar to gnutls_aead_cipher_decrypt(), but it performs
2013
 * in-place encryption on the provided data buffers.
2014
 *
2015
 * Returns: Zero or a negative error code on error.
2016
 *
2017
 * Since: 3.6.10
2018
 **/
2019
int gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
2020
         const void *nonce, size_t nonce_len,
2021
         const giovec_t *auth_iov, int auth_iovcnt,
2022
         const giovec_t *iov, int iovcnt, void *tag,
2023
         size_t tag_size)
2024
0
{
2025
  /* Limitation: this function provides an optimization under the internally registered
2026
   * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
2027
   * then this becomes a convenience function as it missed the lower-level primitives
2028
   * necessary for piecemeal encryption. */
2029
0
  if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) ||
2030
0
      handle->ctx_enc.encrypt == NULL) {
2031
0
    return aead_cipher_decryptv2_fallback(handle, nonce, nonce_len,
2032
0
                  auth_iov, auth_iovcnt,
2033
0
                  iov, iovcnt, tag,
2034
0
                  tag_size);
2035
0
  } else {
2036
0
    return aead_cipher_decryptv2(handle, nonce, nonce_len, auth_iov,
2037
0
               auth_iovcnt, iov, iovcnt, tag,
2038
0
               tag_size);
2039
0
  }
2040
0
}
2041
2042
/**
2043
 * gnutls_aead_cipher_deinit:
2044
 * @handle: is a #gnutls_aead_cipher_hd_t type.
2045
 *
2046
 * This function will deinitialize all resources occupied by the given
2047
 * authenticated-encryption context.
2048
 *
2049
 * Since: 3.4.0
2050
 **/
2051
void gnutls_aead_cipher_deinit(gnutls_aead_cipher_hd_t handle)
2052
0
{
2053
0
  _gnutls_aead_cipher_deinit(handle);
2054
0
  gnutls_free(handle);
2055
0
}
2056
2057
extern gnutls_crypto_kdf_st _gnutls_kdf_ops;
2058
2059
/* Same as @gnutls_hkdf_extract but without changing FIPS context */
2060
int _gnutls_hkdf_extract(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key,
2061
       const gnutls_datum_t *salt, void *output)
2062
0
{
2063
  /* MD5 is only allowed internally for TLS */
2064
0
  if (!is_mac_algo_allowed(mac)) {
2065
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
2066
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
2067
0
  }
2068
2069
  /* We don't check whether MAC is approved, because HKDF is
2070
   * only approved in TLS, which is handled separately. */
2071
2072
0
  return _gnutls_kdf_ops.hkdf_extract(mac, key->data, key->size,
2073
0
              salt ? salt->data : NULL,
2074
0
              salt ? salt->size : 0, output);
2075
0
}
2076
2077
/**
2078
 * gnutls_hkdf_extract:
2079
 * @mac: the mac algorithm used internally
2080
 * @key: the initial keying material
2081
 * @salt: the optional salt
2082
 * @output: the output value of the extract operation
2083
 *
2084
 * This function will derive a fixed-size key using the HKDF-Extract
2085
 * function as defined in RFC 5869.
2086
 *
2087
 * Returns: Zero or a negative error code on error.
2088
 *
2089
 * Since: 3.6.13
2090
 */
2091
int gnutls_hkdf_extract(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key,
2092
      const gnutls_datum_t *salt, void *output)
2093
0
{
2094
0
  int ret;
2095
2096
0
  ret = _gnutls_hkdf_extract(mac, key, salt, output);
2097
0
  if (ret < 0)
2098
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
2099
0
  else
2100
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
2101
2102
0
  return ret;
2103
0
}
2104
2105
/* Same as @gnutls_hkdf_expand but without changing FIPS context */
2106
int _gnutls_hkdf_expand(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key,
2107
      const gnutls_datum_t *info, void *output, size_t length)
2108
0
{
2109
  /* MD5 is only allowed internally for TLS */
2110
0
  if (!is_mac_algo_allowed(mac)) {
2111
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
2112
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
2113
0
  }
2114
2115
  /* We don't check whether MAC is approved, because HKDF is
2116
   * only approved in TLS, which is handled separately. */
2117
2118
0
  return _gnutls_kdf_ops.hkdf_expand(mac, key->data, key->size,
2119
0
             info->data, info->size, output,
2120
0
             length);
2121
0
}
2122
2123
/**
2124
 * gnutls_hkdf_expand:
2125
 * @mac: the mac algorithm used internally
2126
 * @key: the pseudorandom key created with HKDF-Extract
2127
 * @info: the optional informational data
2128
 * @output: the output value of the expand operation
2129
 * @length: the desired length of the output key
2130
 *
2131
 * This function will derive a variable length keying material from
2132
 * the pseudorandom key using the HKDF-Expand function as defined in
2133
 * RFC 5869.
2134
 *
2135
 * Returns: Zero or a negative error code on error.
2136
 *
2137
 * Since: 3.6.13
2138
 */
2139
int gnutls_hkdf_expand(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key,
2140
           const gnutls_datum_t *info, void *output, size_t length)
2141
0
{
2142
0
  int ret;
2143
2144
0
  ret = _gnutls_hkdf_expand(mac, key, info, output, length);
2145
0
  if (ret < 0)
2146
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
2147
0
  else
2148
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
2149
2150
0
  return ret;
2151
0
}
2152
2153
/**
2154
 * gnutls_pbkdf2:
2155
 * @mac: the mac algorithm used internally
2156
 * @key: the initial keying material
2157
 * @salt: the salt
2158
 * @iter_count: the iteration count
2159
 * @output: the output value
2160
 * @length: the desired length of the output key
2161
 *
2162
 * This function will derive a variable length keying material from
2163
 * a password according to PKCS #5 PBKDF2.
2164
 *
2165
 * Returns: Zero or a negative error code on error.
2166
 *
2167
 * Since: 3.6.13
2168
 */
2169
int gnutls_pbkdf2(gnutls_mac_algorithm_t mac, const gnutls_datum_t *key,
2170
      const gnutls_datum_t *salt, unsigned iter_count, void *output,
2171
      size_t length)
2172
0
{
2173
0
  int ret;
2174
0
  bool not_approved = false;
2175
2176
  /* MD5 is only allowed internally for TLS */
2177
0
  if (!is_mac_algo_allowed(mac)) {
2178
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
2179
0
    return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
2180
0
  } else if (!is_mac_algo_hmac_approved_in_fips(mac)) {
2181
    /* ACVP only allows HMAC used with PBKDF2:
2182
     * https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html
2183
     */
2184
0
    not_approved = true;
2185
0
  }
2186
2187
  /* Key lengths and output sizes of less than 112 bits are not approved */
2188
0
  if (key->size < 14 || length < 14) {
2189
0
    not_approved = true;
2190
0
  }
2191
2192
  /* Minimum salt length of 128 bits (SP 800-132 5.1) */
2193
0
  if (salt->size < 16) {
2194
0
    not_approved = true;
2195
0
  }
2196
2197
  /* Minimum iterations bound (SP 800-132 5.2) */
2198
0
  if (iter_count < 1000) {
2199
0
    not_approved = true;
2200
0
  }
2201
2202
0
  ret = _gnutls_kdf_ops.pbkdf2(mac, key->data, key->size, salt->data,
2203
0
             salt->size, iter_count, output, length);
2204
0
  if (ret < 0) {
2205
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
2206
0
  } else if (not_approved) {
2207
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
2208
0
  } else {
2209
0
    _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
2210
0
  }
2211
0
  return ret;
2212
0
}