Corrected bugs in record parsing.
[gnutls.git] / lib / x509 / key_encode.c
blob9aebf505ba47a6b39118f3711698c7109d24b609
1 /*
2 * Copyright (C) 2011-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_global.h>
26 #include <libtasn1.h>
27 #include <gnutls_datum.h>
28 #include "common.h"
29 #include "x509_int.h"
30 #include <gnutls_num.h>
31 #include <gnutls_pk.h>
32 #include <gnutls_mpi.h>
33 #include <gnutls_ecc.h>
35 static int _gnutls_x509_write_rsa_pubkey (gnutls_pk_params_st * params,
36 gnutls_datum_t * der);
37 static int _gnutls_x509_write_dsa_params (gnutls_pk_params_st * params,
38 gnutls_datum_t * der);
39 static int _gnutls_x509_write_dsa_pubkey (gnutls_pk_params_st * params,
40 gnutls_datum_t * der);
43 * some x509 certificate functions that relate to MPI parameter
44 * setting. This writes the BIT STRING subjectPublicKey.
45 * Needs 2 parameters (m,e).
47 * Allocates the space used to store the DER data.
49 static int
50 _gnutls_x509_write_rsa_pubkey (gnutls_pk_params_st * params,
51 gnutls_datum_t * der)
53 int result;
54 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
56 der->data = NULL;
57 der->size = 0;
59 if (params->params_nr < RSA_PUBLIC_PARAMS)
61 gnutls_assert ();
62 result = GNUTLS_E_INVALID_REQUEST;
63 goto cleanup;
66 if ((result = asn1_create_element
67 (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", &spk))
68 != ASN1_SUCCESS)
70 gnutls_assert ();
71 return _gnutls_asn2err (result);
74 result = _gnutls_x509_write_int (spk, "modulus", params->params[0], 1);
75 if (result < 0)
77 gnutls_assert ();
78 goto cleanup;
81 result = _gnutls_x509_write_int (spk, "publicExponent", params->params[1], 1);
82 if (result < 0)
84 gnutls_assert ();
85 goto cleanup;
88 result = _gnutls_x509_der_encode (spk, "", der, 0);
89 if (result < 0)
91 gnutls_assert ();
92 goto cleanup;
95 result = 0;
97 cleanup:
98 asn1_delete_structure (&spk);
100 return result;
104 * some x509 certificate functions that relate to MPI parameter
105 * setting. This writes an ECPoint.
107 * Allocates the space used to store the DER data.
110 _gnutls_x509_write_ecc_pubkey (gnutls_pk_params_st * params,
111 gnutls_datum_t * der)
113 int result;
115 der->data = NULL;
116 der->size = 0;
118 if (params->params_nr < ECC_PUBLIC_PARAMS)
119 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
121 result = _gnutls_ecc_ansi_x963_export(params->flags, params->params[ECC_X], params->params[ECC_Y], /*&out*/der);
122 if (result < 0)
123 return gnutls_assert_val(result);
125 return 0;
129 _gnutls_x509_write_pubkey_params (gnutls_pk_algorithm_t algo,
130 gnutls_pk_params_st* params,
131 gnutls_datum_t * der)
133 switch(algo)
135 case GNUTLS_PK_DSA:
136 return _gnutls_x509_write_dsa_params(params, der);
137 case GNUTLS_PK_RSA:
138 der->data = gnutls_malloc(ASN1_NULL_SIZE);
139 if (der->data == NULL)
140 return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
142 memcpy(der->data, ASN1_NULL, ASN1_NULL_SIZE);
143 der->size = ASN1_NULL_SIZE;
144 return 0;
145 case GNUTLS_PK_EC:
146 return _gnutls_x509_write_ecc_params(params, der);
147 default:
148 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
153 _gnutls_x509_write_pubkey (gnutls_pk_algorithm_t algo,
154 gnutls_pk_params_st* params,
155 gnutls_datum_t * der)
157 switch(algo)
159 case GNUTLS_PK_DSA:
160 return _gnutls_x509_write_dsa_pubkey(params, der);
161 case GNUTLS_PK_RSA:
162 return _gnutls_x509_write_rsa_pubkey(params, der);
163 case GNUTLS_PK_EC:
164 return _gnutls_x509_write_ecc_pubkey(params, der);
165 default:
166 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
171 * This function writes the parameters for DSS keys.
172 * Needs 3 parameters (p,q,g).
174 * Allocates the space used to store the DER data.
176 static int
177 _gnutls_x509_write_dsa_params (gnutls_pk_params_st* params,
178 gnutls_datum_t * der)
180 int result;
181 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
183 der->data = NULL;
184 der->size = 0;
186 if (params->params_nr < DSA_PUBLIC_PARAMS-1)
188 gnutls_assert ();
189 result = GNUTLS_E_INVALID_REQUEST;
190 goto cleanup;
193 if ((result = asn1_create_element
194 (_gnutls_get_gnutls_asn (), "GNUTLS.DSAParameters", &spk))
195 != ASN1_SUCCESS)
197 gnutls_assert ();
198 return _gnutls_asn2err (result);
201 result = _gnutls_x509_write_int (spk, "p", params->params[0], 1);
202 if (result < 0)
204 gnutls_assert ();
205 goto cleanup;
208 result = _gnutls_x509_write_int (spk, "q", params->params[1], 1);
209 if (result < 0)
211 gnutls_assert ();
212 goto cleanup;
215 result = _gnutls_x509_write_int (spk, "g", params->params[2], 1);
216 if (result < 0)
218 gnutls_assert ();
219 goto cleanup;
222 result = _gnutls_x509_der_encode (spk, "", der, 0);
223 if (result < 0)
225 gnutls_assert ();
226 goto cleanup;
229 result = 0;
231 cleanup:
232 asn1_delete_structure (&spk);
233 return result;
237 * This function writes the parameters for ECC keys.
238 * That is the ECParameters struct.
240 * Allocates the space used to store the DER data.
243 _gnutls_x509_write_ecc_params (gnutls_pk_params_st* params,
244 gnutls_datum_t * der)
246 int result;
247 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
248 const char* oid;
250 der->data = NULL;
251 der->size = 0;
253 if (params->params_nr < ECC_PUBLIC_PARAMS)
255 gnutls_assert ();
256 result = GNUTLS_E_INVALID_REQUEST;
257 goto cleanup;
260 oid = _gnutls_ecc_curve_get_oid(params->flags);
261 if (oid == NULL)
262 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
265 if ((result = asn1_create_element
266 (_gnutls_get_gnutls_asn (), "GNUTLS.ECParameters", &spk))
267 != ASN1_SUCCESS)
269 gnutls_assert ();
270 return _gnutls_asn2err (result);
273 if ((result = asn1_write_value (spk, "", "namedCurve", 1)) != ASN1_SUCCESS)
275 gnutls_assert ();
276 result = _gnutls_asn2err (result);
277 goto cleanup;
280 if ((result = asn1_write_value (spk, "namedCurve", oid, 1)) != ASN1_SUCCESS)
282 gnutls_assert ();
283 result = _gnutls_asn2err (result);
284 goto cleanup;
287 result = _gnutls_x509_der_encode (spk, "", der, 0);
288 if (result < 0)
290 gnutls_assert ();
291 goto cleanup;
294 result = 0;
296 cleanup:
297 asn1_delete_structure (&spk);
298 return result;
302 * This function writes the public parameters for DSS keys.
303 * Needs 1 parameter (y).
305 * Allocates the space used to store the DER data.
307 static int
308 _gnutls_x509_write_dsa_pubkey (gnutls_pk_params_st * params,
309 gnutls_datum_t * der)
311 int result;
312 ASN1_TYPE spk = ASN1_TYPE_EMPTY;
314 der->data = NULL;
315 der->size = 0;
317 if (params->params_nr < DSA_PUBLIC_PARAMS)
319 gnutls_assert ();
320 result = GNUTLS_E_INVALID_REQUEST;
321 goto cleanup;
324 if ((result = asn1_create_element
325 (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPublicKey", &spk))
326 != ASN1_SUCCESS)
328 gnutls_assert ();
329 return _gnutls_asn2err (result);
332 result = _gnutls_x509_write_int (spk, "", params->params[3], 1);
333 if (result < 0)
335 gnutls_assert ();
336 goto cleanup;
339 result = _gnutls_x509_der_encode (spk, "", der, 0);
340 if (result < 0)
342 gnutls_assert ();
343 goto cleanup;
346 result = 0;
348 cleanup:
349 asn1_delete_structure (&spk);
350 return result;
353 /* Encodes the RSA parameters into an ASN.1 RSA private key structure.
355 static int
356 _gnutls_asn1_encode_rsa (ASN1_TYPE * c2, gnutls_pk_params_st * params)
358 int result;
359 uint8_t null = '\0';
360 gnutls_pk_params_st pk_params;
361 gnutls_datum_t m, e, d, p, q, u, exp1, exp2;
363 gnutls_pk_params_init(&pk_params);
365 memset (&m, 0, sizeof (m));
366 memset (&p, 0, sizeof (p));
367 memset (&q, 0, sizeof (q));
368 memset (&p, 0, sizeof (p));
369 memset (&u, 0, sizeof (u));
370 memset (&e, 0, sizeof (e));
371 memset (&d, 0, sizeof (d));
372 memset (&exp1, 0, sizeof (exp1));
373 memset (&exp2, 0, sizeof (exp2));
375 result = _gnutls_pk_params_copy (&pk_params, params);
376 if (result < 0)
378 gnutls_assert ();
379 return result;
382 result = _gnutls_pk_fixup (GNUTLS_PK_RSA, GNUTLS_EXPORT, &pk_params);
383 if (result < 0)
385 gnutls_assert ();
386 goto cleanup;
389 /* retrieve as data */
391 result = _gnutls_mpi_dprint_lz (pk_params.params[0], &m);
392 if (result < 0)
394 gnutls_assert ();
395 goto cleanup;
398 result = _gnutls_mpi_dprint_lz (pk_params.params[1], &e);
399 if (result < 0)
401 gnutls_assert ();
402 goto cleanup;
405 result = _gnutls_mpi_dprint_lz (pk_params.params[2], &d);
406 if (result < 0)
408 gnutls_assert ();
409 goto cleanup;
412 result = _gnutls_mpi_dprint_lz (pk_params.params[3], &p);
413 if (result < 0)
415 gnutls_assert ();
416 goto cleanup;
419 result = _gnutls_mpi_dprint_lz (pk_params.params[4], &q);
420 if (result < 0)
422 gnutls_assert ();
423 goto cleanup;
426 result = _gnutls_mpi_dprint_lz (pk_params.params[5], &u);
427 if (result < 0)
429 gnutls_assert ();
430 goto cleanup;
433 result = _gnutls_mpi_dprint_lz (pk_params.params[6], &exp1);
434 if (result < 0)
436 gnutls_assert ();
437 goto cleanup;
440 result = _gnutls_mpi_dprint_lz (pk_params.params[7], &exp2);
441 if (result < 0)
443 gnutls_assert ();
444 goto cleanup;
447 /* Ok. Now we have the data. Create the asn1 structures
450 /* first make sure that no previously allocated data are leaked */
451 if (*c2 != ASN1_TYPE_EMPTY)
453 asn1_delete_structure (c2);
454 *c2 = ASN1_TYPE_EMPTY;
457 if ((result = asn1_create_element
458 (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPrivateKey", c2))
459 != ASN1_SUCCESS)
461 gnutls_assert ();
462 result = _gnutls_asn2err (result);
463 goto cleanup;
466 /* Write PRIME
468 if ((result = asn1_write_value (*c2, "modulus",
469 m.data, m.size)) != ASN1_SUCCESS)
471 gnutls_assert ();
472 result = _gnutls_asn2err (result);
473 goto cleanup;
476 if ((result = asn1_write_value (*c2, "publicExponent",
477 e.data, e.size)) != ASN1_SUCCESS)
479 gnutls_assert ();
480 result = _gnutls_asn2err (result);
481 goto cleanup;
484 if ((result = asn1_write_value (*c2, "privateExponent",
485 d.data, d.size)) != ASN1_SUCCESS)
487 gnutls_assert ();
488 result = _gnutls_asn2err (result);
489 goto cleanup;
492 if ((result = asn1_write_value (*c2, "prime1",
493 p.data, p.size)) != ASN1_SUCCESS)
495 gnutls_assert ();
496 result = _gnutls_asn2err (result);
497 goto cleanup;
500 if ((result = asn1_write_value (*c2, "prime2",
501 q.data, q.size)) != ASN1_SUCCESS)
503 gnutls_assert ();
504 result = _gnutls_asn2err (result);
505 goto cleanup;
508 if ((result = asn1_write_value (*c2, "coefficient",
509 u.data, u.size)) != ASN1_SUCCESS)
511 gnutls_assert ();
512 result = _gnutls_asn2err (result);
514 goto cleanup;
517 if ((result = asn1_write_value (*c2, "exponent1",
518 exp1.data, exp1.size)) != ASN1_SUCCESS)
520 gnutls_assert ();
521 result = _gnutls_asn2err (result);
522 goto cleanup;
525 if ((result = asn1_write_value (*c2, "exponent2",
526 exp2.data, exp2.size)) != ASN1_SUCCESS)
528 gnutls_assert ();
529 result = _gnutls_asn2err (result);
530 goto cleanup;
533 if ((result = asn1_write_value (*c2, "otherPrimeInfos",
534 NULL, 0)) != ASN1_SUCCESS)
536 gnutls_assert ();
537 result = _gnutls_asn2err (result);
538 goto cleanup;
541 if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS)
543 gnutls_assert ();
544 result = _gnutls_asn2err (result);
545 goto cleanup;
548 result = 0;
550 cleanup:
551 if (result != 0)
552 asn1_delete_structure (c2);
554 gnutls_pk_params_release (&pk_params);
556 _gnutls_free_datum (&m);
557 _gnutls_free_datum (&d);
558 _gnutls_free_datum (&e);
559 _gnutls_free_datum (&p);
560 _gnutls_free_datum (&q);
561 _gnutls_free_datum (&u);
562 _gnutls_free_datum (&exp1);
563 _gnutls_free_datum (&exp2);
565 return result;
568 /* Encodes the ECC parameters into an ASN.1 ECPrivateKey structure.
570 static int
571 _gnutls_asn1_encode_ecc (ASN1_TYPE * c2, gnutls_pk_params_st * params)
573 int ret;
574 uint8_t one = '\x01';
575 gnutls_datum pubkey = { NULL, 0 };
576 const char *oid;
578 oid = _gnutls_ecc_curve_get_oid(params->flags);
580 if (params->params_nr != ECC_PRIVATE_PARAMS || oid == NULL)
581 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
583 ret = _gnutls_ecc_ansi_x963_export(params->flags, params->params[ECC_X], params->params[ECC_Y], &pubkey);
584 if (ret < 0)
585 return gnutls_assert_val(ret);
587 /* Ok. Now we have the data. Create the asn1 structures
590 /* first make sure that no previously allocated data are leaked */
591 if (*c2 != ASN1_TYPE_EMPTY)
593 asn1_delete_structure (c2);
594 *c2 = ASN1_TYPE_EMPTY;
597 if ((ret = asn1_create_element
598 (_gnutls_get_gnutls_asn (), "GNUTLS.ECPrivateKey", c2))
599 != ASN1_SUCCESS)
601 gnutls_assert ();
602 ret = _gnutls_asn2err (ret);
603 goto cleanup;
606 if ((ret = asn1_write_value (*c2, "Version", &one, 1)) != ASN1_SUCCESS)
608 gnutls_assert ();
609 ret = _gnutls_asn2err (ret);
610 goto cleanup;
613 ret = _gnutls_x509_write_int (*c2, "privateKey", params->params[ECC_K], 1);
614 if (ret < 0)
616 gnutls_assert ();
617 goto cleanup;
620 if ((ret = asn1_write_value (*c2, "publicKey", pubkey.data, pubkey.size*8)) != ASN1_SUCCESS)
622 gnutls_assert ();
623 ret = _gnutls_asn2err (ret);
624 goto cleanup;
627 /* write our choice */
628 if ((ret = asn1_write_value (*c2, "parameters", "namedCurve", 1)) != ASN1_SUCCESS)
630 gnutls_assert ();
631 ret = _gnutls_asn2err (ret);
632 goto cleanup;
635 if ((ret = asn1_write_value (*c2, "parameters.namedCurve", oid, 1)) != ASN1_SUCCESS)
637 gnutls_assert ();
638 ret = _gnutls_asn2err (ret);
639 goto cleanup;
642 _gnutls_free_datum(&pubkey);
643 return 0;
645 cleanup:
646 asn1_delete_structure (c2);
647 _gnutls_free_datum(&pubkey);
649 return ret;
653 /* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure.
655 static int
656 _gnutls_asn1_encode_dsa (ASN1_TYPE * c2, gnutls_pk_params_st * params)
658 int result, i;
659 size_t size[DSA_PRIVATE_PARAMS], total;
660 uint8_t *p_data, *q_data, *g_data, *x_data, *y_data;
661 uint8_t *all_data = NULL, *p;
662 uint8_t null = '\0';
664 /* Read all the sizes */
665 total = 0;
666 for (i = 0; i < DSA_PRIVATE_PARAMS; i++)
668 _gnutls_mpi_print_lz (params->params[i], NULL, &size[i]);
669 total += size[i];
672 /* Encoding phase.
673 * allocate data enough to hold everything
675 all_data = gnutls_malloc (total);
676 if (all_data == NULL)
678 gnutls_assert ();
679 result = GNUTLS_E_MEMORY_ERROR;
680 goto cleanup;
683 p = all_data;
684 p_data = p;
685 p += size[0];
686 q_data = p;
687 p += size[1];
688 g_data = p;
689 p += size[2];
690 y_data = p;
691 p += size[3];
692 x_data = p;
694 _gnutls_mpi_print_lz (params->params[0], p_data, &size[0]);
695 _gnutls_mpi_print_lz (params->params[1], q_data, &size[1]);
696 _gnutls_mpi_print_lz (params->params[2], g_data, &size[2]);
697 _gnutls_mpi_print_lz (params->params[3], y_data, &size[3]);
698 _gnutls_mpi_print_lz (params->params[4], x_data, &size[4]);
700 /* Ok. Now we have the data. Create the asn1 structures
703 /* first make sure that no previously allocated data are leaked */
704 if (*c2 != ASN1_TYPE_EMPTY)
706 asn1_delete_structure (c2);
707 *c2 = ASN1_TYPE_EMPTY;
710 if ((result = asn1_create_element
711 (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPrivateKey", c2))
712 != ASN1_SUCCESS)
714 gnutls_assert ();
715 result = _gnutls_asn2err (result);
716 goto cleanup;
719 /* Write PRIME
721 if ((result = asn1_write_value (*c2, "p", p_data, size[0])) != ASN1_SUCCESS)
723 gnutls_assert ();
724 result = _gnutls_asn2err (result);
725 goto cleanup;
728 if ((result = asn1_write_value (*c2, "q", q_data, size[1])) != ASN1_SUCCESS)
730 gnutls_assert ();
731 result = _gnutls_asn2err (result);
732 goto cleanup;
735 if ((result = asn1_write_value (*c2, "g", g_data, size[2])) != ASN1_SUCCESS)
737 gnutls_assert ();
738 result = _gnutls_asn2err (result);
739 goto cleanup;
742 if ((result = asn1_write_value (*c2, "Y", y_data, size[3])) != ASN1_SUCCESS)
744 gnutls_assert ();
745 result = _gnutls_asn2err (result);
746 goto cleanup;
749 if ((result = asn1_write_value (*c2, "priv",
750 x_data, size[4])) != ASN1_SUCCESS)
752 gnutls_assert ();
753 result = _gnutls_asn2err (result);
754 goto cleanup;
757 gnutls_free (all_data);
759 if ((result = asn1_write_value (*c2, "version", &null, 1)) != ASN1_SUCCESS)
761 gnutls_assert ();
762 result = _gnutls_asn2err (result);
763 goto cleanup;
766 return 0;
768 cleanup:
769 asn1_delete_structure (c2);
770 gnutls_free (all_data);
772 return result;
775 int _gnutls_asn1_encode_privkey (gnutls_pk_algorithm_t pk, ASN1_TYPE * c2, gnutls_pk_params_st * params)
777 switch(pk)
779 case GNUTLS_PK_RSA:
780 return _gnutls_asn1_encode_rsa(c2, params);
781 case GNUTLS_PK_DSA:
782 return _gnutls_asn1_encode_dsa(c2, params);
783 case GNUTLS_PK_EC:
784 return _gnutls_asn1_encode_ecc(c2, params);
785 default:
786 return GNUTLS_E_UNIMPLEMENTED_FEATURE;