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, ¶ms);
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(¶ms);
467 :
468 1 : ret = _gnutls_pk_generate_params(GNUTLS_PK_DH, bits, ¶ms);
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(¶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
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", ¶ms->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", ¶ms->params[1]);
578 1024 : if (result < 0) {
579 0 : asn1_delete_structure(&c2);
580 0 : _gnutls_mpi_release(¶ms->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(¶ms->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 : }
|