LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - crypto-backend.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 103 117 88.0 %
Date: 2020-10-30 04:50:48 Functions: 14 15 93.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2008-2012 Free Software Foundation, Inc.
       3             :  *
       4             :  * Author: Nikos Mavrogiannopoulos
       5             :  *
       6             :  * This file is part of GnuTLS.
       7             :  *
       8             :  * The GnuTLS is free software; you can redistribute it and/or
       9             :  * modify it under the terms of the GNU Lesser General Public License
      10             :  * as published by the Free Software Foundation; either version 2.1 of
      11             :  * the License, or (at your option) any later version.
      12             :  *
      13             :  * This library is distributed in the hope that it will be useful, but
      14             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      16             :  * Lesser General Public License for more details.
      17             :  *
      18             :  * You should have received a copy of the GNU Lesser General Public License
      19             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      20             :  *
      21             :  */
      22             : 
      23             : #include "errors.h"
      24             : #include "gnutls_int.h"
      25             : #include <gnutls/crypto.h>
      26             : #include <crypto-backend.h>
      27             : #include <crypto.h>
      28             : #include <mpi.h>
      29             : #include <pk.h>
      30             : #include <random.h>
      31             : #include <cipher_int.h>
      32             : 
      33             : /* default values for priorities */
      34             : int crypto_mac_prio = INT_MAX;
      35             : int crypto_digest_prio = INT_MAX;
      36             : int crypto_cipher_prio = INT_MAX;
      37             : 
      38             : typedef struct algo_list {
      39             :         int algorithm;
      40             :         int priority;
      41             :         void *alg_data;
      42             :         int free_alg_data;
      43             :         struct algo_list *next;
      44             : } algo_list;
      45             : 
      46             : #define cipher_list algo_list
      47             : #define mac_list algo_list
      48             : #define digest_list algo_list
      49             : 
      50             : static int
      51       94653 : _algo_register(algo_list * al, int algorithm, int priority, void *s, int free_s)
      52             : {
      53       94653 :         algo_list *cl;
      54       94653 :         algo_list *last_cl = al;
      55       94653 :         int ret;
      56             : 
      57       94653 :         if (al == NULL) {
      58           0 :                 ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
      59           0 :                 goto cleanup;
      60             :         }
      61             : 
      62             :         /* look if there is any cipher with lowest priority. In that case do not add.
      63             :          */
      64             :         cl = al;
      65      436027 :         while (cl && cl->alg_data) {
      66      361673 :                 if (cl->algorithm == algorithm) {
      67       20299 :                         if (cl->priority < priority) {
      68           9 :                                 gnutls_assert();
      69           9 :                                 ret = GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
      70           9 :                                 goto cleanup;
      71             :                         } else {
      72             :                                 /* the current has higher priority -> overwrite */
      73       20290 :                                 cl->algorithm = algorithm;
      74       20290 :                                 cl->priority = priority;
      75       20290 :                                 cl->alg_data = s;
      76       20290 :                                 cl->free_alg_data = free_s;
      77       20290 :                                 return 0;
      78             :                         }
      79             :                 }
      80      341374 :                 cl = cl->next;
      81      341374 :                 if (cl)
      82      341359 :                         last_cl = cl;
      83             :         }
      84             : 
      85       74354 :         cl = gnutls_calloc(1, sizeof(cipher_list));
      86             : 
      87       74354 :         if (cl == NULL) {
      88           0 :                 gnutls_assert();
      89           0 :                 ret = GNUTLS_E_MEMORY_ERROR;
      90           0 :                 goto cleanup;
      91             :         }
      92             : 
      93       74354 :         last_cl->algorithm = algorithm;
      94       74354 :         last_cl->priority = priority;
      95       74354 :         last_cl->alg_data = s;
      96       74354 :         last_cl->free_alg_data = free_s;
      97       74354 :         last_cl->next = cl;
      98             : 
      99       74354 :         return 0;
     100           9 :  cleanup:
     101           9 :         if (free_s) gnutls_free(s);
     102             :         return ret;
     103             : }
     104             : 
     105     1115250 : static const void *_get_algo(algo_list * al, int algo)
     106             : {
     107     1115250 :         cipher_list *cl;
     108             : 
     109             :         /* look if there is any cipher with lowest priority. In that case do not add.
     110             :          */
     111     1115250 :         cl = al;
     112     2425000 :         while (cl && cl->alg_data) {
     113     2345050 :                 if (cl->algorithm == algo) {
     114             :                         return cl->alg_data;
     115             :                 }
     116     1309750 :                 cl = cl->next;
     117             :         }
     118             : 
     119             :         return NULL;
     120             : }
     121             : 
     122             : static cipher_list glob_cl = { GNUTLS_CIPHER_NULL, 0, NULL, 0, NULL };
     123             : static mac_list glob_ml = { GNUTLS_MAC_NULL, 0, NULL, 0, NULL };
     124             : static digest_list glob_dl = { GNUTLS_MAC_NULL, 0, NULL, 0, NULL };
     125             : 
     126        6564 : static void _deregister(algo_list * cl)
     127             : {
     128        6564 :         algo_list *next;
     129             : 
     130        6564 :         next = cl->next;
     131        6564 :         cl->next = NULL;
     132        6564 :         cl = next;
     133             : 
     134       54452 :         while (cl) {
     135       47888 :                 next = cl->next;
     136       47888 :                 if (cl->free_alg_data)
     137           5 :                         gnutls_free(cl->alg_data);
     138       47888 :                 gnutls_free(cl);
     139       47888 :                 cl = next;
     140             :         }
     141        6564 : }
     142             : 
     143        2188 : void _gnutls_crypto_deregister(void)
     144             : {
     145        2188 :         _deregister(&glob_cl);
     146        2188 :         _deregister(&glob_ml);
     147        2188 :         _deregister(&glob_dl);
     148        2188 : }
     149             : 
     150             : /*-
     151             :  * gnutls_crypto_single_cipher_register:
     152             :  * @algorithm: is the gnutls algorithm identifier
     153             :  * @priority: is the priority of the algorithm
     154             :  * @s: is a structure holding new cipher's data
     155             :  *
     156             :  * This function will register a cipher algorithm to be used by
     157             :  * gnutls.  Any algorithm registered will override the included
     158             :  * algorithms and by convention kernel implemented algorithms have
     159             :  * priority of 90 and CPU-assisted of 80.  The algorithm with the lowest priority will be
     160             :  * used by gnutls.
     161             :  *
     162             :  * In the case the registered init or setkey functions return %GNUTLS_E_NEED_FALLBACK,
     163             :  * GnuTLS will attempt to use the next in priority registered cipher.
     164             :  *
     165             :  * This function should be called before gnutls_global_init().
     166             :  *
     167             :  * For simplicity you can use the convenience
     168             :  * gnutls_crypto_single_cipher_register() macro.
     169             :  *
     170             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     171             :  *
     172             :  * Since: 2.6.0
     173             :  -*/
     174             : int
     175       60849 : gnutls_crypto_single_cipher_register(gnutls_cipher_algorithm_t algorithm,
     176             :                                      int priority,
     177             :                                      const gnutls_crypto_cipher_st * s,
     178             :                                      int free_s)
     179             : {
     180             :         /* we override const in case free_s is set */
     181       60849 :         return _algo_register(&glob_cl, algorithm, priority, (void*)s, free_s);
     182             : }
     183             : 
     184             : const gnutls_crypto_cipher_st
     185       92197 :     *_gnutls_get_crypto_cipher(gnutls_cipher_algorithm_t algo)
     186             : {
     187       92197 :         return _get_algo(&glob_cl, algo);
     188             : }
     189             : 
     190             : /**
     191             :  * gnutls_crypto_register_cipher:
     192             :  * @algorithm: is the gnutls algorithm identifier
     193             :  * @priority: is the priority of the algorithm
     194             :  * @init: A function which initializes the cipher
     195             :  * @setkey: A function which sets the key of the cipher
     196             :  * @setiv: A function which sets the nonce/IV of the cipher (non-AEAD)
     197             :  * @encrypt: A function which performs encryption (non-AEAD)
     198             :  * @decrypt: A function which performs decryption (non-AEAD)
     199             :  * @deinit: A function which deinitializes the cipher
     200             :  *
     201             :  * This function will register a cipher algorithm to be used by
     202             :  * gnutls.  Any algorithm registered will override the included
     203             :  * algorithms and by convention kernel implemented algorithms have
     204             :  * priority of 90 and CPU-assisted of 80.  The algorithm with the lowest priority will be
     205             :  * used by gnutls.
     206             :  *
     207             :  * In the case the registered init or setkey functions return %GNUTLS_E_NEED_FALLBACK,
     208             :  * GnuTLS will attempt to use the next in priority registered cipher.
     209             :  *
     210             :  * The functions which are marked as non-AEAD they are not required when
     211             :  * registering a cipher to be used with the new AEAD API introduced in
     212             :  * GnuTLS 3.4.0. Internally GnuTLS uses the new AEAD API.
     213             :  *
     214             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     215             :  *
     216             :  * Since: 3.4.0
     217             :  **/
     218             : int
     219           6 : gnutls_crypto_register_cipher(gnutls_cipher_algorithm_t algorithm,
     220             :                               int priority,
     221             :                               gnutls_cipher_init_func init,
     222             :                               gnutls_cipher_setkey_func setkey,
     223             :                               gnutls_cipher_setiv_func setiv,
     224             :                               gnutls_cipher_encrypt_func encrypt,
     225             :                               gnutls_cipher_decrypt_func decrypt,
     226             :                               gnutls_cipher_deinit_func deinit)
     227             : {
     228           6 :         gnutls_crypto_cipher_st *s = gnutls_calloc(1, sizeof(gnutls_crypto_cipher_st));
     229           6 :         if (s == NULL)
     230           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     231             : 
     232           6 :         s->init = init;
     233           6 :         s->setkey = setkey;
     234           6 :         s->setiv = setiv;
     235           6 :         s->encrypt = encrypt;
     236           6 :         s->decrypt = decrypt;
     237           6 :         s->deinit = deinit;
     238             : 
     239           6 :         return gnutls_crypto_single_cipher_register(algorithm, priority, s, 1);
     240             : }
     241             : 
     242             : /**
     243             :  * gnutls_crypto_register_aead_cipher:
     244             :  * @algorithm: is the gnutls AEAD cipher identifier
     245             :  * @priority: is the priority of the algorithm
     246             :  * @init: A function which initializes the cipher
     247             :  * @setkey: A function which sets the key of the cipher
     248             :  * @aead_encrypt: Perform the AEAD encryption
     249             :  * @aead_decrypt: Perform the AEAD decryption
     250             :  * @deinit: A function which deinitializes the cipher
     251             :  *
     252             :  * This function will register a cipher algorithm to be used by
     253             :  * gnutls.  Any algorithm registered will override the included
     254             :  * algorithms and by convention kernel implemented algorithms have
     255             :  * priority of 90 and CPU-assisted of 80.  The algorithm with the lowest priority will be
     256             :  * used by gnutls.
     257             :  *
     258             :  * In the case the registered init or setkey functions return %GNUTLS_E_NEED_FALLBACK,
     259             :  * GnuTLS will attempt to use the next in priority registered cipher.
     260             :  *
     261             :  * The functions registered will be used with the new AEAD API introduced in
     262             :  * GnuTLS 3.4.0. Internally GnuTLS uses the new AEAD API.
     263             :  *
     264             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     265             :  *
     266             :  * Since: 3.4.0
     267             :  **/
     268             : int
     269           3 : gnutls_crypto_register_aead_cipher(gnutls_cipher_algorithm_t algorithm,
     270             :                               int priority,
     271             :                               gnutls_cipher_init_func init,
     272             :                               gnutls_cipher_setkey_func setkey,
     273             :                               gnutls_cipher_aead_encrypt_func aead_encrypt,
     274             :                               gnutls_cipher_aead_decrypt_func aead_decrypt,
     275             :                               gnutls_cipher_deinit_func deinit)
     276             : {
     277           3 :         gnutls_crypto_cipher_st *s = gnutls_calloc(1, sizeof(gnutls_crypto_cipher_st));
     278           3 :         if (s == NULL)
     279           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     280             : 
     281           3 :         s->init = init;
     282           3 :         s->setkey = setkey;
     283           3 :         s->aead_encrypt = aead_encrypt;
     284           3 :         s->aead_decrypt = aead_decrypt;
     285           3 :         s->deinit = deinit;
     286             : 
     287           3 :         return gnutls_crypto_single_cipher_register(algorithm, priority, s, 1);
     288             : }
     289             : 
     290             : /*-
     291             :  * gnutls_crypto_rnd_register:
     292             :  * @priority: is the priority of the generator
     293             :  * @s: is a structure holding new generator's data
     294             :  *
     295             :  * This function will register a random generator to be used by
     296             :  * gnutls.  Any generator registered will override the included
     297             :  * generator and by convention kernel implemented generators have
     298             :  * priority of 90 and CPU-assisted of 80. The generator with the lowest priority will be
     299             :  * used by gnutls.
     300             :  *
     301             :  * This function should be called before gnutls_global_init().
     302             :  *
     303             :  * For simplicity you can use the convenience
     304             :  * gnutls_crypto_rnd_register() macro.
     305             :  *
     306             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     307             :  *
     308             :  * Since: 2.6.0
     309             :  -*/
     310             : int
     311           0 : gnutls_crypto_rnd_register(int priority, const gnutls_crypto_rnd_st * s)
     312             : {
     313           0 :         if (crypto_rnd_prio >= priority) {
     314           0 :                 memcpy(&_gnutls_rnd_ops, s, sizeof(*s));
     315           0 :                 crypto_rnd_prio = priority;
     316           0 :                 return 0;
     317             :         }
     318             : 
     319             :         return GNUTLS_E_CRYPTO_ALREADY_REGISTERED;
     320             : }
     321             : 
     322             : /*-
     323             :  * gnutls_crypto_single_mac_register:
     324             :  * @algorithm: is the gnutls algorithm identifier
     325             :  * @priority: is the priority of the algorithm
     326             :  * @s: is a structure holding new algorithms's data
     327             :  *
     328             :  * This function will register a MAC algorithm to be used by gnutls.
     329             :  * Any algorithm registered will override the included algorithms and
     330             :  * by convention kernel implemented algorithms have priority of 90
     331             :  *  and CPU-assisted of 80.
     332             :  * The algorithm with the lowest priority will be used by gnutls.
     333             :  *
     334             :  * This function should be called before gnutls_global_init().
     335             :  *
     336             :  * For simplicity you can use the convenience
     337             :  * gnutls_crypto_single_mac_register() macro.
     338             :  *
     339             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     340             :  *
     341             :  * Since: 2.6.0
     342             :  -*/
     343             : int
     344       16902 : gnutls_crypto_single_mac_register(gnutls_mac_algorithm_t algorithm,
     345             :                                   int priority,
     346             :                                   const gnutls_crypto_mac_st * s,
     347             :                                   int free_s)
     348             : {
     349       16902 :         return _algo_register(&glob_ml, algorithm, priority, (void*)s, free_s);
     350             : }
     351             : 
     352       53115 : const gnutls_crypto_mac_st *_gnutls_get_crypto_mac(gnutls_mac_algorithm_t
     353             :                                                    algo)
     354             : {
     355       53115 :         return _get_algo(&glob_ml, algo);
     356             : }
     357             : 
     358             : /*-
     359             :  * gnutls_crypto_single_digest_register:
     360             :  * @algorithm: is the gnutls algorithm identifier
     361             :  * @priority: is the priority of the algorithm
     362             :  * @s: is a structure holding new algorithms's data
     363             :  *
     364             :  * This function will register a digest (hash) algorithm to be used by
     365             :  * gnutls.  Any algorithm registered will override the included
     366             :  * algorithms and by convention kernel implemented algorithms have
     367             :  * priority of 90  and CPU-assisted of 80.  The algorithm with the lowest priority will be
     368             :  * used by gnutls.
     369             :  *
     370             :  * This function should be called before gnutls_global_init().
     371             :  *
     372             :  * For simplicity you can use the convenience
     373             :  * gnutls_crypto_single_digest_register() macro.
     374             :  *
     375             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     376             :  *
     377             :  * Since: 2.6.0
     378             :  -*/
     379             : int
     380       16902 : gnutls_crypto_single_digest_register(gnutls_digest_algorithm_t algorithm,
     381             :                                      int priority,
     382             :                                      const gnutls_crypto_digest_st * s,
     383             :                                      int free_s)
     384             : {
     385       16902 :         return _algo_register(&glob_dl, algorithm, priority, (void*)s, free_s);
     386             : }
     387             : 
     388             : const gnutls_crypto_digest_st
     389      969936 :     *_gnutls_get_crypto_digest(gnutls_digest_algorithm_t algo)
     390             : {
     391      969936 :         return _get_algo(&glob_dl, algo);
     392             : }
     393             : 
     394             : /**
     395             :  * gnutls_crypto_register_mac:
     396             :  * @algorithm: is the gnutls MAC identifier
     397             :  * @priority: is the priority of the algorithm
     398             :  * @init: A function which initializes the MAC
     399             :  * @setkey: A function which sets the key of the MAC
     400             :  * @setnonce: A function which sets the nonce for the mac (may be %NULL for common MAC algorithms)
     401             :  * @hash: Perform the hash operation
     402             :  * @output: Provide the output of the MAC
     403             :  * @deinit: A function which deinitializes the MAC
     404             :  * @hash_fast: Perform the MAC operation in one go
     405             :  *
     406             :  * This function will register a MAC algorithm to be used by gnutls.
     407             :  * Any algorithm registered will override the included algorithms and
     408             :  * by convention kernel implemented algorithms have priority of 90
     409             :  *  and CPU-assisted of 80.
     410             :  * The algorithm with the lowest priority will be used by gnutls.
     411             :  *
     412             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     413             :  *
     414             :  * Since: 3.4.0
     415             :  **/
     416             : int
     417           2 : gnutls_crypto_register_mac(gnutls_mac_algorithm_t algorithm,
     418             :                            int priority,
     419             :                            gnutls_mac_init_func init,
     420             :                            gnutls_mac_setkey_func setkey,
     421             :                            gnutls_mac_setnonce_func setnonce,
     422             :                            gnutls_mac_hash_func hash,
     423             :                            gnutls_mac_output_func output,
     424             :                            gnutls_mac_deinit_func deinit,
     425             :                            gnutls_mac_fast_func hash_fast)
     426             : {
     427           2 :         gnutls_crypto_mac_st *s = gnutls_calloc(1, sizeof(gnutls_crypto_mac_st));
     428           2 :         if (s == NULL)
     429           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     430             : 
     431           2 :         s->init = init;
     432           2 :         s->setkey = setkey;
     433           2 :         s->setnonce = setnonce;
     434           2 :         s->hash = hash;
     435           2 :         s->output = output;
     436           2 :         s->fast = hash_fast;
     437           2 :         s->deinit = deinit;
     438             : 
     439           2 :         return gnutls_crypto_single_mac_register(algorithm, priority, s, 1);
     440             : }
     441             : 
     442             : /**
     443             :  * gnutls_crypto_register_digest:
     444             :  * @algorithm: is the gnutls digest identifier
     445             :  * @priority: is the priority of the algorithm
     446             :  * @init: A function which initializes the digest
     447             :  * @hash: Perform the hash operation
     448             :  * @output: Provide the output of the digest
     449             :  * @deinit: A function which deinitializes the digest
     450             :  * @hash_fast: Perform the digest operation in one go
     451             :  *
     452             :  * This function will register a digest algorithm to be used by gnutls.
     453             :  * Any algorithm registered will override the included algorithms and
     454             :  * by convention kernel implemented algorithms have priority of 90
     455             :  *  and CPU-assisted of 80.
     456             :  * The algorithm with the lowest priority will be used by gnutls.
     457             :  *
     458             :  * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code.
     459             :  *
     460             :  * Since: 3.4.0
     461             :  **/
     462             : int
     463           2 : gnutls_crypto_register_digest(gnutls_digest_algorithm_t algorithm,
     464             :                            int priority,
     465             :                            gnutls_digest_init_func init,
     466             :                            gnutls_digest_hash_func hash,
     467             :                            gnutls_digest_output_func output,
     468             :                            gnutls_digest_deinit_func deinit,
     469             :                            gnutls_digest_fast_func hash_fast)
     470             : {
     471           2 :         gnutls_crypto_digest_st *s = gnutls_calloc(1, sizeof(gnutls_crypto_digest_st));
     472           2 :         if (s == NULL)
     473           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
     474             : 
     475           2 :         s->init = init;
     476           2 :         s->hash = hash;
     477           2 :         s->output = output;
     478           2 :         s->fast = hash_fast;
     479           2 :         s->deinit = deinit;
     480             : 
     481           2 :         return gnutls_crypto_single_digest_register(algorithm, priority, s, 1);
     482             : }

Generated by: LCOV version 1.14