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 library 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
;
53 /* Replaces the prime in the static DH parameters, with a randomly
57 * gnutls_dh_params_import_raw:
58 * @dh_params: Is a structure that will hold the prime numbers
59 * @prime: holds the new prime
60 * @generator: holds the new generator
62 * This function will replace the pair of prime and generator for use
63 * in the Diffie-Hellman key exchange. The new parameters should be
64 * stored in the appropriate gnutls_datum.
66 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
67 * otherwise an error code is returned.
70 gnutls_dh_params_import_raw (gnutls_dh_params_t dh_params
,
71 const gnutls_datum_t
* prime
,
72 const gnutls_datum_t
* generator
)
74 bigint_t tmp_prime
, tmp_g
;
78 if (_gnutls_mpi_scan_nz (&tmp_prime
, prime
->data
, siz
))
81 return GNUTLS_E_MPI_SCAN_FAILED
;
84 siz
= generator
->size
;
85 if (_gnutls_mpi_scan_nz (&tmp_g
, generator
->data
, siz
))
87 _gnutls_mpi_release (&tmp_prime
);
89 return GNUTLS_E_MPI_SCAN_FAILED
;
92 /* store the generated values
94 dh_params
->params
[0] = tmp_prime
;
95 dh_params
->params
[1] = tmp_g
;
102 * gnutls_dh_params_init:
103 * @dh_params: Is a structure that will hold the prime numbers
105 * This function will initialize the DH parameters structure.
107 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
108 * otherwise an error code is returned.
111 gnutls_dh_params_init (gnutls_dh_params_t
* dh_params
)
114 (*dh_params
) = gnutls_calloc (1, sizeof (dh_params_st
));
115 if (*dh_params
== NULL
)
118 return GNUTLS_E_MEMORY_ERROR
;
126 * gnutls_dh_params_deinit:
127 * @dh_params: Is a structure that holds the prime numbers
129 * This function will deinitialize the DH parameters structure.
132 gnutls_dh_params_deinit (gnutls_dh_params_t dh_params
)
134 if (dh_params
== NULL
)
137 _gnutls_mpi_release (&dh_params
->params
[0]);
138 _gnutls_mpi_release (&dh_params
->params
[1]);
140 gnutls_free (dh_params
);
145 * gnutls_dh_params_cpy:
146 * @dst: Is the destination structure, which should be initialized.
147 * @src: Is the source structure
149 * This function will copy the DH parameters structure from source
152 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
153 * otherwise an error code is returned.
156 gnutls_dh_params_cpy (gnutls_dh_params_t dst
, gnutls_dh_params_t src
)
159 return GNUTLS_E_INVALID_REQUEST
;
161 dst
->params
[0] = _gnutls_mpi_copy (src
->params
[0]);
162 dst
->params
[1] = _gnutls_mpi_copy (src
->params
[1]);
164 if (dst
->params
[0] == NULL
|| dst
->params
[1] == NULL
)
165 return GNUTLS_E_MEMORY_ERROR
;
172 * gnutls_dh_params_generate2:
173 * @params: Is the structure that the DH parameters will be stored
174 * @bits: is the prime's number of bits
176 * This function will generate a new pair of prime and generator for use in
177 * the Diffie-Hellman key exchange. The new parameters will be allocated using
178 * gnutls_malloc() and will be stored in the appropriate datum.
179 * This function is normally slow.
181 * Note that the bits value should be one of 768, 1024, 2048, 3072 or 4096.
182 * Also note that the DH parameters are only useful to servers.
183 * Since clients use the parameters sent by the server, it's of
184 * no use to call this in client side.
186 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
187 * otherwise an error code is returned.
190 gnutls_dh_params_generate2 (gnutls_dh_params_t params
, unsigned int bits
)
193 gnutls_group_st group
;
195 ret
= _gnutls_mpi_generate_group (&group
, bits
);
202 params
->params
[0] = group
.p
;
203 params
->params
[1] = group
.g
;
209 * gnutls_dh_params_import_pkcs3:
210 * @params: A structure where the parameters will be copied to
211 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
212 * @format: the format of params. PEM or DER.
214 * This function will extract the DHParams found in a PKCS3 formatted
215 * structure. This is the format generated by "openssl dhparam" tool.
217 * If the structure is PEM encoded, it should have a header
218 * of "BEGIN DH PARAMETERS".
220 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
221 * otherwise an error code is returned.
224 gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params
,
225 const gnutls_datum_t
* pkcs3_params
,
226 gnutls_x509_crt_fmt_t format
)
229 int result
, need_free
= 0;
230 gnutls_datum_t _params
;
232 if (format
== GNUTLS_X509_FMT_PEM
)
236 result
= _gnutls_fbase64_decode ("DH PARAMETERS",
238 pkcs3_params
->size
, &out
);
243 result
= GNUTLS_E_INTERNAL_ERROR
;
249 _params
.size
= result
;
256 _params
.data
= pkcs3_params
->data
;
257 _params
.size
= pkcs3_params
->size
;
260 if ((result
= asn1_create_element
261 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2
))
267 gnutls_free (_params
.data
);
270 return _gnutls_asn2err (result
);
273 result
= asn1_der_decoding (&c2
, _params
.data
, _params
.size
, NULL
);
277 gnutls_free (_params
.data
);
281 if (result
!= ASN1_SUCCESS
)
283 /* couldn't decode DER */
285 _gnutls_x509_log ("DHParams: Decoding error %d\n", result
);
287 asn1_delete_structure (&c2
);
288 return _gnutls_asn2err (result
);
293 result
= _gnutls_x509_read_int (c2
, "prime", ¶ms
->params
[0]);
296 asn1_delete_structure (&c2
);
301 /* read the generator
303 result
= _gnutls_x509_read_int (c2
, "base", ¶ms
->params
[1]);
306 asn1_delete_structure (&c2
);
307 _gnutls_mpi_release (¶ms
->params
[0]);
312 asn1_delete_structure (&c2
);
318 * gnutls_dh_params_export_pkcs3:
319 * @params: Holds the DH parameters
320 * @format: the format of output params. One of PEM or DER.
321 * @params_data: will contain a PKCS3 DHParams structure PEM or DER encoded
322 * @params_data_size: holds the size of params_data (and will be replaced by the actual size of parameters)
324 * This function will export the given dh parameters to a PKCS3
325 * DHParams structure. This is the format generated by "openssl dhparam" tool.
326 * If the buffer provided is not long enough to hold the output, then
327 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
329 * If the structure is PEM encoded, it will have a header
330 * of "BEGIN DH PARAMETERS".
332 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
333 * otherwise an error code is returned.
336 gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params
,
337 gnutls_x509_crt_fmt_t format
,
338 unsigned char *params_data
,
339 size_t * params_data_size
)
342 int result
, _params_data_size
;
343 size_t g_size
, p_size
;
344 opaque
*p_data
, *g_data
;
347 _gnutls_mpi_print_lz (params
->params
[1], NULL
, &g_size
);
348 _gnutls_mpi_print_lz (params
->params
[0], NULL
, &p_size
);
350 all_data
= gnutls_malloc (g_size
+ p_size
);
351 if (all_data
== NULL
)
354 return GNUTLS_E_MEMORY_ERROR
;
357 p_data
= &all_data
[0];
358 g_data
= &all_data
[p_size
];
360 _gnutls_mpi_print_lz (params
->params
[0], p_data
, &p_size
);
361 _gnutls_mpi_print_lz (params
->params
[1], g_data
, &g_size
);
363 /* Ok. Now we have the data. Create the asn1 structures
366 if ((result
= asn1_create_element
367 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2
))
371 gnutls_free (all_data
);
372 return _gnutls_asn2err (result
);
377 if ((result
= asn1_write_value (c2
, "prime",
378 p_data
, p_size
)) != ASN1_SUCCESS
)
381 gnutls_free (all_data
);
382 asn1_delete_structure (&c2
);
383 return _gnutls_asn2err (result
);
386 /* Write the GENERATOR
388 if ((result
= asn1_write_value (c2
, "base",
389 g_data
, g_size
)) != ASN1_SUCCESS
)
392 gnutls_free (all_data
);
393 asn1_delete_structure (&c2
);
394 return _gnutls_asn2err (result
);
397 gnutls_free (all_data
);
399 if ((result
= asn1_write_value (c2
, "privateValueLength",
400 NULL
, 0)) != ASN1_SUCCESS
)
403 asn1_delete_structure (&c2
);
404 return _gnutls_asn2err (result
);
407 if (format
== GNUTLS_X509_FMT_DER
)
409 if (params_data
== NULL
)
410 *params_data_size
= 0;
412 _params_data_size
= *params_data_size
;
414 asn1_der_coding (c2
, "", params_data
, &_params_data_size
, NULL
);
415 *params_data_size
= _params_data_size
;
416 asn1_delete_structure (&c2
);
418 if (result
!= ASN1_SUCCESS
)
421 if (result
== ASN1_MEM_ERROR
)
422 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
424 return _gnutls_asn2err (result
);
435 asn1_der_coding (c2
, "", NULL
, &len
, NULL
);
437 tmp
= gnutls_malloc (len
);
441 asn1_delete_structure (&c2
);
442 return GNUTLS_E_MEMORY_ERROR
;
446 asn1_der_coding (c2
, "", tmp
, &len
, NULL
)) != ASN1_SUCCESS
)
450 asn1_delete_structure (&c2
);
451 return _gnutls_asn2err (result
);
454 asn1_delete_structure (&c2
);
456 result
= _gnutls_fbase64_encode ("DH PARAMETERS", tmp
, len
, &out
);
470 return GNUTLS_E_INTERNAL_ERROR
;
473 if ((unsigned) result
> *params_data_size
)
477 *params_data_size
= result
;
478 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
481 *params_data_size
= result
- 1;
484 memcpy (params_data
, out
, result
);
494 * gnutls_dh_params_export_raw:
495 * @params: Holds the DH parameters
496 * @prime: will hold the new prime
497 * @generator: will hold the new generator
498 * @bits: if non null will hold is the prime's number of bits
500 * This function will export the pair of prime and generator for use
501 * in the Diffie-Hellman key exchange. The new parameters will be
502 * allocated using gnutls_malloc() and will be stored in the
505 * Returns: On success, %GNUTLS_E_SUCCESS (zero) is returned,
506 * otherwise an error code is returned.
509 gnutls_dh_params_export_raw (gnutls_dh_params_t params
,
510 gnutls_datum_t
* prime
,
511 gnutls_datum_t
* generator
, unsigned int *bits
)
515 if (params
->params
[1] == NULL
|| params
->params
[0] == NULL
)
518 return GNUTLS_E_INVALID_REQUEST
;
521 ret
= _gnutls_mpi_dprint (params
->params
[1], generator
);
528 ret
= _gnutls_mpi_dprint (params
->params
[0], prime
);
532 _gnutls_free_datum (generator
);
537 *bits
= _gnutls_mpi_get_nbits (params
->params
[0]);