LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - crypto-api.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 376 472 79.7 %
Date: 2020-10-30 04:50:48 Functions: 40 42 95.2 %
Legend: Lines: hit not hit

          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             : }

Generated by: LCOV version 1.14