LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - dh-session.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 86 143 60.1 %
Date: 2020-10-30 04:50:48 Functions: 7 7 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2001-2015 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2015 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             : /* This file contains certificate authentication functions to be exported in the
      25             :  * API which did not fit elsewhere.
      26             :  */
      27             : 
      28             : #include "gnutls_int.h"
      29             : #include <auth/srp_kx.h>
      30             : #include <auth/anon.h>
      31             : #include <auth/cert.h>
      32             : #include <auth/psk.h>
      33             : #include "errors.h"
      34             : #include <auth.h>
      35             : #include <state.h>
      36             : #include <datum.h>
      37             : #include <algorithms.h>
      38             : 
      39             : /* ANON & DHE */
      40             : 
      41             : #if defined(ENABLE_DHE) || defined(ENABLE_ANON)
      42             : /**
      43             :  * gnutls_dh_set_prime_bits:
      44             :  * @session: is a #gnutls_session_t type.
      45             :  * @bits: is the number of bits
      46             :  *
      47             :  * This function sets the number of bits, for use in a Diffie-Hellman
      48             :  * key exchange.  This is used both in DH ephemeral and DH anonymous
      49             :  * cipher suites.  This will set the minimum size of the prime that
      50             :  * will be used for the handshake.
      51             :  *
      52             :  * In the client side it sets the minimum accepted number of bits.  If
      53             :  * a server sends a prime with less bits than that
      54             :  * %GNUTLS_E_DH_PRIME_UNACCEPTABLE will be returned by the handshake.
      55             :  *
      56             :  * Note that this function will warn via the audit log for value that
      57             :  * are believed to be weak.
      58             :  *
      59             :  * The function has no effect in server side.
      60             :  * 
      61             :  * Note that since 3.1.7 this function is deprecated. The minimum
      62             :  * number of bits is set by the priority string level.
      63             :  * Also this function must be called after gnutls_priority_set_direct()
      64             :  * or the set value may be overridden by the selected priority options.
      65             :  *
      66             :  *
      67             :  **/
      68        1974 : void gnutls_dh_set_prime_bits(gnutls_session_t session, unsigned int bits)
      69             : {
      70        1974 :         if (bits < gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, GNUTLS_SEC_PARAM_WEAK)
      71           0 :                 && bits != 0)
      72           0 :                 _gnutls_audit_log(session,
      73             :                                   "Note that the security level of the Diffie-Hellman key exchange has been lowered to %u bits and this may allow decryption of the session data\n",
      74             :                                   bits);
      75        1974 :         session->internals.dh_prime_bits = bits;
      76        1974 : }
      77             : 
      78             : 
      79             : /**
      80             :  * gnutls_dh_get_group:
      81             :  * @session: is a gnutls session
      82             :  * @raw_gen: will hold the generator.
      83             :  * @raw_prime: will hold the prime.
      84             :  *
      85             :  * This function will return the group parameters used in the last
      86             :  * Diffie-Hellman key exchange with the peer.  These are the prime and
      87             :  * the generator used.  This function should be used for both
      88             :  * anonymous and ephemeral Diffie-Hellman.  The output parameters must
      89             :  * be freed with gnutls_free().
      90             :  *
      91             :  * Note, that the prime and generator are exported as non-negative
      92             :  * integers and may include a leading zero byte.
      93             :  *
      94             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
      95             :  *   an error code is returned.
      96             :  **/
      97             : int
      98        1004 : gnutls_dh_get_group(gnutls_session_t session,
      99             :                     gnutls_datum_t * raw_gen, gnutls_datum_t * raw_prime)
     100             : {
     101        1004 :         dh_info_st *dh;
     102        1004 :         int ret;
     103        1004 :         anon_auth_info_t anon_info;
     104        1004 :         cert_auth_info_t cert_info;
     105        1004 :         psk_auth_info_t psk_info;
     106             : 
     107        1004 :         switch (gnutls_auth_get_type(session)) {
     108             :         case GNUTLS_CRD_ANON:
     109           0 :                 anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
     110           0 :                 if (anon_info == NULL)
     111           0 :                         return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     112           0 :                 dh = &anon_info->dh;
     113           0 :                 break;
     114             :         case GNUTLS_CRD_PSK:
     115           2 :                 psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
     116           2 :                 if (psk_info == NULL)
     117           0 :                         return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     118           2 :                 dh = &psk_info->dh;
     119           2 :                 break;
     120             :         case GNUTLS_CRD_CERTIFICATE:
     121        1002 :                 cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
     122        1002 :                 if (cert_info == NULL)
     123           0 :                         return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     124        1002 :                 dh = &cert_info->dh;
     125        1002 :                 break;
     126           0 :         default:
     127           0 :                 gnutls_assert();
     128             :                 return GNUTLS_E_INVALID_REQUEST;
     129             :         }
     130             : 
     131        1004 :         ret = _gnutls_set_datum(raw_prime, dh->prime.data, dh->prime.size);
     132        1004 :         if (ret < 0) {
     133           0 :                 gnutls_assert();
     134           0 :                 return ret;
     135             :         }
     136             : 
     137        1004 :         ret =
     138        2008 :             _gnutls_set_datum(raw_gen, dh->generator.data,
     139        1004 :                               dh->generator.size);
     140        1004 :         if (ret < 0) {
     141           0 :                 gnutls_assert();
     142           0 :                 _gnutls_free_datum(raw_prime);
     143           0 :                 return ret;
     144             :         }
     145             : 
     146             :         return 0;
     147             : }
     148             : 
     149             : /**
     150             :  * gnutls_dh_get_pubkey:
     151             :  * @session: is a gnutls session
     152             :  * @raw_key: will hold the public key.
     153             :  *
     154             :  * This function will return the peer's public key used in the last
     155             :  * Diffie-Hellman key exchange.  This function should be used for both
     156             :  * anonymous and ephemeral Diffie-Hellman.  The output parameters must
     157             :  * be freed with gnutls_free().
     158             :  *
     159             :  * Note, that public key is exported as non-negative
     160             :  * integer and may include a leading zero byte.
     161             :  *
     162             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
     163             :  *   an error code is returned.
     164             :  **/
     165             : int
     166           9 : gnutls_dh_get_pubkey(gnutls_session_t session, gnutls_datum_t * raw_key)
     167             : {
     168           9 :         dh_info_st *dh;
     169           9 :         anon_auth_info_t anon_info;
     170           9 :         cert_auth_info_t cert_info;
     171           9 :         psk_auth_info_t psk_info;
     172             : 
     173           9 :         switch (gnutls_auth_get_type(session)) {
     174             :         case GNUTLS_CRD_ANON:
     175             :                 {
     176           0 :                         anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
     177           0 :                         if (anon_info == NULL)
     178           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     179           0 :                         dh = &anon_info->dh;
     180           0 :                         break;
     181             :                 }
     182             :         case GNUTLS_CRD_PSK:
     183             :                 {
     184           2 :                         psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
     185           2 :                         if (psk_info == NULL)
     186           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     187           2 :                         dh = &psk_info->dh;
     188           2 :                         break;
     189             :                 }
     190             :         case GNUTLS_CRD_CERTIFICATE:
     191             :                 {
     192             : 
     193           6 :                         cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
     194           6 :                         if (cert_info == NULL)
     195           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     196           6 :                         dh = &cert_info->dh;
     197           6 :                         break;
     198             :                 }
     199           1 :         default:
     200           1 :                 gnutls_assert();
     201             :                 return GNUTLS_E_INVALID_REQUEST;
     202             :         }
     203             : 
     204           8 :         return _gnutls_set_datum(raw_key, dh->public_key.data,
     205           8 :                                  dh->public_key.size);
     206             : }
     207             : 
     208             : /**
     209             :  * gnutls_dh_get_secret_bits:
     210             :  * @session: is a gnutls session
     211             :  *
     212             :  * This function will return the bits used in the last Diffie-Hellman
     213             :  * key exchange with the peer.  Should be used for both anonymous and
     214             :  * ephemeral Diffie-Hellman.
     215             :  *
     216             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise
     217             :  *   an error code is returned.
     218             :  **/
     219        1004 : int gnutls_dh_get_secret_bits(gnutls_session_t session)
     220             : {
     221        1004 :         switch (gnutls_auth_get_type(session)) {
     222             :         case GNUTLS_CRD_ANON:
     223             :                 {
     224           0 :                         anon_auth_info_t info;
     225             : 
     226           0 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
     227           0 :                         if (info == NULL)
     228           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     229           0 :                         return info->dh.secret_bits;
     230             :                 }
     231             :         case GNUTLS_CRD_PSK:
     232             :                 {
     233           2 :                         psk_auth_info_t info;
     234             : 
     235           2 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
     236           2 :                         if (info == NULL)
     237           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     238           2 :                         return info->dh.secret_bits;
     239             :                 }
     240             :         case GNUTLS_CRD_CERTIFICATE:
     241             :                 {
     242        1002 :                         cert_auth_info_t info;
     243             : 
     244        1002 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
     245        1002 :                         if (info == NULL)
     246           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     247             : 
     248        1002 :                         return info->dh.secret_bits;
     249             :                 }
     250           0 :         default:
     251           0 :                 gnutls_assert();
     252             :                 return GNUTLS_E_INVALID_REQUEST;
     253             :         }
     254             : }
     255             : 
     256             : 
     257        3044 : static int mpi_buf2bits(gnutls_datum_t * mpi_buf)
     258             : {
     259        3044 :         bigint_t mpi;
     260        3044 :         int rc;
     261             : 
     262        3044 :         rc = _gnutls_mpi_init_scan_nz(&mpi, mpi_buf->data, mpi_buf->size);
     263        3044 :         if (rc) {
     264           0 :                 gnutls_assert();
     265           0 :                 return rc;
     266             :         }
     267             : 
     268        3044 :         rc = _gnutls_mpi_get_nbits(mpi);
     269        3044 :         _gnutls_mpi_release(&mpi);
     270             : 
     271             :         return rc;
     272             : }
     273             : 
     274             : /**
     275             :  * gnutls_dh_get_prime_bits:
     276             :  * @session: is a gnutls session
     277             :  *
     278             :  * This function will return the bits of the prime used in the last
     279             :  * Diffie-Hellman key exchange with the peer.  Should be used for both
     280             :  * anonymous and ephemeral Diffie-Hellman.  Note that some ciphers,
     281             :  * like RSA and DSA without DHE, do not use a Diffie-Hellman key
     282             :  * exchange, and then this function will return 0.
     283             :  *
     284             :  * Returns: The Diffie-Hellman bit strength is returned, or 0 if no
     285             :  *   Diffie-Hellman key exchange was done, or a negative error code on
     286             :  *   failure.
     287             :  **/
     288        2385 : int gnutls_dh_get_prime_bits(gnutls_session_t session)
     289             : {
     290        2385 :         dh_info_st *dh;
     291             : 
     292        2385 :         switch (gnutls_auth_get_type(session)) {
     293             :         case GNUTLS_CRD_ANON:
     294             :                 {
     295           0 :                         anon_auth_info_t info;
     296             : 
     297           0 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
     298           0 :                         if (info == NULL)
     299           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     300           0 :                         dh = &info->dh;
     301           0 :                         break;
     302             :                 }
     303             :         case GNUTLS_CRD_PSK:
     304             :                 {
     305           2 :                         psk_auth_info_t info;
     306             : 
     307           2 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
     308           2 :                         if (info == NULL)
     309           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     310           2 :                         dh = &info->dh;
     311           2 :                         break;
     312             :                 }
     313             :         case GNUTLS_CRD_CERTIFICATE:
     314             :                 {
     315        2042 :                         cert_auth_info_t info;
     316             : 
     317        2042 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
     318        2042 :                         if (info == NULL)
     319           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     320             : 
     321        2042 :                         dh = &info->dh;
     322        2042 :                         break;
     323             :                 }
     324         341 :         default:
     325         341 :                 gnutls_assert();
     326             :                 return GNUTLS_E_INVALID_REQUEST;
     327             :         }
     328             : 
     329        2044 :         if(dh->prime.size == 0)
     330             :                 return 0;
     331             : 
     332        2044 :         return mpi_buf2bits(&dh->prime);
     333             : }
     334             : 
     335             : 
     336             : /**
     337             :  * gnutls_dh_get_peers_public_bits:
     338             :  * @session: is a gnutls session
     339             :  *
     340             :  * Get the Diffie-Hellman public key bit size.  Can be used for both
     341             :  * anonymous and ephemeral Diffie-Hellman.
     342             :  *
     343             :  * Returns: The public key bit size used in the last Diffie-Hellman
     344             :  *   key exchange with the peer, or a negative error code in case of error.
     345             :  **/
     346        1000 : int gnutls_dh_get_peers_public_bits(gnutls_session_t session)
     347             : {
     348        1000 :         dh_info_st *dh;
     349             : 
     350        1000 :         switch (gnutls_auth_get_type(session)) {
     351             :         case GNUTLS_CRD_ANON:
     352             :                 {
     353           0 :                         anon_auth_info_t info;
     354             : 
     355           0 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON);
     356           0 :                         if (info == NULL)
     357           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     358             : 
     359           0 :                         dh = &info->dh;
     360           0 :                         break;
     361             :                 }
     362             :         case GNUTLS_CRD_PSK:
     363             :                 {
     364           0 :                         psk_auth_info_t info;
     365             : 
     366           0 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK);
     367           0 :                         if (info == NULL)
     368           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     369             : 
     370           0 :                         dh = &info->dh;
     371           0 :                         break;
     372             :                 }
     373             :         case GNUTLS_CRD_CERTIFICATE:
     374             :                 {
     375        1000 :                         cert_auth_info_t info;
     376             : 
     377        1000 :                         info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE);
     378        1000 :                         if (info == NULL)
     379           0 :                                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     380             : 
     381        1000 :                         dh = &info->dh;
     382        1000 :                         break;
     383             :                 }
     384           0 :         default:
     385           0 :                 gnutls_assert();
     386             :                 return GNUTLS_E_INVALID_REQUEST;
     387             :         }
     388             : 
     389        1000 :         return mpi_buf2bits(&dh->public_key);
     390             : }
     391             : 
     392             : #endif                          /* DH */
     393             : 

Generated by: LCOV version 1.14