2 * Copyright (C) 2000-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <gnutls_errors.h>
25 #include <gnutls_datum.h>
26 #include <x509_b64.h> /* for PKCS3 PEM decoding */
27 #include <gnutls_global.h>
28 #include <gnutls_dh.h>
29 #include <gnutls_pk.h>
30 #include <x509/common.h>
31 #include <gnutls/crypto.h>
32 #include "x509/x509_int.h"
33 #include <gnutls_mpi.h>
37 * _gnutls_get_dh_params - Returns the DH parameters pointer
38 * @dh_params: is an DH parameters structure, or NULL.
39 * @func: is a callback function to receive the parameters or NULL.
40 * @session: a gnutls session.
42 * This function will return the dh parameters pointer.
45 _gnutls_get_dh_params(gnutls_dh_params_t dh_params,
46 gnutls_params_function * func,
47 gnutls_session_t session)
49 gnutls_params_st params;
52 /* if cached return the cached */
53 if (session->internals.params.dh_params)
54 return session->internals.params.dh_params;
57 session->internals.params.dh_params = dh_params;
59 ret = func(session, GNUTLS_PARAMS_DH, ¶ms);
60 if (ret == 0 && params.type == GNUTLS_PARAMS_DH) {
61 session->internals.params.dh_params =
63 session->internals.params.free_dh_params =
68 return session->internals.params.dh_params;
71 /* returns the prime and the generator of DH params.
73 const bigint_t *_gnutls_dh_params_to_mpi(gnutls_dh_params_t dh_primes)
75 if (dh_primes == NULL || dh_primes->params[1] == NULL ||
76 dh_primes->params[0] == NULL) {
80 return dh_primes->params;
85 * gnutls_dh_params_import_raw:
86 * @dh_params: Is a structure that will hold the prime numbers
87 * @prime: holds the new prime
88 * @generator: holds the new generator
90 * This function will replace the pair of prime and generator for use
91 * in the Diffie-Hellman key exchange. The new parameters should be
92 * stored in the appropriate gnutls_datum.
94 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
95 * otherwise a negative error code is returned.
98 gnutls_dh_params_import_raw(gnutls_dh_params_t dh_params,
99 const gnutls_datum_t * prime,
100 const gnutls_datum_t * generator)
102 bigint_t tmp_prime, tmp_g;
106 if (_gnutls_mpi_init_scan_nz(&tmp_prime, prime->data, siz)) {
108 return GNUTLS_E_MPI_SCAN_FAILED;
111 siz = generator->size;
112 if (_gnutls_mpi_init_scan_nz(&tmp_g, generator->data, siz)) {
113 _gnutls_mpi_release(&tmp_prime);
115 return GNUTLS_E_MPI_SCAN_FAILED;
118 /* store the generated values
120 dh_params->params[0] = tmp_prime;
121 dh_params->params[1] = tmp_g;
128 * gnutls_dh_params_init:
129 * @dh_params: Is a structure that will hold the prime numbers
131 * This function will initialize the DH parameters structure.
133 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
134 * otherwise a negative error code is returned.
136 int gnutls_dh_params_init(gnutls_dh_params_t * dh_params)
139 (*dh_params) = gnutls_calloc(1, sizeof(dh_params_st));
140 if (*dh_params == NULL) {
142 return GNUTLS_E_MEMORY_ERROR;
150 * gnutls_dh_params_deinit:
151 * @dh_params: Is a structure that holds the prime numbers
153 * This function will deinitialize the DH parameters structure.
155 void gnutls_dh_params_deinit(gnutls_dh_params_t dh_params)
157 if (dh_params == NULL)
160 _gnutls_mpi_release(&dh_params->params[0]);
161 _gnutls_mpi_release(&dh_params->params[1]);
163 gnutls_free(dh_params);
168 * gnutls_dh_params_cpy:
169 * @dst: Is the destination structure, which should be initialized.
170 * @src: Is the source structure
172 * This function will copy the DH parameters structure from source
175 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
176 * otherwise a negative error code is returned.
178 int gnutls_dh_params_cpy(gnutls_dh_params_t dst, gnutls_dh_params_t src)
181 return GNUTLS_E_INVALID_REQUEST;
183 dst->params[0] = _gnutls_mpi_copy(src->params[0]);
184 dst->params[1] = _gnutls_mpi_copy(src->params[1]);
185 dst->q_bits = src->q_bits;
187 if (dst->params[0] == NULL || dst->params[1] == NULL)
188 return GNUTLS_E_MEMORY_ERROR;
195 * gnutls_dh_params_generate2:
196 * @dparams: Is the structure that the DH parameters will be stored
197 * @bits: is the prime's number of bits
199 * This function will generate a new pair of prime and generator for use in
200 * the Diffie-Hellman key exchange. The new parameters will be allocated using
201 * gnutls_malloc() and will be stored in the appropriate datum.
202 * This function is normally slow.
204 * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits() to
205 * get bits for %GNUTLS_PK_DSA.
206 * Also note that the DH parameters are only useful to servers.
207 * Since clients use the parameters sent by the server, it's of
208 * no use to call this in client side.
210 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
211 * otherwise a negative error code is returned.
214 gnutls_dh_params_generate2(gnutls_dh_params_t dparams, unsigned int bits)
217 gnutls_pk_params_st params;
219 gnutls_pk_params_init(¶ms);
221 ret = _gnutls_pk_generate_params(GNUTLS_PK_DH, bits, ¶ms);
223 return gnutls_assert_val(ret);
225 dparams->params[0] = params.params[DSA_P];
226 dparams->params[1] = params.params[DSA_G];
227 dparams->q_bits = _gnutls_mpi_get_nbits(params.params[DSA_Q]);
229 _gnutls_mpi_release(¶ms.params[DSA_Q]);
235 * gnutls_dh_params_import_pkcs3:
236 * @params: A structure where the parameters will be copied to
237 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
238 * @format: the format of params. PEM or DER.
240 * This function will extract the DHParams found in a PKCS3 formatted
241 * structure. This is the format generated by "openssl dhparam" tool.
243 * If the structure is PEM encoded, it should have a header
244 * of "BEGIN DH PARAMETERS".
246 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
247 * otherwise a negative error code is returned.
250 gnutls_dh_params_import_pkcs3(gnutls_dh_params_t params,
251 const gnutls_datum_t * pkcs3_params,
252 gnutls_x509_crt_fmt_t format)
255 int result, need_free = 0;
257 gnutls_datum_t _params;
259 if (format == GNUTLS_X509_FMT_PEM) {
261 result = _gnutls_fbase64_decode("DH PARAMETERS",
268 result = GNUTLS_E_INTERNAL_ERROR;
275 _params.data = pkcs3_params->data;
276 _params.size = pkcs3_params->size;
279 if ((result = asn1_create_element
280 (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2))
283 if (need_free != 0) {
284 gnutls_free(_params.data);
287 return _gnutls_asn2err(result);
290 result = asn1_der_decoding(&c2, _params.data, _params.size, NULL);
292 if (need_free != 0) {
293 gnutls_free(_params.data);
297 if (result != ASN1_SUCCESS) {
298 /* couldn't decode DER */
300 _gnutls_debug_log("DHParams: Decoding error %d\n", result);
302 asn1_delete_structure(&c2);
303 return _gnutls_asn2err(result);
307 result = _gnutls_x509_read_uint(c2, "privateValueLength", &q_bits);
312 params->q_bits = q_bits;
316 result = _gnutls_x509_read_int(c2, "prime", ¶ms->params[0]);
318 asn1_delete_structure(&c2);
323 if (_gnutls_mpi_cmp_ui(params->params[0], 0) == 0) {
324 asn1_delete_structure(&c2);
325 return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
328 /* read the generator
330 result = _gnutls_x509_read_int(c2, "base", ¶ms->params[1]);
332 asn1_delete_structure(&c2);
333 _gnutls_mpi_release(¶ms->params[0]);
338 if (_gnutls_mpi_cmp_ui(params->params[1], 0) == 0) {
339 asn1_delete_structure(&c2);
340 _gnutls_mpi_release(¶ms->params[0]);
341 return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
344 asn1_delete_structure(&c2);
350 * gnutls_dh_params_export_pkcs3:
351 * @params: Holds the DH parameters
352 * @format: the format of output params. One of PEM or DER.
353 * @params_data: will contain a PKCS3 DHParams structure PEM or DER encoded
354 * @params_data_size: holds the size of params_data (and will be replaced by the actual size of parameters)
356 * This function will export the given dh parameters to a PKCS3
357 * DHParams structure. This is the format generated by "openssl dhparam" tool.
358 * If the buffer provided is not long enough to hold the output, then
359 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
361 * If the structure is PEM encoded, it will have a header
362 * of "BEGIN DH PARAMETERS".
364 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
365 * otherwise a negative error code is returned.
368 gnutls_dh_params_export_pkcs3(gnutls_dh_params_t params,
369 gnutls_x509_crt_fmt_t format,
370 unsigned char *params_data,
371 size_t * params_data_size)
376 ret = gnutls_dh_params_export2_pkcs3(params, format, &out);
378 return gnutls_assert_val(ret);
380 if (*params_data_size < (unsigned) out.size + 1) {
382 gnutls_free(out.data);
383 *params_data_size = out.size + 1;
384 return GNUTLS_E_SHORT_MEMORY_BUFFER;
387 *params_data_size = out.size;
389 memcpy(params_data, out.data, out.size);
390 params_data[out.size] = 0;
393 gnutls_free(out.data);
399 * gnutls_dh_params_export2_pkcs3:
400 * @params: Holds the DH parameters
401 * @format: the format of output params. One of PEM or DER.
402 * @out: will contain a PKCS3 DHParams structure PEM or DER encoded
404 * This function will export the given dh parameters to a PKCS3
405 * DHParams structure. This is the format generated by "openssl dhparam" tool.
406 * The data in @out will be allocated using gnutls_malloc().
408 * If the structure is PEM encoded, it will have a header
409 * of "BEGIN DH PARAMETERS".
411 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
412 * otherwise a negative error code is returned.
417 gnutls_dh_params_export2_pkcs3(gnutls_dh_params_t params,
418 gnutls_x509_crt_fmt_t format,
419 gnutls_datum_t * out)
423 size_t g_size, p_size;
424 uint8_t *p_data, *g_data;
427 _gnutls_mpi_print_lz(params->params[1], NULL, &g_size);
428 _gnutls_mpi_print_lz(params->params[0], NULL, &p_size);
430 all_data = gnutls_malloc(g_size + p_size);
431 if (all_data == NULL) {
433 return GNUTLS_E_MEMORY_ERROR;
436 p_data = &all_data[0];
437 _gnutls_mpi_print_lz(params->params[0], p_data, &p_size);
439 g_data = &all_data[p_size];
440 _gnutls_mpi_print_lz(params->params[1], g_data, &g_size);
443 /* Ok. Now we have the data. Create the asn1 structures
446 if ((result = asn1_create_element
447 (_gnutls_get_gnutls_asn(), "GNUTLS.DHParameter", &c2))
450 gnutls_free(all_data);
451 return _gnutls_asn2err(result);
456 if ((result = asn1_write_value(c2, "prime",
457 p_data, p_size)) != ASN1_SUCCESS) {
459 gnutls_free(all_data);
460 asn1_delete_structure(&c2);
461 return _gnutls_asn2err(result);
464 if (params->q_bits > 0)
466 _gnutls_x509_write_uint32(c2, "privateValueLength",
470 asn1_write_value(c2, "privateValueLength", NULL, 0);
474 gnutls_free(all_data);
475 asn1_delete_structure(&c2);
476 return _gnutls_asn2err(result);
479 /* Write the GENERATOR
481 if ((result = asn1_write_value(c2, "base",
482 g_data, g_size)) != ASN1_SUCCESS) {
484 gnutls_free(all_data);
485 asn1_delete_structure(&c2);
486 return _gnutls_asn2err(result);
489 gnutls_free(all_data);
492 if (format == GNUTLS_X509_FMT_DER) {
493 result = _gnutls_x509_der_encode(c2, "", out, 0);
495 asn1_delete_structure(&c2);
498 return gnutls_assert_val(result);
503 result = _gnutls_x509_der_encode(c2, "", &t, 0);
505 asn1_delete_structure(&c2);
508 return gnutls_assert_val(result);
511 _gnutls_fbase64_encode("DH PARAMETERS", t.data, t.size,
526 * gnutls_dh_params_export_raw:
527 * @params: Holds the DH parameters
528 * @prime: will hold the new prime
529 * @generator: will hold the new generator
530 * @bits: if non null will hold the secret key's number of bits
532 * This function will export the pair of prime and generator for use
533 * in the Diffie-Hellman key exchange. The new parameters will be
534 * allocated using gnutls_malloc() and will be stored in the
537 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
538 * otherwise a negative error code is returned.
541 gnutls_dh_params_export_raw(gnutls_dh_params_t params,
542 gnutls_datum_t * prime,
543 gnutls_datum_t * generator, unsigned int *bits)
547 if (params->params[1] == NULL || params->params[0] == NULL) {
549 return GNUTLS_E_INVALID_REQUEST;
552 ret = _gnutls_mpi_dprint(params->params[1], generator);
558 ret = _gnutls_mpi_dprint(params->params[0], prime);
561 _gnutls_free_datum(generator);
566 *bits = params->q_bits;