Coverage Report

Created: 2023-03-26 08:33

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