Update gnulib files.
[gnutls.git] / lib / gnutls_dh_primes.c
blob242ec89b81fee8c9fda049d49e44d2f67348d14c
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 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,
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 /* Replaces the prime in the static DH parameters, with a randomly
54 * generated one.
56 /**
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.
68 **/
69 int
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;
75 size_t siz;
77 siz = prime->size;
78 if (_gnutls_mpi_scan_nz (&tmp_prime, prime->data, siz))
80 gnutls_assert ();
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);
88 gnutls_assert ();
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;
97 return 0;
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)
117 gnutls_assert ();
118 return GNUTLS_E_MEMORY_ERROR;
121 return 0;
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.
131 void
132 gnutls_dh_params_deinit (gnutls_dh_params_t dh_params)
134 if (dh_params == NULL)
135 return;
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
150 * to destination.
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)
158 if (src == NULL)
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;
167 return 0;
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)
192 int ret;
193 gnutls_group_st group;
195 ret = _gnutls_mpi_generate_group (&group, bits);
196 if (ret < 0)
198 gnutls_assert ();
199 return ret;
202 params->params[0] = group.p;
203 params->params[1] = group.g;
205 return 0;
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)
228 ASN1_TYPE c2;
229 int result, need_free = 0;
230 gnutls_datum_t _params;
232 if (format == GNUTLS_X509_FMT_PEM)
234 opaque *out;
236 result = _gnutls_fbase64_decode ("DH PARAMETERS",
237 pkcs3_params->data,
238 pkcs3_params->size, &out);
240 if (result <= 0)
242 if (result == 0)
243 result = GNUTLS_E_INTERNAL_ERROR;
244 gnutls_assert ();
245 return result;
248 _params.data = out;
249 _params.size = result;
251 need_free = 1;
254 else
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))
262 != ASN1_SUCCESS)
264 gnutls_assert ();
265 if (need_free != 0)
267 gnutls_free (_params.data);
268 _params.data = NULL;
270 return _gnutls_asn2err (result);
273 result = asn1_der_decoding (&c2, _params.data, _params.size, NULL);
275 if (need_free != 0)
277 gnutls_free (_params.data);
278 _params.data = NULL;
281 if (result != ASN1_SUCCESS)
283 /* couldn't decode DER */
285 _gnutls_x509_log ("DHParams: Decoding error %d\n", result);
286 gnutls_assert ();
287 asn1_delete_structure (&c2);
288 return _gnutls_asn2err (result);
291 /* Read PRIME
293 result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
294 if (result < 0)
296 asn1_delete_structure (&c2);
297 gnutls_assert ();
298 return result;
301 /* read the generator
303 result = _gnutls_x509_read_int (c2, "base", &params->params[1]);
304 if (result < 0)
306 asn1_delete_structure (&c2);
307 _gnutls_mpi_release (&params->params[0]);
308 gnutls_assert ();
309 return result;
312 asn1_delete_structure (&c2);
314 return 0;
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)
341 ASN1_TYPE c2;
342 int result, _params_data_size;
343 size_t g_size, p_size;
344 opaque *p_data, *g_data;
345 opaque *all_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)
353 gnutls_assert ();
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))
368 != ASN1_SUCCESS)
370 gnutls_assert ();
371 gnutls_free (all_data);
372 return _gnutls_asn2err (result);
375 /* Write PRIME
377 if ((result = asn1_write_value (c2, "prime",
378 p_data, p_size)) != ASN1_SUCCESS)
380 gnutls_assert ();
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)
391 gnutls_assert ();
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)
402 gnutls_assert ();
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;
413 result =
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)
420 gnutls_assert ();
421 if (result == ASN1_MEM_ERROR)
422 return GNUTLS_E_SHORT_MEMORY_BUFFER;
424 return _gnutls_asn2err (result);
428 else
429 { /* PEM */
430 opaque *tmp;
431 opaque *out;
432 int len;
434 len = 0;
435 asn1_der_coding (c2, "", NULL, &len, NULL);
437 tmp = gnutls_malloc (len);
438 if (tmp == NULL)
440 gnutls_assert ();
441 asn1_delete_structure (&c2);
442 return GNUTLS_E_MEMORY_ERROR;
445 if ((result =
446 asn1_der_coding (c2, "", tmp, &len, NULL)) != ASN1_SUCCESS)
448 gnutls_assert ();
449 gnutls_free (tmp);
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);
458 gnutls_free (tmp);
460 if (result < 0)
462 gnutls_assert ();
463 return result;
466 if (result == 0)
467 { /* oooops */
468 gnutls_assert ();
469 gnutls_free (out);
470 return GNUTLS_E_INTERNAL_ERROR;
473 if ((unsigned) result > *params_data_size)
475 gnutls_assert ();
476 gnutls_free (out);
477 *params_data_size = result;
478 return GNUTLS_E_SHORT_MEMORY_BUFFER;
481 *params_data_size = result - 1;
483 if (params_data)
484 memcpy (params_data, out, result);
486 gnutls_free (out);
490 return 0;
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
503 * appropriate datum.
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)
513 int ret;
515 if (params->params[1] == NULL || params->params[0] == NULL)
517 gnutls_assert ();
518 return GNUTLS_E_INVALID_REQUEST;
521 ret = _gnutls_mpi_dprint (params->params[1], generator);
522 if (ret < 0)
524 gnutls_assert ();
525 return ret;
528 ret = _gnutls_mpi_dprint (params->params[0], prime);
529 if (ret < 0)
531 gnutls_assert ();
532 _gnutls_free_datum (generator);
533 return ret;
536 if (bits)
537 *bits = _gnutls_mpi_get_nbits (params->params[0]);
539 return 0;