xref: /optee_os/lib/libmbedtls/mbedtls/library/x509_csr.c (revision 32b3180828fa15a49ccc86ecb4be9d274c140c89)
1817466cbSJens Wiklander /*
2817466cbSJens Wiklander  *  X.509 Certificate Signing Request (CSR) parsing
3817466cbSJens Wiklander  *
47901324dSJerome Forissier  *  Copyright The Mbed TLS Contributors
57901324dSJerome Forissier  *  SPDX-License-Identifier: Apache-2.0
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  */
19817466cbSJens Wiklander /*
20817466cbSJens Wiklander  *  The ITU-T X.509 standard defines a certificate format for PKI.
21817466cbSJens Wiklander  *
22817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
23817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
24817466cbSJens Wiklander  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
25817466cbSJens Wiklander  *
26817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
27817466cbSJens Wiklander  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
28817466cbSJens Wiklander  */
29817466cbSJens Wiklander 
307901324dSJerome Forissier #include "common.h"
31817466cbSJens Wiklander 
32817466cbSJens Wiklander #if defined(MBEDTLS_X509_CSR_PARSE_C)
33817466cbSJens Wiklander 
34817466cbSJens Wiklander #include "mbedtls/x509_csr.h"
3511fa71b9SJerome Forissier #include "mbedtls/error.h"
36817466cbSJens Wiklander #include "mbedtls/oid.h"
373d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
38817466cbSJens Wiklander 
39817466cbSJens Wiklander #include <string.h>
40817466cbSJens Wiklander 
41817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
42817466cbSJens Wiklander #include "mbedtls/pem.h"
43817466cbSJens Wiklander #endif
44817466cbSJens Wiklander 
45817466cbSJens Wiklander #include "mbedtls/platform.h"
46817466cbSJens Wiklander 
47817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
48817466cbSJens Wiklander #include <stdio.h>
49817466cbSJens Wiklander #endif
50817466cbSJens Wiklander 
51817466cbSJens Wiklander /*
52817466cbSJens Wiklander  *  Version  ::=  INTEGER  {  v1(0)  }
53817466cbSJens Wiklander  */
54817466cbSJens Wiklander static int x509_csr_get_version(unsigned char **p,
55817466cbSJens Wiklander                                 const unsigned char *end,
56817466cbSJens Wiklander                                 int *ver)
57817466cbSJens Wiklander {
5811fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
59817466cbSJens Wiklander 
60*32b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
61*32b31808SJens Wiklander         if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
62817466cbSJens Wiklander             *ver = 0;
63*32b31808SJens Wiklander             return 0;
64817466cbSJens Wiklander         }
65817466cbSJens Wiklander 
66*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
67817466cbSJens Wiklander     }
68817466cbSJens Wiklander 
69*32b31808SJens Wiklander     return 0;
70*32b31808SJens Wiklander }
71*32b31808SJens Wiklander 
72*32b31808SJens Wiklander /*
73*32b31808SJens Wiklander  * Parse CSR extension requests in DER format
74*32b31808SJens Wiklander  */
75*32b31808SJens Wiklander static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
76*32b31808SJens Wiklander                                      unsigned char **p, const unsigned char *end)
77*32b31808SJens Wiklander {
78*32b31808SJens Wiklander     int ret;
79*32b31808SJens Wiklander     size_t len;
80*32b31808SJens Wiklander     unsigned char *end_ext_data;
81*32b31808SJens Wiklander     while (*p < end) {
82*32b31808SJens Wiklander         mbedtls_x509_buf extn_oid = { 0, 0, NULL };
83*32b31808SJens Wiklander         int ext_type = 0;
84*32b31808SJens Wiklander 
85*32b31808SJens Wiklander         /* Read sequence tag */
86*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_tag(p, end, &len,
87*32b31808SJens Wiklander                                         MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
88*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
89*32b31808SJens Wiklander         }
90*32b31808SJens Wiklander 
91*32b31808SJens Wiklander         end_ext_data = *p + len;
92*32b31808SJens Wiklander 
93*32b31808SJens Wiklander         /* Get extension ID */
94*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
95*32b31808SJens Wiklander                                         MBEDTLS_ASN1_OID)) != 0) {
96*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
97*32b31808SJens Wiklander         }
98*32b31808SJens Wiklander 
99*32b31808SJens Wiklander         extn_oid.tag = MBEDTLS_ASN1_OID;
100*32b31808SJens Wiklander         extn_oid.p = *p;
101*32b31808SJens Wiklander         *p += extn_oid.len;
102*32b31808SJens Wiklander 
103*32b31808SJens Wiklander         /* Data should be octet string type */
104*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
105*32b31808SJens Wiklander                                         MBEDTLS_ASN1_OCTET_STRING)) != 0) {
106*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
107*32b31808SJens Wiklander         }
108*32b31808SJens Wiklander 
109*32b31808SJens Wiklander         if (*p + len != end_ext_data) {
110*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
111*32b31808SJens Wiklander                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
112*32b31808SJens Wiklander         }
113*32b31808SJens Wiklander 
114*32b31808SJens Wiklander         /*
115*32b31808SJens Wiklander          * Detect supported extensions and skip unsupported extensions
116*32b31808SJens Wiklander          */
117*32b31808SJens Wiklander         ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
118*32b31808SJens Wiklander 
119*32b31808SJens Wiklander         if (ret == 0) {
120*32b31808SJens Wiklander             /* Forbid repeated extensions */
121*32b31808SJens Wiklander             if ((csr->ext_types & ext_type) != 0) {
122*32b31808SJens Wiklander                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
123*32b31808SJens Wiklander                                          MBEDTLS_ERR_ASN1_INVALID_DATA);
124*32b31808SJens Wiklander             }
125*32b31808SJens Wiklander 
126*32b31808SJens Wiklander             csr->ext_types |= ext_type;
127*32b31808SJens Wiklander 
128*32b31808SJens Wiklander             switch (ext_type) {
129*32b31808SJens Wiklander                 case MBEDTLS_X509_EXT_KEY_USAGE:
130*32b31808SJens Wiklander                     /* Parse key usage */
131*32b31808SJens Wiklander                     if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,
132*32b31808SJens Wiklander                                                           &csr->key_usage)) != 0) {
133*32b31808SJens Wiklander                         return ret;
134*32b31808SJens Wiklander                     }
135*32b31808SJens Wiklander                     break;
136*32b31808SJens Wiklander 
137*32b31808SJens Wiklander                 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
138*32b31808SJens Wiklander                     /* Parse subject alt name */
139*32b31808SJens Wiklander                     if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,
140*32b31808SJens Wiklander                                                                  &csr->subject_alt_names)) != 0) {
141*32b31808SJens Wiklander                         return ret;
142*32b31808SJens Wiklander                     }
143*32b31808SJens Wiklander                     break;
144*32b31808SJens Wiklander 
145*32b31808SJens Wiklander                 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
146*32b31808SJens Wiklander                     /* Parse netscape certificate type */
147*32b31808SJens Wiklander                     if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,
148*32b31808SJens Wiklander                                                              &csr->ns_cert_type)) != 0) {
149*32b31808SJens Wiklander                         return ret;
150*32b31808SJens Wiklander                     }
151*32b31808SJens Wiklander                     break;
152*32b31808SJens Wiklander                 default:
153*32b31808SJens Wiklander                     break;
154*32b31808SJens Wiklander             }
155*32b31808SJens Wiklander         }
156*32b31808SJens Wiklander         *p = end_ext_data;
157*32b31808SJens Wiklander     }
158*32b31808SJens Wiklander 
159*32b31808SJens Wiklander     if (*p != end) {
160*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
161*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
162*32b31808SJens Wiklander     }
163*32b31808SJens Wiklander 
164*32b31808SJens Wiklander     return 0;
165*32b31808SJens Wiklander }
166*32b31808SJens Wiklander 
167*32b31808SJens Wiklander /*
168*32b31808SJens Wiklander  * Parse CSR attributes in DER format
169*32b31808SJens Wiklander  */
170*32b31808SJens Wiklander static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
171*32b31808SJens Wiklander                                      const unsigned char *start, const unsigned char *end)
172*32b31808SJens Wiklander {
173*32b31808SJens Wiklander     int ret;
174*32b31808SJens Wiklander     size_t len;
175*32b31808SJens Wiklander     unsigned char *end_attr_data;
176*32b31808SJens Wiklander     unsigned char **p = (unsigned char **) &start;
177*32b31808SJens Wiklander 
178*32b31808SJens Wiklander     while (*p < end) {
179*32b31808SJens Wiklander         mbedtls_x509_buf attr_oid = { 0, 0, NULL };
180*32b31808SJens Wiklander 
181*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_tag(p, end, &len,
182*32b31808SJens Wiklander                                         MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
183*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
184*32b31808SJens Wiklander         }
185*32b31808SJens Wiklander         end_attr_data = *p + len;
186*32b31808SJens Wiklander 
187*32b31808SJens Wiklander         /* Get attribute ID */
188*32b31808SJens Wiklander         if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len,
189*32b31808SJens Wiklander                                         MBEDTLS_ASN1_OID)) != 0) {
190*32b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
191*32b31808SJens Wiklander         }
192*32b31808SJens Wiklander 
193*32b31808SJens Wiklander         attr_oid.tag = MBEDTLS_ASN1_OID;
194*32b31808SJens Wiklander         attr_oid.p = *p;
195*32b31808SJens Wiklander         *p += attr_oid.len;
196*32b31808SJens Wiklander 
197*32b31808SJens Wiklander         /* Check that this is an extension-request attribute */
198*32b31808SJens Wiklander         if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) {
199*32b31808SJens Wiklander             if ((ret = mbedtls_asn1_get_tag(p, end, &len,
200*32b31808SJens Wiklander                                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
201*32b31808SJens Wiklander                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
202*32b31808SJens Wiklander             }
203*32b31808SJens Wiklander 
204*32b31808SJens Wiklander             if ((ret = mbedtls_asn1_get_tag(p, end, &len,
205*32b31808SJens Wiklander                                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
206*32b31808SJens Wiklander                 0) {
207*32b31808SJens Wiklander                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
208*32b31808SJens Wiklander             }
209*32b31808SJens Wiklander 
210*32b31808SJens Wiklander             if ((ret = x509_csr_parse_extensions(csr, p, *p + len)) != 0) {
211*32b31808SJens Wiklander                 return ret;
212*32b31808SJens Wiklander             }
213*32b31808SJens Wiklander 
214*32b31808SJens Wiklander             if (*p != end_attr_data) {
215*32b31808SJens Wiklander                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
216*32b31808SJens Wiklander                                          MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
217*32b31808SJens Wiklander             }
218*32b31808SJens Wiklander         }
219*32b31808SJens Wiklander 
220*32b31808SJens Wiklander         *p = end_attr_data;
221*32b31808SJens Wiklander     }
222*32b31808SJens Wiklander 
223*32b31808SJens Wiklander     if (*p != end) {
224*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
225*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
226*32b31808SJens Wiklander     }
227*32b31808SJens Wiklander 
228*32b31808SJens Wiklander     return 0;
229817466cbSJens Wiklander }
230817466cbSJens Wiklander 
231817466cbSJens Wiklander /*
232817466cbSJens Wiklander  * Parse a CSR in DER format
233817466cbSJens Wiklander  */
234817466cbSJens Wiklander int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
235817466cbSJens Wiklander                                const unsigned char *buf, size_t buflen)
236817466cbSJens Wiklander {
23711fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
238817466cbSJens Wiklander     size_t len;
239817466cbSJens Wiklander     unsigned char *p, *end;
240817466cbSJens Wiklander     mbedtls_x509_buf sig_params;
241817466cbSJens Wiklander 
242817466cbSJens Wiklander     memset(&sig_params, 0, sizeof(mbedtls_x509_buf));
243817466cbSJens Wiklander 
244817466cbSJens Wiklander     /*
245817466cbSJens Wiklander      * Check for valid input
246817466cbSJens Wiklander      */
247*32b31808SJens Wiklander     if (csr == NULL || buf == NULL || buflen == 0) {
248*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
249*32b31808SJens Wiklander     }
250817466cbSJens Wiklander 
251817466cbSJens Wiklander     mbedtls_x509_csr_init(csr);
252817466cbSJens Wiklander 
253817466cbSJens Wiklander     /*
254817466cbSJens Wiklander      * first copy the raw DER data
255817466cbSJens Wiklander      */
256817466cbSJens Wiklander     p = mbedtls_calloc(1, len = buflen);
257817466cbSJens Wiklander 
258*32b31808SJens Wiklander     if (p == NULL) {
259*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_ALLOC_FAILED;
260*32b31808SJens Wiklander     }
261817466cbSJens Wiklander 
262817466cbSJens Wiklander     memcpy(p, buf, buflen);
263817466cbSJens Wiklander 
264817466cbSJens Wiklander     csr->raw.p = p;
265817466cbSJens Wiklander     csr->raw.len = len;
266817466cbSJens Wiklander     end = p + len;
267817466cbSJens Wiklander 
268817466cbSJens Wiklander     /*
269817466cbSJens Wiklander      *  CertificationRequest ::= SEQUENCE {
270817466cbSJens Wiklander      *       certificationRequestInfo CertificationRequestInfo,
271817466cbSJens Wiklander      *       signatureAlgorithm AlgorithmIdentifier,
272817466cbSJens Wiklander      *       signature          BIT STRING
273817466cbSJens Wiklander      *  }
274817466cbSJens Wiklander      */
275817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
276*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
277817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
278*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_INVALID_FORMAT;
279817466cbSJens Wiklander     }
280817466cbSJens Wiklander 
281*32b31808SJens Wiklander     if (len != (size_t) (end - p)) {
282817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
283*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
284*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
285817466cbSJens Wiklander     }
286817466cbSJens Wiklander 
287817466cbSJens Wiklander     /*
288817466cbSJens Wiklander      *  CertificationRequestInfo ::= SEQUENCE {
289817466cbSJens Wiklander      */
290817466cbSJens Wiklander     csr->cri.p = p;
291817466cbSJens Wiklander 
292817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
293*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
294817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
295*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
296817466cbSJens Wiklander     }
297817466cbSJens Wiklander 
298817466cbSJens Wiklander     end = p + len;
299817466cbSJens Wiklander     csr->cri.len = end - csr->cri.p;
300817466cbSJens Wiklander 
301817466cbSJens Wiklander     /*
302817466cbSJens Wiklander      *  Version  ::=  INTEGER {  v1(0) }
303817466cbSJens Wiklander      */
304*32b31808SJens Wiklander     if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) {
305817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
306*32b31808SJens Wiklander         return ret;
307817466cbSJens Wiklander     }
308817466cbSJens Wiklander 
309*32b31808SJens Wiklander     if (csr->version != 0) {
310817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
311*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
312817466cbSJens Wiklander     }
313817466cbSJens Wiklander 
314817466cbSJens Wiklander     csr->version++;
315817466cbSJens Wiklander 
316817466cbSJens Wiklander     /*
317817466cbSJens Wiklander      *  subject               Name
318817466cbSJens Wiklander      */
319817466cbSJens Wiklander     csr->subject_raw.p = p;
320817466cbSJens Wiklander 
321817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
322*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
323817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
324*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
325817466cbSJens Wiklander     }
326817466cbSJens Wiklander 
327*32b31808SJens Wiklander     if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) {
328817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
329*32b31808SJens Wiklander         return ret;
330817466cbSJens Wiklander     }
331817466cbSJens Wiklander 
332817466cbSJens Wiklander     csr->subject_raw.len = p - csr->subject_raw.p;
333817466cbSJens Wiklander 
334817466cbSJens Wiklander     /*
335817466cbSJens Wiklander      *  subjectPKInfo SubjectPublicKeyInfo
336817466cbSJens Wiklander      */
337*32b31808SJens Wiklander     if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) {
338817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
339*32b31808SJens Wiklander         return ret;
340817466cbSJens Wiklander     }
341817466cbSJens Wiklander 
342817466cbSJens Wiklander     /*
343817466cbSJens Wiklander      *  attributes    [0] Attributes
344817466cbSJens Wiklander      *
345817466cbSJens Wiklander      *  The list of possible attributes is open-ended, though RFC 2985
346817466cbSJens Wiklander      *  (PKCS#9) defines a few in section 5.4. We currently don't support any,
347817466cbSJens Wiklander      *  so we just ignore them. This is a safe thing to do as the worst thing
348817466cbSJens Wiklander      *  that could happen is that we issue a certificate that does not match
349817466cbSJens Wiklander      *  the requester's expectations - this cannot cause a violation of our
350817466cbSJens Wiklander      *  signature policies.
351817466cbSJens Wiklander      */
352817466cbSJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
353*32b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
354*32b31808SJens Wiklander         0) {
355817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
356*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
357*32b31808SJens Wiklander     }
358*32b31808SJens Wiklander 
359*32b31808SJens Wiklander     if ((ret = x509_csr_parse_attributes(csr, p, p + len)) != 0) {
360*32b31808SJens Wiklander         mbedtls_x509_csr_free(csr);
361*32b31808SJens Wiklander         return ret;
362817466cbSJens Wiklander     }
363817466cbSJens Wiklander 
364817466cbSJens Wiklander     p += len;
365817466cbSJens Wiklander 
366817466cbSJens Wiklander     end = csr->raw.p + csr->raw.len;
367817466cbSJens Wiklander 
368817466cbSJens Wiklander     /*
369817466cbSJens Wiklander      *  signatureAlgorithm   AlgorithmIdentifier,
370817466cbSJens Wiklander      *  signature            BIT STRING
371817466cbSJens Wiklander      */
372*32b31808SJens Wiklander     if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) {
373817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
374*32b31808SJens Wiklander         return ret;
375817466cbSJens Wiklander     }
376817466cbSJens Wiklander 
377817466cbSJens Wiklander     if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params,
378817466cbSJens Wiklander                                         &csr->sig_md, &csr->sig_pk,
379*32b31808SJens Wiklander                                         &csr->sig_opts)) != 0) {
380817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
381*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;
382817466cbSJens Wiklander     }
383817466cbSJens Wiklander 
384*32b31808SJens Wiklander     if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) {
385817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
386*32b31808SJens Wiklander         return ret;
387817466cbSJens Wiklander     }
388817466cbSJens Wiklander 
389*32b31808SJens Wiklander     if (p != end) {
390817466cbSJens Wiklander         mbedtls_x509_csr_free(csr);
391*32b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
392*32b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
393817466cbSJens Wiklander     }
394817466cbSJens Wiklander 
395*32b31808SJens Wiklander     return 0;
396817466cbSJens Wiklander }
397817466cbSJens Wiklander 
398817466cbSJens Wiklander /*
399817466cbSJens Wiklander  * Parse a CSR, allowing for PEM or raw DER encoding
400817466cbSJens Wiklander  */
401817466cbSJens Wiklander int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen)
402817466cbSJens Wiklander {
403817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
40411fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
405817466cbSJens Wiklander     size_t use_len;
406817466cbSJens Wiklander     mbedtls_pem_context pem;
407817466cbSJens Wiklander #endif
408817466cbSJens Wiklander 
409817466cbSJens Wiklander     /*
410817466cbSJens Wiklander      * Check for valid input
411817466cbSJens Wiklander      */
412*32b31808SJens Wiklander     if (csr == NULL || buf == NULL || buflen == 0) {
413*32b31808SJens Wiklander         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
414*32b31808SJens Wiklander     }
415817466cbSJens Wiklander 
416817466cbSJens Wiklander #if defined(MBEDTLS_PEM_PARSE_C)
417817466cbSJens Wiklander     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
418*32b31808SJens Wiklander     if (buf[buflen - 1] == '\0') {
4193d3b0591SJens Wiklander         mbedtls_pem_init(&pem);
420817466cbSJens Wiklander         ret = mbedtls_pem_read_buffer(&pem,
421817466cbSJens Wiklander                                       "-----BEGIN CERTIFICATE REQUEST-----",
422817466cbSJens Wiklander                                       "-----END CERTIFICATE REQUEST-----",
423817466cbSJens Wiklander                                       buf, NULL, 0, &use_len);
424*32b31808SJens Wiklander         if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
4255b25c76aSJerome Forissier             ret = mbedtls_pem_read_buffer(&pem,
4265b25c76aSJerome Forissier                                           "-----BEGIN NEW CERTIFICATE REQUEST-----",
4275b25c76aSJerome Forissier                                           "-----END NEW CERTIFICATE REQUEST-----",
4285b25c76aSJerome Forissier                                           buf, NULL, 0, &use_len);
4295b25c76aSJerome Forissier         }
430817466cbSJens Wiklander 
431*32b31808SJens Wiklander         if (ret == 0) {
432817466cbSJens Wiklander             /*
433817466cbSJens Wiklander              * Was PEM encoded, parse the result
434817466cbSJens Wiklander              */
4353d3b0591SJens Wiklander             ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen);
4365b25c76aSJerome Forissier         }
437817466cbSJens Wiklander 
438817466cbSJens Wiklander         mbedtls_pem_free(&pem);
439*32b31808SJens Wiklander         if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
440*32b31808SJens Wiklander             return ret;
441*32b31808SJens Wiklander         }
442817466cbSJens Wiklander     }
443817466cbSJens Wiklander #endif /* MBEDTLS_PEM_PARSE_C */
444*32b31808SJens Wiklander     return mbedtls_x509_csr_parse_der(csr, buf, buflen);
445817466cbSJens Wiklander }
446817466cbSJens Wiklander 
447817466cbSJens Wiklander #if defined(MBEDTLS_FS_IO)
448817466cbSJens Wiklander /*
449817466cbSJens Wiklander  * Load a CSR into the structure
450817466cbSJens Wiklander  */
451817466cbSJens Wiklander int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)
452817466cbSJens Wiklander {
45311fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
454817466cbSJens Wiklander     size_t n;
455817466cbSJens Wiklander     unsigned char *buf;
456817466cbSJens Wiklander 
457*32b31808SJens Wiklander     if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
458*32b31808SJens Wiklander         return ret;
459*32b31808SJens Wiklander     }
460817466cbSJens Wiklander 
461817466cbSJens Wiklander     ret = mbedtls_x509_csr_parse(csr, buf, n);
462817466cbSJens Wiklander 
4633d3b0591SJens Wiklander     mbedtls_platform_zeroize(buf, n);
464817466cbSJens Wiklander     mbedtls_free(buf);
465817466cbSJens Wiklander 
466*32b31808SJens Wiklander     return ret;
467817466cbSJens Wiklander }
468817466cbSJens Wiklander #endif /* MBEDTLS_FS_IO */
469817466cbSJens Wiklander 
470*32b31808SJens Wiklander #if !defined(MBEDTLS_X509_REMOVE_INFO)
471817466cbSJens Wiklander #define BEFORE_COLON    14
472817466cbSJens Wiklander #define BC              "14"
473817466cbSJens Wiklander /*
474817466cbSJens Wiklander  * Return an informational string about the CSR.
475817466cbSJens Wiklander  */
476817466cbSJens Wiklander int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,
477817466cbSJens Wiklander                           const mbedtls_x509_csr *csr)
478817466cbSJens Wiklander {
47911fa71b9SJerome Forissier     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
480817466cbSJens Wiklander     size_t n;
481817466cbSJens Wiklander     char *p;
482817466cbSJens Wiklander     char key_size_str[BEFORE_COLON];
483817466cbSJens Wiklander 
484817466cbSJens Wiklander     p = buf;
485817466cbSJens Wiklander     n = size;
486817466cbSJens Wiklander 
487817466cbSJens Wiklander     ret = mbedtls_snprintf(p, n, "%sCSR version   : %d",
488817466cbSJens Wiklander                            prefix, csr->version);
489817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
490817466cbSJens Wiklander 
491817466cbSJens Wiklander     ret = mbedtls_snprintf(p, n, "\n%ssubject name  : ", prefix);
492817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
493817466cbSJens Wiklander     ret = mbedtls_x509_dn_gets(p, n, &csr->subject);
494817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
495817466cbSJens Wiklander 
496817466cbSJens Wiklander     ret = mbedtls_snprintf(p, n, "\n%ssigned using  : ", prefix);
497817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
498817466cbSJens Wiklander 
499817466cbSJens Wiklander     ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
500817466cbSJens Wiklander                                     csr->sig_opts);
501817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
502817466cbSJens Wiklander 
503817466cbSJens Wiklander     if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
504*32b31808SJens Wiklander                                             mbedtls_pk_get_name(&csr->pk))) != 0) {
505*32b31808SJens Wiklander         return ret;
506817466cbSJens Wiklander     }
507817466cbSJens Wiklander 
508817466cbSJens Wiklander     ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
509817466cbSJens Wiklander                            (int) mbedtls_pk_get_bitlen(&csr->pk));
510817466cbSJens Wiklander     MBEDTLS_X509_SAFE_SNPRINTF;
511817466cbSJens Wiklander 
512*32b31808SJens Wiklander     /*
513*32b31808SJens Wiklander      * Optional extensions
514*32b31808SJens Wiklander      */
515*32b31808SJens Wiklander 
516*32b31808SJens Wiklander     if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
517*32b31808SJens Wiklander         ret = mbedtls_snprintf(p, n, "\n%ssubject alt name  :", prefix);
518*32b31808SJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
519*32b31808SJens Wiklander 
520*32b31808SJens Wiklander         if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,
521*32b31808SJens Wiklander                                                       &csr->subject_alt_names,
522*32b31808SJens Wiklander                                                       prefix)) != 0) {
523*32b31808SJens Wiklander             return ret;
524817466cbSJens Wiklander         }
525*32b31808SJens Wiklander     }
526*32b31808SJens Wiklander 
527*32b31808SJens Wiklander     if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
528*32b31808SJens Wiklander         ret = mbedtls_snprintf(p, n, "\n%scert. type        : ", prefix);
529*32b31808SJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
530*32b31808SJens Wiklander 
531*32b31808SJens Wiklander         if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) {
532*32b31808SJens Wiklander             return ret;
533*32b31808SJens Wiklander         }
534*32b31808SJens Wiklander     }
535*32b31808SJens Wiklander 
536*32b31808SJens Wiklander     if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
537*32b31808SJens Wiklander         ret = mbedtls_snprintf(p, n, "\n%skey usage         : ", prefix);
538*32b31808SJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
539*32b31808SJens Wiklander 
540*32b31808SJens Wiklander         if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) {
541*32b31808SJens Wiklander             return ret;
542*32b31808SJens Wiklander         }
543*32b31808SJens Wiklander     }
544*32b31808SJens Wiklander 
545*32b31808SJens Wiklander     if (csr->ext_types != 0) {
546*32b31808SJens Wiklander         ret = mbedtls_snprintf(p, n, "\n");
547*32b31808SJens Wiklander         MBEDTLS_X509_SAFE_SNPRINTF;
548*32b31808SJens Wiklander     }
549*32b31808SJens Wiklander 
550*32b31808SJens Wiklander     return (int) (size - n);
551*32b31808SJens Wiklander }
552*32b31808SJens Wiklander #endif /* MBEDTLS_X509_REMOVE_INFO */
553817466cbSJens Wiklander 
554817466cbSJens Wiklander /*
555817466cbSJens Wiklander  * Initialize a CSR
556817466cbSJens Wiklander  */
557817466cbSJens Wiklander void mbedtls_x509_csr_init(mbedtls_x509_csr *csr)
558817466cbSJens Wiklander {
559817466cbSJens Wiklander     memset(csr, 0, sizeof(mbedtls_x509_csr));
560817466cbSJens Wiklander }
561817466cbSJens Wiklander 
562817466cbSJens Wiklander /*
563817466cbSJens Wiklander  * Unallocate all CSR data
564817466cbSJens Wiklander  */
565817466cbSJens Wiklander void mbedtls_x509_csr_free(mbedtls_x509_csr *csr)
566817466cbSJens Wiklander {
567*32b31808SJens Wiklander     if (csr == NULL) {
568817466cbSJens Wiklander         return;
569*32b31808SJens Wiklander     }
570817466cbSJens Wiklander 
571817466cbSJens Wiklander     mbedtls_pk_free(&csr->pk);
572817466cbSJens Wiklander 
573817466cbSJens Wiklander #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
574817466cbSJens Wiklander     mbedtls_free(csr->sig_opts);
575817466cbSJens Wiklander #endif
576817466cbSJens Wiklander 
577*32b31808SJens Wiklander     mbedtls_asn1_free_named_data_list_shallow(csr->subject.next);
578*32b31808SJens Wiklander     mbedtls_asn1_sequence_free(csr->subject_alt_names.next);
579817466cbSJens Wiklander 
580*32b31808SJens Wiklander     if (csr->raw.p != NULL) {
5813d3b0591SJens Wiklander         mbedtls_platform_zeroize(csr->raw.p, csr->raw.len);
582817466cbSJens Wiklander         mbedtls_free(csr->raw.p);
583817466cbSJens Wiklander     }
584817466cbSJens Wiklander 
5853d3b0591SJens Wiklander     mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));
586817466cbSJens Wiklander }
587817466cbSJens Wiklander 
588817466cbSJens Wiklander #endif /* MBEDTLS_X509_CSR_PARSE_C */
589