LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - cipher_int.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 175 216 81.0 %
Date: 2020-10-30 04:50:48 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2009-2013 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2013 Nikos Mavrogiannopoulos
       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 <crypto.h>
      30             : #include <fips.h>
      31             : #include <algorithms.h>
      32             : 
      33             : #define SR_FB(x, cleanup) ret=(x); if ( ret<0 ) { \
      34             :   if (ret == GNUTLS_E_NEED_FALLBACK) { \
      35             :     if (handle->handle) \
      36             :         handle->deinit(handle->handle); \
      37             :     goto fallback; \
      38             :   } \
      39             :   gnutls_assert(); \
      40             :   ret = GNUTLS_E_INTERNAL_ERROR; \
      41             :   goto cleanup; \
      42             :   }
      43             : 
      44             : #define SR(x, cleanup) if ( (x)<0 ) { \
      45             :   gnutls_assert(); \
      46             :   ret = GNUTLS_E_INTERNAL_ERROR; \
      47             :   goto cleanup; \
      48             :   }
      49             : 
      50             : /* Returns true(non-zero) or false(0) if the 
      51             :  * provided cipher exists
      52             :  */
      53       39442 : int _gnutls_cipher_exists(gnutls_cipher_algorithm_t cipher)
      54             : {
      55       39442 :         const gnutls_crypto_cipher_st *cc;
      56       39442 :         int ret;
      57             : 
      58       39442 :         if (is_cipher_algo_forbidden(cipher))
      59             :                 return 0;
      60             : 
      61             :         /* All the other ciphers are disabled on the back-end library.
      62             :          * The NULL needs to be detected here as it is not a cipher
      63             :          * that is provided by the back-end.
      64             :          */
      65       39442 :         if (cipher == GNUTLS_CIPHER_NULL)
      66             :                 return 1;
      67             : 
      68       39393 :         cc = _gnutls_get_crypto_cipher(cipher);
      69       39393 :         if (cc != NULL)
      70             :                 return 1;
      71             : 
      72       12673 :         ret = _gnutls_cipher_ops.exists(cipher);
      73       12673 :         return ret;
      74             : }
      75             : 
      76             : int
      77       52662 : _gnutls_cipher_init(cipher_hd_st *handle, const cipher_entry_st *e,
      78             :                     const gnutls_datum_t *key, const gnutls_datum_t *iv,
      79             :                     int enc)
      80             : {
      81       52662 :         int ret = GNUTLS_E_INTERNAL_ERROR;
      82       52662 :         const gnutls_crypto_cipher_st *cc = NULL;
      83             : 
      84       52662 :         if (unlikely(e == NULL || e->id == GNUTLS_CIPHER_NULL))
      85           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
      86             : 
      87       52662 :         FAIL_IF_LIB_ERROR;
      88             : 
      89       52662 :         handle->e = e;
      90       52662 :         handle->handle = NULL;
      91             : 
      92             :         /* check if a cipher has been registered
      93             :          */
      94       52662 :         cc = _gnutls_get_crypto_cipher(e->id);
      95       52662 :         if (cc != NULL) {
      96       45571 :                 handle->encrypt = cc->encrypt;
      97       45571 :                 handle->decrypt = cc->decrypt;
      98       45571 :                 handle->aead_encrypt = cc->aead_encrypt;
      99       45571 :                 handle->aead_decrypt = cc->aead_decrypt;
     100       45571 :                 handle->deinit = cc->deinit;
     101       45571 :                 handle->auth = cc->auth;
     102       45571 :                 handle->tag = cc->tag;
     103       45571 :                 handle->setiv = cc->setiv;
     104       45571 :                 handle->getiv = cc->getiv;
     105       45571 :                 handle->setkey = cc->setkey;
     106             : 
     107             :                 /* if cc->init() returns GNUTLS_E_NEED_FALLBACK we
     108             :                  * use the default ciphers */
     109       45571 :                 SR_FB(cc->init(e->id, &handle->handle, enc), cc_cleanup);
     110       45571 :                 SR_FB(cc->setkey(handle->handle, key->data, key->size),
     111       45570 :                    cc_cleanup);
     112       45570 :                 if (iv) {
     113       10177 :                         if (unlikely(cc->setiv == NULL)) /* the API doesn't accept IV */
     114           0 :                                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     115       10177 :                         SR(cc->setiv(handle->handle, iv->data, iv->size),
     116       45570 :                            cc_cleanup);
     117             :                 }
     118             : 
     119       45570 :                 return 0;
     120             :         }
     121             : 
     122        7091 :  fallback:
     123        7091 :         handle->encrypt = _gnutls_cipher_ops.encrypt;
     124        7091 :         handle->decrypt = _gnutls_cipher_ops.decrypt;
     125        7091 :         handle->aead_encrypt = _gnutls_cipher_ops.aead_encrypt;
     126        7091 :         handle->aead_decrypt = _gnutls_cipher_ops.aead_decrypt;
     127        7091 :         handle->deinit = _gnutls_cipher_ops.deinit;
     128        7091 :         handle->auth = _gnutls_cipher_ops.auth;
     129        7091 :         handle->tag = _gnutls_cipher_ops.tag;
     130        7091 :         handle->setiv = _gnutls_cipher_ops.setiv;
     131        7091 :         handle->getiv = _gnutls_cipher_ops.getiv;
     132        7091 :         handle->setkey = _gnutls_cipher_ops.setkey;
     133             : 
     134             :         /* otherwise use generic cipher interface
     135             :          */
     136        7091 :         ret = _gnutls_cipher_ops.init(e->id, &handle->handle, enc);
     137        7091 :         if (ret < 0) {
     138           0 :                 gnutls_assert();
     139           0 :                 return ret;
     140             :         }
     141             : 
     142        7091 :         ret =
     143       14182 :             _gnutls_cipher_ops.setkey(handle->handle, key->data,
     144        7091 :                                       key->size);
     145        7091 :         if (ret < 0) {
     146           0 :                 gnutls_assert();
     147           0 :                 goto cc_cleanup;
     148             :         }
     149             : 
     150        7091 :         if (iv) {
     151        1689 :                 ret =
     152        3378 :                     _gnutls_cipher_ops.setiv(handle->handle, iv->data,
     153        1689 :                                              iv->size);
     154        1689 :                 if (ret < 0) {
     155           0 :                         gnutls_assert();
     156           0 :                         goto cc_cleanup;
     157             :                 }
     158             :         }
     159             : 
     160             :         return 0;
     161             : 
     162           1 :       cc_cleanup:
     163             : 
     164           1 :         if (handle->handle)
     165           1 :                 handle->deinit(handle->handle);
     166             : 
     167             :         return ret;
     168             : }
     169             : 
     170             : /* Auth_cipher API 
     171             :  */
     172       18824 : int _gnutls_auth_cipher_init(auth_cipher_hd_st * handle,
     173             :                              const cipher_entry_st * e,
     174             :                              const gnutls_datum_t * cipher_key,
     175             :                              const gnutls_datum_t * iv,
     176             :                              const mac_entry_st * me,
     177             :                              const gnutls_datum_t * mac_key,
     178             :                              unsigned etm,
     179             : #ifdef ENABLE_SSL3
     180             :                              unsigned ssl_hmac,
     181             : #endif
     182             :                              int enc)
     183             : {
     184       18824 :         int ret;
     185             : 
     186       18824 :         if (unlikely(e == NULL))
     187           0 :                 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
     188             : 
     189       18824 :         FAIL_IF_LIB_ERROR;
     190             : 
     191       18824 :         memset(handle, 0, sizeof(*handle));
     192       18824 :         handle->etm = etm;
     193             : 
     194       18824 :         if (e->id != GNUTLS_CIPHER_NULL) {
     195       18744 :                 handle->non_null = 1;
     196       18744 :                 ret =
     197       18744 :                     _gnutls_cipher_init(&handle->cipher, e, cipher_key, iv,
     198             :                                         enc);
     199       18744 :                 if (ret < 0)
     200           0 :                         return gnutls_assert_val(ret);
     201             :         } else
     202          80 :                 handle->non_null = 0;
     203             : 
     204       18824 :         if (me->id != GNUTLS_MAC_AEAD) {
     205        9150 :                 handle->is_mac = 1;
     206             : #ifdef ENABLE_SSL3
     207             :                 handle->ssl_hmac = ssl_hmac;
     208             : 
     209             :                 if (ssl_hmac)
     210             :                         ret =
     211             :                             _gnutls_mac_init_ssl3(&handle->mac.dig, me,
     212             :                                                   mac_key->data,
     213             :                                                   mac_key->size);
     214             :                 else
     215             : #endif
     216        9150 :                         ret =
     217       18300 :                             _gnutls_mac_init(&handle->mac.mac, me,
     218        9150 :                                              mac_key->data, mac_key->size);
     219        9150 :                 if (ret < 0) {
     220           0 :                         gnutls_assert();
     221           0 :                         goto cleanup;
     222             :                 }
     223             : #ifdef ENABLE_GOST
     224        9150 :                 handle->continuous_mac = !!(me->flags & GNUTLS_MAC_FLAG_CONTINUOUS_MAC);
     225             : #endif
     226             : 
     227       18300 :                 handle->tag_size = _gnutls_mac_get_algo_len(me);
     228        9674 :         } else if (_gnutls_cipher_algo_is_aead(e)) {
     229        9674 :                 handle->tag_size = _gnutls_cipher_get_tag_size(e);
     230             :         } else {
     231           0 :                 gnutls_assert();
     232           0 :                 ret = GNUTLS_E_INVALID_REQUEST;
     233           0 :                 goto cleanup;
     234             :         }
     235             : 
     236             :         return 0;
     237           0 :       cleanup:
     238           0 :         if (handle->non_null != 0)
     239           0 :                 _gnutls_cipher_deinit(&handle->cipher);
     240             :         return ret;
     241             : 
     242             : }
     243             : 
     244             : #ifdef ENABLE_SSL3
     245             : # define MAC(handle, text, textlen) \
     246             :                 if (handle->ssl_hmac) { \
     247             :                         ret = \
     248             :                             _gnutls_hash(&handle->mac.dig, text, textlen); \
     249             :                 } else { \
     250             :                         ret = _gnutls_mac(&handle->mac.mac, text, textlen); \
     251             :                 } \
     252             :                 if (unlikely(ret < 0)) \
     253             :                         return gnutls_assert_val(ret)
     254             : #else
     255             : # define MAC(handle, text, textlen) \
     256             :                 ret = _gnutls_mac(&handle->mac.mac, text, textlen); \
     257             :                 if (unlikely(ret < 0)) \
     258             :                         return gnutls_assert_val(ret)
     259             : #endif
     260             : 
     261     4173110 : int _gnutls_auth_cipher_add_auth(auth_cipher_hd_st * handle,
     262             :                                  const void *text, int textlen)
     263             : {
     264     4173110 :         int ret;
     265             : 
     266     4173110 :         if (handle->is_mac) {
     267     6876590 :                 MAC(handle, text, textlen);
     268      734753 :         } else if (_gnutls_cipher_is_aead(&handle->cipher))
     269           0 :                 return _gnutls_cipher_auth(&handle->cipher, text, textlen);
     270             :         return 0;
     271             : }
     272             : 
     273             : 
     274             : /* The caller must make sure that textlen+pad_size+tag_size is divided by the block size of the cipher */
     275     1287180 : int _gnutls_auth_cipher_encrypt2_tag(auth_cipher_hd_st * handle,
     276             :                                      const uint8_t * text, int textlen,
     277             :                                      void *_ciphertext, int ciphertextlen,
     278             :                                      int pad_size)
     279             : {
     280     1287180 :         int ret;
     281     1287180 :         uint8_t *ciphertext = _ciphertext;
     282     2574370 :         unsigned blocksize =
     283     1287180 :             _gnutls_cipher_get_block_size(handle->cipher.e);
     284     1287180 :         unsigned l;
     285             : 
     286     1287180 :         assert(ciphertext != NULL);
     287             : 
     288     1287180 :         if (handle->is_mac) { /* cipher + mac */
     289     1231140 :                 if (handle->non_null == 0) { /* NULL cipher + MAC */
     290      393328 :                         MAC(handle, text, textlen);
     291             : 
     292      196664 :                         if (unlikely(textlen + pad_size + handle->tag_size) >
     293             :                             ciphertextlen)
     294           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     295             : 
     296      196664 :                         if (text != ciphertext)
     297      196664 :                                 memcpy(ciphertext, text, textlen);
     298      196664 :                         ret =
     299      393328 :                             _gnutls_auth_cipher_tag(handle,
     300      196664 :                                                     ciphertext + textlen,
     301      196664 :                                                     handle->tag_size);
     302      196664 :                         if (ret < 0)
     303           0 :                                 return gnutls_assert_val(ret);
     304             : 
     305             :                 } else {
     306     1034480 :                         uint8_t *orig_ciphertext = ciphertext;
     307             : 
     308     1034480 :                         if (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK) {
     309      754270 :                                 MAC(handle, text, textlen);
     310             :                         }
     311             : 
     312     1034480 :                         if (unlikely(textlen + pad_size + handle->tag_size) >
     313             :                             ciphertextlen)
     314           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     315             : 
     316     1034480 :                         assert(blocksize != 0);
     317     1034480 :                         l = (textlen / blocksize) * blocksize;
     318     1034480 :                         if (l > 0) {
     319     1028750 :                                 ret =
     320     1028750 :                                         _gnutls_cipher_encrypt2(&handle->cipher, text,
     321             :                                                             l, ciphertext,
     322             :                                                             ciphertextlen);
     323     1028750 :                                 if (ret < 0)
     324           0 :                                         return gnutls_assert_val(ret);
     325             : 
     326     1028750 :                                 textlen -= l;
     327     1028750 :                                 text += l;
     328     1028750 :                                 ciphertext += l;
     329     1028750 :                                 ciphertextlen -= l;
     330             :                         }
     331             : 
     332     1034480 :                         if (ciphertext != text && textlen > 0)
     333      620961 :                                 memcpy(ciphertext, text, textlen);
     334             : 
     335     1034480 :                         if (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK) {
     336      377190 :                                 ret =
     337      754380 :                                     _gnutls_auth_cipher_tag(handle,
     338      377190 :                                                             ciphertext + textlen,
     339      377190 :                                                             handle->tag_size);
     340      377190 :                                 if (ret < 0)
     341           0 :                                         return gnutls_assert_val(ret);
     342      377190 :                                 textlen += handle->tag_size;
     343             :                         }
     344             : 
     345             :                         /* TLS 1.0 style padding */
     346     1034480 :                         if (pad_size > 0) {
     347      668577 :                                 memset(ciphertext + textlen, pad_size - 1,
     348             :                                        pad_size);
     349      668577 :                                 textlen += pad_size;
     350             :                         }
     351             : 
     352     1034480 :                         ret =
     353     1034480 :                             _gnutls_cipher_encrypt2(&handle->cipher,
     354             :                                                     ciphertext, textlen,
     355             :                                                     ciphertext,
     356             :                                                     ciphertextlen);
     357     1034480 :                         if (ret < 0)
     358           0 :                                 return gnutls_assert_val(ret);
     359             : 
     360     1034480 :                         if (handle->etm != 0 && handle->cipher.e->type == CIPHER_BLOCK) {
     361     1313190 :                                 MAC(handle, orig_ciphertext, l);
     362     1314580 :                                 MAC(handle, ciphertext, textlen);
     363             : 
     364      657288 :                                 ret =
     365     1314580 :                                         _gnutls_auth_cipher_tag(handle,
     366      657288 :                                                         ciphertext + textlen,
     367      657288 :                                                         handle->tag_size);
     368      657288 :                                 if (ret < 0)
     369           0 :                                         return gnutls_assert_val(ret);
     370             :                         }
     371             :                 }
     372       56041 :         } else if (_gnutls_cipher_is_aead(&handle->cipher)) {
     373           0 :                 ret =
     374           0 :                     _gnutls_cipher_encrypt2(&handle->cipher, text, textlen,
     375             :                                             ciphertext, ciphertextlen);
     376           0 :                 if (unlikely(ret < 0))
     377           0 :                         return gnutls_assert_val(ret);
     378             : 
     379           0 :                 ret =
     380           0 :                     _gnutls_auth_cipher_tag(handle, ciphertext + textlen,
     381           0 :                                             handle->tag_size);
     382           0 :                 if (unlikely(ret < 0))
     383           0 :                         return gnutls_assert_val(ret);
     384       56041 :         } else if (handle->non_null == 0 && text != ciphertext) /* NULL cipher - no MAC */
     385       56041 :                 memcpy(ciphertext, text, textlen);
     386             : 
     387             :         return 0;
     388             : }
     389             : 
     390     1241280 : int _gnutls_auth_cipher_decrypt2(auth_cipher_hd_st * handle,
     391             :                                  const void *ciphertext, int ciphertextlen,
     392             :                                  void *text, int textlen)
     393             : {
     394     1241280 :         int ret;
     395             : 
     396     1241280 :         if (unlikely(ciphertextlen > textlen))
     397           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     398             : 
     399     1241280 :         if (handle->is_mac && (handle->etm != 0 && handle->cipher.e->type == CIPHER_BLOCK)) {
     400             :                 /* The MAC is not to be hashed */
     401           0 :                 ciphertextlen -= handle->tag_size;
     402             : 
     403           0 :                 MAC(handle, ciphertext, ciphertextlen);
     404             :         }
     405             : 
     406     1241280 :         if (handle->non_null != 0) {
     407      365894 :                 ret =
     408      365894 :                     _gnutls_cipher_decrypt2(&handle->cipher, ciphertext,
     409             :                                             ciphertextlen, text, textlen);
     410      365894 :                 if (ret < 0)
     411           0 :                         return gnutls_assert_val(ret);
     412      875390 :         } else if (handle->non_null == 0 && text != ciphertext)
     413      875390 :                 memcpy(text, ciphertext, ciphertextlen);
     414             : 
     415     1241280 :         if (handle->is_mac && (handle->etm == 0 || handle->cipher.e->type != CIPHER_BLOCK)) {
     416             :                 /* The MAC is not to be hashed */
     417      562572 :                 ciphertextlen -= handle->tag_size;
     418             : 
     419     1125140 :                 MAC(handle, text, ciphertextlen);
     420             :         }
     421             : 
     422             :         return 0;
     423             : }
     424             : 
     425     3138310 : int _gnutls_auth_cipher_tag(auth_cipher_hd_st * handle, void *tag,
     426             :                             int tag_size)
     427             : {
     428     3138310 :         if (handle->is_mac) {
     429             : #ifdef ENABLE_SSL3
     430             :                 if (handle->ssl_hmac) {
     431             :                         int ret =
     432             :                             _gnutls_mac_output_ssl3(&handle->mac.dig, tag);
     433             :                         if (ret < 0)
     434             :                                 return gnutls_assert_val(ret);
     435             :                 } else
     436             : #endif
     437             : #ifdef ENABLE_GOST
     438             :                 /* draft-smyshlyaev-tls12-gost-suites section 4.1.2 */
     439     2459600 :                 if (handle->continuous_mac) {
     440         216 :                         mac_hd_st temp_mac;
     441         216 :                         int ret = _gnutls_mac_copy(&handle->mac.mac, &temp_mac);
     442         216 :                         if (ret < 0)
     443           0 :                                 return gnutls_assert_val(ret);
     444         216 :                         _gnutls_mac_deinit(&temp_mac, tag);
     445             :                 } else
     446             : #endif
     447     2459380 :                         _gnutls_mac_output(&handle->mac.mac, tag);
     448      678712 :         } else if (_gnutls_cipher_is_aead(&handle->cipher)) {
     449           0 :                 _gnutls_cipher_tag(&handle->cipher, tag, tag_size);
     450             :         } else
     451      678712 :                 memset(tag, 0, tag_size);
     452             : 
     453             :         return 0;
     454             : }
     455             : 
     456       81098 : void _gnutls_auth_cipher_deinit(auth_cipher_hd_st * handle)
     457             : {
     458       81098 :         if (handle->is_mac) {
     459             : #ifdef ENABLE_SSL3
     460             :                 if (handle->ssl_hmac)        /* failure here doesn't matter */
     461             :                         _gnutls_mac_deinit_ssl3(&handle->mac.dig, NULL);
     462             :                 else
     463             : #endif
     464        9068 :                         _gnutls_mac_deinit(&handle->mac.mac, NULL);
     465             :         }
     466       81098 :         if (handle->non_null != 0)
     467       18638 :                 _gnutls_cipher_deinit(&handle->cipher);
     468       81098 : }

Generated by: LCOV version 1.14