Line data Source code
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 :
36 : typedef struct api_cipher_hd_st {
37 : cipher_hd_st ctx_enc;
38 : cipher_hd_st ctx_dec;
39 : } api_cipher_hd_st;
40 :
41 : /**
42 : * gnutls_cipher_init:
43 : * @handle: is a #gnutls_cipher_hd_t type
44 : * @cipher: the encryption algorithm to use
45 : * @key: the key to be used for encryption/decryption
46 : * @iv: the IV to use (if not applicable set NULL)
47 : *
48 : * This function will initialize the @handle context to be usable
49 : * for encryption/decryption of data. This will effectively use the
50 : * current crypto backend in use by gnutls or the cryptographic
51 : * accelerator in use.
52 : *
53 : * Returns: Zero or a negative error code on error.
54 : *
55 : * Since: 2.10.0
56 : **/
57 : int
58 842 : 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 : {
62 842 : api_cipher_hd_st *h;
63 842 : int ret;
64 842 : const cipher_entry_st* e;
65 :
66 842 : if (is_cipher_algo_forbidden(cipher))
67 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
68 :
69 842 : e = cipher_to_entry(cipher);
70 842 : if (e == NULL || (e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD))
71 8 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
72 :
73 834 : h = gnutls_calloc(1, sizeof(api_cipher_hd_st));
74 834 : if (h == NULL) {
75 0 : gnutls_assert();
76 0 : return GNUTLS_E_MEMORY_ERROR;
77 : }
78 :
79 834 : ret =
80 834 : _gnutls_cipher_init(&h->ctx_enc, e, key,
81 : iv, 1);
82 834 : if (ret < 0) {
83 0 : gnutls_free(h);
84 0 : return ret;
85 : }
86 :
87 834 : if (_gnutls_cipher_type(e) == CIPHER_BLOCK) {
88 686 : ret =
89 686 : _gnutls_cipher_init(&h->ctx_dec, e, key, iv, 0);
90 686 : if (ret < 0) {
91 0 : gnutls_free(h);
92 0 : return ret;
93 : }
94 : }
95 :
96 834 : *handle = h;
97 :
98 834 : return ret;
99 : }
100 :
101 : /**
102 : * gnutls_cipher_tag:
103 : * @handle: is a #gnutls_cipher_hd_t type
104 : * @tag: will hold the tag
105 : * @tag_size: the length of the tag to return
106 : *
107 : * This function operates on authenticated encryption with
108 : * associated data (AEAD) ciphers and will return the
109 : * output tag.
110 : *
111 : * Returns: Zero or a negative error code on error.
112 : *
113 : * Since: 3.0
114 : **/
115 : int
116 12 : gnutls_cipher_tag(gnutls_cipher_hd_t handle, void *tag, size_t tag_size)
117 : {
118 12 : api_cipher_hd_st *h = handle;
119 :
120 12 : if (_gnutls_cipher_is_aead(&h->ctx_enc) == 0)
121 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
122 :
123 12 : _gnutls_cipher_tag(&h->ctx_enc, tag, tag_size);
124 :
125 : return 0;
126 : }
127 :
128 : /**
129 : * gnutls_cipher_add_auth:
130 : * @handle: is a #gnutls_cipher_hd_t type
131 : * @ptext: the data to be authenticated
132 : * @ptext_size: the length of the data
133 : *
134 : * This function operates on authenticated encryption with
135 : * associated data (AEAD) ciphers and authenticate the
136 : * input data. This function can only be called once
137 : * and before any encryption operations.
138 : *
139 : * Returns: Zero or a negative error code on error.
140 : *
141 : * Since: 3.0
142 : **/
143 : int
144 18 : gnutls_cipher_add_auth(gnutls_cipher_hd_t handle, const void *ptext,
145 : size_t ptext_size)
146 : {
147 18 : api_cipher_hd_st *h = handle;
148 :
149 18 : if (_gnutls_cipher_is_aead(&h->ctx_enc) == 0)
150 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
151 :
152 18 : return _gnutls_cipher_auth(&h->ctx_enc, ptext, ptext_size);
153 : }
154 :
155 : /**
156 : * gnutls_cipher_set_iv:
157 : * @handle: is a #gnutls_cipher_hd_t type
158 : * @iv: the IV to set
159 : * @ivlen: the length of the IV
160 : *
161 : * This function will set the IV to be used for the next
162 : * encryption block.
163 : *
164 : * Since: 3.0
165 : **/
166 : void
167 270 : gnutls_cipher_set_iv(gnutls_cipher_hd_t handle, void *iv, size_t ivlen)
168 : {
169 270 : api_cipher_hd_st *h = handle;
170 :
171 270 : if (_gnutls_cipher_setiv(&h->ctx_enc, iv, ivlen) < 0) {
172 0 : _gnutls_switch_lib_state(LIB_STATE_ERROR);
173 : }
174 :
175 270 : if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK)
176 140 : if (_gnutls_cipher_setiv(&h->ctx_dec, iv, ivlen) < 0) {
177 0 : _gnutls_switch_lib_state(LIB_STATE_ERROR);
178 : }
179 270 : }
180 :
181 : /*-
182 : * _gnutls_cipher_get_iv:
183 : * @handle: is a #gnutls_cipher_hd_t type
184 : * @iv: the IV to set
185 : * @ivlen: the length of the IV
186 : *
187 : * This function will retrieve the internally calculated IV value. It is
188 : * intended to be used for modes like CFB. @iv must have @ivlen length
189 : * at least.
190 : *
191 : * This is solely for validation purposes of our crypto
192 : * implementation. For other purposes, the IV can be typically
193 : * calculated from the initial IV value and the subsequent ciphertext
194 : * values. As such, this function only works with the internally
195 : * registered ciphers.
196 : *
197 : * Returns: The length of IV or a negative error code on error.
198 : *
199 : * Since: 3.6.8
200 : -*/
201 : int
202 15 : _gnutls_cipher_get_iv(gnutls_cipher_hd_t handle, void *iv, size_t ivlen)
203 : {
204 15 : api_cipher_hd_st *h = handle;
205 :
206 15 : return _gnutls_cipher_getiv(&h->ctx_enc, iv, ivlen);
207 : }
208 :
209 : /*-
210 : * _gnutls_cipher_set_key:
211 : * @handle: is a #gnutls_cipher_hd_t type
212 : * @key: the key to set
213 : * @keylen: the length of the key
214 : *
215 : * This function will set the key used by the cipher
216 : *
217 : * This is solely for validation purposes of our crypto
218 : * implementation. For other purposes, the key should be set at the time of
219 : * cipher setup. As such, this function only works with the internally
220 : * registered ciphers.
221 : *
222 : * Returns: Zero or a negative error code on error.
223 : *
224 : * Since: 3.6.14
225 : -*/
226 : int
227 20 : _gnutls_cipher_set_key(gnutls_cipher_hd_t handle, void *key, size_t keylen)
228 : {
229 20 : api_cipher_hd_st *h = handle;
230 :
231 20 : return _gnutls_cipher_setkey(&h->ctx_enc, key, keylen);
232 : }
233 :
234 : /**
235 : * gnutls_cipher_encrypt:
236 : * @handle: is a #gnutls_cipher_hd_t type
237 : * @ptext: the data to encrypt
238 : * @ptext_len: the length of data to encrypt
239 : *
240 : * This function will encrypt the given data using the algorithm
241 : * specified by the context.
242 : *
243 : * Returns: Zero or a negative error code on error.
244 : *
245 : * Since: 2.10.0
246 : **/
247 : int
248 139 : gnutls_cipher_encrypt(gnutls_cipher_hd_t handle, void *ptext,
249 : size_t ptext_len)
250 : {
251 139 : api_cipher_hd_st *h = handle;
252 :
253 139 : return _gnutls_cipher_encrypt(&h->ctx_enc, ptext, ptext_len);
254 : }
255 :
256 : /**
257 : * gnutls_cipher_decrypt:
258 : * @handle: is a #gnutls_cipher_hd_t type
259 : * @ctext: the data to decrypt
260 : * @ctext_len: the length of data to decrypt
261 : *
262 : * This function will decrypt the given data using the algorithm
263 : * specified by the context.
264 : *
265 : * Note that in AEAD ciphers, this will not check the tag. You will
266 : * need to compare the tag sent with the value returned from gnutls_cipher_tag().
267 : *
268 : * Returns: Zero or a negative error code on error.
269 : *
270 : * Since: 2.10.0
271 : **/
272 : int
273 133 : gnutls_cipher_decrypt(gnutls_cipher_hd_t handle, void *ctext,
274 : size_t ctext_len)
275 : {
276 133 : api_cipher_hd_st *h = handle;
277 :
278 133 : if (_gnutls_cipher_type(h->ctx_enc.e) != CIPHER_BLOCK)
279 120 : return _gnutls_cipher_decrypt(&h->ctx_enc, ctext,
280 : ctext_len);
281 : else
282 146 : return _gnutls_cipher_decrypt(&h->ctx_dec, ctext,
283 : ctext_len);
284 : }
285 :
286 : /**
287 : * gnutls_cipher_encrypt2:
288 : * @handle: is a #gnutls_cipher_hd_t type
289 : * @ptext: the data to encrypt
290 : * @ptext_len: the length of data to encrypt
291 : * @ctext: the encrypted data
292 : * @ctext_len: the available length for encrypted data
293 : *
294 : * This function will encrypt the given data using the algorithm
295 : * specified by the context. For block ciphers the @ptext_len must be
296 : * a multiple of the block size. For the supported ciphers the encrypted
297 : * data length will equal the plaintext size.
298 : *
299 : * Returns: Zero or a negative error code on error.
300 : *
301 : * Since: 2.12.0
302 : **/
303 : int
304 1197 : gnutls_cipher_encrypt2(gnutls_cipher_hd_t handle, const void *ptext,
305 : size_t ptext_len, void *ctext,
306 : size_t ctext_len)
307 : {
308 1197 : api_cipher_hd_st *h = handle;
309 :
310 1197 : return _gnutls_cipher_encrypt2(&h->ctx_enc, ptext, ptext_len,
311 : ctext, ctext_len);
312 : }
313 :
314 : /**
315 : * gnutls_cipher_decrypt2:
316 : * @handle: is a #gnutls_cipher_hd_t type
317 : * @ctext: the data to decrypt
318 : * @ctext_len: the length of data to decrypt
319 : * @ptext: the decrypted data
320 : * @ptext_len: the available length for decrypted data
321 : *
322 : * This function will decrypt the given data using the algorithm
323 : * specified by the context. For block ciphers the @ctext_len must be
324 : * a multiple of the block size. For the supported ciphers the plaintext
325 : * data length will equal the ciphertext size.
326 : *
327 : * Note that in AEAD ciphers, this will not check the tag. You will
328 : * need to compare the tag sent with the value returned from gnutls_cipher_tag().
329 : *
330 : * Returns: Zero or a negative error code on error.
331 : *
332 : * Since: 2.12.0
333 : **/
334 : int
335 1015 : gnutls_cipher_decrypt2(gnutls_cipher_hd_t handle, const void *ctext,
336 : size_t ctext_len, void *ptext, size_t ptext_len)
337 : {
338 1015 : api_cipher_hd_st *h = handle;
339 :
340 1015 : if (_gnutls_cipher_type(h->ctx_enc.e) != CIPHER_BLOCK)
341 150 : return _gnutls_cipher_decrypt2(&h->ctx_enc, ctext,
342 : ctext_len, ptext,
343 : ptext_len);
344 : else
345 1880 : return _gnutls_cipher_decrypt2(&h->ctx_dec, ctext,
346 : ctext_len, ptext,
347 : ptext_len);
348 : }
349 :
350 : /**
351 : * gnutls_cipher_deinit:
352 : * @handle: is a #gnutls_cipher_hd_t type
353 : *
354 : * This function will deinitialize all resources occupied by the given
355 : * encryption context.
356 : *
357 : * Since: 2.10.0
358 : **/
359 834 : void gnutls_cipher_deinit(gnutls_cipher_hd_t handle)
360 : {
361 834 : api_cipher_hd_st *h = handle;
362 :
363 834 : _gnutls_cipher_deinit(&h->ctx_enc);
364 834 : if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK)
365 686 : _gnutls_cipher_deinit(&h->ctx_dec);
366 834 : gnutls_free(handle);
367 834 : }
368 :
369 :
370 : /* HMAC */
371 :
372 :
373 : /**
374 : * gnutls_hmac_init:
375 : * @dig: is a #gnutls_hmac_hd_t type
376 : * @algorithm: the HMAC algorithm to use
377 : * @key: the key to be used for encryption
378 : * @keylen: the length of the key
379 : *
380 : * This function will initialize an context that can be used to
381 : * produce a Message Authentication Code (MAC) of data. This will
382 : * effectively use the current crypto backend in use by gnutls or the
383 : * cryptographic accelerator in use.
384 : *
385 : * Note that despite the name of this function, it can be used
386 : * for other MAC algorithms than HMAC.
387 : *
388 : * Returns: Zero or a negative error code on error.
389 : *
390 : * Since: 2.10.0
391 : **/
392 : int
393 65 : gnutls_hmac_init(gnutls_hmac_hd_t * dig,
394 : gnutls_mac_algorithm_t algorithm,
395 : const void *key, size_t keylen)
396 : {
397 : /* MD5 is only allowed internally for TLS */
398 65 : if (is_mac_algo_forbidden(algorithm))
399 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
400 :
401 65 : *dig = gnutls_malloc(sizeof(mac_hd_st));
402 65 : if (*dig == NULL) {
403 0 : gnutls_assert();
404 0 : return GNUTLS_E_MEMORY_ERROR;
405 : }
406 :
407 65 : return _gnutls_mac_init(((mac_hd_st *) * dig),
408 : mac_to_entry(algorithm), key, keylen);
409 : }
410 :
411 : /**
412 : * gnutls_hmac_set_nonce:
413 : * @handle: is a #gnutls_hmac_hd_t type
414 : * @nonce: the data to set as nonce
415 : * @nonce_len: the length of data
416 : *
417 : * This function will set the nonce in the MAC algorithm.
418 : *
419 : * Since: 3.2.0
420 : **/
421 : void
422 6 : gnutls_hmac_set_nonce(gnutls_hmac_hd_t handle, const void *nonce,
423 : size_t nonce_len)
424 : {
425 6 : _gnutls_mac_set_nonce((mac_hd_st *) handle, nonce, nonce_len);
426 6 : }
427 :
428 : /**
429 : * gnutls_hmac:
430 : * @handle: is a #gnutls_hmac_hd_t type
431 : * @ptext: the data to hash
432 : * @ptext_len: the length of data to hash
433 : *
434 : * This function will hash the given data using the algorithm
435 : * specified by the context.
436 : *
437 : * Returns: Zero or a negative error code on error.
438 : *
439 : * Since: 2.10.0
440 : **/
441 216 : int gnutls_hmac(gnutls_hmac_hd_t handle, const void *ptext, size_t ptext_len)
442 : {
443 216 : return _gnutls_mac((mac_hd_st *) handle, ptext, ptext_len);
444 : }
445 :
446 : /**
447 : * gnutls_hmac_output:
448 : * @handle: is a #gnutls_hmac_hd_t type
449 : * @digest: is the output value of the MAC
450 : *
451 : * This function will output the current MAC value
452 : * and reset the state of the MAC.
453 : *
454 : * Since: 2.10.0
455 : **/
456 0 : void gnutls_hmac_output(gnutls_hmac_hd_t handle, void *digest)
457 : {
458 0 : _gnutls_mac_output((mac_hd_st *) handle, digest);
459 0 : }
460 :
461 : /**
462 : * gnutls_hmac_deinit:
463 : * @handle: is a #gnutls_hmac_hd_t type
464 : * @digest: is the output value of the MAC
465 : *
466 : * This function will deinitialize all resources occupied by
467 : * the given hmac context.
468 : *
469 : * Since: 2.10.0
470 : **/
471 99 : void gnutls_hmac_deinit(gnutls_hmac_hd_t handle, void *digest)
472 : {
473 99 : _gnutls_mac_deinit((mac_hd_st *) handle, digest);
474 99 : gnutls_free(handle);
475 99 : }
476 :
477 : /**
478 : * gnutls_hmac_get_len:
479 : * @algorithm: the hmac algorithm to use
480 : *
481 : * This function will return the length of the output data
482 : * of the given hmac algorithm.
483 : *
484 : * Returns: The length or zero on error.
485 : *
486 : * Since: 2.10.0
487 : **/
488 36 : unsigned gnutls_hmac_get_len(gnutls_mac_algorithm_t algorithm)
489 : {
490 36 : return _gnutls_mac_get_algo_len(mac_to_entry(algorithm));
491 : }
492 :
493 : /**
494 : * gnutls_hmac_get_key_size:
495 : * @algorithm: the mac algorithm to use
496 : *
497 : * This function will return the size of the key to be used with this
498 : * algorithm. On the algorithms which may accept arbitrary key sizes,
499 : * the returned size is the MAC key size used in the TLS protocol.
500 : *
501 : * Returns: The key size or zero on error.
502 : *
503 : * Since: 3.6.12
504 : **/
505 0 : unsigned gnutls_hmac_get_key_size(gnutls_mac_algorithm_t algorithm)
506 : {
507 0 : return _gnutls_mac_get_key_size(mac_to_entry(algorithm));
508 : }
509 :
510 : /**
511 : * gnutls_hmac_fast:
512 : * @algorithm: the hash algorithm to use
513 : * @key: the key to use
514 : * @keylen: the length of the key
515 : * @ptext: the data to hash
516 : * @ptext_len: the length of data to hash
517 : * @digest: is the output value of the hash
518 : *
519 : * This convenience function will hash the given data and return output
520 : * on a single call. Note, this call will not work for MAC algorithms
521 : * that require nonce (like UMAC or GMAC).
522 : *
523 : * Returns: Zero or a negative error code on error.
524 : *
525 : * Since: 2.10.0
526 : **/
527 : int
528 26600 : gnutls_hmac_fast(gnutls_mac_algorithm_t algorithm,
529 : const void *key, size_t keylen,
530 : const void *ptext, size_t ptext_len, void *digest)
531 : {
532 26600 : if (is_mac_algo_forbidden(algorithm))
533 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
534 :
535 26600 : return _gnutls_mac_fast(algorithm, key, keylen, ptext, ptext_len,
536 : digest);
537 : }
538 :
539 : /**
540 : * gnutls_hmac_copy:
541 : * @handle: is a #gnutls_hmac_hd_t type
542 : *
543 : * This function will create a copy of MAC context, containing all its current
544 : * state. Copying contexts for MACs registered using
545 : * gnutls_crypto_register_mac() is not supported and will always result in an
546 : * error.
547 : *
548 : * Returns: new MAC context or NULL in case of an error.
549 : *
550 : * Since: 3.6.9
551 : */
552 36 : gnutls_hmac_hd_t gnutls_hmac_copy(gnutls_hmac_hd_t handle)
553 : {
554 36 : gnutls_hmac_hd_t dig;
555 :
556 36 : dig = gnutls_malloc(sizeof(mac_hd_st));
557 36 : if (dig == NULL) {
558 0 : gnutls_assert();
559 0 : return NULL;
560 : }
561 :
562 36 : if (_gnutls_mac_copy((const mac_hd_st *) handle, (mac_hd_st *)dig) != GNUTLS_E_SUCCESS) {
563 2 : gnutls_assert();
564 2 : gnutls_free(dig);
565 2 : return NULL;
566 : }
567 :
568 : return dig;
569 : }
570 :
571 : /* HASH */
572 :
573 : /**
574 : * gnutls_hash_init:
575 : * @dig: is a #gnutls_hash_hd_t type
576 : * @algorithm: the hash algorithm to use
577 : *
578 : * This function will initialize an context that can be used to
579 : * produce a Message Digest of data. This will effectively use the
580 : * current crypto backend in use by gnutls or the cryptographic
581 : * accelerator in use.
582 : *
583 : * Returns: Zero or a negative error code on error.
584 : *
585 : * Since: 2.10.0
586 : **/
587 : int
588 112 : gnutls_hash_init(gnutls_hash_hd_t * dig,
589 : gnutls_digest_algorithm_t algorithm)
590 : {
591 112 : if (is_mac_algo_forbidden(DIG_TO_MAC(algorithm)))
592 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
593 :
594 112 : *dig = gnutls_malloc(sizeof(digest_hd_st));
595 112 : if (*dig == NULL) {
596 0 : gnutls_assert();
597 0 : return GNUTLS_E_MEMORY_ERROR;
598 : }
599 :
600 112 : return _gnutls_hash_init(((digest_hd_st *) * dig),
601 : hash_to_entry(algorithm));
602 : }
603 :
604 : /**
605 : * gnutls_hash:
606 : * @handle: is a #gnutls_hash_hd_t type
607 : * @ptext: the data to hash
608 : * @ptext_len: the length of data to hash
609 : *
610 : * This function will hash the given data using the algorithm
611 : * specified by the context.
612 : *
613 : * Returns: Zero or a negative error code on error.
614 : *
615 : * Since: 2.10.0
616 : **/
617 131326 : int gnutls_hash(gnutls_hash_hd_t handle, const void *ptext, size_t ptext_len)
618 : {
619 131326 : return _gnutls_hash((digest_hd_st *) handle, ptext, ptext_len);
620 : }
621 :
622 : /**
623 : * gnutls_hash_output:
624 : * @handle: is a #gnutls_hash_hd_t type
625 : * @digest: is the output value of the hash
626 : *
627 : * This function will output the current hash value
628 : * and reset the state of the hash.
629 : *
630 : * Since: 2.10.0
631 : **/
632 2 : void gnutls_hash_output(gnutls_hash_hd_t handle, void *digest)
633 : {
634 4 : _gnutls_hash_output((digest_hd_st *) handle, digest);
635 2 : }
636 :
637 : /**
638 : * gnutls_hash_deinit:
639 : * @handle: is a #gnutls_hash_hd_t type
640 : * @digest: is the output value of the hash
641 : *
642 : * This function will deinitialize all resources occupied by
643 : * the given hash context.
644 : *
645 : * Since: 2.10.0
646 : **/
647 144 : void gnutls_hash_deinit(gnutls_hash_hd_t handle, void *digest)
648 : {
649 144 : _gnutls_hash_deinit((digest_hd_st *) handle, digest);
650 144 : gnutls_free(handle);
651 144 : }
652 :
653 : /**
654 : * gnutls_hash_get_len:
655 : * @algorithm: the hash algorithm to use
656 : *
657 : * This function will return the length of the output data
658 : * of the given hash algorithm.
659 : *
660 : * Returns: The length or zero on error.
661 : *
662 : * Since: 2.10.0
663 : **/
664 299 : unsigned gnutls_hash_get_len(gnutls_digest_algorithm_t algorithm)
665 : {
666 299 : return _gnutls_hash_get_algo_len(hash_to_entry(algorithm));
667 : }
668 :
669 : /**
670 : * gnutls_hash_fast:
671 : * @algorithm: the hash algorithm to use
672 : * @ptext: the data to hash
673 : * @ptext_len: the length of data to hash
674 : * @digest: is the output value of the hash
675 : *
676 : * This convenience function will hash the given data and return output
677 : * on a single call.
678 : *
679 : * Returns: Zero or a negative error code on error.
680 : *
681 : * Since: 2.10.0
682 : **/
683 : int
684 77051 : gnutls_hash_fast(gnutls_digest_algorithm_t algorithm,
685 : const void *ptext, size_t ptext_len, void *digest)
686 : {
687 77051 : if (is_mac_algo_forbidden(DIG_TO_MAC(algorithm)))
688 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
689 :
690 77051 : return _gnutls_hash_fast(algorithm, ptext, ptext_len, digest);
691 : }
692 :
693 : /**
694 : * gnutls_hash_copy:
695 : * @handle: is a #gnutls_hash_hd_t type
696 : *
697 : * This function will create a copy of Message Digest context, containing all
698 : * its current state. Copying contexts for Message Digests registered using
699 : * gnutls_crypto_register_digest() is not supported and will always result in
700 : * an error.
701 : *
702 : * Returns: new Message Digest context or NULL in case of an error.
703 : *
704 : * Since: 3.6.9
705 : */
706 36 : gnutls_hash_hd_t gnutls_hash_copy(gnutls_hash_hd_t handle)
707 : {
708 36 : gnutls_hash_hd_t dig;
709 :
710 36 : dig = gnutls_malloc(sizeof(digest_hd_st));
711 36 : if (dig == NULL) {
712 0 : gnutls_assert();
713 0 : return NULL;
714 : }
715 :
716 36 : if (_gnutls_hash_copy((const digest_hd_st *) handle, (digest_hd_st *)dig) != GNUTLS_E_SUCCESS) {
717 4 : gnutls_assert();
718 4 : gnutls_free(dig);
719 4 : return NULL;
720 : }
721 :
722 : return dig;
723 : }
724 :
725 : /**
726 : * gnutls_key_generate:
727 : * @key: is a pointer to a #gnutls_datum_t which will contain a newly
728 : * created key
729 : * @key_size: the number of bytes of the key
730 : *
731 : * Generates a random key of @key_size bytes.
732 : *
733 : * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
734 : * error code.
735 : *
736 : * Since: 3.0
737 : **/
738 685 : int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size)
739 : {
740 685 : int ret;
741 :
742 685 : FAIL_IF_LIB_ERROR;
743 :
744 : #ifdef ENABLE_FIPS140
745 : /* The FIPS140 approved RNGs are not allowed to be used
746 : * to extract key sizes longer than their original seed.
747 : */
748 : if (_gnutls_fips_mode_enabled() != 0 &&
749 : key_size > FIPS140_RND_KEY_SIZE)
750 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
751 : #endif
752 :
753 685 : key->size = key_size;
754 685 : key->data = gnutls_malloc(key->size);
755 685 : if (!key->data) {
756 0 : gnutls_assert();
757 0 : return GNUTLS_E_MEMORY_ERROR;
758 : }
759 :
760 685 : ret = gnutls_rnd(GNUTLS_RND_RANDOM, key->data, key->size);
761 685 : if (ret < 0) {
762 0 : gnutls_assert();
763 0 : _gnutls_free_datum(key);
764 0 : return ret;
765 : }
766 :
767 : return 0;
768 : }
769 :
770 : /* AEAD API */
771 :
772 : /**
773 : * gnutls_aead_cipher_init:
774 : * @handle: is a #gnutls_aead_cipher_hd_t type.
775 : * @cipher: the authenticated-encryption algorithm to use
776 : * @key: The key to be used for encryption
777 : *
778 : * This function will initialize an context that can be used for
779 : * encryption/decryption of data. This will effectively use the
780 : * current crypto backend in use by gnutls or the cryptographic
781 : * accelerator in use.
782 : *
783 : * Returns: Zero or a negative error code on error.
784 : *
785 : * Since: 3.4.0
786 : **/
787 541 : int gnutls_aead_cipher_init(gnutls_aead_cipher_hd_t *handle,
788 : gnutls_cipher_algorithm_t cipher,
789 : const gnutls_datum_t *key)
790 : {
791 541 : api_aead_cipher_hd_st *h;
792 541 : const cipher_entry_st *e;
793 541 : int ret;
794 :
795 541 : if (is_cipher_algo_forbidden(cipher))
796 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
797 :
798 541 : e = cipher_to_entry(cipher);
799 541 : if (e == NULL || e->type != CIPHER_AEAD)
800 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
801 :
802 541 : h = gnutls_calloc(1, sizeof(api_aead_cipher_hd_st));
803 541 : if (h == NULL) {
804 0 : gnutls_assert();
805 0 : return GNUTLS_E_MEMORY_ERROR;
806 : }
807 :
808 541 : ret = _gnutls_aead_cipher_init(h, cipher, key);
809 541 : if (ret < 0) {
810 0 : gnutls_free(h);
811 0 : return ret;
812 : }
813 :
814 541 : *handle = h;
815 :
816 541 : return ret;
817 : }
818 :
819 : /**
820 : * gnutls_aead_cipher_decrypt:
821 : * @handle: is a #gnutls_aead_cipher_hd_t type.
822 : * @nonce: the nonce to set
823 : * @nonce_len: The length of the nonce
824 : * @auth: additional data to be authenticated
825 : * @auth_len: The length of the data
826 : * @tag_size: The size of the tag to use (use zero for the default)
827 : * @ctext: the data to decrypt (including the authentication tag)
828 : * @ctext_len: the length of data to decrypt (includes tag size)
829 : * @ptext: the decrypted data
830 : * @ptext_len: the length of decrypted data (initially must hold the maximum available size)
831 : *
832 : * This function will decrypt the given data using the algorithm
833 : * specified by the context. This function must be provided the complete
834 : * data to be decrypted, including the authentication tag. On several
835 : * AEAD ciphers, the authentication tag is appended to the ciphertext,
836 : * though this is not a general rule. This function will fail if
837 : * the tag verification fails.
838 : *
839 : * Returns: Zero or a negative error code on verification failure or other error.
840 : *
841 : * Since: 3.4.0
842 : **/
843 : int
844 430699 : gnutls_aead_cipher_decrypt(gnutls_aead_cipher_hd_t handle,
845 : const void *nonce, size_t nonce_len,
846 : const void *auth, size_t auth_len,
847 : size_t tag_size,
848 : const void *ctext, size_t ctext_len,
849 : void *ptext, size_t *ptext_len)
850 : {
851 430699 : int ret;
852 430699 : api_aead_cipher_hd_st *h = handle;
853 :
854 430699 : if (tag_size == 0)
855 0 : tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
856 861398 : else if (tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e))
857 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
858 :
859 430699 : if (unlikely(ctext_len < tag_size))
860 0 : return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
861 :
862 430699 : ret = _gnutls_aead_cipher_decrypt(&h->ctx_enc,
863 : nonce, nonce_len,
864 : auth, auth_len,
865 : tag_size,
866 : ctext, ctext_len,
867 : ptext, *ptext_len);
868 430699 : if (unlikely(ret < 0))
869 124 : return gnutls_assert_val(ret);
870 :
871 : /* That assumes that AEAD ciphers are stream */
872 430589 : *ptext_len = ctext_len - tag_size;
873 :
874 430589 : return 0;
875 : }
876 :
877 :
878 : /**
879 : * gnutls_aead_cipher_encrypt:
880 : * @handle: is a #gnutls_aead_cipher_hd_t type.
881 : * @nonce: the nonce to set
882 : * @nonce_len: The length of the nonce
883 : * @auth: additional data to be authenticated
884 : * @auth_len: The length of the data
885 : * @tag_size: The size of the tag to use (use zero for the default)
886 : * @ptext: the data to encrypt
887 : * @ptext_len: The length of data to encrypt
888 : * @ctext: the encrypted data including authentication tag
889 : * @ctext_len: the length of encrypted data (initially must hold the maximum available size, including space for tag)
890 : *
891 : * This function will encrypt the given data using the algorithm
892 : * specified by the context. The output data will contain the
893 : * authentication tag.
894 : *
895 : * Returns: Zero or a negative error code on error.
896 : *
897 : * Since: 3.4.0
898 : **/
899 : int
900 33402 : gnutls_aead_cipher_encrypt(gnutls_aead_cipher_hd_t handle,
901 : const void *nonce, size_t nonce_len,
902 : const void *auth, size_t auth_len,
903 : size_t tag_size,
904 : const void *ptext, size_t ptext_len,
905 : void *ctext, size_t *ctext_len)
906 : {
907 33402 : api_aead_cipher_hd_st *h = handle;
908 33402 : int ret;
909 :
910 33402 : if (tag_size == 0)
911 0 : tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
912 66804 : else if (tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e))
913 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
914 :
915 33402 : if (unlikely(*ctext_len < ptext_len + tag_size))
916 0 : return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
917 :
918 33402 : ret = _gnutls_aead_cipher_encrypt(&h->ctx_enc,
919 : nonce, nonce_len,
920 : auth, auth_len,
921 : tag_size,
922 : ptext, ptext_len,
923 : ctext, *ctext_len);
924 33402 : if (unlikely(ret < 0))
925 0 : return gnutls_assert_val(ret);
926 :
927 : /* That assumes that AEAD ciphers are stream */
928 33402 : *ctext_len = ptext_len + tag_size;
929 :
930 33402 : return 0;
931 : }
932 :
933 : struct iov_store_st {
934 : void *data;
935 : size_t size;
936 : };
937 :
938 65876 : static void iov_store_free(struct iov_store_st *s)
939 : {
940 65876 : gnutls_free(s->data);
941 65876 : }
942 :
943 4 : static int iov_store_grow(struct iov_store_st *s, size_t length)
944 : {
945 4 : void *data;
946 :
947 4 : s->size += length;
948 4 : data = gnutls_realloc(s->data, s->size);
949 4 : if (data == NULL)
950 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
951 :
952 4 : s->data = data;
953 4 : return 0;
954 : }
955 :
956 : static int
957 65876 : copy_from_iov(struct iov_store_st *dst, const giovec_t *iov, int iovcnt)
958 : {
959 65876 : memset(dst, 0, sizeof(*dst));
960 65876 : if (iovcnt == 0) {
961 : return 0;
962 : } else {
963 65876 : int i;
964 65876 : uint8_t *p;
965 :
966 65876 : dst->size = 0;
967 164937 : for (i=0;i<iovcnt;i++)
968 99061 : dst->size += iov[i].iov_len;
969 65876 : dst->data = gnutls_malloc(dst->size);
970 65876 : if (dst->data == NULL)
971 0 : return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
972 :
973 : p = dst->data;
974 164937 : for (i=0;i<iovcnt;i++) {
975 99061 : if (iov[i].iov_len > 0)
976 99023 : memcpy(p, iov[i].iov_base, iov[i].iov_len);
977 99061 : p += iov[i].iov_len;
978 : }
979 :
980 : return 0;
981 : }
982 : }
983 :
984 : static int
985 4 : copy_to_iov(struct iov_store_st *src, size_t size,
986 : const giovec_t *iov, int iovcnt)
987 : {
988 4 : size_t offset = 0;
989 4 : int i;
990 :
991 4 : if (unlikely(src->size < size))
992 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
993 :
994 10 : for (i = 0; i < iovcnt && size > 0; i++) {
995 6 : size_t to_copy = MIN(size, iov[i].iov_len);
996 6 : memcpy(iov[i].iov_base, (uint8_t *) src->data + offset, to_copy);
997 6 : offset += to_copy;
998 6 : size -= to_copy;
999 : }
1000 4 : if (size > 0)
1001 0 : return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
1002 : return 0;
1003 : }
1004 :
1005 :
1006 : /**
1007 : * gnutls_aead_cipher_encryptv:
1008 : * @handle: is a #gnutls_aead_cipher_hd_t type.
1009 : * @nonce: the nonce to set
1010 : * @nonce_len: The length of the nonce
1011 : * @auth_iov: additional data to be authenticated
1012 : * @auth_iovcnt: The number of buffers in @auth_iov
1013 : * @tag_size: The size of the tag to use (use zero for the default)
1014 : * @iov: the data to be encrypted
1015 : * @iovcnt: The number of buffers in @iov
1016 : * @ctext: the encrypted data including authentication tag
1017 : * @ctext_len: the length of encrypted data (initially must hold the maximum available size, including space for tag)
1018 : *
1019 : * This function will encrypt the provided data buffers using the algorithm
1020 : * specified by the context. The output data will contain the
1021 : * authentication tag.
1022 : *
1023 : * Returns: Zero or a negative error code on error.
1024 : *
1025 : * Since: 3.6.3
1026 : **/
1027 : int
1028 451218 : gnutls_aead_cipher_encryptv(gnutls_aead_cipher_hd_t handle,
1029 : const void *nonce, size_t nonce_len,
1030 : const giovec_t *auth_iov, int auth_iovcnt,
1031 : size_t tag_size,
1032 : const giovec_t *iov, int iovcnt,
1033 : void *ctext, size_t *ctext_len)
1034 : {
1035 451218 : api_aead_cipher_hd_st *h = handle;
1036 451218 : ssize_t ret;
1037 451218 : uint8_t *dst;
1038 451218 : size_t dst_size, total = 0;
1039 451218 : uint8_t *p;
1040 451218 : size_t len;
1041 451218 : size_t blocksize = handle->ctx_enc.e->blocksize;
1042 451218 : struct iov_iter_st iter;
1043 :
1044 : /* Limitation: this function provides an optimization under the internally registered
1045 : * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
1046 : * then this becomes a convenience function as it missed the lower-level primitives
1047 : * necessary for piecemeal encryption. */
1048 :
1049 451218 : if (tag_size == 0)
1050 0 : tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
1051 902436 : else if (tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e))
1052 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1053 :
1054 451218 : if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) || handle->ctx_enc.encrypt == NULL) {
1055 : /* ciphertext cannot be produced in a piecemeal approach */
1056 32934 : struct iov_store_st auth;
1057 32934 : struct iov_store_st ptext;
1058 :
1059 32934 : ret = copy_from_iov(&auth, auth_iov, auth_iovcnt);
1060 32934 : if (ret < 0)
1061 0 : return gnutls_assert_val(ret);
1062 :
1063 32934 : ret = copy_from_iov(&ptext, iov, iovcnt);
1064 32934 : if (ret < 0) {
1065 0 : iov_store_free(&auth);
1066 0 : return gnutls_assert_val(ret);
1067 : }
1068 :
1069 65868 : ret = gnutls_aead_cipher_encrypt(handle, nonce, nonce_len,
1070 32934 : auth.data, auth.size,
1071 : tag_size,
1072 32934 : ptext.data, ptext.size,
1073 : ctext, ctext_len);
1074 32934 : iov_store_free(&auth);
1075 32934 : iov_store_free(&ptext);
1076 :
1077 32934 : return ret;
1078 : }
1079 :
1080 418284 : ret = _gnutls_cipher_setiv(&handle->ctx_enc, nonce, nonce_len);
1081 418284 : if (unlikely(ret < 0))
1082 0 : return gnutls_assert_val(ret);
1083 :
1084 418284 : ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
1085 418284 : if (unlikely(ret < 0))
1086 0 : return gnutls_assert_val(ret);
1087 836544 : while (1) {
1088 836544 : ret = _gnutls_iov_iter_next(&iter, &p);
1089 836544 : if (unlikely(ret < 0))
1090 0 : return gnutls_assert_val(ret);
1091 836544 : if (ret == 0)
1092 : break;
1093 418260 : ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
1094 418260 : if (unlikely(ret < 0))
1095 0 : return gnutls_assert_val(ret);
1096 : }
1097 :
1098 418284 : dst = ctext;
1099 418284 : dst_size = *ctext_len;
1100 :
1101 418284 : ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
1102 418284 : if (unlikely(ret < 0))
1103 0 : return gnutls_assert_val(ret);
1104 1708280 : while (1) {
1105 1063280 : ret = _gnutls_iov_iter_next(&iter, &p);
1106 1063280 : if (unlikely(ret < 0))
1107 0 : return gnutls_assert_val(ret);
1108 1063280 : if (ret == 0)
1109 : break;
1110 644996 : len = ret;
1111 644996 : ret = _gnutls_cipher_encrypt2(&handle->ctx_enc,
1112 : p, len,
1113 : dst, dst_size);
1114 644996 : if (unlikely(ret < 0))
1115 0 : return gnutls_assert_val(ret);
1116 644996 : DECR_LEN(dst_size, len);
1117 644996 : dst += len;
1118 644996 : total += len;
1119 : }
1120 :
1121 418284 : if (dst_size < tag_size)
1122 0 : return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
1123 :
1124 418284 : _gnutls_cipher_tag(&handle->ctx_enc, dst, tag_size);
1125 :
1126 418284 : total += tag_size;
1127 418284 : *ctext_len = total;
1128 :
1129 418284 : return 0;
1130 : }
1131 :
1132 : /**
1133 : * gnutls_aead_cipher_encryptv2:
1134 : * @handle: is a #gnutls_aead_cipher_hd_t type.
1135 : * @nonce: the nonce to set
1136 : * @nonce_len: The length of the nonce
1137 : * @auth_iov: additional data to be authenticated
1138 : * @auth_iovcnt: The number of buffers in @auth_iov
1139 : * @iov: the data to be encrypted
1140 : * @iovcnt: The number of buffers in @iov
1141 : * @tag: The authentication tag
1142 : * @tag_size: The size of the tag to use (use zero for the default)
1143 : *
1144 : * This is similar to gnutls_aead_cipher_encrypt(), but it performs
1145 : * in-place encryption on the provided data buffers.
1146 : *
1147 : * Returns: Zero or a negative error code on error.
1148 : *
1149 : * Since: 3.6.10
1150 : **/
1151 : int
1152 10 : gnutls_aead_cipher_encryptv2(gnutls_aead_cipher_hd_t handle,
1153 : const void *nonce, size_t nonce_len,
1154 : const giovec_t *auth_iov, int auth_iovcnt,
1155 : const giovec_t *iov, int iovcnt,
1156 : void *tag, size_t *tag_size)
1157 : {
1158 10 : api_aead_cipher_hd_st *h = handle;
1159 10 : ssize_t ret;
1160 10 : uint8_t *p;
1161 10 : size_t len;
1162 10 : ssize_t blocksize = handle->ctx_enc.e->blocksize;
1163 10 : struct iov_iter_st iter;
1164 10 : size_t _tag_size;
1165 :
1166 10 : if (tag_size == NULL || *tag_size == 0)
1167 10 : _tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
1168 : else
1169 : _tag_size = *tag_size;
1170 :
1171 20 : if (_tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e))
1172 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1173 :
1174 : /* Limitation: this function provides an optimization under the internally registered
1175 : * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
1176 : * then this becomes a convenience function as it missed the lower-level primitives
1177 : * necessary for piecemeal encryption. */
1178 10 : if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) || handle->ctx_enc.encrypt == NULL) {
1179 : /* ciphertext cannot be produced in a piecemeal approach */
1180 2 : struct iov_store_st auth;
1181 2 : struct iov_store_st ptext;
1182 2 : size_t ptext_size;
1183 :
1184 2 : ret = copy_from_iov(&auth, auth_iov, auth_iovcnt);
1185 2 : if (ret < 0)
1186 0 : return gnutls_assert_val(ret);
1187 :
1188 2 : ret = copy_from_iov(&ptext, iov, iovcnt);
1189 2 : if (ret < 0) {
1190 0 : gnutls_assert();
1191 0 : goto fallback_fail;
1192 : }
1193 :
1194 2 : ptext_size = ptext.size;
1195 :
1196 : /* append space for tag */
1197 2 : ret = iov_store_grow(&ptext, _tag_size);
1198 2 : if (ret < 0) {
1199 0 : gnutls_assert();
1200 0 : goto fallback_fail;
1201 : }
1202 :
1203 4 : ret = gnutls_aead_cipher_encrypt(handle, nonce, nonce_len,
1204 2 : auth.data, auth.size,
1205 : _tag_size,
1206 : ptext.data, ptext_size,
1207 : ptext.data, &ptext.size);
1208 2 : if (ret < 0) {
1209 0 : gnutls_assert();
1210 0 : goto fallback_fail;
1211 : }
1212 :
1213 2 : ret = copy_to_iov(&ptext, ptext_size, iov, iovcnt);
1214 2 : if (ret < 0) {
1215 0 : gnutls_assert();
1216 0 : goto fallback_fail;
1217 : }
1218 :
1219 2 : if (tag != NULL)
1220 2 : memcpy(tag,
1221 2 : (uint8_t *) ptext.data + ptext_size,
1222 : _tag_size);
1223 2 : if (tag_size != NULL)
1224 2 : *tag_size = _tag_size;
1225 :
1226 0 : fallback_fail:
1227 2 : iov_store_free(&auth);
1228 2 : iov_store_free(&ptext);
1229 :
1230 2 : return ret;
1231 : }
1232 :
1233 8 : ret = _gnutls_cipher_setiv(&handle->ctx_enc, nonce, nonce_len);
1234 8 : if (unlikely(ret < 0))
1235 0 : return gnutls_assert_val(ret);
1236 :
1237 8 : ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
1238 8 : if (unlikely(ret < 0))
1239 0 : return gnutls_assert_val(ret);
1240 24 : while (1) {
1241 24 : ret = _gnutls_iov_iter_next(&iter, &p);
1242 24 : if (unlikely(ret < 0))
1243 0 : return gnutls_assert_val(ret);
1244 24 : if (ret == 0)
1245 : break;
1246 16 : ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
1247 16 : if (unlikely(ret < 0))
1248 0 : return gnutls_assert_val(ret);
1249 : }
1250 :
1251 8 : ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
1252 8 : if (unlikely(ret < 0))
1253 0 : return gnutls_assert_val(ret);
1254 23 : while (1) {
1255 23 : ret = _gnutls_iov_iter_next(&iter, &p);
1256 23 : if (unlikely(ret < 0))
1257 0 : return gnutls_assert_val(ret);
1258 23 : if (ret == 0)
1259 : break;
1260 :
1261 15 : len = ret;
1262 15 : ret = _gnutls_cipher_encrypt2(&handle->ctx_enc, p, len, p, len);
1263 15 : if (unlikely(ret < 0))
1264 0 : return gnutls_assert_val(ret);
1265 :
1266 15 : ret = _gnutls_iov_iter_sync(&iter, p, len);
1267 15 : if (unlikely(ret < 0))
1268 0 : return gnutls_assert_val(ret);
1269 : }
1270 :
1271 8 : if (tag != NULL)
1272 8 : _gnutls_cipher_tag(&handle->ctx_enc, tag, _tag_size);
1273 8 : if (tag_size != NULL)
1274 8 : *tag_size = _tag_size;
1275 :
1276 : return 0;
1277 : }
1278 :
1279 : /**
1280 : * gnutls_aead_cipher_decryptv2:
1281 : * @handle: is a #gnutls_aead_cipher_hd_t type.
1282 : * @nonce: the nonce to set
1283 : * @nonce_len: The length of the nonce
1284 : * @auth_iov: additional data to be authenticated
1285 : * @auth_iovcnt: The number of buffers in @auth_iov
1286 : * @iov: the data to decrypt
1287 : * @iovcnt: The number of buffers in @iov
1288 : * @tag: The authentication tag
1289 : * @tag_size: The size of the tag to use (use zero for the default)
1290 : *
1291 : * This is similar to gnutls_aead_cipher_decrypt(), but it performs
1292 : * in-place encryption on the provided data buffers.
1293 : *
1294 : * Returns: Zero or a negative error code on error.
1295 : *
1296 : * Since: 3.6.10
1297 : **/
1298 : int
1299 10 : gnutls_aead_cipher_decryptv2(gnutls_aead_cipher_hd_t handle,
1300 : const void *nonce, size_t nonce_len,
1301 : const giovec_t *auth_iov, int auth_iovcnt,
1302 : const giovec_t *iov, int iovcnt,
1303 : void *tag, size_t tag_size)
1304 : {
1305 10 : api_aead_cipher_hd_st *h = handle;
1306 10 : ssize_t ret;
1307 10 : uint8_t *p;
1308 10 : size_t len;
1309 10 : ssize_t blocksize = handle->ctx_enc.e->blocksize;
1310 10 : struct iov_iter_st iter;
1311 10 : uint8_t _tag[MAX_HASH_SIZE];
1312 :
1313 10 : if (tag_size == 0)
1314 0 : tag_size = _gnutls_cipher_get_tag_size(h->ctx_enc.e);
1315 20 : else if (tag_size > (unsigned)_gnutls_cipher_get_tag_size(h->ctx_enc.e))
1316 0 : return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
1317 :
1318 : /* Limitation: this function provides an optimization under the internally registered
1319 : * AEAD ciphers. When an AEAD cipher is used registered with gnutls_crypto_register_aead_cipher(),
1320 : * then this becomes a convenience function as it missed the lower-level primitives
1321 : * necessary for piecemeal encryption. */
1322 10 : if ((handle->ctx_enc.e->flags & GNUTLS_CIPHER_FLAG_ONLY_AEAD) || handle->ctx_enc.encrypt == NULL) {
1323 : /* ciphertext cannot be produced in a piecemeal approach */
1324 2 : struct iov_store_st auth;
1325 2 : struct iov_store_st ctext;
1326 2 : size_t ctext_size;
1327 :
1328 2 : ret = copy_from_iov(&auth, auth_iov, auth_iovcnt);
1329 2 : if (ret < 0)
1330 0 : return gnutls_assert_val(ret);
1331 :
1332 2 : ret = copy_from_iov(&ctext, iov, iovcnt);
1333 2 : if (ret < 0) {
1334 0 : gnutls_assert();
1335 0 : goto fallback_fail;
1336 : }
1337 :
1338 2 : ctext_size = ctext.size;
1339 :
1340 : /* append tag */
1341 2 : ret = iov_store_grow(&ctext, tag_size);
1342 2 : if (ret < 0) {
1343 0 : gnutls_assert();
1344 0 : goto fallback_fail;
1345 : }
1346 2 : memcpy((uint8_t *) ctext.data + ctext_size, tag, tag_size);
1347 :
1348 4 : ret = gnutls_aead_cipher_decrypt(handle, nonce, nonce_len,
1349 2 : auth.data, auth.size,
1350 : tag_size,
1351 : ctext.data, ctext.size,
1352 : ctext.data, &ctext_size);
1353 2 : if (ret < 0) {
1354 0 : gnutls_assert();
1355 0 : goto fallback_fail;
1356 : }
1357 :
1358 2 : ret = copy_to_iov(&ctext, ctext_size, iov, iovcnt);
1359 2 : if (ret < 0) {
1360 0 : gnutls_assert();
1361 0 : goto fallback_fail;
1362 : }
1363 :
1364 2 : fallback_fail:
1365 2 : iov_store_free(&auth);
1366 2 : iov_store_free(&ctext);
1367 :
1368 2 : return ret;
1369 : }
1370 :
1371 8 : ret = _gnutls_cipher_setiv(&handle->ctx_enc, nonce, nonce_len);
1372 8 : if (unlikely(ret < 0))
1373 0 : return gnutls_assert_val(ret);
1374 :
1375 8 : ret = _gnutls_iov_iter_init(&iter, auth_iov, auth_iovcnt, blocksize);
1376 8 : if (unlikely(ret < 0))
1377 0 : return gnutls_assert_val(ret);
1378 24 : while (1) {
1379 24 : ret = _gnutls_iov_iter_next(&iter, &p);
1380 24 : if (unlikely(ret < 0))
1381 0 : return gnutls_assert_val(ret);
1382 24 : if (ret == 0)
1383 : break;
1384 16 : ret = _gnutls_cipher_auth(&handle->ctx_enc, p, ret);
1385 16 : if (unlikely(ret < 0))
1386 0 : return gnutls_assert_val(ret);
1387 : }
1388 :
1389 8 : ret = _gnutls_iov_iter_init(&iter, iov, iovcnt, blocksize);
1390 8 : if (unlikely(ret < 0))
1391 0 : return gnutls_assert_val(ret);
1392 23 : while (1) {
1393 23 : ret = _gnutls_iov_iter_next(&iter, &p);
1394 23 : if (unlikely(ret < 0))
1395 0 : return gnutls_assert_val(ret);
1396 23 : if (ret == 0)
1397 : break;
1398 :
1399 15 : len = ret;
1400 15 : ret = _gnutls_cipher_decrypt2(&handle->ctx_enc, p, len, p, len);
1401 15 : if (unlikely(ret < 0))
1402 0 : return gnutls_assert_val(ret);
1403 :
1404 15 : ret = _gnutls_iov_iter_sync(&iter, p, len);
1405 15 : if (unlikely(ret < 0))
1406 0 : return gnutls_assert_val(ret);
1407 : }
1408 :
1409 8 : if (tag != NULL) {
1410 8 : _gnutls_cipher_tag(&handle->ctx_enc, _tag, tag_size);
1411 8 : if (gnutls_memcmp(_tag, tag, tag_size) != 0)
1412 0 : return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
1413 : }
1414 :
1415 : return 0;
1416 : }
1417 :
1418 : /**
1419 : * gnutls_aead_cipher_deinit:
1420 : * @handle: is a #gnutls_aead_cipher_hd_t type.
1421 : *
1422 : * This function will deinitialize all resources occupied by the given
1423 : * authenticated-encryption context.
1424 : *
1425 : * Since: 3.4.0
1426 : **/
1427 541 : void gnutls_aead_cipher_deinit(gnutls_aead_cipher_hd_t handle)
1428 : {
1429 541 : _gnutls_aead_cipher_deinit(handle);
1430 541 : gnutls_free(handle);
1431 541 : }
1432 :
1433 : extern gnutls_crypto_kdf_st _gnutls_kdf_ops;
1434 :
1435 : /**
1436 : * gnutls_hkdf_extract:
1437 : * @mac: the mac algorithm used internally
1438 : * @key: the initial keying material
1439 : * @salt: the optional salt
1440 : * @output: the output value of the extract operation
1441 : *
1442 : * This function will derive a fixed-size key using the HKDF-Extract
1443 : * function as defined in RFC 5869.
1444 : *
1445 : * Returns: Zero or a negative error code on error.
1446 : *
1447 : * Since: 3.6.13
1448 : */
1449 : int
1450 11455 : gnutls_hkdf_extract(gnutls_mac_algorithm_t mac,
1451 : const gnutls_datum_t *key,
1452 : const gnutls_datum_t *salt,
1453 : void *output)
1454 : {
1455 : /* MD5 is only allowed internally for TLS */
1456 11455 : if (is_mac_algo_forbidden(mac))
1457 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
1458 :
1459 22910 : return _gnutls_kdf_ops.hkdf_extract(mac, key->data, key->size,
1460 : salt ? salt->data : NULL,
1461 11455 : salt ? salt->size : 0,
1462 : output);
1463 : }
1464 :
1465 : /**
1466 : * gnutls_hkdf_expand:
1467 : * @mac: the mac algorithm used internally
1468 : * @key: the pseudorandom key created with HKDF-Extract
1469 : * @info: the optional informational data
1470 : * @output: the output value of the expand operation
1471 : * @length: the desired length of the output key
1472 : *
1473 : * This function will derive a variable length keying material from
1474 : * the pseudorandom key using the HKDF-Expand function as defined in
1475 : * RFC 5869.
1476 : *
1477 : * Returns: Zero or a negative error code on error.
1478 : *
1479 : * Since: 3.6.13
1480 : */
1481 : int
1482 115954 : gnutls_hkdf_expand(gnutls_mac_algorithm_t mac,
1483 : const gnutls_datum_t *key,
1484 : const gnutls_datum_t *info,
1485 : void *output, size_t length)
1486 : {
1487 : /* MD5 is only allowed internally for TLS */
1488 115954 : if (is_mac_algo_forbidden(mac))
1489 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
1490 :
1491 115954 : return _gnutls_kdf_ops.hkdf_expand(mac, key->data, key->size,
1492 115954 : info->data, info->size,
1493 : output, length);
1494 : }
1495 :
1496 : /**
1497 : * gnutls_pbkdf2:
1498 : * @mac: the mac algorithm used internally
1499 : * @key: the initial keying material
1500 : * @salt: the salt
1501 : * @iter_count: the iteration count
1502 : * @output: the output value
1503 : * @length: the desired length of the output key
1504 : *
1505 : * This function will derive a variable length keying material from
1506 : * a password according to PKCS #5 PBKDF2.
1507 : *
1508 : * Returns: Zero or a negative error code on error.
1509 : *
1510 : * Since: 3.6.13
1511 : */
1512 : int
1513 518 : gnutls_pbkdf2(gnutls_mac_algorithm_t mac,
1514 : const gnutls_datum_t *key,
1515 : const gnutls_datum_t *salt,
1516 : unsigned iter_count,
1517 : void *output, size_t length)
1518 : {
1519 : /* MD5 is only allowed internally for TLS */
1520 518 : if (is_mac_algo_forbidden(mac))
1521 : return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
1522 :
1523 518 : return _gnutls_kdf_ops.pbkdf2(mac, key->data, key->size,
1524 518 : salt->data, salt->size, iter_count,
1525 : output, length);
1526 : }
|