added new functions
[gnutls.git] / lib / gnutls_dh_primes.c
blob4eb16388ef4c23b2ce49db66fadf4d0bfb6b13e0
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 <x509/common.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]);
158 dst->q_bits = src->q_bits;
160 if (dst->params[0] == NULL || dst->params[1] == NULL)
161 return GNUTLS_E_MEMORY_ERROR;
163 return 0;
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)
189 int ret;
190 gnutls_group_st group;
192 ret = _gnutls_mpi_generate_group (&group, bits);
193 if (ret < 0)
195 gnutls_assert ();
196 return ret;
199 params->params[0] = group.p;
200 params->params[1] = group.g;
201 params->q_bits = group.q_bits;
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 (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)
226 ASN1_TYPE c2;
227 int result, need_free = 0;
228 unsigned int q_bits;
229 gnutls_datum_t _params;
231 if (format == GNUTLS_X509_FMT_PEM)
234 result = _gnutls_fbase64_decode ("DH PARAMETERS",
235 pkcs3_params->data,
236 pkcs3_params->size, &_params);
238 if (result <= 0)
240 if (result == 0)
241 result = GNUTLS_E_INTERNAL_ERROR;
242 gnutls_assert ();
243 return result;
246 need_free = 1;
248 else
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))
256 != ASN1_SUCCESS)
258 gnutls_assert ();
259 if (need_free != 0)
261 gnutls_free (_params.data);
262 _params.data = NULL;
264 return _gnutls_asn2err (result);
267 result = asn1_der_decoding (&c2, _params.data, _params.size, NULL);
269 if (need_free != 0)
271 gnutls_free (_params.data);
272 _params.data = NULL;
275 if (result != ASN1_SUCCESS)
277 /* couldn't decode DER */
279 _gnutls_debug_log ("DHParams: Decoding error %d\n", result);
280 gnutls_assert ();
281 asn1_delete_structure (&c2);
282 return _gnutls_asn2err (result);
285 /* Read q length */
286 result = _gnutls_x509_read_uint (c2, "privateValueLength", &q_bits);
287 if (result < 0)
289 gnutls_assert ();
290 params->q_bits = 0;
292 else
293 params->q_bits = q_bits;
295 /* Read PRIME
297 result = _gnutls_x509_read_int (c2, "prime", &params->params[0]);
298 if (result < 0)
300 asn1_delete_structure (&c2);
301 gnutls_assert ();
302 return result;
305 /* read the generator
307 result = _gnutls_x509_read_int (c2, "base", &params->params[1]);
308 if (result < 0)
310 asn1_delete_structure (&c2);
311 _gnutls_mpi_release (&params->params[0]);
312 gnutls_assert ();
313 return result;
316 asn1_delete_structure (&c2);
318 return 0;
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)
345 gnutls_datum_t out;
346 int ret;
348 ret = gnutls_dh_params_export2_pkcs3( params, format, &out);
349 if (ret < 0)
350 return gnutls_assert_val(ret);
352 if (*params_data_size < (unsigned) out.size+1)
354 gnutls_assert ();
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;
361 if (params_data)
363 memcpy( params_data, out.data, out.size);
364 params_data[out.size] = 0;
367 gnutls_free(out.data);
369 return 0;
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)
393 ASN1_TYPE c2;
394 int result;
395 size_t g_size, p_size;
396 uint8_t *p_data, *g_data;
397 uint8_t *all_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)
405 gnutls_assert ();
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))
421 != ASN1_SUCCESS)
423 gnutls_assert ();
424 gnutls_free (all_data);
425 return _gnutls_asn2err (result);
428 /* Write PRIME
430 if ((result = asn1_write_value (c2, "prime",
431 p_data, p_size)) != ASN1_SUCCESS)
433 gnutls_assert ();
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);
441 else
442 result = asn1_write_value (c2, "privateValueLength", NULL, 0);
444 if (result < 0)
446 gnutls_assert ();
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)
457 gnutls_assert ();
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);
472 if (result < 0)
473 return gnutls_assert_val (result);
476 else
477 { /* PEM */
478 gnutls_datum_t t;
480 result = _gnutls_x509_der_encode(c2, "", &t, 0);
482 asn1_delete_structure (&c2);
484 if (result < 0)
485 return gnutls_assert_val (result);
487 result = _gnutls_fbase64_encode("DH PARAMETERS", t.data, t.size, out);
489 gnutls_free (t.data);
491 if (result < 0)
493 gnutls_assert ();
494 return result;
498 return 0;
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
511 * appropriate datum.
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)
521 int ret;
523 if (params->params[1] == NULL || params->params[0] == NULL)
525 gnutls_assert ();
526 return GNUTLS_E_INVALID_REQUEST;
529 ret = _gnutls_mpi_dprint (params->params[1], generator);
530 if (ret < 0)
532 gnutls_assert ();
533 return ret;
536 ret = _gnutls_mpi_dprint (params->params[0], prime);
537 if (ret < 0)
539 gnutls_assert ();
540 _gnutls_free_datum (generator);
541 return ret;
544 if (bits)
545 *bits = params->q_bits;
547 return 0;