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>
27 #include <gnutls_datum.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.
50 _gnutls_x509_write_rsa_pubkey (gnutls_pk_params_st
* params
,
54 ASN1_TYPE spk
= ASN1_TYPE_EMPTY
;
59 if (params
->params_nr
< RSA_PUBLIC_PARAMS
)
62 result
= GNUTLS_E_INVALID_REQUEST
;
66 if ((result
= asn1_create_element
67 (_gnutls_get_gnutls_asn (), "GNUTLS.RSAPublicKey", &spk
))
71 return _gnutls_asn2err (result
);
74 result
= _gnutls_x509_write_int (spk
, "modulus", params
->params
[0], 1);
81 result
= _gnutls_x509_write_int (spk
, "publicExponent", params
->params
[1], 1);
88 result
= _gnutls_x509_der_encode (spk
, "", der
, 0);
98 asn1_delete_structure (&spk
);
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
)
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
);
123 return gnutls_assert_val(result
);
129 _gnutls_x509_write_pubkey_params (gnutls_pk_algorithm_t algo
,
130 gnutls_pk_params_st
* params
,
131 gnutls_datum_t
* der
)
136 return _gnutls_x509_write_dsa_params(params
, der
);
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
;
146 return _gnutls_x509_write_ecc_params(params
, der
);
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
)
160 return _gnutls_x509_write_dsa_pubkey(params
, der
);
162 return _gnutls_x509_write_rsa_pubkey(params
, der
);
164 return _gnutls_x509_write_ecc_pubkey(params
, der
);
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.
177 _gnutls_x509_write_dsa_params (gnutls_pk_params_st
* params
,
178 gnutls_datum_t
* der
)
181 ASN1_TYPE spk
= ASN1_TYPE_EMPTY
;
186 if (params
->params_nr
< DSA_PUBLIC_PARAMS
-1)
189 result
= GNUTLS_E_INVALID_REQUEST
;
193 if ((result
= asn1_create_element
194 (_gnutls_get_gnutls_asn (), "GNUTLS.DSAParameters", &spk
))
198 return _gnutls_asn2err (result
);
201 result
= _gnutls_x509_write_int (spk
, "p", params
->params
[0], 1);
208 result
= _gnutls_x509_write_int (spk
, "q", params
->params
[1], 1);
215 result
= _gnutls_x509_write_int (spk
, "g", params
->params
[2], 1);
222 result
= _gnutls_x509_der_encode (spk
, "", der
, 0);
232 asn1_delete_structure (&spk
);
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
)
247 ASN1_TYPE spk
= ASN1_TYPE_EMPTY
;
253 if (params
->params_nr
< ECC_PUBLIC_PARAMS
)
256 result
= GNUTLS_E_INVALID_REQUEST
;
260 oid
= _gnutls_ecc_curve_get_oid(params
->flags
);
262 return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST
);
265 if ((result
= asn1_create_element
266 (_gnutls_get_gnutls_asn (), "GNUTLS.ECParameters", &spk
))
270 return _gnutls_asn2err (result
);
273 if ((result
= asn1_write_value (spk
, "", "namedCurve", 1)) != ASN1_SUCCESS
)
276 result
= _gnutls_asn2err (result
);
280 if ((result
= asn1_write_value (spk
, "namedCurve", oid
, 1)) != ASN1_SUCCESS
)
283 result
= _gnutls_asn2err (result
);
287 result
= _gnutls_x509_der_encode (spk
, "", der
, 0);
297 asn1_delete_structure (&spk
);
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.
308 _gnutls_x509_write_dsa_pubkey (gnutls_pk_params_st
* params
,
309 gnutls_datum_t
* der
)
312 ASN1_TYPE spk
= ASN1_TYPE_EMPTY
;
317 if (params
->params_nr
< DSA_PUBLIC_PARAMS
)
320 result
= GNUTLS_E_INVALID_REQUEST
;
324 if ((result
= asn1_create_element
325 (_gnutls_get_gnutls_asn (), "GNUTLS.DSAPublicKey", &spk
))
329 return _gnutls_asn2err (result
);
332 result
= _gnutls_x509_write_int (spk
, "", params
->params
[3], 1);
339 result
= _gnutls_x509_der_encode (spk
, "", der
, 0);
349 asn1_delete_structure (&spk
);
353 /* Encodes the RSA parameters into an ASN.1 RSA private key structure.
356 _gnutls_asn1_encode_rsa (ASN1_TYPE
* c2
, gnutls_pk_params_st
* params
)
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
);
382 result
= _gnutls_pk_fixup (GNUTLS_PK_RSA
, GNUTLS_EXPORT
, &pk_params
);
389 /* retrieve as data */
391 result
= _gnutls_mpi_dprint_lz (pk_params
.params
[0], &m
);
398 result
= _gnutls_mpi_dprint_lz (pk_params
.params
[1], &e
);
405 result
= _gnutls_mpi_dprint_lz (pk_params
.params
[2], &d
);
412 result
= _gnutls_mpi_dprint_lz (pk_params
.params
[3], &p
);
419 result
= _gnutls_mpi_dprint_lz (pk_params
.params
[4], &q
);
426 result
= _gnutls_mpi_dprint_lz (pk_params
.params
[5], &u
);
433 result
= _gnutls_mpi_dprint_lz (pk_params
.params
[6], &exp1
);
440 result
= _gnutls_mpi_dprint_lz (pk_params
.params
[7], &exp2
);
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
))
462 result
= _gnutls_asn2err (result
);
468 if ((result
= asn1_write_value (*c2
, "modulus",
469 m
.data
, m
.size
)) != ASN1_SUCCESS
)
472 result
= _gnutls_asn2err (result
);
476 if ((result
= asn1_write_value (*c2
, "publicExponent",
477 e
.data
, e
.size
)) != ASN1_SUCCESS
)
480 result
= _gnutls_asn2err (result
);
484 if ((result
= asn1_write_value (*c2
, "privateExponent",
485 d
.data
, d
.size
)) != ASN1_SUCCESS
)
488 result
= _gnutls_asn2err (result
);
492 if ((result
= asn1_write_value (*c2
, "prime1",
493 p
.data
, p
.size
)) != ASN1_SUCCESS
)
496 result
= _gnutls_asn2err (result
);
500 if ((result
= asn1_write_value (*c2
, "prime2",
501 q
.data
, q
.size
)) != ASN1_SUCCESS
)
504 result
= _gnutls_asn2err (result
);
508 if ((result
= asn1_write_value (*c2
, "coefficient",
509 u
.data
, u
.size
)) != ASN1_SUCCESS
)
512 result
= _gnutls_asn2err (result
);
517 if ((result
= asn1_write_value (*c2
, "exponent1",
518 exp1
.data
, exp1
.size
)) != ASN1_SUCCESS
)
521 result
= _gnutls_asn2err (result
);
525 if ((result
= asn1_write_value (*c2
, "exponent2",
526 exp2
.data
, exp2
.size
)) != ASN1_SUCCESS
)
529 result
= _gnutls_asn2err (result
);
533 if ((result
= asn1_write_value (*c2
, "otherPrimeInfos",
534 NULL
, 0)) != ASN1_SUCCESS
)
537 result
= _gnutls_asn2err (result
);
541 if ((result
= asn1_write_value (*c2
, "version", &null
, 1)) != ASN1_SUCCESS
)
544 result
= _gnutls_asn2err (result
);
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
);
568 /* Encodes the ECC parameters into an ASN.1 ECPrivateKey structure.
571 _gnutls_asn1_encode_ecc (ASN1_TYPE
* c2
, gnutls_pk_params_st
* params
)
574 uint8_t one
= '\x01';
575 gnutls_datum pubkey
= { NULL
, 0 };
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
);
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
))
602 ret
= _gnutls_asn2err (ret
);
606 if ((ret
= asn1_write_value (*c2
, "Version", &one
, 1)) != ASN1_SUCCESS
)
609 ret
= _gnutls_asn2err (ret
);
613 ret
= _gnutls_x509_write_int (*c2
, "privateKey", params
->params
[ECC_K
], 1);
620 if ((ret
= asn1_write_value (*c2
, "publicKey", pubkey
.data
, pubkey
.size
*8)) != ASN1_SUCCESS
)
623 ret
= _gnutls_asn2err (ret
);
627 /* write our choice */
628 if ((ret
= asn1_write_value (*c2
, "parameters", "namedCurve", 1)) != ASN1_SUCCESS
)
631 ret
= _gnutls_asn2err (ret
);
635 if ((ret
= asn1_write_value (*c2
, "parameters.namedCurve", oid
, 1)) != ASN1_SUCCESS
)
638 ret
= _gnutls_asn2err (ret
);
642 _gnutls_free_datum(&pubkey
);
646 asn1_delete_structure (c2
);
647 _gnutls_free_datum(&pubkey
);
653 /* Encodes the DSA parameters into an ASN.1 DSAPrivateKey structure.
656 _gnutls_asn1_encode_dsa (ASN1_TYPE
* c2
, gnutls_pk_params_st
* params
)
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
;
664 /* Read all the sizes */
666 for (i
= 0; i
< DSA_PRIVATE_PARAMS
; i
++)
668 _gnutls_mpi_print_lz (params
->params
[i
], NULL
, &size
[i
]);
673 * allocate data enough to hold everything
675 all_data
= gnutls_malloc (total
);
676 if (all_data
== NULL
)
679 result
= GNUTLS_E_MEMORY_ERROR
;
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
))
715 result
= _gnutls_asn2err (result
);
721 if ((result
= asn1_write_value (*c2
, "p", p_data
, size
[0])) != ASN1_SUCCESS
)
724 result
= _gnutls_asn2err (result
);
728 if ((result
= asn1_write_value (*c2
, "q", q_data
, size
[1])) != ASN1_SUCCESS
)
731 result
= _gnutls_asn2err (result
);
735 if ((result
= asn1_write_value (*c2
, "g", g_data
, size
[2])) != ASN1_SUCCESS
)
738 result
= _gnutls_asn2err (result
);
742 if ((result
= asn1_write_value (*c2
, "Y", y_data
, size
[3])) != ASN1_SUCCESS
)
745 result
= _gnutls_asn2err (result
);
749 if ((result
= asn1_write_value (*c2
, "priv",
750 x_data
, size
[4])) != ASN1_SUCCESS
)
753 result
= _gnutls_asn2err (result
);
757 gnutls_free (all_data
);
759 if ((result
= asn1_write_value (*c2
, "version", &null
, 1)) != ASN1_SUCCESS
)
762 result
= _gnutls_asn2err (result
);
769 asn1_delete_structure (c2
);
770 gnutls_free (all_data
);
775 int _gnutls_asn1_encode_privkey (gnutls_pk_algorithm_t pk
, ASN1_TYPE
* c2
, gnutls_pk_params_st
* params
)
780 return _gnutls_asn1_encode_rsa(c2
, params
);
782 return _gnutls_asn1_encode_dsa(c2
, params
);
784 return _gnutls_asn1_encode_ecc(c2
, params
);
786 return GNUTLS_E_UNIMPLEMENTED_FEATURE
;