LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/auth - dh_common.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 162 185 87.6 %
Date: 2020-10-30 04:50:48 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2002-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             : /* This file contains common stuff in Ephemeral Diffie-Hellman (DHE)
      24             :  * and Anonymous DH key exchange(DHA). These are used in the handshake
      25             :  * procedure of the certificate and anonymous authentication.
      26             :  */
      27             : 
      28             : #include "gnutls_int.h"
      29             : #include "auth.h"
      30             : #include "errors.h"
      31             : #include "dh.h"
      32             : #include "num.h"
      33             : #include "tls-sig.h"
      34             : #include <datum.h>
      35             : #include <x509.h>
      36             : #include <state.h>
      37             : #include <pk.h>
      38             : #include <auth/dh_common.h>
      39             : #include <algorithms.h>
      40             : #include <auth/psk.h>
      41             : 
      42             : #if defined(ENABLE_DHE) || defined(ENABLE_ANON)
      43             : 
      44             : /* Frees the dh_info_st structure.
      45             :  */
      46       13454 : void _gnutls_free_dh_info(dh_info_st * dh)
      47             : {
      48       13454 :         dh->secret_bits = 0;
      49       13454 :         _gnutls_free_datum(&dh->prime);
      50       13454 :         _gnutls_free_datum(&dh->generator);
      51       13454 :         _gnutls_free_datum(&dh->public_key);
      52       13454 : }
      53             : 
      54             : int
      55        2004 : _gnutls_proc_dh_common_client_kx(gnutls_session_t session,
      56             :                                  uint8_t * data, size_t _data_size,
      57             :                                  gnutls_datum_t * psk_key)
      58             : {
      59        2004 :         uint16_t n_Y;
      60        2004 :         size_t _n_Y;
      61        2004 :         int ret;
      62        2004 :         ssize_t data_size = _data_size;
      63        2004 :         gnutls_datum_t tmp_dh_key = {NULL, 0};
      64        2004 :         gnutls_pk_params_st peer_pub;
      65             :         
      66        2004 :         gnutls_pk_params_init(&peer_pub);
      67             : 
      68        2004 :         DECR_LEN(data_size, 2);
      69        2002 :         n_Y = _gnutls_read_uint16(&data[0]);
      70        2002 :         _n_Y = n_Y;
      71             : 
      72        2002 :         DECR_LEN(data_size, n_Y);
      73             : 
      74        1999 :         if (data_size != 0)
      75           4 :                 return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
      76             : 
      77        1996 :         if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.client_Y, &data[2], _n_Y)) {
      78           4 :                 gnutls_assert();
      79           4 :                 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER; /* most likely zero or illegal size */
      80             :         }
      81             : 
      82        1992 :         _gnutls_dh_set_peer_public(session, session->key.proto.tls12.dh.client_Y);
      83             : 
      84        1992 :         peer_pub.params[DH_Y] = session->key.proto.tls12.dh.client_Y;
      85             : 
      86             :         /* calculate the key after calculating the message */
      87        1992 :         ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.proto.tls12.dh.params, &peer_pub);
      88        1992 :         if (ret < 0) {
      89          10 :                 gnutls_assert();
      90          10 :                 goto error;
      91             :         }
      92             : 
      93        1982 :         if (psk_key == NULL) {
      94        1629 :                 session->key.key.data = tmp_dh_key.data;
      95        1629 :                 session->key.key.size = tmp_dh_key.size;
      96             :         } else {                /* In DHE_PSK the key is set differently */
      97         353 :                 ret =
      98         353 :                     _gnutls_set_psk_session_key(session, psk_key,
      99             :                                                 &tmp_dh_key);
     100         353 :                 _gnutls_free_temp_key_datum(&tmp_dh_key);
     101             :         }
     102             :         
     103        1982 :         if (ret < 0) {
     104           0 :                 gnutls_assert();
     105           0 :                 goto error;
     106             :         }
     107             : 
     108             :         ret = 0;
     109        1992 :  error:
     110        1992 :         _gnutls_mpi_release(&session->key.proto.tls12.dh.client_Y);
     111        1992 :         gnutls_pk_params_clear(&session->key.proto.tls12.dh.params);
     112             : 
     113        1992 :         return ret;
     114             : }
     115             : 
     116         193 : int _gnutls_gen_dh_common_client_kx(gnutls_session_t session,
     117             :                                     gnutls_buffer_st * data)
     118             : {
     119         193 :         return _gnutls_gen_dh_common_client_kx_int(session, data, NULL);
     120             : }
     121             : 
     122             : int
     123         223 : _gnutls_gen_dh_common_client_kx_int(gnutls_session_t session,
     124             :                                     gnutls_buffer_st * data,
     125             :                                     gnutls_datum_t * pskkey)
     126             : {
     127         223 :         int ret;
     128         223 :         gnutls_pk_params_st peer_pub;
     129         223 :         gnutls_datum_t tmp_dh_key = {NULL, 0};
     130         223 :         unsigned init_pos = data->length;
     131             :         
     132         223 :         gnutls_pk_params_init(&peer_pub);
     133             : 
     134         223 :         ret =
     135         223 :             _gnutls_pk_generate_keys(GNUTLS_PK_DH, 0,
     136             :                                      &session->key.proto.tls12.dh.params, 1);
     137         223 :         if (ret < 0)
     138           1 :                 return gnutls_assert_val(ret);
     139             : 
     140         222 :         _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_X]));
     141             : 
     142         222 :         ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_Y], 0);
     143         222 :         if (ret < 0) {
     144           0 :                 gnutls_assert();
     145           0 :                 goto error;
     146             :         }
     147             :         
     148         222 :         peer_pub.params[DH_Y] = session->key.proto.tls12.dh.client_Y;
     149             : 
     150             :         /* calculate the key after calculating the message */
     151         222 :         ret = _gnutls_pk_derive(GNUTLS_PK_DH, &tmp_dh_key, &session->key.proto.tls12.dh.params, &peer_pub);
     152         222 :         if (ret < 0) {
     153           2 :                 gnutls_assert();
     154           2 :                 goto error;
     155             :         }
     156             : 
     157         220 :         if (session->security_parameters.cs->kx_algorithm != GNUTLS_KX_DHE_PSK) {
     158         193 :                 session->key.key.data = tmp_dh_key.data;
     159         193 :                 session->key.key.size = tmp_dh_key.size;
     160             :         } else {                /* In DHE_PSK the key is set differently */
     161          27 :                 ret =
     162          27 :                     _gnutls_set_psk_session_key(session, pskkey,
     163             :                                                 &tmp_dh_key);
     164          27 :                 _gnutls_free_temp_key_datum(&tmp_dh_key);
     165             :         }
     166             : 
     167         220 :         if (ret < 0) {
     168           0 :                 gnutls_assert();
     169           0 :                 goto error;
     170             :         }
     171             : 
     172         220 :         ret = data->length - init_pos;
     173             : 
     174         222 :  error:
     175         222 :         gnutls_pk_params_clear(&session->key.proto.tls12.dh.params);
     176         222 :         return ret;
     177             : }
     178             : 
     179             : /* Returns the bytes parsed */
     180             : int
     181         245 : _gnutls_proc_dh_common_server_kx(gnutls_session_t session,
     182             :                                  uint8_t * data, size_t _data_size)
     183             : {
     184         245 :         uint16_t n_Y, n_g, n_p;
     185         245 :         size_t _n_Y, _n_g, _n_p, _n_q;
     186         245 :         uint8_t *data_p;
     187         245 :         uint8_t *data_g;
     188         245 :         uint8_t *data_Y;
     189         245 :         uint8_t *data_q = NULL;
     190         245 :         int i, bits, ret, p_bits;
     191         245 :         unsigned j;
     192         245 :         ssize_t data_size = _data_size;
     193             : 
     194             :         /* just in case we are resuming a session */
     195         245 :         gnutls_pk_params_release(&session->key.proto.tls12.dh.params);
     196             : 
     197         245 :         gnutls_pk_params_init(&session->key.proto.tls12.dh.params);
     198             : 
     199         245 :         i = 0;
     200             : 
     201         245 :         DECR_LEN(data_size, 2);
     202         244 :         n_p = _gnutls_read_uint16(&data[i]);
     203         244 :         i += 2;
     204             : 
     205         244 :         DECR_LEN(data_size, n_p);
     206         242 :         data_p = &data[i];
     207         242 :         i += n_p;
     208             : 
     209         242 :         DECR_LEN(data_size, 2);
     210         242 :         n_g = _gnutls_read_uint16(&data[i]);
     211         242 :         i += 2;
     212             : 
     213         242 :         DECR_LEN(data_size, n_g);
     214         240 :         data_g = &data[i];
     215         240 :         i += n_g;
     216             : 
     217         240 :         DECR_LEN(data_size, 2);
     218         239 :         n_Y = _gnutls_read_uint16(&data[i]);
     219         239 :         i += 2;
     220             : 
     221         239 :         DECR_LEN(data_size, n_Y);
     222         237 :         data_Y = &data[i];
     223             : 
     224         237 :         _n_Y = n_Y;
     225         237 :         _n_g = n_g;
     226         237 :         _n_p = n_p;
     227             : 
     228         237 :         if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.client_Y, data_Y, _n_Y) != 0) {
     229           2 :                 gnutls_assert();
     230           2 :                 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
     231             :         }
     232             : 
     233             :         /* if we are doing RFC7919 */
     234         235 :         if (session->internals.priorities->groups.have_ffdhe != 0) {
     235             :                 /* verify whether the received parameters match the advertised, otherwise
     236             :                  * log that. */
     237         419 :                 for (j=0;j<session->internals.priorities->groups.size;j++) {
     238         403 :                         if (session->internals.priorities->groups.entry[j]->generator &&
     239         268 :                             session->internals.priorities->groups.entry[j]->generator->size == n_g &&
     240         248 :                             session->internals.priorities->groups.entry[j]->prime->size == n_p &&
     241         174 :                             memcmp(session->internals.priorities->groups.entry[j]->generator->data,
     242         171 :                                    data_g, n_g) == 0 &&
     243         171 :                             memcmp(session->internals.priorities->groups.entry[j]->prime->data,
     244             :                                    data_p, n_p) == 0) {
     245             : 
     246         169 :                                 session->internals.hsk_flags |= HSK_USED_FFDHE;
     247         169 :                                 _gnutls_session_group_set(session, session->internals.priorities->groups.entry[j]);
     248         169 :                                 session->key.proto.tls12.dh.params.qbits = *session->internals.priorities->groups.entry[j]->q_bits;
     249         169 :                                 data_q = session->internals.priorities->groups.entry[j]->q->data;
     250         169 :                                 _n_q = session->internals.priorities->groups.entry[j]->q->size;
     251         169 :                                 break;
     252             :                         }
     253             :                 }
     254             : 
     255         185 :                 if (!(session->internals.hsk_flags & HSK_USED_FFDHE)) {
     256          16 :                         _gnutls_audit_log(session, "FFDHE groups advertised, but server didn't support it; falling back to server's choice\n");
     257             :                 }
     258             :         }
     259             : 
     260             : #ifdef ENABLE_FIPS140
     261             :         if (gnutls_fips140_mode_enabled() &&
     262             :             !_gnutls_dh_prime_match_fips_approved(data_p, n_p, data_g, n_g, NULL, NULL)) {
     263             :                 gnutls_assert();
     264             :                 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
     265             :         }
     266             : #endif
     267             : 
     268         235 :         if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.params.params[DH_G], data_g, _n_g) != 0) {
     269           2 :                 gnutls_assert();
     270           2 :                 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
     271             :         }
     272             : 
     273         233 :         if (_gnutls_mpi_init_scan_nz(&session->key.proto.tls12.dh.params.params[DH_P], data_p, _n_p) != 0) {
     274           1 :                 gnutls_assert();
     275             :                 /* we release now because session->key.proto.tls12.dh.params.params_nr is not yet set */
     276           1 :                 _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_G]);
     277           1 :                 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
     278             :         }
     279         232 :         if (data_q && _gnutls_mpi_init_scan_nz(
     280             :                             &session->key.proto.tls12.dh.params.params[DH_Q],
     281             :                             data_q, _n_q) != 0) {
     282             :                 /* we release now because params_nr is not yet set */
     283           0 :                 _gnutls_mpi_release(
     284             :                         &session->key.proto.tls12.dh.params.params[DH_P]);
     285           0 :                 _gnutls_mpi_release(
     286             :                         &session->key.proto.tls12.dh.params.params[DH_G]);
     287           0 :                 return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
     288             :         }
     289             : 
     290             :         /* include, possibly empty, q */
     291         232 :         session->key.proto.tls12.dh.params.params_nr = 3;
     292         232 :         session->key.proto.tls12.dh.params.algo = GNUTLS_PK_DH;
     293             : 
     294         232 :         if (!(session->internals.hsk_flags & HSK_USED_FFDHE)) {
     295          63 :                 bits = _gnutls_dh_get_min_prime_bits(session);
     296          63 :                 if (bits < 0) {
     297           0 :                         gnutls_assert();
     298           0 :                         return bits;
     299             :                 }
     300             : 
     301          63 :                 p_bits = _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_P]);
     302          63 :                 if (p_bits < bits) {
     303             :                         /* the prime used by the peer is not acceptable
     304             :                          */
     305           0 :                         gnutls_assert();
     306           0 :                         _gnutls_debug_log
     307             :                             ("Received a prime of %u bits, limit is %u\n",
     308             :                              (unsigned) _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_P]),
     309             :                              (unsigned) bits);
     310           0 :                         return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
     311             :                 }
     312             : 
     313          63 :                 if (p_bits >= DEFAULT_MAX_VERIFY_BITS) {
     314           1 :                         gnutls_assert();
     315           1 :                         _gnutls_debug_log
     316             :                             ("Received a prime of %u bits, limit is %u\n",
     317             :                              (unsigned) p_bits,
     318             :                              (unsigned) DEFAULT_MAX_VERIFY_BITS);
     319           1 :                         return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
     320             :                 }
     321             :         }
     322             : 
     323         231 :         _gnutls_dh_save_group(session, session->key.proto.tls12.dh.params.params[DH_G],
     324             :                              session->key.proto.tls12.dh.params.params[DH_P]);
     325         231 :         _gnutls_dh_set_peer_public(session, session->key.proto.tls12.dh.client_Y);
     326             : 
     327         231 :         ret = n_Y + n_p + n_g + 6;
     328             : 
     329         231 :         return ret;
     330             : }
     331             : 
     332             : int
     333        2166 : _gnutls_dh_common_print_server_kx(gnutls_session_t session,
     334             :                                   gnutls_buffer_st * data)
     335             : {
     336        2166 :         int ret;
     337        2166 :         unsigned q_bits = session->key.proto.tls12.dh.params.qbits;
     338        2166 :         unsigned init_pos = data->length;
     339             : 
     340        2166 :         if (q_bits < 192 && q_bits != 0) {
     341           0 :                 gnutls_assert();
     342           0 :                 _gnutls_debug_log("too small q_bits value for DH: %u\n", q_bits);
     343             :                 q_bits = 0; /* auto-detect */
     344             :         }
     345             : 
     346             :         /* Y=g^x mod p */
     347        2166 :         ret =
     348        2166 :             _gnutls_pk_generate_keys(GNUTLS_PK_DH, q_bits,
     349             :                                      &session->key.proto.tls12.dh.params, 1);
     350        2166 :         if (ret < 0)
     351           0 :                 return gnutls_assert_val(ret);
     352             : 
     353        2166 :         _gnutls_dh_set_secret_bits(session, _gnutls_mpi_get_nbits(session->key.proto.tls12.dh.params.params[DH_X]));
     354             : 
     355        2166 :         ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_P], 0);
     356        2166 :         if (ret < 0) {
     357           0 :                 gnutls_assert();
     358           0 :                 goto cleanup;
     359             :         }
     360             : 
     361        2166 :         ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_G], 0);
     362        2166 :         if (ret < 0) {
     363           0 :                 gnutls_assert();
     364           0 :                 goto cleanup;
     365             :         }
     366             : 
     367        2166 :         ret = _gnutls_buffer_append_mpi(data, 16, session->key.proto.tls12.dh.params.params[DH_Y], 0);
     368        2166 :         if (ret < 0) {
     369           0 :                 gnutls_assert();
     370           0 :                 goto cleanup;
     371             :         }
     372             : 
     373        2166 :         ret = data->length - init_pos;
     374             : 
     375             : cleanup:
     376             :         return ret;
     377             : }
     378             : 
     379             : #endif

Generated by: LCOV version 1.14