Coverage Report

Created: 2025-03-06 06:58

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