guile: Fix `priorities' test to use `run-test'.
[gnutls.git] / lib / gnutls_dh_primes.c
blobc4ea423d75f874fab5f5f5aee7ff157d21258597
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 3 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 License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>
24 #include <gnutls_int.h>
25 #include <gnutls_errors.h>
26 #include <gnutls_datum.h>
27 #include <x509_b64.h> /* for PKCS3 PEM decoding */
28 #include <gnutls_global.h>
29 #include <gnutls_dh.h>
30 #include <gnutls_pk.h>
31 #include <gnutls/crypto.h>
32 #include "x509/x509_int.h"
33 #include "debug.h"
36 /* returns the prime and the generator of DH params.
38 const bigint_t *
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)
44 return NULL;
47 return dh_primes->params;
51 /**
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.
63 **/
64 int
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;
70 size_t siz;
72 siz = prime->size;
73 if (_gnutls_mpi_scan_nz (&tmp_prime, prime->data, siz))
75 gnutls_assert ();
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);
83 gnutls_assert ();
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;
92 return 0;
96 /**
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)
112 gnutls_assert ();
113 return GNUTLS_E_MEMORY_ERROR;
116 return 0;
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.
126 void
127 gnutls_dh_params_deinit (gnutls_dh_params_t dh_params)
129 if (dh_params == NULL)
130 return;
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
145 * to destination.
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)
153 if (src == NULL)
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]);
159 if (dst->params[0] == NULL || dst->params[1] == NULL)
160 return GNUTLS_E_MEMORY_ERROR;
162 return 0;
167 * gnutls_dh_params_generate2:
168 * @params: Is the structure that the DH parameters will be stored
169 * @bits: is the prime's number of bits
171 * This function will generate a new pair of prime and generator for use in
172 * the Diffie-Hellman key exchange. The new parameters will be allocated using
173 * gnutls_malloc() and will be stored in the appropriate datum.
174 * This function is normally slow.
176 * Do not set the number of bits directly, use gnutls_sec_param_to_pk_bits() to
177 * get bits for %GNUTLS_PK_DSA.
178 * Also note that the DH parameters are only useful to servers.
179 * Since clients use the parameters sent by the server, it's of
180 * no use to call this in client side.
182 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
183 * otherwise a negative error code is returned.
186 gnutls_dh_params_generate2 (gnutls_dh_params_t params, unsigned int bits)
188 int ret;
189 gnutls_group_st group;
191 ret = _gnutls_mpi_generate_group (&group, bits);
192 if (ret < 0)
194 gnutls_assert ();
195 return ret;
198 params->params[0] = group.p;
199 params->params[1] = group.g;
201 return 0;
205 * gnutls_dh_params_import_pkcs3:
206 * @params: A structure where the parameters will be copied to
207 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
208 * @format: the format of params. PEM or DER.
210 * This function will extract the DHParams found in a PKCS3 formatted
211 * structure. This is the format generated by "openssl dhparam" tool.
213 * If the structure is PEM encoded, it should have a header
214 * of "BEGIN DH PARAMETERS".
216 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
217 * otherwise a negative error code is returned.
220 gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
221 const gnutls_datum_t * pkcs3_params,
222 gnutls_x509_crt_fmt_t format)
224 ASN1_TYPE c2;
225 int result, need_free = 0;
226 gnutls_datum_t _params;
228 if (format == GNUTLS_X509_FMT_PEM)
230 opaque *out;
232 result = _gnutls_fbase64_decode ("DH PARAMETERS",
233 pkcs3_params->data,
234 pkcs3_params->size, &out);
236 if (result <= 0)
238 if (result == 0)
239 result = GNUTLS_E_INTERNAL_ERROR;
240 gnutls_assert ();
241 return result;
244 _params.data = out;
245 _params.size = result;
247 need_free = 1;
250 else
252 _params.data = pkcs3_params->data;
253 _params.size = pkcs3_params->size;
256 if ((result = asn1_create_element
257 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2))
258 != ASN1_SUCCESS)
260 gnutls_assert ();
261 if (need_free != 0)
263 gnutls_free (_params.data);
264 _params.data = NULL;
266 return _gnutls_asn2err (result);
269 result = asn1_der_decoding (&c2, _params.data, _params.size, NULL);
271 if (need_free != 0)
273 gnutls_free (_params.data);
274 _params.data = NULL;
277 if (result != ASN1_SUCCESS)
279 /* couldn't decode DER */
281 _gnutls_debug_log ("DHParams: Decoding error %d\n", result);
282 gnutls_assert ();
283 asn1_delete_structure (&c2);
284 return _gnutls_asn2err (result);
287 /* Read PRIME
289 result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
290 if (result < 0)
292 asn1_delete_structure (&c2);
293 gnutls_assert ();
294 return result;
297 /* read the generator
299 result = _gnutls_x509_read_int (c2, "base", &params->params[1]);
300 if (result < 0)
302 asn1_delete_structure (&c2);
303 _gnutls_mpi_release (&params->params[0]);
304 gnutls_assert ();
305 return result;
308 asn1_delete_structure (&c2);
310 return 0;
314 * gnutls_dh_params_export_pkcs3:
315 * @params: Holds the DH parameters
316 * @format: the format of output params. One of PEM or DER.
317 * @params_data: will contain a PKCS3 DHParams structure PEM or DER encoded
318 * @params_data_size: holds the size of params_data (and will be replaced by the actual size of parameters)
320 * This function will export the given dh parameters to a PKCS3
321 * DHParams structure. This is the format generated by "openssl dhparam" tool.
322 * If the buffer provided is not long enough to hold the output, then
323 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
325 * If the structure is PEM encoded, it will have a header
326 * of "BEGIN DH PARAMETERS".
328 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
329 * otherwise a negative error code is returned.
332 gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params,
333 gnutls_x509_crt_fmt_t format,
334 unsigned char *params_data,
335 size_t * params_data_size)
337 ASN1_TYPE c2;
338 int result, _params_data_size;
339 size_t g_size, p_size;
340 opaque *p_data, *g_data;
341 opaque *all_data;
343 _gnutls_mpi_print_lz (params->params[1], NULL, &g_size);
344 _gnutls_mpi_print_lz (params->params[0], NULL, &p_size);
346 all_data = gnutls_malloc (g_size + p_size);
347 if (all_data == NULL)
349 gnutls_assert ();
350 return GNUTLS_E_MEMORY_ERROR;
353 p_data = &all_data[0];
354 _gnutls_mpi_print_lz (params->params[0], p_data, &p_size);
356 g_data = &all_data[p_size];
357 _gnutls_mpi_print_lz (params->params[1], g_data, &g_size);
360 /* Ok. Now we have the data. Create the asn1 structures
363 if ((result = asn1_create_element
364 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2))
365 != ASN1_SUCCESS)
367 gnutls_assert ();
368 gnutls_free (all_data);
369 return _gnutls_asn2err (result);
372 /* Write PRIME
374 if ((result = asn1_write_value (c2, "prime",
375 p_data, p_size)) != ASN1_SUCCESS)
377 gnutls_assert ();
378 gnutls_free (all_data);
379 asn1_delete_structure (&c2);
380 return _gnutls_asn2err (result);
383 /* Write the GENERATOR
385 if ((result = asn1_write_value (c2, "base",
386 g_data, g_size)) != ASN1_SUCCESS)
388 gnutls_assert ();
389 gnutls_free (all_data);
390 asn1_delete_structure (&c2);
391 return _gnutls_asn2err (result);
394 gnutls_free (all_data);
396 if ((result = asn1_write_value (c2, "privateValueLength",
397 NULL, 0)) != ASN1_SUCCESS)
399 gnutls_assert ();
400 asn1_delete_structure (&c2);
401 return _gnutls_asn2err (result);
404 if (format == GNUTLS_X509_FMT_DER)
406 if (params_data == NULL)
407 *params_data_size = 0;
409 _params_data_size = *params_data_size;
410 result =
411 asn1_der_coding (c2, "", params_data, &_params_data_size, NULL);
412 *params_data_size = _params_data_size;
413 asn1_delete_structure (&c2);
415 if (result != ASN1_SUCCESS)
417 gnutls_assert ();
418 if (result == ASN1_MEM_ERROR)
419 return GNUTLS_E_SHORT_MEMORY_BUFFER;
421 return _gnutls_asn2err (result);
425 else
426 { /* PEM */
427 opaque *tmp;
428 opaque *out;
429 int len;
431 len = 0;
432 asn1_der_coding (c2, "", NULL, &len, NULL);
434 tmp = gnutls_malloc (len);
435 if (tmp == NULL)
437 gnutls_assert ();
438 asn1_delete_structure (&c2);
439 return GNUTLS_E_MEMORY_ERROR;
442 if ((result =
443 asn1_der_coding (c2, "", tmp, &len, NULL)) != ASN1_SUCCESS)
445 gnutls_assert ();
446 gnutls_free (tmp);
447 asn1_delete_structure (&c2);
448 return _gnutls_asn2err (result);
451 asn1_delete_structure (&c2);
453 result = _gnutls_fbase64_encode ("DH PARAMETERS", tmp, len, &out);
455 gnutls_free (tmp);
457 if (result < 0)
459 gnutls_assert ();
460 return result;
463 if (result == 0)
464 { /* oooops */
465 gnutls_assert ();
466 gnutls_free (out);
467 return GNUTLS_E_INTERNAL_ERROR;
470 if ((unsigned) result > *params_data_size)
472 gnutls_assert ();
473 gnutls_free (out);
474 *params_data_size = result;
475 return GNUTLS_E_SHORT_MEMORY_BUFFER;
478 *params_data_size = result - 1;
480 if (params_data)
481 memcpy (params_data, out, result);
483 gnutls_free (out);
487 return 0;
491 * gnutls_dh_params_export_raw:
492 * @params: Holds the DH parameters
493 * @prime: will hold the new prime
494 * @generator: will hold the new generator
495 * @bits: if non null will hold is the prime's number of bits
497 * This function will export the pair of prime and generator for use
498 * in the Diffie-Hellman key exchange. The new parameters will be
499 * allocated using gnutls_malloc() and will be stored in the
500 * appropriate datum.
502 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
503 * otherwise a negative error code is returned.
506 gnutls_dh_params_export_raw (gnutls_dh_params_t params,
507 gnutls_datum_t * prime,
508 gnutls_datum_t * generator, unsigned int *bits)
510 int ret;
512 if (params->params[1] == NULL || params->params[0] == NULL)
514 gnutls_assert ();
515 return GNUTLS_E_INVALID_REQUEST;
518 ret = _gnutls_mpi_dprint (params->params[1], generator);
519 if (ret < 0)
521 gnutls_assert ();
522 return ret;
525 ret = _gnutls_mpi_dprint (params->params[0], prime);
526 if (ret < 0)
528 gnutls_assert ();
529 _gnutls_free_datum (generator);
530 return ret;
533 if (bits)
534 *bits = _gnutls_mpi_get_nbits (params->params[0]);
536 return 0;