LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib - dh.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 228 327 69.7 %
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) 2000-2012 Free Software Foundation, Inc.
       3             :  * Copyright (C) 2017 Red Hat, Inc.
       4             :  *
       5             :  * Author: Nikos Mavrogiannopoulos
       6             :  *
       7             :  * This file is part of GnuTLS.
       8             :  *
       9             :  * The GnuTLS is free software; you can redistribute it and/or
      10             :  * modify it under the terms of the GNU Lesser General Public License
      11             :  * as published by the Free Software Foundation; either version 2.1 of
      12             :  * the License, or (at your option) any later version.
      13             :  *
      14             :  * This library is distributed in the hope that it will be useful, but
      15             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      17             :  * Lesser General Public License for more details.
      18             :  *
      19             :  * You should have received a copy of the GNU Lesser General Public License
      20             :  * along with this program.  If not, see <https://www.gnu.org/licenses/>
      21             :  *
      22             :  */
      23             : 
      24             : #include "gnutls_int.h"
      25             : #include "errors.h"
      26             : #include <datum.h>
      27             : #include <x509_b64.h>             /* for PKCS3 PEM decoding */
      28             : #include <global.h>
      29             : #include <dh.h>
      30             : #include <pk.h>
      31             : #include <x509/common.h>
      32             : #include <gnutls/crypto.h>
      33             : #include "x509/x509_int.h"
      34             : #include <mpi.h>
      35             : #include "debug.h"
      36             : #include "state.h"
      37             : 
      38             : static
      39        2166 : int set_dh_pk_params(gnutls_session_t session, bigint_t g, bigint_t p,
      40             :                      bigint_t q, unsigned q_bits)
      41             : {
      42             :         /* just in case we are resuming a session */
      43        2166 :         gnutls_pk_params_release(&session->key.proto.tls12.dh.params);
      44             : 
      45        2166 :         gnutls_pk_params_init(&session->key.proto.tls12.dh.params);
      46             : 
      47        2166 :         session->key.proto.tls12.dh.params.params[DH_G] = _gnutls_mpi_copy(g);
      48        2166 :         if (session->key.proto.tls12.dh.params.params[DH_G] == NULL)
      49           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
      50             : 
      51        2166 :         session->key.proto.tls12.dh.params.params[DH_P] = _gnutls_mpi_copy(p);
      52        2166 :         if (session->key.proto.tls12.dh.params.params[DH_P] == NULL) {
      53           0 :                 _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_G]);
      54           0 :                 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
      55             :         }
      56             : 
      57        2166 :         if (q) {
      58         570 :                 session->key.proto.tls12.dh.params.params[DH_Q] = _gnutls_mpi_copy(q);
      59         570 :                 if (session->key.proto.tls12.dh.params.params[DH_Q] == NULL) {
      60           0 :                         _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_P]);
      61           0 :                         _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_G]);
      62           0 :                         return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
      63             :                 }
      64             :         }
      65             :         /* include, possibly empty, q */
      66        2166 :         session->key.proto.tls12.dh.params.params_nr = 3;
      67        2166 :         session->key.proto.tls12.dh.params.algo = GNUTLS_PK_DH;
      68        2166 :         session->key.proto.tls12.dh.params.qbits = q_bits;
      69             : 
      70        2166 :         return 0;
      71             : }
      72             : 
      73             : /* Use all available information to decide the DH parameters to use,
      74             :  * that being the negotiated RFC7919 group, the callback, and the
      75             :  * provided parameters structure.
      76             :  */
      77             : int
      78        2166 : _gnutls_figure_dh_params(gnutls_session_t session, gnutls_dh_params_t dh_params,
      79             :                       gnutls_params_function * func, gnutls_sec_param_t sec_param)
      80             : {
      81        2166 :         gnutls_params_st params;
      82        2166 :         bigint_t p, g, q = NULL;
      83        2166 :         unsigned free_pg = 0;
      84        2166 :         int ret;
      85        2166 :         unsigned q_bits = 0, i;
      86        2166 :         const gnutls_group_entry_st *group;
      87             : 
      88        2166 :         group = get_group(session);
      89             : 
      90        2166 :         params.deinit = 0;
      91             : 
      92             :         /* if we negotiated RFC7919 FFDHE */
      93        2166 :         if (group && group->pk == GNUTLS_PK_DH) {
      94        1539 :                 for (i=0;i<session->internals.priorities->groups.size;i++) {
      95        1539 :                         if (session->internals.priorities->groups.entry[i] == group) {
      96        1140 :                                 ret = _gnutls_mpi_init_scan_nz(&p,
      97         570 :                                                 session->internals.priorities->groups.entry[i]->prime->data,
      98         570 :                                                 session->internals.priorities->groups.entry[i]->prime->size);
      99         570 :                                 if (ret < 0)
     100           0 :                                         return gnutls_assert_val(ret);
     101             : 
     102         570 :                                 free_pg = 1;
     103             : 
     104        1140 :                                 ret = _gnutls_mpi_init_scan_nz(&g,
     105         570 :                                                 session->internals.priorities->groups.entry[i]->generator->data,
     106         570 :                                                 session->internals.priorities->groups.entry[i]->generator->size);
     107         570 :                                 if (ret < 0) {
     108           0 :                                         gnutls_assert();
     109           0 :                                         goto cleanup;
     110             :                                 }
     111             : 
     112        1140 :                                 ret = _gnutls_mpi_init_scan_nz(&q,
     113         570 :                                                 session->internals.priorities->groups.entry[i]->q->data,
     114         570 :                                                 session->internals.priorities->groups.entry[i]->q->size);
     115         570 :                                 if (ret < 0) {
     116           0 :                                         gnutls_assert();
     117           0 :                                         goto cleanup;
     118             :                                 }
     119             : 
     120         570 :                                 session->internals.hsk_flags |= HSK_USED_FFDHE;
     121         570 :                                 q_bits = *session->internals.priorities->groups.entry[i]->q_bits;
     122         570 :                                 goto finished;
     123             :                         }
     124             :                 }
     125             : 
     126             :                 /* didn't find anything, that shouldn't have occurred
     127             :                  * as we received that extension */
     128           0 :                 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
     129        1596 :         } else if (sec_param) {
     130        1514 :                 unsigned bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, sec_param)/8;
     131             : 
     132        8969 :                 for (i=0;i<session->internals.priorities->groups.size;i++) {
     133        8952 :                         if (!session->internals.priorities->groups.entry[i]->prime)
     134        7455 :                                 continue;
     135             : 
     136        1497 :                         if (bits <= session->internals.priorities->groups.entry[i]->prime->size) {
     137        2994 :                                 ret = _gnutls_mpi_init_scan_nz(&p,
     138        1497 :                                                 session->internals.priorities->groups.entry[i]->prime->data,
     139             :                                                 session->internals.priorities->groups.entry[i]->prime->size);
     140        1497 :                                 if (ret < 0)
     141           0 :                                         return gnutls_assert_val(ret);
     142             : 
     143        1497 :                                 free_pg = 1;
     144             : 
     145        2994 :                                 ret = _gnutls_mpi_init_scan_nz(&g,
     146        1497 :                                                 session->internals.priorities->groups.entry[i]->generator->data,
     147        1497 :                                                 session->internals.priorities->groups.entry[i]->generator->size);
     148        1497 :                                 if (ret < 0) {
     149           0 :                                         gnutls_assert();
     150           0 :                                         goto cleanup;
     151             :                                 }
     152             : 
     153        1497 :                                 q_bits = *session->internals.priorities->groups.entry[i]->q_bits;
     154        1497 :                                 goto finished;
     155             :                         }
     156             :                 }
     157             : 
     158             :         }
     159             : 
     160          99 :         if (dh_params) {
     161          17 :                 p = dh_params->params[0];
     162          17 :                 g = dh_params->params[1];
     163          17 :                 q_bits = dh_params->q_bits;
     164          82 :         } else if (func) {
     165          82 :                 ret = func(session, GNUTLS_PARAMS_DH, &params);
     166          82 :                 if (ret == 0 && params.type == GNUTLS_PARAMS_DH) {
     167          82 :                         p = params.params.dh->params[0];
     168          82 :                         g = params.params.dh->params[1];
     169          82 :                         q_bits = params.params.dh->q_bits;
     170             :                 } else
     171           0 :                         return gnutls_assert_val(GNUTLS_E_NO_TEMPORARY_DH_PARAMS);
     172             :         } else
     173           0 :                 return gnutls_assert_val(GNUTLS_E_NO_TEMPORARY_DH_PARAMS);
     174             : 
     175        2166 :  finished:
     176        2166 :         _gnutls_dh_save_group(session, g, p);
     177             : 
     178        2166 :         ret = set_dh_pk_params(session, g, p, q, q_bits);
     179        2166 :         if (ret < 0) {
     180           0 :                 gnutls_assert();
     181             :         }
     182             : 
     183        2166 :  cleanup:
     184        2166 :         if (free_pg) {
     185        2067 :                 _gnutls_mpi_release(&p);
     186        2067 :                 _gnutls_mpi_release(&q);
     187        2067 :                 _gnutls_mpi_release(&g);
     188             :         }
     189        2166 :         if (params.deinit && params.type == GNUTLS_PARAMS_DH)
     190           0 :                 gnutls_dh_params_deinit(params.params.dh);
     191             : 
     192             :         return ret;
     193             : 
     194             : }
     195             : 
     196             : /* returns the prime and the generator of DH params.
     197             :  */
     198           0 : const bigint_t *_gnutls_dh_params_to_mpi(gnutls_dh_params_t dh_primes)
     199             : {
     200           0 :         if (dh_primes == NULL || dh_primes->params[1] == NULL ||
     201           0 :             dh_primes->params[0] == NULL) {
     202             :                 return NULL;
     203             :         }
     204             : 
     205           0 :         return dh_primes->params;
     206             : }
     207             : 
     208             : 
     209             : /**
     210             :  * gnutls_dh_params_import_raw:
     211             :  * @dh_params: The parameters
     212             :  * @prime: holds the new prime
     213             :  * @generator: holds the new generator
     214             :  *
     215             :  * This function will replace the pair of prime and generator for use
     216             :  * in the Diffie-Hellman key exchange.  The new parameters should be
     217             :  * stored in the appropriate gnutls_datum.
     218             :  *
     219             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     220             :  *   otherwise a negative error code is returned.
     221             :  **/
     222             : int
     223        1000 : gnutls_dh_params_import_raw(gnutls_dh_params_t dh_params,
     224             :                             const gnutls_datum_t * prime,
     225             :                             const gnutls_datum_t * generator)
     226             : {
     227        1000 :         return gnutls_dh_params_import_raw2(dh_params, prime, generator, 0);
     228             : }
     229             : 
     230             : /**
     231             :  * gnutls_dh_params_import_dsa:
     232             :  * @dh_params: The parameters
     233             :  * @key: holds a DSA private key
     234             :  *
     235             :  * This function will import the prime and generator of the DSA key for use 
     236             :  * in the Diffie-Hellman key exchange.
     237             :  *
     238             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     239             :  *   otherwise a negative error code is returned.
     240             :  **/
     241             : int
     242           3 : gnutls_dh_params_import_dsa(gnutls_dh_params_t dh_params, gnutls_x509_privkey_t key)
     243             : {
     244           3 :         gnutls_datum_t p, g, q;
     245           3 :         int ret;
     246             : 
     247           3 :         ret = gnutls_x509_privkey_export_dsa_raw(key, &p, &q, &g, NULL, NULL);
     248           3 :         if (ret < 0)
     249           0 :                 return gnutls_assert_val(ret);
     250             : 
     251           3 :         ret = gnutls_dh_params_import_raw3(dh_params, &p, &q, &g);
     252             : 
     253           3 :         gnutls_free(p.data);
     254           3 :         gnutls_free(g.data);
     255           3 :         gnutls_free(q.data);
     256             : 
     257           3 :         return ret;
     258             : }
     259             : 
     260             : /**
     261             :  * gnutls_dh_params_import_raw2:
     262             :  * @dh_params: The parameters
     263             :  * @prime: holds the new prime
     264             :  * @generator: holds the new generator
     265             :  * @key_bits: the private key bits (set to zero when unknown)
     266             :  *
     267             :  * This function will replace the pair of prime and generator for use
     268             :  * in the Diffie-Hellman key exchange.  The new parameters should be
     269             :  * stored in the appropriate gnutls_datum.
     270             :  *
     271             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     272             :  *   otherwise a negative error code is returned.
     273             :  **/
     274             : int
     275        1000 : gnutls_dh_params_import_raw2(gnutls_dh_params_t dh_params,
     276             :                              const gnutls_datum_t * prime,
     277             :                              const gnutls_datum_t * generator,
     278             :                              unsigned key_bits)
     279             : {
     280        1000 :         bigint_t tmp_prime, tmp_g;
     281        1000 :         size_t siz;
     282             : 
     283        1000 :         siz = prime->size;
     284        1000 :         if (_gnutls_mpi_init_scan_nz(&tmp_prime, prime->data, siz)) {
     285           0 :                 gnutls_assert();
     286           0 :                 return GNUTLS_E_MPI_SCAN_FAILED;
     287             :         }
     288             : 
     289        1000 :         siz = generator->size;
     290        1000 :         if (_gnutls_mpi_init_scan_nz(&tmp_g, generator->data, siz)) {
     291           0 :                 _gnutls_mpi_release(&tmp_prime);
     292           0 :                 gnutls_assert();
     293           0 :                 return GNUTLS_E_MPI_SCAN_FAILED;
     294             :         }
     295             : 
     296             :         /* store the generated values
     297             :          */
     298        1000 :         dh_params->params[0] = tmp_prime;
     299        1000 :         dh_params->params[1] = tmp_g;
     300        1000 :         dh_params->q_bits = key_bits;
     301             : 
     302        1000 :         return 0;
     303             : }
     304             : 
     305             : /**
     306             :  * gnutls_dh_params_import_raw3:
     307             :  * @dh_params: The parameters
     308             :  * @prime: holds the new prime
     309             :  * @q: holds the subgroup if available, otherwise NULL
     310             :  * @generator: holds the new generator
     311             :  *
     312             :  * This function will replace the pair of prime and generator for use
     313             :  * in the Diffie-Hellman key exchange.  The new parameters should be
     314             :  * stored in the appropriate gnutls_datum.
     315             :  *
     316             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     317             :  *   otherwise a negative error code is returned.
     318             :  **/
     319             : int
     320           3 : gnutls_dh_params_import_raw3(gnutls_dh_params_t dh_params,
     321             :                              const gnutls_datum_t * prime,
     322             :                              const gnutls_datum_t * q,
     323             :                              const gnutls_datum_t * generator)
     324             : {
     325           3 :         bigint_t tmp_p, tmp_g, tmp_q = NULL;
     326             : 
     327           3 :         if (_gnutls_mpi_init_scan_nz(&tmp_p, prime->data, prime->size)) {
     328           0 :                 gnutls_assert();
     329           0 :                 return GNUTLS_E_MPI_SCAN_FAILED;
     330             :         }
     331             : 
     332           3 :         if (_gnutls_mpi_init_scan_nz(&tmp_g, generator->data,
     333           3 :                                      generator->size)) {
     334           0 :                 _gnutls_mpi_release(&tmp_p);
     335           0 :                 gnutls_assert();
     336           0 :                 return GNUTLS_E_MPI_SCAN_FAILED;
     337             :         }
     338             : 
     339           3 :         if (q) {
     340           3 :                 if (_gnutls_mpi_init_scan_nz(&tmp_q, q->data, q->size)) {
     341           0 :                         _gnutls_mpi_release(&tmp_p);
     342           0 :                         _gnutls_mpi_release(&tmp_g);
     343           0 :                         gnutls_assert();
     344           0 :                         return GNUTLS_E_MPI_SCAN_FAILED;
     345             :                 }
     346             :         } else if (_gnutls_fips_mode_enabled()) {
     347             :                 /* Mandatory in FIPS mode */
     348             :                 gnutls_assert();
     349             :                 return GNUTLS_E_DH_PRIME_UNACCEPTABLE;
     350             :         }
     351             : 
     352             :         /* store the generated values
     353             :          */
     354           3 :         dh_params->params[0] = tmp_p;
     355           3 :         dh_params->params[1] = tmp_g;
     356           3 :         dh_params->params[2] = tmp_q;
     357           3 :         if (tmp_q)
     358           3 :                 dh_params->q_bits = _gnutls_mpi_get_nbits(tmp_q);
     359             : 
     360             :         return 0;
     361             : }
     362             : 
     363             : /**
     364             :  * gnutls_dh_params_init:
     365             :  * @dh_params: The parameters
     366             :  *
     367             :  * This function will initialize the DH parameters type.
     368             :  *
     369             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     370             :  *   otherwise a negative error code is returned.
     371             :  **/
     372        2188 : int gnutls_dh_params_init(gnutls_dh_params_t * dh_params)
     373             : {
     374             : 
     375        2188 :         (*dh_params) = gnutls_calloc(1, sizeof(dh_params_st));
     376        2188 :         if (*dh_params == NULL) {
     377           0 :                 gnutls_assert();
     378           0 :                 return GNUTLS_E_MEMORY_ERROR;
     379             :         }
     380             : 
     381             :         return 0;
     382             : 
     383             : }
     384             : 
     385             : /**
     386             :  * gnutls_dh_params_deinit:
     387             :  * @dh_params: The parameters
     388             :  *
     389             :  * This function will deinitialize the DH parameters type.
     390             :  **/
     391        2074 : void gnutls_dh_params_deinit(gnutls_dh_params_t dh_params)
     392             : {
     393        2074 :         if (dh_params == NULL)
     394             :                 return;
     395             : 
     396        2074 :         _gnutls_mpi_release(&dh_params->params[0]);
     397        2074 :         _gnutls_mpi_release(&dh_params->params[1]);
     398        2074 :         _gnutls_mpi_release(&dh_params->params[2]);
     399             : 
     400        2074 :         gnutls_free(dh_params);
     401             : 
     402             : }
     403             : 
     404             : /**
     405             :  * gnutls_dh_params_cpy:
     406             :  * @dst: Is the destination parameters, which should be initialized.
     407             :  * @src: Is the source parameters
     408             :  *
     409             :  * This function will copy the DH parameters structure from source
     410             :  * to destination. The destination should be already initialized.
     411             :  *
     412             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     413             :  *   otherwise a negative error code is returned.
     414             :  **/
     415           1 : int gnutls_dh_params_cpy(gnutls_dh_params_t dst, gnutls_dh_params_t src)
     416             : {
     417           1 :         if (src == NULL)
     418             :                 return GNUTLS_E_INVALID_REQUEST;
     419             : 
     420           1 :         dst->params[0] = _gnutls_mpi_copy(src->params[0]);
     421           1 :         dst->params[1] = _gnutls_mpi_copy(src->params[1]);
     422           1 :         if (src->params[2])
     423           1 :                 dst->params[2] = _gnutls_mpi_copy(src->params[2]);
     424           1 :         dst->q_bits = src->q_bits;
     425             : 
     426           1 :         if (dst->params[0] == NULL || dst->params[1] == NULL)
     427           0 :                 return GNUTLS_E_MEMORY_ERROR;
     428             : 
     429             :         return 0;
     430             : }
     431             : 
     432             : 
     433             : /**
     434             :  * gnutls_dh_params_generate2:
     435             :  * @dparams: The parameters
     436             :  * @bits: is the prime's number of bits
     437             :  *
     438             :  * This function will generate a new pair of prime and generator for use in
     439             :  * the Diffie-Hellman key exchange. This may take long time.
     440             :  *
     441             :  * It is recommended not to set the number of bits directly, but 
     442             :  * use gnutls_sec_param_to_pk_bits() instead.
     443             : 
     444             :  * Also note that the DH parameters are only useful to servers.
     445             :  * Since clients use the parameters sent by the server, it's of
     446             :  * no use to call this in client side.
     447             :  *
     448             :  * The parameters generated are of the DSA form. It also is possible
     449             :  * to generate provable parameters (following the Shawe-Taylor
     450             :  * algorithm), using gnutls_x509_privkey_generate2() with DSA option
     451             :  * and the %GNUTLS_PRIVKEY_FLAG_PROVABLE flag set. These can the
     452             :  * be imported with gnutls_dh_params_import_dsa().
     453             :  *
     454             :  * It is no longer recommended for applications to generate parameters.
     455             :  * See the "Parameter generation" section in the manual.
     456             :  *
     457             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     458             :  *   otherwise a negative error code is returned.
     459             :  **/
     460             : int
     461           1 : gnutls_dh_params_generate2(gnutls_dh_params_t dparams, unsigned int bits)
     462             : {
     463           1 :         int ret;
     464           1 :         gnutls_pk_params_st params;
     465             : 
     466           1 :         gnutls_pk_params_init(&params);
     467             : 
     468           1 :         ret = _gnutls_pk_generate_params(GNUTLS_PK_DH, bits, &params);
     469           1 :         if (ret < 0)
     470           0 :                 return gnutls_assert_val(ret);
     471             : 
     472           1 :         dparams->params[0] = params.params[DSA_P];
     473           1 :         dparams->params[1] = params.params[DSA_G];
     474           1 :         dparams->q_bits = _gnutls_mpi_get_nbits(params.params[DSA_Q]);
     475             : 
     476           1 :         _gnutls_mpi_release(&params.params[DSA_Q]);
     477             : 
     478             :         return 0;
     479             : }
     480             : 
     481             : /**
     482             :  * gnutls_dh_params_import_pkcs3:
     483             :  * @params: The parameters
     484             :  * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
     485             :  * @format: the format of params. PEM or DER.
     486             :  *
     487             :  * This function will extract the DHParams found in a PKCS3 formatted
     488             :  * structure. This is the format generated by "openssl dhparam" tool.
     489             :  *
     490             :  * If the structure is PEM encoded, it should have a header
     491             :  * of "BEGIN DH PARAMETERS".
     492             :  *
     493             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     494             :  *   otherwise a negative error code is returned.
     495             :  **/
     496             : int
     497        1024 : gnutls_dh_params_import_pkcs3(gnutls_dh_params_t params,
     498             :                               const gnutls_datum_t * pkcs3_params,
     499             :                               gnutls_x509_crt_fmt_t format)
     500             : {
     501        1024 :         ASN1_TYPE c2;
     502        1024 :         int result, need_free = 0;
     503        1024 :         unsigned int q_bits;
     504        1024 :         gnutls_datum_t _params;
     505             : 
     506        1024 :         if (format == GNUTLS_X509_FMT_PEM) {
     507             : 
     508        2048 :                 result = _gnutls_fbase64_decode("DH PARAMETERS",
     509        1024 :                                                 pkcs3_params->data,
     510        1024 :                                                 pkcs3_params->size,
     511             :                                                 &_params);
     512             : 
     513        1024 :                 if (result < 0) {
     514           0 :                         gnutls_assert();
     515           0 :                         return result;
     516             :                 }
     517             : 
     518             :                 need_free = 1;
     519             :         } else {
     520           0 :                 _params.data = pkcs3_params->data;
     521           0 :                 _params.size = pkcs3_params->size;
     522             :         }
     523             : 
     524        1024 :         if ((result = asn1_create_element
     525             :              (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2))
     526             :             != ASN1_SUCCESS) {
     527           0 :                 gnutls_assert();
     528           0 :                 if (need_free != 0) {
     529           0 :                         gnutls_free(_params.data);
     530           0 :                         _params.data = NULL;
     531             :                 }
     532           0 :                 return _gnutls_asn2err(result);
     533             :         }
     534             : 
     535             :         /* PKCS#3 doesn't specify whether DHParameter is encoded as
     536             :          * BER or DER, thus we don't restrict libtasn1 to DER subset */
     537        1024 :         result = asn1_der_decoding(&c2, _params.data, _params.size, NULL);
     538             : 
     539        1024 :         if (need_free != 0) {
     540        1024 :                 gnutls_free(_params.data);
     541        1024 :                 _params.data = NULL;
     542             :         }
     543             : 
     544        1024 :         if (result != ASN1_SUCCESS) {
     545             :                 /* couldn't decode DER */
     546             : 
     547           0 :                 _gnutls_debug_log("DHParams: Decoding error %d\n", result);
     548           0 :                 gnutls_assert();
     549           0 :                 asn1_delete_structure(&c2);
     550           0 :                 return _gnutls_asn2err(result);
     551             :         }
     552             : 
     553             :         /* Read q length */
     554        1024 :         result = _gnutls_x509_read_uint(c2, "privateValueLength", &q_bits);
     555        1024 :         if (result < 0) {
     556         946 :                 gnutls_assert();
     557         946 :                 params->q_bits = 0;
     558             :         } else
     559          78 :                 params->q_bits = q_bits;
     560             : 
     561             :         /* Read PRIME 
     562             :          */
     563        1024 :         result = _gnutls_x509_read_int(c2, "prime", &params->params[0]);
     564        1024 :         if (result < 0) {
     565           0 :                 asn1_delete_structure(&c2);
     566           0 :                 gnutls_assert();
     567           0 :                 return result;
     568             :         }
     569             : 
     570        1024 :         if (_gnutls_mpi_cmp_ui(params->params[0], 0) == 0) {
     571           0 :                 asn1_delete_structure(&c2);
     572           0 :                 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
     573             :         }
     574             : 
     575             :         /* read the generator
     576             :          */
     577        1024 :         result = _gnutls_x509_read_int(c2, "base", &params->params[1]);
     578        1024 :         if (result < 0) {
     579           0 :                 asn1_delete_structure(&c2);
     580           0 :                 _gnutls_mpi_release(&params->params[0]);
     581           0 :                 gnutls_assert();
     582           0 :                 return result;
     583             :         }
     584             : 
     585        1024 :         if (_gnutls_mpi_cmp_ui(params->params[1], 0) == 0) {
     586           0 :                 asn1_delete_structure(&c2);
     587           0 :                 _gnutls_mpi_release(&params->params[0]);
     588           0 :                 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
     589             :         }
     590             : 
     591        1024 :         asn1_delete_structure(&c2);
     592             : 
     593        1024 :         return 0;
     594             : }
     595             : 
     596             : /**
     597             :  * gnutls_dh_params_export_pkcs3:
     598             :  * @params: Holds the DH parameters
     599             :  * @format: the format of output params. One of PEM or DER.
     600             :  * @params_data: will contain a PKCS3 DHParams structure PEM or DER encoded
     601             :  * @params_data_size: holds the size of params_data (and will be replaced by the actual size of parameters)
     602             :  *
     603             :  * This function will export the given dh parameters to a PKCS3
     604             :  * DHParams structure. This is the format generated by "openssl dhparam" tool.
     605             :  * If the buffer provided is not long enough to hold the output, then
     606             :  * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
     607             :  *
     608             :  * If the structure is PEM encoded, it will have a header
     609             :  * of "BEGIN DH PARAMETERS".
     610             :  *
     611             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     612             :  *   otherwise a negative error code is returned.
     613             :  **/
     614             : int
     615        2002 : gnutls_dh_params_export_pkcs3(gnutls_dh_params_t params,
     616             :                               gnutls_x509_crt_fmt_t format,
     617             :                               unsigned char *params_data,
     618             :                               size_t * params_data_size)
     619             : {
     620        2002 :         gnutls_datum_t out = {NULL, 0};
     621        2002 :         int ret;
     622             : 
     623        2002 :         ret = gnutls_dh_params_export2_pkcs3(params, format, &out);
     624        2002 :         if (ret < 0)
     625           0 :                 return gnutls_assert_val(ret);
     626             : 
     627        2002 :         if (*params_data_size < (unsigned) out.size + 1) {
     628        1000 :                 gnutls_assert();
     629        1000 :                 gnutls_free(out.data);
     630        1000 :                 *params_data_size = out.size + 1;
     631        1000 :                 return GNUTLS_E_SHORT_MEMORY_BUFFER;
     632             :         }
     633             : 
     634        1002 :         assert(out.data != NULL);
     635        1002 :         *params_data_size = out.size;
     636        1002 :         if (params_data) {
     637        1002 :                 memcpy(params_data, out.data, out.size);
     638        1002 :                 params_data[out.size] = 0;
     639             :         }
     640             : 
     641        1002 :         gnutls_free(out.data);
     642             : 
     643        1002 :         return 0;
     644             : }
     645             : 
     646             : /**
     647             :  * gnutls_dh_params_export2_pkcs3:
     648             :  * @params: Holds the DH parameters
     649             :  * @format: the format of output params. One of PEM or DER.
     650             :  * @out: will contain a PKCS3 DHParams structure PEM or DER encoded
     651             :  *
     652             :  * This function will export the given dh parameters to a PKCS3
     653             :  * DHParams structure. This is the format generated by "openssl dhparam" tool.
     654             :  * The data in @out will be allocated using gnutls_malloc().
     655             :  *
     656             :  * If the structure is PEM encoded, it will have a header
     657             :  * of "BEGIN DH PARAMETERS".
     658             :  *
     659             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     660             :  *   otherwise a negative error code is returned.
     661             :  *
     662             :  * Since: 3.1.3
     663             :  **/
     664             : int
     665        2002 : gnutls_dh_params_export2_pkcs3(gnutls_dh_params_t params,
     666             :                                gnutls_x509_crt_fmt_t format,
     667             :                                gnutls_datum_t * out)
     668             : {
     669        2002 :         ASN1_TYPE c2;
     670        2002 :         int result;
     671        2002 :         size_t g_size, p_size;
     672        2002 :         uint8_t *p_data, *g_data;
     673        2002 :         uint8_t *all_data;
     674             : 
     675        2002 :         _gnutls_mpi_print_lz(params->params[1], NULL, &g_size);
     676        2002 :         _gnutls_mpi_print_lz(params->params[0], NULL, &p_size);
     677             : 
     678        2002 :         all_data = gnutls_malloc(g_size + p_size);
     679        2002 :         if (all_data == NULL) {
     680           0 :                 gnutls_assert();
     681           0 :                 return GNUTLS_E_MEMORY_ERROR;
     682             :         }
     683             : 
     684        2002 :         p_data = &all_data[0];
     685        2002 :         _gnutls_mpi_print_lz(params->params[0], p_data, &p_size);
     686             : 
     687        2002 :         g_data = &all_data[p_size];
     688        2002 :         _gnutls_mpi_print_lz(params->params[1], g_data, &g_size);
     689             : 
     690             : 
     691             :         /* Ok. Now we have the data. Create the asn1 structures
     692             :          */
     693             : 
     694        2002 :         if ((result = asn1_create_element
     695             :              (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2))
     696             :             != ASN1_SUCCESS) {
     697           0 :                 gnutls_assert();
     698           0 :                 gnutls_free(all_data);
     699           0 :                 return _gnutls_asn2err(result);
     700             :         }
     701             : 
     702             :         /* Write PRIME 
     703             :          */
     704        2002 :         if ((result = asn1_write_value(c2, "prime",
     705             :                                        p_data, p_size)) != ASN1_SUCCESS) {
     706           0 :                 gnutls_assert();
     707           0 :                 gnutls_free(all_data);
     708           0 :                 asn1_delete_structure(&c2);
     709           0 :                 return _gnutls_asn2err(result);
     710             :         }
     711             : 
     712        2002 :         if (params->q_bits > 0)
     713           2 :                 result =
     714           2 :                     _gnutls_x509_write_uint32(c2, "privateValueLength",
     715             :                                               params->q_bits);
     716             :         else
     717        2000 :                 result =
     718        2000 :                     asn1_write_value(c2, "privateValueLength", NULL, 0);
     719             : 
     720        2002 :         if (result < 0) {
     721           0 :                 gnutls_assert();
     722           0 :                 gnutls_free(all_data);
     723           0 :                 asn1_delete_structure(&c2);
     724           0 :                 return _gnutls_asn2err(result);
     725             :         }
     726             : 
     727             :         /* Write the GENERATOR
     728             :          */
     729        2002 :         if ((result = asn1_write_value(c2, "base",
     730             :                                        g_data, g_size)) != ASN1_SUCCESS) {
     731           0 :                 gnutls_assert();
     732           0 :                 gnutls_free(all_data);
     733           0 :                 asn1_delete_structure(&c2);
     734           0 :                 return _gnutls_asn2err(result);
     735             :         }
     736             : 
     737        2002 :         gnutls_free(all_data);
     738             : 
     739             : 
     740        2002 :         if (format == GNUTLS_X509_FMT_DER) {
     741           0 :                 result = _gnutls_x509_der_encode(c2, "", out, 0);
     742             : 
     743           0 :                 asn1_delete_structure(&c2);
     744             : 
     745           0 :                 if (result < 0)
     746           0 :                         return gnutls_assert_val(result);
     747             : 
     748             :         } else {                /* PEM */
     749        2002 :                 gnutls_datum_t t;
     750             : 
     751        2002 :                 result = _gnutls_x509_der_encode(c2, "", &t, 0);
     752             : 
     753        2002 :                 asn1_delete_structure(&c2);
     754             : 
     755        2002 :                 if (result < 0)
     756           0 :                         return gnutls_assert_val(result);
     757             : 
     758        2002 :                 result =
     759        2002 :                     _gnutls_fbase64_encode("DH PARAMETERS", t.data, t.size,
     760             :                                            out);
     761             : 
     762        2002 :                 gnutls_free(t.data);
     763             : 
     764        2002 :                 if (result < 0) {
     765           0 :                         gnutls_assert();
     766           0 :                         return result;
     767             :                 }
     768             :         }
     769             : 
     770             :         return 0;
     771             : }
     772             : 
     773             : /**
     774             :  * gnutls_dh_params_export_raw:
     775             :  * @params: Holds the DH parameters
     776             :  * @prime: will hold the new prime
     777             :  * @generator: will hold the new generator
     778             :  * @bits: if non null will hold the secret key's number of bits
     779             :  *
     780             :  * This function will export the pair of prime and generator for use
     781             :  * in the Diffie-Hellman key exchange.  The new parameters will be
     782             :  * allocated using gnutls_malloc() and will be stored in the
     783             :  * appropriate datum.
     784             :  *
     785             :  * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
     786             :  *   otherwise a negative error code is returned.
     787             :  **/
     788             : int
     789           3 : gnutls_dh_params_export_raw(gnutls_dh_params_t params,
     790             :                             gnutls_datum_t * prime,
     791             :                             gnutls_datum_t * generator, unsigned int *bits)
     792             : {
     793           3 :         int ret;
     794             : 
     795           3 :         if (params->params[1] == NULL || params->params[0] == NULL) {
     796           0 :                 gnutls_assert();
     797           0 :                 return GNUTLS_E_INVALID_REQUEST;
     798             :         }
     799             : 
     800           3 :         ret = _gnutls_mpi_dprint(params->params[1], generator);
     801           3 :         if (ret < 0) {
     802           0 :                 gnutls_assert();
     803           0 :                 return ret;
     804             :         }
     805             : 
     806           3 :         ret = _gnutls_mpi_dprint(params->params[0], prime);
     807           3 :         if (ret < 0) {
     808           0 :                 gnutls_assert();
     809           0 :                 _gnutls_free_datum(generator);
     810           0 :                 return ret;
     811             :         }
     812             : 
     813           3 :         if (bits)
     814           3 :                 *bits = params->q_bits;
     815             : 
     816             :         return 0;
     817             : 
     818             : }

Generated by: LCOV version 1.14