doc update
[gnutls:gnutls.git] / lib / x509 / key_decode.c
1 /*
2  * Copyright (C) 2011-2012 Free Software Foundation, Inc.
3  * Copyright (C) 2013 Red Hat
4  *
5  * Author: Nikos Mavrogiannopoulos
6  *
7  * This file is part of GnuTLS.
8  *
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 2.1 of
12  * the License, or (at your option) any later version.
13  *
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.
18  *
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/>
21  *
22  */
23
24 #include <gnutls_int.h>
25 #include <gnutls_errors.h>
26 #include <gnutls_global.h>
27 #include <libtasn1.h>
28 #include <gnutls_datum.h>
29 #include "common.h"
30 #include "x509_int.h"
31 #include <gnutls_num.h>
32 #include <gnutls_ecc.h>
33
34 static int _gnutls_x509_read_rsa_pubkey(uint8_t * der, int dersize,
35                                         gnutls_pk_params_st * params);
36 static int _gnutls_x509_read_dsa_pubkey(uint8_t * der, int dersize,
37                                         gnutls_pk_params_st * params);
38 static int _gnutls_x509_read_ecc_pubkey(uint8_t * der, int dersize,
39                                         gnutls_pk_params_st * params);
40
41 static int
42 _gnutls_x509_read_dsa_params(uint8_t * der, int dersize,
43                              gnutls_pk_params_st * params);
44
45 /*
46  * some x509 certificate parsing functions that relate to MPI parameter
47  * extraction. This reads the BIT STRING subjectPublicKey.
48  * Returns 2 parameters (m,e). It does not set params_nr.
49  */
50 int
51 _gnutls_x509_read_rsa_pubkey(uint8_t * der, int dersize,
52                              gnutls_pk_params_st * params)
53 {
54         int result;
55         ASN1_TYPE spk = ASN1_TYPE_EMPTY;
56
57         if ((result = asn1_create_element
58              (_gnutls_get_gnutls_asn(), "GNUTLS.RSAPublicKey", &spk))
59             != ASN1_SUCCESS) {
60                 gnutls_assert();
61                 return _gnutls_asn2err(result);
62         }
63
64         result = asn1_der_decoding(&spk, der, dersize, NULL);
65
66         if (result != ASN1_SUCCESS) {
67                 gnutls_assert();
68                 asn1_delete_structure(&spk);
69                 return _gnutls_asn2err(result);
70         }
71
72
73         if ((result =
74              _gnutls_x509_read_int(spk, "modulus",
75                                    &params->params[0])) < 0) {
76                 gnutls_assert();
77                 asn1_delete_structure(&spk);
78                 return GNUTLS_E_ASN1_GENERIC_ERROR;
79         }
80
81         if ((result = _gnutls_x509_read_int(spk, "publicExponent",
82                                             &params->params[1])) < 0) {
83                 gnutls_assert();
84                 _gnutls_mpi_release(&params->params[0]);
85                 asn1_delete_structure(&spk);
86                 return GNUTLS_E_ASN1_GENERIC_ERROR;
87         }
88
89         asn1_delete_structure(&spk);
90
91         return 0;
92
93 }
94
95 /*
96  * some x509 certificate parsing functions that relate to MPI parameter
97  * extraction. This reads the BIT STRING subjectPublicKey.
98  * Returns 2 parameters (m,e). It does not set params_nr.
99  */
100 int
101 _gnutls_x509_read_ecc_pubkey(uint8_t * der, int dersize,
102                              gnutls_pk_params_st * params)
103 {
104         /* RFC5480 defines the public key to be an ECPoint (i.e. OCTET STRING),
105          * Then it says that the OCTET STRING _value_ is converted to BIT STRING.
106          * That means that the value we place there is the raw X9.62 one. */
107         return _gnutls_ecc_ansi_x963_import(der, dersize,
108                                             &params->params[ECC_X],
109                                             &params->params[ECC_Y]);
110 }
111
112
113 /* reads p,q and g 
114  * from the certificate (subjectPublicKey BIT STRING).
115  * params[0-2]. It does NOT set params_nr.
116  */
117 static int
118 _gnutls_x509_read_dsa_params(uint8_t * der, int dersize,
119                              gnutls_pk_params_st * params)
120 {
121         int result;
122         ASN1_TYPE spk = ASN1_TYPE_EMPTY;
123
124         if ((result = asn1_create_element
125              (_gnutls_get_pkix(), "PKIX1.Dss-Parms",
126               &spk)) != ASN1_SUCCESS) {
127                 gnutls_assert();
128                 return _gnutls_asn2err(result);
129         }
130
131         result = asn1_der_decoding(&spk, der, dersize, NULL);
132
133         if (result != ASN1_SUCCESS) {
134                 gnutls_assert();
135                 asn1_delete_structure(&spk);
136                 return _gnutls_asn2err(result);
137         }
138
139         /* FIXME: If the parameters are not included in the certificate
140          * then the issuer's parameters should be used. This is not
141          * done yet.
142          */
143
144         /* Read p */
145
146         if ((result =
147              _gnutls_x509_read_int(spk, "p", &params->params[0])) < 0) {
148                 gnutls_assert();
149                 asn1_delete_structure(&spk);
150                 return GNUTLS_E_ASN1_GENERIC_ERROR;
151         }
152
153         /* Read q */
154
155         if ((result =
156              _gnutls_x509_read_int(spk, "q", &params->params[1])) < 0) {
157                 gnutls_assert();
158                 asn1_delete_structure(&spk);
159                 _gnutls_mpi_release(&params->params[0]);
160                 return GNUTLS_E_ASN1_GENERIC_ERROR;
161         }
162
163         /* Read g */
164
165         if ((result =
166              _gnutls_x509_read_int(spk, "g", &params->params[2])) < 0) {
167                 gnutls_assert();
168                 asn1_delete_structure(&spk);
169                 _gnutls_mpi_release(&params->params[0]);
170                 _gnutls_mpi_release(&params->params[1]);
171                 return GNUTLS_E_ASN1_GENERIC_ERROR;
172         }
173
174         asn1_delete_structure(&spk);
175
176         return 0;
177
178 }
179
180 /* reads the curve from the certificate.
181  * params[0-4]. It does NOT set params_nr.
182  */
183 int
184 _gnutls_x509_read_ecc_params(uint8_t * der, int dersize,
185                              unsigned int * curve)
186 {
187         int ret;
188         ASN1_TYPE spk = ASN1_TYPE_EMPTY;
189         char oid[MAX_OID_SIZE];
190         int oid_size;
191
192         if ((ret = asn1_create_element
193              (_gnutls_get_gnutls_asn(), "GNUTLS.ECParameters",
194               &spk)) != ASN1_SUCCESS) {
195                 gnutls_assert();
196                 return _gnutls_asn2err(ret);
197         }
198
199         ret = asn1_der_decoding(&spk, der, dersize, NULL);
200
201         if (ret != ASN1_SUCCESS) {
202                 gnutls_assert();
203                 ret = _gnutls_asn2err(ret);
204                 goto cleanup;
205         }
206
207         /* Read curve */
208         /* read the curve */
209         oid_size = sizeof(oid);
210         ret = asn1_read_value(spk, "namedCurve", oid, &oid_size);
211         if (ret != ASN1_SUCCESS) {
212                 gnutls_assert();
213                 ret = _gnutls_asn2err(ret);
214                 goto cleanup;
215         }
216
217         *curve = _gnutls_oid_to_ecc_curve(oid);
218         if (*curve == GNUTLS_ECC_CURVE_INVALID) {
219                 _gnutls_debug_log("Curve %s is not supported\n", oid);
220                 gnutls_assert();
221                 ret = GNUTLS_E_ECC_UNSUPPORTED_CURVE;
222                 goto cleanup;
223         }
224
225         ret = 0;
226
227       cleanup:
228
229         asn1_delete_structure(&spk);
230
231         return ret;
232
233 }
234
235 int _gnutls_x509_read_pubkey(gnutls_pk_algorithm_t algo, uint8_t * der,
236                              int dersize, gnutls_pk_params_st * params)
237 {
238         int ret;
239
240         switch (algo) {
241         case GNUTLS_PK_RSA:
242                 ret = _gnutls_x509_read_rsa_pubkey(der, dersize, params);
243                 if (ret >= 0)
244                         params->params_nr = RSA_PUBLIC_PARAMS;
245                 break;
246         case GNUTLS_PK_DSA:
247                 ret = _gnutls_x509_read_dsa_pubkey(der, dersize, params);
248                 if (ret >= 0)
249                         params->params_nr = DSA_PUBLIC_PARAMS;
250                 break;
251         case GNUTLS_PK_EC:
252                 ret = _gnutls_x509_read_ecc_pubkey(der, dersize, params);
253                 if (ret >= 0)
254                         params->params_nr = ECC_PUBLIC_PARAMS;
255                 break;
256         default:
257                 ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
258                 break;
259         }
260         return ret;
261 }
262
263 int _gnutls_x509_read_pubkey_params(gnutls_pk_algorithm_t algo,
264                                     uint8_t * der, int dersize,
265                                     gnutls_pk_params_st * params)
266 {
267         switch (algo) {
268         case GNUTLS_PK_RSA:
269                 return 0;
270         case GNUTLS_PK_DSA:
271                 return _gnutls_x509_read_dsa_params(der, dersize, params);
272         case GNUTLS_PK_EC:
273                 return _gnutls_x509_read_ecc_params(der, dersize, &params->flags);
274         default:
275                 return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
276         }
277 }
278
279 /* reads DSA's Y
280  * from the certificate 
281  * only sets params[3]
282  */
283 int
284 _gnutls_x509_read_dsa_pubkey(uint8_t * der, int dersize,
285                              gnutls_pk_params_st * params)
286 {
287         /* do not set a number */
288         params->params_nr = 0;
289         return _gnutls_x509_read_der_int(der, dersize, &params->params[3]);
290 }