Add `gnutls/dtls.h' to the distribution.
[gnutls.git] / lib / gnutls_dh_primes.c
blob091388ee2a5cb535ca7e971990835650c0b72d4c
1 /*
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,
22 * USA
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"
35 #include "debug.h"
38 /* returns the prime and the generator of DH params.
40 const bigint_t *
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)
46 return NULL;
49 return dh_primes->params;
53 /**
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.
65 **/
66 int
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;
72 size_t siz;
74 siz = prime->size;
75 if (_gnutls_mpi_scan_nz (&tmp_prime, prime->data, siz))
77 gnutls_assert ();
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);
85 gnutls_assert ();
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;
94 return 0;
98 /**
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)
114 gnutls_assert ();
115 return GNUTLS_E_MEMORY_ERROR;
118 return 0;
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.
128 void
129 gnutls_dh_params_deinit (gnutls_dh_params_t dh_params)
131 if (dh_params == NULL)
132 return;
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
147 * to destination.
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)
155 if (src == NULL)
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;
164 return 0;
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)
190 int ret;
191 gnutls_group_st group;
193 ret = _gnutls_mpi_generate_group (&group, bits);
194 if (ret < 0)
196 gnutls_assert ();
197 return ret;
200 params->params[0] = group.p;
201 params->params[1] = group.g;
203 return 0;
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)
226 ASN1_TYPE c2;
227 int result, need_free = 0;
228 gnutls_datum_t _params;
230 if (format == GNUTLS_X509_FMT_PEM)
232 opaque *out;
234 result = _gnutls_fbase64_decode ("DH PARAMETERS",
235 pkcs3_params->data,
236 pkcs3_params->size, &out);
238 if (result <= 0)
240 if (result == 0)
241 result = GNUTLS_E_INTERNAL_ERROR;
242 gnutls_assert ();
243 return result;
246 _params.data = out;
247 _params.size = result;
249 need_free = 1;
252 else
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))
260 != ASN1_SUCCESS)
262 gnutls_assert ();
263 if (need_free != 0)
265 gnutls_free (_params.data);
266 _params.data = NULL;
268 return _gnutls_asn2err (result);
271 result = asn1_der_decoding (&c2, _params.data, _params.size, NULL);
273 if (need_free != 0)
275 gnutls_free (_params.data);
276 _params.data = NULL;
279 if (result != ASN1_SUCCESS)
281 /* couldn't decode DER */
283 _gnutls_debug_log ("DHParams: Decoding error %d\n", result);
284 gnutls_assert ();
285 asn1_delete_structure (&c2);
286 return _gnutls_asn2err (result);
289 /* Read PRIME
291 result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
292 if (result < 0)
294 asn1_delete_structure (&c2);
295 gnutls_assert ();
296 return result;
299 /* read the generator
301 result = _gnutls_x509_read_int (c2, "base", &params->params[1]);
302 if (result < 0)
304 asn1_delete_structure (&c2);
305 _gnutls_mpi_release (&params->params[0]);
306 gnutls_assert ();
307 return result;
310 asn1_delete_structure (&c2);
312 return 0;
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)
339 ASN1_TYPE c2;
340 int result, _params_data_size;
341 size_t g_size, p_size;
342 opaque *p_data, *g_data;
343 opaque *all_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)
351 gnutls_assert ();
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))
367 != ASN1_SUCCESS)
369 gnutls_assert ();
370 gnutls_free (all_data);
371 return _gnutls_asn2err (result);
374 /* Write PRIME
376 if ((result = asn1_write_value (c2, "prime",
377 p_data, p_size)) != ASN1_SUCCESS)
379 gnutls_assert ();
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)
390 gnutls_assert ();
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)
401 gnutls_assert ();
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;
412 result =
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)
419 gnutls_assert ();
420 if (result == ASN1_MEM_ERROR)
421 return GNUTLS_E_SHORT_MEMORY_BUFFER;
423 return _gnutls_asn2err (result);
427 else
428 { /* PEM */
429 opaque *tmp;
430 opaque *out;
431 int len;
433 len = 0;
434 asn1_der_coding (c2, "", NULL, &len, NULL);
436 tmp = gnutls_malloc (len);
437 if (tmp == NULL)
439 gnutls_assert ();
440 asn1_delete_structure (&c2);
441 return GNUTLS_E_MEMORY_ERROR;
444 if ((result =
445 asn1_der_coding (c2, "", tmp, &len, NULL)) != ASN1_SUCCESS)
447 gnutls_assert ();
448 gnutls_free (tmp);
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);
457 gnutls_free (tmp);
459 if (result < 0)
461 gnutls_assert ();
462 return result;
465 if (result == 0)
466 { /* oooops */
467 gnutls_assert ();
468 gnutls_free (out);
469 return GNUTLS_E_INTERNAL_ERROR;
472 if ((unsigned) result > *params_data_size)
474 gnutls_assert ();
475 gnutls_free (out);
476 *params_data_size = result;
477 return GNUTLS_E_SHORT_MEMORY_BUFFER;
480 *params_data_size = result - 1;
482 if (params_data)
483 memcpy (params_data, out, result);
485 gnutls_free (out);
489 return 0;
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
502 * appropriate datum.
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)
512 int ret;
514 if (params->params[1] == NULL || params->params[0] == NULL)
516 gnutls_assert ();
517 return GNUTLS_E_INVALID_REQUEST;
520 ret = _gnutls_mpi_dprint (params->params[1], generator);
521 if (ret < 0)
523 gnutls_assert ();
524 return ret;
527 ret = _gnutls_mpi_dprint (params->params[0], prime);
528 if (ret < 0)
530 gnutls_assert ();
531 _gnutls_free_datum (generator);
532 return ret;
535 if (bits)
536 *bits = _gnutls_mpi_get_nbits (params->params[0]);
538 return 0;