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
set_dh_pk_params(gnutls_session_t session,bigint_t g,bigint_t p,bigint_t q,unsigned q_bits)39 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 gnutls_pk_params_release(&session->key.proto.tls12.dh.params);
44
45 gnutls_pk_params_init(&session->key.proto.tls12.dh.params);
46
47 session->key.proto.tls12.dh.params.params[DH_G] = _gnutls_mpi_copy(g);
48 if (session->key.proto.tls12.dh.params.params[DH_G] == NULL)
49 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
50
51 session->key.proto.tls12.dh.params.params[DH_P] = _gnutls_mpi_copy(p);
52 if (session->key.proto.tls12.dh.params.params[DH_P] == NULL) {
53 _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_G]);
54 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
55 }
56
57 if (q) {
58 session->key.proto.tls12.dh.params.params[DH_Q] = _gnutls_mpi_copy(q);
59 if (session->key.proto.tls12.dh.params.params[DH_Q] == NULL) {
60 _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_P]);
61 _gnutls_mpi_release(&session->key.proto.tls12.dh.params.params[DH_G]);
62 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
63 }
64 }
65 /* include, possibly empty, q */
66 session->key.proto.tls12.dh.params.params_nr = 3;
67 session->key.proto.tls12.dh.params.algo = GNUTLS_PK_DH;
68 session->key.proto.tls12.dh.params.qbits = q_bits;
69
70 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
_gnutls_figure_dh_params(gnutls_session_t session,gnutls_dh_params_t dh_params,gnutls_params_function * func,gnutls_sec_param_t sec_param)78 _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 gnutls_params_st params;
82 bigint_t p, g, q = NULL;
83 unsigned free_pg = 0;
84 int ret;
85 unsigned q_bits = 0, i;
86 const gnutls_group_entry_st *group;
87
88 group = get_group(session);
89
90 params.deinit = 0;
91
92 /* if we negotiated RFC7919 FFDHE */
93 if (group && group->pk == GNUTLS_PK_DH) {
94 for (i=0;i<session->internals.priorities->groups.size;i++) {
95 if (session->internals.priorities->groups.entry[i] == group) {
96 ret = _gnutls_mpi_init_scan_nz(&p,
97 session->internals.priorities->groups.entry[i]->prime->data,
98 session->internals.priorities->groups.entry[i]->prime->size);
99 if (ret < 0)
100 return gnutls_assert_val(ret);
101
102 free_pg = 1;
103
104 ret = _gnutls_mpi_init_scan_nz(&g,
105 session->internals.priorities->groups.entry[i]->generator->data,
106 session->internals.priorities->groups.entry[i]->generator->size);
107 if (ret < 0) {
108 gnutls_assert();
109 goto cleanup;
110 }
111
112 ret = _gnutls_mpi_init_scan_nz(&q,
113 session->internals.priorities->groups.entry[i]->q->data,
114 session->internals.priorities->groups.entry[i]->q->size);
115 if (ret < 0) {
116 gnutls_assert();
117 goto cleanup;
118 }
119
120 session->internals.hsk_flags |= HSK_USED_FFDHE;
121 q_bits = *session->internals.priorities->groups.entry[i]->q_bits;
122 goto finished;
123 }
124 }
125
126 /* didn't find anything, that shouldn't have occurred
127 * as we received that extension */
128 return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
129 } else if (sec_param) {
130 unsigned bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, sec_param)/8;
131
132 for (i=0;i<session->internals.priorities->groups.size;i++) {
133 if (!session->internals.priorities->groups.entry[i]->prime)
134 continue;
135
136 if (bits <= session->internals.priorities->groups.entry[i]->prime->size) {
137 ret = _gnutls_mpi_init_scan_nz(&p,
138 session->internals.priorities->groups.entry[i]->prime->data,
139 session->internals.priorities->groups.entry[i]->prime->size);
140 if (ret < 0)
141 return gnutls_assert_val(ret);
142
143 free_pg = 1;
144
145 ret = _gnutls_mpi_init_scan_nz(&g,
146 session->internals.priorities->groups.entry[i]->generator->data,
147 session->internals.priorities->groups.entry[i]->generator->size);
148 if (ret < 0) {
149 gnutls_assert();
150 goto cleanup;
151 }
152
153 q_bits = *session->internals.priorities->groups.entry[i]->q_bits;
154 goto finished;
155 }
156 }
157
158 }
159
160 if (dh_params) {
161 p = dh_params->params[0];
162 g = dh_params->params[1];
163 q_bits = dh_params->q_bits;
164 } else if (func) {
165 ret = func(session, GNUTLS_PARAMS_DH, ¶ms);
166 if (ret == 0 && params.type == GNUTLS_PARAMS_DH) {
167 p = params.params.dh->params[0];
168 g = params.params.dh->params[1];
169 q_bits = params.params.dh->q_bits;
170 } else
171 return gnutls_assert_val(GNUTLS_E_NO_TEMPORARY_DH_PARAMS);
172 } else
173 return gnutls_assert_val(GNUTLS_E_NO_TEMPORARY_DH_PARAMS);
174
175 finished:
176 _gnutls_dh_save_group(session, g, p);
177
178 ret = set_dh_pk_params(session, g, p, q, q_bits);
179 if (ret < 0) {
180 gnutls_assert();
181 }
182
183 cleanup:
184 if (free_pg) {
185 _gnutls_mpi_release(&p);
186 _gnutls_mpi_release(&q);
187 _gnutls_mpi_release(&g);
188 }
189 if (params.deinit && params.type == GNUTLS_PARAMS_DH)
190 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 */
_gnutls_dh_params_to_mpi(gnutls_dh_params_t dh_primes)198 const bigint_t *_gnutls_dh_params_to_mpi(gnutls_dh_params_t dh_primes)
199 {
200 if (dh_primes == NULL || dh_primes->params[1] == NULL ||
201 dh_primes->params[0] == NULL) {
202 return NULL;
203 }
204
205 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
gnutls_dh_params_import_raw(gnutls_dh_params_t dh_params,const gnutls_datum_t * prime,const gnutls_datum_t * generator)223 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 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
gnutls_dh_params_import_dsa(gnutls_dh_params_t dh_params,gnutls_x509_privkey_t key)242 gnutls_dh_params_import_dsa(gnutls_dh_params_t dh_params, gnutls_x509_privkey_t key)
243 {
244 gnutls_datum_t p, g, q;
245 int ret;
246
247 ret = gnutls_x509_privkey_export_dsa_raw(key, &p, &q, &g, NULL, NULL);
248 if (ret < 0)
249 return gnutls_assert_val(ret);
250
251 ret = gnutls_dh_params_import_raw3(dh_params, &p, &q, &g);
252
253 gnutls_free(p.data);
254 gnutls_free(g.data);
255 gnutls_free(q.data);
256
257 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
gnutls_dh_params_import_raw2(gnutls_dh_params_t dh_params,const gnutls_datum_t * prime,const gnutls_datum_t * generator,unsigned key_bits)275 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 bigint_t tmp_prime, tmp_g;
281 size_t siz;
282
283 siz = prime->size;
284 if (_gnutls_mpi_init_scan_nz(&tmp_prime, prime->data, siz)) {
285 gnutls_assert();
286 return GNUTLS_E_MPI_SCAN_FAILED;
287 }
288
289 siz = generator->size;
290 if (_gnutls_mpi_init_scan_nz(&tmp_g, generator->data, siz)) {
291 _gnutls_mpi_release(&tmp_prime);
292 gnutls_assert();
293 return GNUTLS_E_MPI_SCAN_FAILED;
294 }
295
296 /* store the generated values
297 */
298 dh_params->params[0] = tmp_prime;
299 dh_params->params[1] = tmp_g;
300 dh_params->q_bits = key_bits;
301
302 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
gnutls_dh_params_import_raw3(gnutls_dh_params_t dh_params,const gnutls_datum_t * prime,const gnutls_datum_t * q,const gnutls_datum_t * generator)320 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 bigint_t tmp_p, tmp_g, tmp_q = NULL;
326
327 if (_gnutls_mpi_init_scan_nz(&tmp_p, prime->data, prime->size)) {
328 gnutls_assert();
329 return GNUTLS_E_MPI_SCAN_FAILED;
330 }
331
332 if (_gnutls_mpi_init_scan_nz(&tmp_g, generator->data,
333 generator->size)) {
334 _gnutls_mpi_release(&tmp_p);
335 gnutls_assert();
336 return GNUTLS_E_MPI_SCAN_FAILED;
337 }
338
339 if (q) {
340 if (_gnutls_mpi_init_scan_nz(&tmp_q, q->data, q->size)) {
341 _gnutls_mpi_release(&tmp_p);
342 _gnutls_mpi_release(&tmp_g);
343 gnutls_assert();
344 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 dh_params->params[0] = tmp_p;
355 dh_params->params[1] = tmp_g;
356 dh_params->params[2] = tmp_q;
357 if (tmp_q)
358 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 **/
gnutls_dh_params_init(gnutls_dh_params_t * dh_params)372 int gnutls_dh_params_init(gnutls_dh_params_t * dh_params)
373 {
374
375 (*dh_params) = gnutls_calloc(1, sizeof(dh_params_st));
376 if (*dh_params == NULL) {
377 gnutls_assert();
378 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 **/
gnutls_dh_params_deinit(gnutls_dh_params_t dh_params)391 void gnutls_dh_params_deinit(gnutls_dh_params_t dh_params)
392 {
393 if (dh_params == NULL)
394 return;
395
396 _gnutls_mpi_release(&dh_params->params[0]);
397 _gnutls_mpi_release(&dh_params->params[1]);
398 _gnutls_mpi_release(&dh_params->params[2]);
399
400 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 **/
gnutls_dh_params_cpy(gnutls_dh_params_t dst,gnutls_dh_params_t src)415 int gnutls_dh_params_cpy(gnutls_dh_params_t dst, gnutls_dh_params_t src)
416 {
417 if (src == NULL)
418 return GNUTLS_E_INVALID_REQUEST;
419
420 dst->params[0] = _gnutls_mpi_copy(src->params[0]);
421 dst->params[1] = _gnutls_mpi_copy(src->params[1]);
422 if (src->params[2])
423 dst->params[2] = _gnutls_mpi_copy(src->params[2]);
424 dst->q_bits = src->q_bits;
425
426 if (dst->params[0] == NULL || dst->params[1] == NULL)
427 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
gnutls_dh_params_generate2(gnutls_dh_params_t dparams,unsigned int bits)461 gnutls_dh_params_generate2(gnutls_dh_params_t dparams, unsigned int bits)
462 {
463 int ret;
464 gnutls_pk_params_st params;
465
466 gnutls_pk_params_init(¶ms);
467
468 ret = _gnutls_pk_generate_params(GNUTLS_PK_DH, bits, ¶ms);
469 if (ret < 0)
470 return gnutls_assert_val(ret);
471
472 dparams->params[0] = params.params[DSA_P];
473 dparams->params[1] = params.params[DSA_G];
474 dparams->q_bits = _gnutls_mpi_get_nbits(params.params[DSA_Q]);
475
476 _gnutls_mpi_release(¶ms.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
gnutls_dh_params_import_pkcs3(gnutls_dh_params_t params,const gnutls_datum_t * pkcs3_params,gnutls_x509_crt_fmt_t format)497 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 ASN1_TYPE c2;
502 int result, need_free = 0;
503 unsigned int q_bits;
504 gnutls_datum_t _params;
505
506 if (format == GNUTLS_X509_FMT_PEM) {
507
508 result = _gnutls_fbase64_decode("DH PARAMETERS",
509 pkcs3_params->data,
510 pkcs3_params->size,
511 &_params);
512
513 if (result < 0) {
514 gnutls_assert();
515 return result;
516 }
517
518 need_free = 1;
519 } else {
520 _params.data = pkcs3_params->data;
521 _params.size = pkcs3_params->size;
522 }
523
524 if ((result = asn1_create_element
525 (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2))
526 != ASN1_SUCCESS) {
527 gnutls_assert();
528 if (need_free != 0) {
529 gnutls_free(_params.data);
530 _params.data = NULL;
531 }
532 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 result = asn1_der_decoding(&c2, _params.data, _params.size, NULL);
538
539 if (need_free != 0) {
540 gnutls_free(_params.data);
541 _params.data = NULL;
542 }
543
544 if (result != ASN1_SUCCESS) {
545 /* couldn't decode DER */
546
547 _gnutls_debug_log("DHParams: Decoding error %d\n", result);
548 gnutls_assert();
549 asn1_delete_structure(&c2);
550 return _gnutls_asn2err(result);
551 }
552
553 /* Read q length */
554 result = _gnutls_x509_read_uint(c2, "privateValueLength", &q_bits);
555 if (result < 0) {
556 gnutls_assert();
557 params->q_bits = 0;
558 } else
559 params->q_bits = q_bits;
560
561 /* Read PRIME
562 */
563 result = _gnutls_x509_read_int(c2, "prime", ¶ms->params[0]);
564 if (result < 0) {
565 asn1_delete_structure(&c2);
566 gnutls_assert();
567 return result;
568 }
569
570 if (_gnutls_mpi_cmp_ui(params->params[0], 0) == 0) {
571 asn1_delete_structure(&c2);
572 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
573 }
574
575 /* read the generator
576 */
577 result = _gnutls_x509_read_int(c2, "base", ¶ms->params[1]);
578 if (result < 0) {
579 asn1_delete_structure(&c2);
580 _gnutls_mpi_release(¶ms->params[0]);
581 gnutls_assert();
582 return result;
583 }
584
585 if (_gnutls_mpi_cmp_ui(params->params[1], 0) == 0) {
586 asn1_delete_structure(&c2);
587 _gnutls_mpi_release(¶ms->params[0]);
588 return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
589 }
590
591 asn1_delete_structure(&c2);
592
593 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
gnutls_dh_params_export_pkcs3(gnutls_dh_params_t params,gnutls_x509_crt_fmt_t format,unsigned char * params_data,size_t * params_data_size)615 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 gnutls_datum_t out = {NULL, 0};
621 int ret;
622
623 ret = gnutls_dh_params_export2_pkcs3(params, format, &out);
624 if (ret < 0)
625 return gnutls_assert_val(ret);
626
627 if (*params_data_size < (unsigned) out.size + 1) {
628 gnutls_assert();
629 gnutls_free(out.data);
630 *params_data_size = out.size + 1;
631 return GNUTLS_E_SHORT_MEMORY_BUFFER;
632 }
633
634 assert(out.data != NULL);
635 *params_data_size = out.size;
636 if (params_data) {
637 memcpy(params_data, out.data, out.size);
638 params_data[out.size] = 0;
639 }
640
641 gnutls_free(out.data);
642
643 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
gnutls_dh_params_export2_pkcs3(gnutls_dh_params_t params,gnutls_x509_crt_fmt_t format,gnutls_datum_t * out)665 gnutls_dh_params_export2_pkcs3(gnutls_dh_params_t params,
666 gnutls_x509_crt_fmt_t format,
667 gnutls_datum_t * out)
668 {
669 ASN1_TYPE c2;
670 int result;
671 size_t g_size, p_size;
672 uint8_t *p_data, *g_data;
673 uint8_t *all_data;
674
675 _gnutls_mpi_print_lz(params->params[1], NULL, &g_size);
676 _gnutls_mpi_print_lz(params->params[0], NULL, &p_size);
677
678 all_data = gnutls_malloc(g_size + p_size);
679 if (all_data == NULL) {
680 gnutls_assert();
681 return GNUTLS_E_MEMORY_ERROR;
682 }
683
684 p_data = &all_data[0];
685 _gnutls_mpi_print_lz(params->params[0], p_data, &p_size);
686
687 g_data = &all_data[p_size];
688 _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 if ((result = asn1_create_element
695 (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2))
696 != ASN1_SUCCESS) {
697 gnutls_assert();
698 gnutls_free(all_data);
699 return _gnutls_asn2err(result);
700 }
701
702 /* Write PRIME
703 */
704 if ((result = asn1_write_value(c2, "prime",
705 p_data, p_size)) != ASN1_SUCCESS) {
706 gnutls_assert();
707 gnutls_free(all_data);
708 asn1_delete_structure(&c2);
709 return _gnutls_asn2err(result);
710 }
711
712 if (params->q_bits > 0)
713 result =
714 _gnutls_x509_write_uint32(c2, "privateValueLength",
715 params->q_bits);
716 else
717 result =
718 asn1_write_value(c2, "privateValueLength", NULL, 0);
719
720 if (result < 0) {
721 gnutls_assert();
722 gnutls_free(all_data);
723 asn1_delete_structure(&c2);
724 return _gnutls_asn2err(result);
725 }
726
727 /* Write the GENERATOR
728 */
729 if ((result = asn1_write_value(c2, "base",
730 g_data, g_size)) != ASN1_SUCCESS) {
731 gnutls_assert();
732 gnutls_free(all_data);
733 asn1_delete_structure(&c2);
734 return _gnutls_asn2err(result);
735 }
736
737 gnutls_free(all_data);
738
739
740 if (format == GNUTLS_X509_FMT_DER) {
741 result = _gnutls_x509_der_encode(c2, "", out, 0);
742
743 asn1_delete_structure(&c2);
744
745 if (result < 0)
746 return gnutls_assert_val(result);
747
748 } else { /* PEM */
749 gnutls_datum_t t;
750
751 result = _gnutls_x509_der_encode(c2, "", &t, 0);
752
753 asn1_delete_structure(&c2);
754
755 if (result < 0)
756 return gnutls_assert_val(result);
757
758 result =
759 _gnutls_fbase64_encode("DH PARAMETERS", t.data, t.size,
760 out);
761
762 gnutls_free(t.data);
763
764 if (result < 0) {
765 gnutls_assert();
766 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
gnutls_dh_params_export_raw(gnutls_dh_params_t params,gnutls_datum_t * prime,gnutls_datum_t * generator,unsigned int * bits)789 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 int ret;
794
795 if (params->params[1] == NULL || params->params[0] == NULL) {
796 gnutls_assert();
797 return GNUTLS_E_INVALID_REQUEST;
798 }
799
800 ret = _gnutls_mpi_dprint(params->params[1], generator);
801 if (ret < 0) {
802 gnutls_assert();
803 return ret;
804 }
805
806 ret = _gnutls_mpi_dprint(params->params[0], prime);
807 if (ret < 0) {
808 gnutls_assert();
809 _gnutls_free_datum(generator);
810 return ret;
811 }
812
813 if (bits)
814 *bits = params->q_bits;
815
816 return 0;
817
818 }
819