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 3 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"
36 /* returns the prime and the generator of DH params.
39 _gnutls_dh_params_to_mpi (gnutls_dh_params_t dh_primes
)
41 if (dh_primes
== NULL
|| dh_primes
->params
[1] == NULL
||
42 dh_primes
->params
[0] == NULL
)
47 return dh_primes
->params
;
52 * gnutls_dh_params_import_raw:
53 * @dh_params: Is a structure that will hold the prime numbers
54 * @prime: holds the new prime
55 * @generator: holds the new generator
57 * This function will replace the pair of prime and generator for use
58 * in the Diffie-Hellman key exchange. The new parameters should be
59 * stored in the appropriate gnutls_datum.
61 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
62 * otherwise a negative error code is returned.
65 gnutls_dh_params_import_raw (gnutls_dh_params_t dh_params
,
66 const gnutls_datum_t
* prime
,
67 const gnutls_datum_t
* generator
)
69 bigint_t tmp_prime
, tmp_g
;
73 if (_gnutls_mpi_scan_nz (&tmp_prime
, prime
->data
, siz
))
76 return GNUTLS_E_MPI_SCAN_FAILED
;
79 siz
= generator
->size
;
80 if (_gnutls_mpi_scan_nz (&tmp_g
, generator
->data
, siz
))
82 _gnutls_mpi_release (&tmp_prime
);
84 return GNUTLS_E_MPI_SCAN_FAILED
;
87 /* store the generated values
89 dh_params
->params
[0] = tmp_prime
;
90 dh_params
->params
[1] = tmp_g
;
97 * gnutls_dh_params_init:
98 * @dh_params: Is a structure that will hold the prime numbers
100 * This function will initialize the DH parameters structure.
102 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
103 * otherwise a negative error code is returned.
106 gnutls_dh_params_init (gnutls_dh_params_t
* dh_params
)
109 (*dh_params
) = gnutls_calloc (1, sizeof (dh_params_st
));
110 if (*dh_params
== NULL
)
113 return GNUTLS_E_MEMORY_ERROR
;
121 * gnutls_dh_params_deinit:
122 * @dh_params: Is a structure that holds the prime numbers
124 * This function will deinitialize the DH parameters structure.
127 gnutls_dh_params_deinit (gnutls_dh_params_t dh_params
)
129 if (dh_params
== NULL
)
132 _gnutls_mpi_release (&dh_params
->params
[0]);
133 _gnutls_mpi_release (&dh_params
->params
[1]);
135 gnutls_free (dh_params
);
140 * gnutls_dh_params_cpy:
141 * @dst: Is the destination structure, which should be initialized.
142 * @src: Is the source structure
144 * This function will copy the DH parameters structure from source
147 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
148 * otherwise a negative error code is returned.
151 gnutls_dh_params_cpy (gnutls_dh_params_t dst
, gnutls_dh_params_t src
)
154 return GNUTLS_E_INVALID_REQUEST
;
156 dst
->params
[0] = _gnutls_mpi_copy (src
->params
[0]);
157 dst
->params
[1] = _gnutls_mpi_copy (src
->params
[1]);
158 dst
->q_bits
= src
->q_bits
;
160 if (dst
->params
[0] == NULL
|| dst
->params
[1] == NULL
)
161 return GNUTLS_E_MEMORY_ERROR
;
168 * gnutls_dh_params_generate2:
169 * @params: Is the structure that the DH parameters will be stored
170 * @bits: is the prime's number of bits
172 * This function will generate a new pair of prime and generator for use in
173 * the Diffie-Hellman key exchange. The new parameters will be allocated using
174 * gnutls_malloc() and will be stored in the appropriate datum.
175 * This function is normally slow.
177 * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits() to
178 * get bits for %GNUTLS_PK_DSA.
179 * Also note that the DH parameters are only useful to servers.
180 * Since clients use the parameters sent by the server, it's of
181 * no use to call this in client side.
183 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
184 * otherwise a negative error code is returned.
187 gnutls_dh_params_generate2 (gnutls_dh_params_t params
, unsigned int bits
)
190 gnutls_group_st group
;
192 ret
= _gnutls_mpi_generate_group (&group
, bits
);
199 params
->params
[0] = group
.p
;
200 params
->params
[1] = group
.g
;
201 params
->q_bits
= group
.q_bits
;
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 (0) is returned,
219 * otherwise a negative 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;
229 gnutls_datum_t _params
;
231 if (format
== GNUTLS_X509_FMT_PEM
)
234 result
= _gnutls_fbase64_decode ("DH PARAMETERS",
236 pkcs3_params
->size
, &_params
);
241 result
= GNUTLS_E_INTERNAL_ERROR
;
250 _params
.data
= pkcs3_params
->data
;
251 _params
.size
= pkcs3_params
->size
;
254 if ((result
= asn1_create_element
255 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2
))
261 gnutls_free (_params
.data
);
264 return _gnutls_asn2err (result
);
267 result
= asn1_der_decoding (&c2
, _params
.data
, _params
.size
, NULL
);
271 gnutls_free (_params
.data
);
275 if (result
!= ASN1_SUCCESS
)
277 /* couldn't decode DER */
279 _gnutls_debug_log ("DHParams: Decoding error %d\n", result
);
281 asn1_delete_structure (&c2
);
282 return _gnutls_asn2err (result
);
286 result
= _gnutls_x509_read_uint (c2
, "privateValueLength", &q_bits
);
293 params
->q_bits
= q_bits
;
297 result
= _gnutls_x509_read_int (c2
, "prime", ¶ms
->params
[0]);
300 asn1_delete_structure (&c2
);
305 /* read the generator
307 result
= _gnutls_x509_read_int (c2
, "base", ¶ms
->params
[1]);
310 asn1_delete_structure (&c2
);
311 _gnutls_mpi_release (¶ms
->params
[0]);
316 asn1_delete_structure (&c2
);
322 * gnutls_dh_params_export_pkcs3:
323 * @params: Holds the DH parameters
324 * @format: the format of output params. One of PEM or DER.
325 * @params_data: will contain a PKCS3 DHParams structure PEM or DER encoded
326 * @params_data_size: holds the size of params_data (and will be replaced by the actual size of parameters)
328 * This function will export the given dh parameters to a PKCS3
329 * DHParams structure. This is the format generated by "openssl dhparam" tool.
330 * If the buffer provided is not long enough to hold the output, then
331 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
333 * If the structure is PEM encoded, it will have a header
334 * of "BEGIN DH PARAMETERS".
336 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
337 * otherwise a negative error code is returned.
340 gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params
,
341 gnutls_x509_crt_fmt_t format
,
342 unsigned char *params_data
,
343 size_t * params_data_size
)
348 ret
= gnutls_dh_params_export2_pkcs3( params
, format
, &out
);
350 return gnutls_assert_val(ret
);
352 if (*params_data_size
< (unsigned) out
.size
+1)
355 gnutls_free (out
.data
);
356 *params_data_size
= out
.size
+ 1;
357 return GNUTLS_E_SHORT_MEMORY_BUFFER
;
360 *params_data_size
= out
.size
;
363 memcpy( params_data
, out
.data
, out
.size
);
364 params_data
[out
.size
] = 0;
367 gnutls_free(out
.data
);
373 * gnutls_dh_params_export2_pkcs3:
374 * @params: Holds the DH parameters
375 * @format: the format of output params. One of PEM or DER.
376 * @out: will contain a PKCS3 DHParams structure PEM or DER encoded
378 * This function will export the given dh parameters to a PKCS3
379 * DHParams structure. This is the format generated by "openssl dhparam" tool.
380 * The data in @out will be allocated using gnutls_malloc().
382 * If the structure is PEM encoded, it will have a header
383 * of "BEGIN DH PARAMETERS".
385 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
386 * otherwise a negative error code is returned.
389 gnutls_dh_params_export2_pkcs3 (gnutls_dh_params_t params
,
390 gnutls_x509_crt_fmt_t format
,
391 gnutls_datum_t
* out
)
395 size_t g_size
, p_size
;
396 uint8_t *p_data
, *g_data
;
399 _gnutls_mpi_print_lz (params
->params
[1], NULL
, &g_size
);
400 _gnutls_mpi_print_lz (params
->params
[0], NULL
, &p_size
);
402 all_data
= gnutls_malloc (g_size
+ p_size
);
403 if (all_data
== NULL
)
406 return GNUTLS_E_MEMORY_ERROR
;
409 p_data
= &all_data
[0];
410 _gnutls_mpi_print_lz (params
->params
[0], p_data
, &p_size
);
412 g_data
= &all_data
[p_size
];
413 _gnutls_mpi_print_lz (params
->params
[1], g_data
, &g_size
);
416 /* Ok. Now we have the data. Create the asn1 structures
419 if ((result
= asn1_create_element
420 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2
))
424 gnutls_free (all_data
);
425 return _gnutls_asn2err (result
);
430 if ((result
= asn1_write_value (c2
, "prime",
431 p_data
, p_size
)) != ASN1_SUCCESS
)
434 gnutls_free (all_data
);
435 asn1_delete_structure (&c2
);
436 return _gnutls_asn2err (result
);
439 if (params
->q_bits
> 0)
440 result
= _gnutls_x509_write_uint32 (c2
, "privateValueLength", params
->q_bits
);
442 result
= asn1_write_value (c2
, "privateValueLength", NULL
, 0);
447 gnutls_free (all_data
);
448 asn1_delete_structure (&c2
);
449 return _gnutls_asn2err (result
);
452 /* Write the GENERATOR
454 if ((result
= asn1_write_value (c2
, "base",
455 g_data
, g_size
)) != ASN1_SUCCESS
)
458 gnutls_free (all_data
);
459 asn1_delete_structure (&c2
);
460 return _gnutls_asn2err (result
);
463 gnutls_free (all_data
);
466 if (format
== GNUTLS_X509_FMT_DER
)
468 result
= _gnutls_x509_der_encode(c2
, "", out
, 0);
470 asn1_delete_structure (&c2
);
473 return gnutls_assert_val (result
);
480 result
= _gnutls_x509_der_encode(c2
, "", &t
, 0);
482 asn1_delete_structure (&c2
);
485 return gnutls_assert_val (result
);
487 result
= _gnutls_fbase64_encode("DH PARAMETERS", t
.data
, t
.size
, out
);
489 gnutls_free (t
.data
);
502 * gnutls_dh_params_export_raw:
503 * @params: Holds the DH parameters
504 * @prime: will hold the new prime
505 * @generator: will hold the new generator
506 * @bits: if non null will hold the secret key's number of bits
508 * This function will export the pair of prime and generator for use
509 * in the Diffie-Hellman key exchange. The new parameters will be
510 * allocated using gnutls_malloc() and will be stored in the
513 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
514 * otherwise a negative error code is returned.
517 gnutls_dh_params_export_raw (gnutls_dh_params_t params
,
518 gnutls_datum_t
* prime
,
519 gnutls_datum_t
* generator
, unsigned int *bits
)
523 if (params
->params
[1] == NULL
|| params
->params
[0] == NULL
)
526 return GNUTLS_E_INVALID_REQUEST
;
529 ret
= _gnutls_mpi_dprint (params
->params
[1], generator
);
536 ret
= _gnutls_mpi_dprint (params
->params
[0], prime
);
540 _gnutls_free_datum (generator
);
545 *bits
= params
->q_bits
;