cleaned up errno handling.
[gnutls.git] / lib / gnutls_dh_primes.c
blob70d73d2efd21c2905aac55eaf1935b9eaa5efc9d
1 /*
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 <gnutls/crypto.h>
31 #include "x509/x509_int.h"
32 #include "debug.h"
35 /* returns the prime and the generator of DH params.
37 const bigint_t *
38 _gnutls_dh_params_to_mpi (gnutls_dh_params_t dh_primes)
40 if (dh_primes == NULL || dh_primes->params[1] == NULL ||
41 dh_primes->params[0] == NULL)
43 return NULL;
46 return dh_primes->params;
50 /**
51 * gnutls_dh_params_import_raw:
52 * @dh_params: Is a structure that will hold the prime numbers
53 * @prime: holds the new prime
54 * @generator: holds the new generator
56 * This function will replace the pair of prime and generator for use
57 * in the Diffie-Hellman key exchange. The new parameters should be
58 * stored in the appropriate gnutls_datum.
60 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
61 * otherwise a negative error code is returned.
62 **/
63 int
64 gnutls_dh_params_import_raw (gnutls_dh_params_t dh_params,
65 const gnutls_datum_t * prime,
66 const gnutls_datum_t * generator)
68 bigint_t tmp_prime, tmp_g;
69 size_t siz;
71 siz = prime->size;
72 if (_gnutls_mpi_scan_nz (&tmp_prime, prime->data, siz))
74 gnutls_assert ();
75 return GNUTLS_E_MPI_SCAN_FAILED;
78 siz = generator->size;
79 if (_gnutls_mpi_scan_nz (&tmp_g, generator->data, siz))
81 _gnutls_mpi_release (&tmp_prime);
82 gnutls_assert ();
83 return GNUTLS_E_MPI_SCAN_FAILED;
86 /* store the generated values
88 dh_params->params[0] = tmp_prime;
89 dh_params->params[1] = tmp_g;
91 return 0;
95 /**
96 * gnutls_dh_params_init:
97 * @dh_params: Is a structure that will hold the prime numbers
99 * This function will initialize the DH parameters structure.
101 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
102 * otherwise a negative error code is returned.
105 gnutls_dh_params_init (gnutls_dh_params_t * dh_params)
108 (*dh_params) = gnutls_calloc (1, sizeof (dh_params_st));
109 if (*dh_params == NULL)
111 gnutls_assert ();
112 return GNUTLS_E_MEMORY_ERROR;
115 return 0;
120 * gnutls_dh_params_deinit:
121 * @dh_params: Is a structure that holds the prime numbers
123 * This function will deinitialize the DH parameters structure.
125 void
126 gnutls_dh_params_deinit (gnutls_dh_params_t dh_params)
128 if (dh_params == NULL)
129 return;
131 _gnutls_mpi_release (&dh_params->params[0]);
132 _gnutls_mpi_release (&dh_params->params[1]);
134 gnutls_free (dh_params);
139 * gnutls_dh_params_cpy:
140 * @dst: Is the destination structure, which should be initialized.
141 * @src: Is the source structure
143 * This function will copy the DH parameters structure from source
144 * to destination.
146 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
147 * otherwise a negative error code is returned.
150 gnutls_dh_params_cpy (gnutls_dh_params_t dst, gnutls_dh_params_t src)
152 if (src == NULL)
153 return GNUTLS_E_INVALID_REQUEST;
155 dst->params[0] = _gnutls_mpi_copy (src->params[0]);
156 dst->params[1] = _gnutls_mpi_copy (src->params[1]);
157 dst->q_bits = src->q_bits;
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;
200 params->q_bits = group.q_bits;
202 return 0;
206 * gnutls_dh_params_import_pkcs3:
207 * @params: A structure where the parameters will be copied to
208 * @pkcs3_params: should contain a PKCS3 DHParams structure PEM or DER encoded
209 * @format: the format of params. PEM or DER.
211 * This function will extract the DHParams found in a PKCS3 formatted
212 * structure. This is the format generated by "openssl dhparam" tool.
214 * If the structure is PEM encoded, it should have a header
215 * of "BEGIN DH PARAMETERS".
217 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
218 * otherwise a negative error code is returned.
221 gnutls_dh_params_import_pkcs3 (gnutls_dh_params_t params,
222 const gnutls_datum_t * pkcs3_params,
223 gnutls_x509_crt_fmt_t format)
225 ASN1_TYPE c2;
226 int result, need_free = 0;
227 unsigned int q_bits;
228 gnutls_datum_t _params;
230 if (format == GNUTLS_X509_FMT_PEM)
232 uint8_t *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 q length */
290 result = _gnutls_x509_read_uint (c2, "privateValueLength", &q_bits);
291 if (result < 0)
293 gnutls_assert ();
294 params->q_bits = 0;
296 else
297 params->q_bits = q_bits;
299 /* Read PRIME
301 result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
302 if (result < 0)
304 asn1_delete_structure (&c2);
305 gnutls_assert ();
306 return result;
309 /* read the generator
311 result = _gnutls_x509_read_int (c2, "base", &params->params[1]);
312 if (result < 0)
314 asn1_delete_structure (&c2);
315 _gnutls_mpi_release (&params->params[0]);
316 gnutls_assert ();
317 return result;
320 asn1_delete_structure (&c2);
322 return 0;
326 * gnutls_dh_params_export_pkcs3:
327 * @params: Holds the DH parameters
328 * @format: the format of output params. One of PEM or DER.
329 * @params_data: will contain a PKCS3 DHParams structure PEM or DER encoded
330 * @params_data_size: holds the size of params_data (and will be replaced by the actual size of parameters)
332 * This function will export the given dh parameters to a PKCS3
333 * DHParams structure. This is the format generated by "openssl dhparam" tool.
334 * If the buffer provided is not long enough to hold the output, then
335 * GNUTLS_E_SHORT_MEMORY_BUFFER will be returned.
337 * If the structure is PEM encoded, it will have a header
338 * of "BEGIN DH PARAMETERS".
340 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
341 * otherwise a negative error code is returned.
344 gnutls_dh_params_export_pkcs3 (gnutls_dh_params_t params,
345 gnutls_x509_crt_fmt_t format,
346 unsigned char *params_data,
347 size_t * params_data_size)
349 ASN1_TYPE c2;
350 int result, _params_data_size;
351 size_t g_size, p_size;
352 uint8_t *p_data, *g_data;
353 uint8_t *all_data;
355 _gnutls_mpi_print_lz (params->params[1], NULL, &g_size);
356 _gnutls_mpi_print_lz (params->params[0], NULL, &p_size);
358 all_data = gnutls_malloc (g_size + p_size);
359 if (all_data == NULL)
361 gnutls_assert ();
362 return GNUTLS_E_MEMORY_ERROR;
365 p_data = &all_data[0];
366 _gnutls_mpi_print_lz (params->params[0], p_data, &p_size);
368 g_data = &all_data[p_size];
369 _gnutls_mpi_print_lz (params->params[1], g_data, &g_size);
372 /* Ok. Now we have the data. Create the asn1 structures
375 if ((result = asn1_create_element
376 (_gnutls_get_gnutls_asn (), "GNUTLS.DHParameter", &c2))
377 != ASN1_SUCCESS)
379 gnutls_assert ();
380 gnutls_free (all_data);
381 return _gnutls_asn2err (result);
384 /* Write PRIME
386 if ((result = asn1_write_value (c2, "prime",
387 p_data, p_size)) != ASN1_SUCCESS)
389 gnutls_assert ();
390 gnutls_free (all_data);
391 asn1_delete_structure (&c2);
392 return _gnutls_asn2err (result);
395 if (params->q_bits > 0)
396 result = _gnutls_x509_write_uint32 (c2, "privateValueLength", params->q_bits);
397 else
398 result = asn1_write_value (c2, "privateValueLength", NULL, 0);
400 if (result < 0)
402 gnutls_assert ();
403 asn1_delete_structure (&c2);
404 return _gnutls_asn2err (result);
407 /* Write the GENERATOR
409 if ((result = asn1_write_value (c2, "base",
410 g_data, g_size)) != ASN1_SUCCESS)
412 gnutls_assert ();
413 gnutls_free (all_data);
414 asn1_delete_structure (&c2);
415 return _gnutls_asn2err (result);
418 gnutls_free (all_data);
421 if (format == GNUTLS_X509_FMT_DER)
423 if (params_data == NULL)
424 *params_data_size = 0;
426 _params_data_size = *params_data_size;
427 result =
428 asn1_der_coding (c2, "", params_data, &_params_data_size, NULL);
429 *params_data_size = _params_data_size;
430 asn1_delete_structure (&c2);
432 if (result != ASN1_SUCCESS)
434 gnutls_assert ();
435 if (result == ASN1_MEM_ERROR)
436 return GNUTLS_E_SHORT_MEMORY_BUFFER;
438 return _gnutls_asn2err (result);
442 else
443 { /* PEM */
444 uint8_t *tmp;
445 uint8_t *out;
446 int len;
448 len = 0;
449 asn1_der_coding (c2, "", NULL, &len, NULL);
451 tmp = gnutls_malloc (len);
452 if (tmp == NULL)
454 gnutls_assert ();
455 asn1_delete_structure (&c2);
456 return GNUTLS_E_MEMORY_ERROR;
459 if ((result =
460 asn1_der_coding (c2, "", tmp, &len, NULL)) != ASN1_SUCCESS)
462 gnutls_assert ();
463 gnutls_free (tmp);
464 asn1_delete_structure (&c2);
465 return _gnutls_asn2err (result);
468 asn1_delete_structure (&c2);
470 result = _gnutls_fbase64_encode ("DH PARAMETERS", tmp, len, &out);
472 gnutls_free (tmp);
474 if (result < 0)
476 gnutls_assert ();
477 return result;
480 if (result == 0)
481 { /* oooops */
482 gnutls_assert ();
483 gnutls_free (out);
484 return GNUTLS_E_INTERNAL_ERROR;
487 if ((unsigned) result > *params_data_size)
489 gnutls_assert ();
490 gnutls_free (out);
491 *params_data_size = result;
492 return GNUTLS_E_SHORT_MEMORY_BUFFER;
495 *params_data_size = result - 1;
497 if (params_data)
498 memcpy (params_data, out, result);
500 gnutls_free (out);
504 return 0;
508 * gnutls_dh_params_export_raw:
509 * @params: Holds the DH parameters
510 * @prime: will hold the new prime
511 * @generator: will hold the new generator
512 * @bits: if non null will hold the secret key's number of bits
514 * This function will export the pair of prime and generator for use
515 * in the Diffie-Hellman key exchange. The new parameters will be
516 * allocated using gnutls_malloc() and will be stored in the
517 * appropriate datum.
519 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned,
520 * otherwise a negative error code is returned.
523 gnutls_dh_params_export_raw (gnutls_dh_params_t params,
524 gnutls_datum_t * prime,
525 gnutls_datum_t * generator, unsigned int *bits)
527 int ret;
529 if (params->params[1] == NULL || params->params[0] == NULL)
531 gnutls_assert ();
532 return GNUTLS_E_INVALID_REQUEST;
535 ret = _gnutls_mpi_dprint (params->params[1], generator);
536 if (ret < 0)
538 gnutls_assert ();
539 return ret;
542 ret = _gnutls_mpi_dprint (params->params[0], prime);
543 if (ret < 0)
545 gnutls_assert ();
546 _gnutls_free_datum (generator);
547 return ret;
550 if (bits)
551 *bits = params->q_bits;
553 return 0;