2 * Copyright (C) 2000, 2001, 2003, 2004, 2005, 2008, 2009, 2010 Free
3 * Software Foundation, Inc.
5 * Author: Nikos Mavrogiannopoulos
7 * This file is part of GnuTLS.
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.
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.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
26 #include <gnutls_int.h>
27 #include <gnutls_errors.h>
28 #include <gnutls_datum.h>
29 #include <x509_b64.h> /* for PKCS3 PEM decoding */
30 #include <gnutls_global.h>
31 #include <gnutls_dh.h>
32 #include <gnutls_pk.h>
33 #include <gnutls/crypto.h>
34 #include "x509/x509_int.h"
38 /* returns the prime and the generator of DH params.
41 _gnutls_dh_params_to_mpi (gnutls_dh_params_t dh_primes
)
43 if (dh_primes
== NULL
|| dh_primes
->params
[1] == NULL
||
44 dh_primes
->params
[0] == NULL
)
49 return dh_primes
->params
;
54 * gnutls_dh_params_import_raw:
55 * @dh_params: Is a structure that will hold the prime numbers
56 * @prime: holds the new prime
57 * @generator: holds the new generator
59 * This function will replace the pair of prime and generator for use
60 * in the Diffie-Hellman key exchange. The new parameters should be
61 * stored in the appropriate gnutls_datum.
63 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
64 * otherwise an error code is returned.
67 gnutls_dh_params_import_raw (gnutls_dh_params_t dh_params
,
68 const gnutls_datum_t
* prime
,
69 const gnutls_datum_t
* generator
)
71 bigint_t tmp_prime
, tmp_g
;
75 if (_gnutls_mpi_scan_nz (&tmp_prime
, prime
->data
, siz
))
78 return GNUTLS_E_MPI_SCAN_FAILED
;
81 siz
= generator
->size
;
82 if (_gnutls_mpi_scan_nz (&tmp_g
, generator
->data
, siz
))
84 _gnutls_mpi_release (&tmp_prime
);
86 return GNUTLS_E_MPI_SCAN_FAILED
;
89 /* store the generated values
91 dh_params
->params
[0] = tmp_prime
;
92 dh_params
->params
[1] = tmp_g
;
99 * gnutls_dh_params_init:
100 * @dh_params: Is a structure that will hold the prime numbers
102 * This function will initialize the DH parameters structure.
104 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
105 * otherwise an error code is returned.
108 gnutls_dh_params_init (gnutls_dh_params_t
* dh_params
)
111 (*dh_params
) = gnutls_calloc (1, sizeof (dh_params_st
));
112 if (*dh_params
== NULL
)
115 return GNUTLS_E_MEMORY_ERROR
;
123 * gnutls_dh_params_deinit:
124 * @dh_params: Is a structure that holds the prime numbers
126 * This function will deinitialize the DH parameters structure.
129 gnutls_dh_params_deinit (gnutls_dh_params_t dh_params
)
131 if (dh_params
== NULL
)
134 _gnutls_mpi_release (&dh_params
->params
[0]);
135 _gnutls_mpi_release (&dh_params
->params
[1]);
137 gnutls_free (dh_params
);
142 * gnutls_dh_params_cpy:
143 * @dst: Is the destination structure, which should be initialized.
144 * @src: Is the source structure
146 * This function will copy the DH parameters structure from source
149 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
150 * otherwise an error code is returned.
153 gnutls_dh_params_cpy (gnutls_dh_params_t dst
, gnutls_dh_params_t src
)
156 return GNUTLS_E_INVALID_REQUEST
;
158 dst
->params
[0] = _gnutls_mpi_copy (src
->params
[0]);
159 dst
->params
[1] = _gnutls_mpi_copy (src
->params
[1]);
161 if (dst
->params
[0] == NULL
|| dst
->params
[1] == NULL
)
162 return GNUTLS_E_MEMORY_ERROR
;
169 * gnutls_dh_params_generate2:
170 * @params: Is the structure that the DH parameters will be stored
171 * @bits: is the prime's number of bits
173 * This function will generate a new pair of prime and generator for use in
174 * the Diffie-Hellman key exchange. The new parameters will be allocated using
175 * gnutls_malloc() and will be stored in the appropriate datum.
176 * This function is normally slow.
178 * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits() to
179 * get bits for %GNUTLS_PK_DSA.
180 * Also note that the DH parameters are only useful to servers.
181 * Since clients use the parameters sent by the server, it's of
182 * no use to call this in client side.
184 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
185 * otherwise an error code is returned.
188 gnutls_dh_params_generate2 (gnutls_dh_params_t params
, unsigned int bits
)
191 gnutls_group_st group
;
193 ret
= _gnutls_mpi_generate_group (&group
, bits
);
200 params
->params
[0] = group
.p
;
201 params
->params
[1] = group
.g
;
207 * gnutls_dh_params_import_pkcs3:
208 * @params: A structure where the parameters will be copied to
209 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
210 * @format: the format of params. PEM or DER.
212 * This function will extract the DHParams found in a PKCS3 formatted
213 * structure. This is the format generated by "openssl dhparam" tool.
215 * If the structure is PEM encoded, it should have a header
216 * of "BEGIN DH PARAMETERS".
218 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
219 * otherwise an error code is returned.
222 gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params
,
223 const gnutls_datum_t
* pkcs3_params
,
224 gnutls_x509_crt_fmt_t format
)
227 int result
, need_free
= 0;
228 gnutls_datum_t _params
;
230 if (format
== GNUTLS_X509_FMT_PEM
)
234 result
= _gnutls_fbase64_decode ("DH PARAMETERS",
236 pkcs3_params
->size
, &out
);
241 result
= GNUTLS_E_INTERNAL_ERROR
;
247 _params
.size
= result
;
254 _params
.data
= pkcs3_params
->data
;
255 _params
.size
= pkcs3_params
->size
;
258 if ((result
= asn1_create_element
259 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2
))
265 gnutls_free (_params
.data
);
268 return _gnutls_asn2err (result
);
271 result
= asn1_der_decoding (&c2
, _params
.data
, _params
.size
, NULL
);
275 gnutls_free (_params
.data
);
279 if (result
!= ASN1_SUCCESS
)
281 /* couldn't decode DER */
283 _gnutls_debug_log ("DHParams: Decoding error %d\n", result
);
285 asn1_delete_structure (&c2
);
286 return _gnutls_asn2err (result
);
291 result
= _gnutls_x509_read_int (c2
, "prime", ¶ms
->params
[0]);
294 asn1_delete_structure (&c2
);
299 /* read the generator
301 result
= _gnutls_x509_read_int (c2
, "base", ¶ms
->params
[1]);
304 asn1_delete_structure (&c2
);
305 _gnutls_mpi_release (¶ms
->params
[0]);
310 asn1_delete_structure (&c2
);
316 * gnutls_dh_params_export_pkcs3:
317 * @params: Holds the DH parameters
318 * @format: the format of output params. One of PEM or DER.
319 * @params_data: will contain a PKCS3 DHParams structure PEM or DER encoded
320 * @params_data_size: holds the size of params_data (and will be replaced by the actual size of parameters)
322 * This function will export the given dh parameters to a PKCS3
323 * DHParams structure. This is the format generated by "openssl dhparam" tool.
324 * If the buffer provided is not long enough to hold the output, then
325 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
327 * If the structure is PEM encoded, it will have a header
328 * of "BEGIN DH PARAMETERS".
330 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
331 * otherwise an error code is returned.
334 gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params
,
335 gnutls_x509_crt_fmt_t format
,
336 unsigned char *params_data
,
337 size_t * params_data_size
)
340 int result
, _params_data_size
;
341 size_t g_size
, p_size
;
342 opaque
*p_data
, *g_data
;
345 _gnutls_mpi_print_lz (params
->params
[1], NULL
, &g_size
);
346 _gnutls_mpi_print_lz (params
->params
[0], NULL
, &p_size
);
348 all_data
= gnutls_malloc (g_size
+ p_size
);
349 if (all_data
== NULL
)
352 return GNUTLS_E_MEMORY_ERROR
;
355 p_data
= &all_data
[0];
356 _gnutls_mpi_print_lz (params
->params
[0], p_data
, &p_size
);
358 g_data
= &all_data
[p_size
];
359 _gnutls_mpi_print_lz (params
->params
[1], g_data
, &g_size
);
362 /* Ok. Now we have the data. Create the asn1 structures
365 if ((result
= asn1_create_element
366 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2
))
370 gnutls_free (all_data
);
371 return _gnutls_asn2err (result
);
376 if ((result
= asn1_write_value (c2
, "prime",
377 p_data
, p_size
)) != ASN1_SUCCESS
)
380 gnutls_free (all_data
);
381 asn1_delete_structure (&c2
);
382 return _gnutls_asn2err (result
);
385 /* Write the GENERATOR
387 if ((result
= asn1_write_value (c2
, "base",
388 g_data
, g_size
)) != ASN1_SUCCESS
)
391 gnutls_free (all_data
);
392 asn1_delete_structure (&c2
);
393 return _gnutls_asn2err (result
);
396 gnutls_free (all_data
);
398 if ((result
= asn1_write_value (c2
, "privateValueLength",
399 NULL
, 0)) != ASN1_SUCCESS
)
402 asn1_delete_structure (&c2
);
403 return _gnutls_asn2err (result
);
406 if (format
== GNUTLS_X509_FMT_DER
)
408 if (params_data
== NULL
)
409 *params_data_size
= 0;
411 _params_data_size
= *params_data_size
;
413 asn1_der_coding (c2
, "", params_data
, &_params_data_size
, NULL
);
414 *params_data_size
= _params_data_size
;
415 asn1_delete_structure (&c2
);
417 if (result
!= ASN1_SUCCESS
)
420 if (result
== ASN1_MEM_ERROR
)
421 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
423 return _gnutls_asn2err (result
);
434 asn1_der_coding (c2
, "", NULL
, &len
, NULL
);
436 tmp
= gnutls_malloc (len
);
440 asn1_delete_structure (&c2
);
441 return GNUTLS_E_MEMORY_ERROR
;
445 asn1_der_coding (c2
, "", tmp
, &len
, NULL
)) != ASN1_SUCCESS
)
449 asn1_delete_structure (&c2
);
450 return _gnutls_asn2err (result
);
453 asn1_delete_structure (&c2
);
455 result
= _gnutls_fbase64_encode ("DH PARAMETERS", tmp
, len
, &out
);
469 return GNUTLS_E_INTERNAL_ERROR
;
472 if ((unsigned) result
> *params_data_size
)
476 *params_data_size
= result
;
477 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
480 *params_data_size
= result
- 1;
483 memcpy (params_data
, out
, result
);
493 * gnutls_dh_params_export_raw:
494 * @params: Holds the DH parameters
495 * @prime: will hold the new prime
496 * @generator: will hold the new generator
497 * @bits: if non null will hold is the prime's number of bits
499 * This function will export the pair of prime and generator for use
500 * in the Diffie-Hellman key exchange. The new parameters will be
501 * allocated using gnutls_malloc() and will be stored in the
504 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
505 * otherwise an error code is returned.
508 gnutls_dh_params_export_raw (gnutls_dh_params_t params
,
509 gnutls_datum_t
* prime
,
510 gnutls_datum_t
* generator
, unsigned int *bits
)
514 if (params
->params
[1] == NULL
|| params
->params
[0] == NULL
)
517 return GNUTLS_E_INVALID_REQUEST
;
520 ret
= _gnutls_mpi_dprint (params
->params
[1], generator
);
527 ret
= _gnutls_mpi_dprint (params
->params
[0], prime
);
531 _gnutls_free_datum (generator
);
536 *bits
= _gnutls_mpi_get_nbits (params
->params
[0]);