Coverage Report

Created: 2023-03-26 07:33

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