• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  X.509 Certificate Signing Request (CSR) parsing
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  */
19 /*
20  *  The ITU-T X.509 standard defines a certificate format for PKI.
21  *
22  *  http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
23  *  http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
24  *  http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
25  *
26  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
27  *  http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
28  */
29 
30 #include "common.h"
31 
32 #if defined(MBEDTLS_X509_CSR_PARSE_C)
33 
34 #include "mbedtls/x509_csr.h"
35 #include "mbedtls/error.h"
36 #include "mbedtls/oid.h"
37 #include "mbedtls/platform_util.h"
38 
39 #include <string.h>
40 
41 #if defined(MBEDTLS_PEM_PARSE_C)
42 #include "mbedtls/pem.h"
43 #endif
44 
45 #include "mbedtls/platform.h"
46 
47 #if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
48 #include <stdio.h>
49 #endif
50 
51 /*
52  *  Version  ::=  INTEGER  {  v1(0)  }
53  */
x509_csr_get_version(unsigned char ** p,const unsigned char * end,int * ver)54 static int x509_csr_get_version(unsigned char **p,
55                                 const unsigned char *end,
56                                 int *ver)
57 {
58     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
59 
60     if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
61         if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
62             *ver = 0;
63             return 0;
64         }
65 
66         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
67     }
68 
69     return 0;
70 }
71 
72 /*
73  * Parse CSR extension requests in DER format
74  */
x509_csr_parse_extensions(mbedtls_x509_csr * csr,unsigned char ** p,const unsigned char * end)75 static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
76                                      unsigned char **p, const unsigned char *end)
77 {
78     int ret;
79     size_t len;
80     unsigned char *end_ext_data;
81     while (*p < end) {
82         mbedtls_x509_buf extn_oid = { 0, 0, NULL };
83         int ext_type = 0;
84 
85         /* Read sequence tag */
86         if ((ret = mbedtls_asn1_get_tag(p, end, &len,
87                                         MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
88             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
89         }
90 
91         end_ext_data = *p + len;
92 
93         /* Get extension ID */
94         if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
95                                         MBEDTLS_ASN1_OID)) != 0) {
96             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
97         }
98 
99         extn_oid.tag = MBEDTLS_ASN1_OID;
100         extn_oid.p = *p;
101         *p += extn_oid.len;
102 
103         /* Data should be octet string type */
104         if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
105                                         MBEDTLS_ASN1_OCTET_STRING)) != 0) {
106             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
107         }
108 
109         if (*p + len != end_ext_data) {
110             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
111                                      MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
112         }
113 
114         /*
115          * Detect supported extensions and skip unsupported extensions
116          */
117         ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
118 
119         if (ret == 0) {
120             /* Forbid repeated extensions */
121             if ((csr->ext_types & ext_type) != 0) {
122                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
123                                          MBEDTLS_ERR_ASN1_INVALID_DATA);
124             }
125 
126             csr->ext_types |= ext_type;
127 
128             switch (ext_type) {
129                 case MBEDTLS_X509_EXT_KEY_USAGE:
130                     /* Parse key usage */
131                     if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,
132                                                           &csr->key_usage)) != 0) {
133                         return ret;
134                     }
135                     break;
136 
137                 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
138                     /* Parse subject alt name */
139                     if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,
140                                                                  &csr->subject_alt_names)) != 0) {
141                         return ret;
142                     }
143                     break;
144 
145                 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
146                     /* Parse netscape certificate type */
147                     if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,
148                                                              &csr->ns_cert_type)) != 0) {
149                         return ret;
150                     }
151                     break;
152                 default:
153                     break;
154             }
155         }
156         *p = end_ext_data;
157     }
158 
159     if (*p != end) {
160         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
161                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
162     }
163 
164     return 0;
165 }
166 
167 /*
168  * Parse CSR attributes in DER format
169  */
x509_csr_parse_attributes(mbedtls_x509_csr * csr,const unsigned char * start,const unsigned char * end)170 static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
171                                      const unsigned char *start, const unsigned char *end)
172 {
173     int ret;
174     size_t len;
175     unsigned char *end_attr_data;
176     unsigned char **p = (unsigned char **) &start;
177 
178     while (*p < end) {
179         mbedtls_x509_buf attr_oid = { 0, 0, NULL };
180 
181         if ((ret = mbedtls_asn1_get_tag(p, end, &len,
182                                         MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
183             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
184         }
185         end_attr_data = *p + len;
186 
187         /* Get attribute ID */
188         if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len,
189                                         MBEDTLS_ASN1_OID)) != 0) {
190             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
191         }
192 
193         attr_oid.tag = MBEDTLS_ASN1_OID;
194         attr_oid.p = *p;
195         *p += attr_oid.len;
196 
197         /* Check that this is an extension-request attribute */
198         if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) {
199             if ((ret = mbedtls_asn1_get_tag(p, end, &len,
200                                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
201                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
202             }
203 
204             if ((ret = mbedtls_asn1_get_tag(p, end, &len,
205                                             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
206                 0) {
207                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
208             }
209 
210             if ((ret = x509_csr_parse_extensions(csr, p, *p + len)) != 0) {
211                 return ret;
212             }
213 
214             if (*p != end_attr_data) {
215                 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
216                                          MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
217             }
218         }
219 
220         *p = end_attr_data;
221     }
222 
223     if (*p != end) {
224         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
225                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
226     }
227 
228     return 0;
229 }
230 
231 /*
232  * Parse a CSR in DER format
233  */
mbedtls_x509_csr_parse_der(mbedtls_x509_csr * csr,const unsigned char * buf,size_t buflen)234 int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
235                                const unsigned char *buf, size_t buflen)
236 {
237     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
238     size_t len;
239     unsigned char *p, *end;
240     mbedtls_x509_buf sig_params;
241 
242     memset(&sig_params, 0, sizeof(mbedtls_x509_buf));
243 
244     /*
245      * Check for valid input
246      */
247     if (csr == NULL || buf == NULL || buflen == 0) {
248         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
249     }
250 
251     mbedtls_x509_csr_init(csr);
252 
253     /*
254      * first copy the raw DER data
255      */
256     p = mbedtls_calloc(1, len = buflen);
257 
258     if (p == NULL) {
259         return MBEDTLS_ERR_X509_ALLOC_FAILED;
260     }
261 
262     memcpy(p, buf, buflen);
263 
264     csr->raw.p = p;
265     csr->raw.len = len;
266     end = p + len;
267 
268     /*
269      *  CertificationRequest ::= SEQUENCE {
270      *       certificationRequestInfo CertificationRequestInfo,
271      *       signatureAlgorithm AlgorithmIdentifier,
272      *       signature          BIT STRING
273      *  }
274      */
275     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
276                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
277         mbedtls_x509_csr_free(csr);
278         return MBEDTLS_ERR_X509_INVALID_FORMAT;
279     }
280 
281     if (len != (size_t) (end - p)) {
282         mbedtls_x509_csr_free(csr);
283         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
284                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
285     }
286 
287     /*
288      *  CertificationRequestInfo ::= SEQUENCE {
289      */
290     csr->cri.p = p;
291 
292     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
293                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
294         mbedtls_x509_csr_free(csr);
295         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
296     }
297 
298     end = p + len;
299     csr->cri.len = end - csr->cri.p;
300 
301     /*
302      *  Version  ::=  INTEGER {  v1(0) }
303      */
304     if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) {
305         mbedtls_x509_csr_free(csr);
306         return ret;
307     }
308 
309     if (csr->version != 0) {
310         mbedtls_x509_csr_free(csr);
311         return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
312     }
313 
314     csr->version++;
315 
316     /*
317      *  subject               Name
318      */
319     csr->subject_raw.p = p;
320 
321     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
322                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
323         mbedtls_x509_csr_free(csr);
324         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
325     }
326 
327     if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) {
328         mbedtls_x509_csr_free(csr);
329         return ret;
330     }
331 
332     csr->subject_raw.len = p - csr->subject_raw.p;
333 
334     /*
335      *  subjectPKInfo SubjectPublicKeyInfo
336      */
337     if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) {
338         mbedtls_x509_csr_free(csr);
339         return ret;
340     }
341 
342     /*
343      *  attributes    [0] Attributes
344      *
345      *  The list of possible attributes is open-ended, though RFC 2985
346      *  (PKCS#9) defines a few in section 5.4. We currently don't support any,
347      *  so we just ignore them. This is a safe thing to do as the worst thing
348      *  that could happen is that we issue a certificate that does not match
349      *  the requester's expectations - this cannot cause a violation of our
350      *  signature policies.
351      */
352     if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
353                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
354         0) {
355         mbedtls_x509_csr_free(csr);
356         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
357     }
358 
359     if ((ret = x509_csr_parse_attributes(csr, p, p + len)) != 0) {
360         mbedtls_x509_csr_free(csr);
361         return ret;
362     }
363 
364     p += len;
365 
366     end = csr->raw.p + csr->raw.len;
367 
368     /*
369      *  signatureAlgorithm   AlgorithmIdentifier,
370      *  signature            BIT STRING
371      */
372     if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) {
373         mbedtls_x509_csr_free(csr);
374         return ret;
375     }
376 
377     if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params,
378                                         &csr->sig_md, &csr->sig_pk,
379                                         &csr->sig_opts)) != 0) {
380         mbedtls_x509_csr_free(csr);
381         return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;
382     }
383 
384     if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) {
385         mbedtls_x509_csr_free(csr);
386         return ret;
387     }
388 
389     if (p != end) {
390         mbedtls_x509_csr_free(csr);
391         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
392                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
393     }
394 
395     return 0;
396 }
397 
398 /*
399  * Parse a CSR, allowing for PEM or raw DER encoding
400  */
mbedtls_x509_csr_parse(mbedtls_x509_csr * csr,const unsigned char * buf,size_t buflen)401 int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen)
402 {
403 #if defined(MBEDTLS_PEM_PARSE_C)
404     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
405     size_t use_len;
406     mbedtls_pem_context pem;
407 #endif
408 
409     /*
410      * Check for valid input
411      */
412     if (csr == NULL || buf == NULL || buflen == 0) {
413         return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
414     }
415 
416 #if defined(MBEDTLS_PEM_PARSE_C)
417     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
418     if (buf[buflen - 1] == '\0') {
419         mbedtls_pem_init(&pem);
420         ret = mbedtls_pem_read_buffer(&pem,
421                                       "-----BEGIN CERTIFICATE REQUEST-----",
422                                       "-----END CERTIFICATE REQUEST-----",
423                                       buf, NULL, 0, &use_len);
424         if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
425             ret = mbedtls_pem_read_buffer(&pem,
426                                           "-----BEGIN NEW CERTIFICATE REQUEST-----",
427                                           "-----END NEW CERTIFICATE REQUEST-----",
428                                           buf, NULL, 0, &use_len);
429         }
430 
431         if (ret == 0) {
432             /*
433              * Was PEM encoded, parse the result
434              */
435             ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen);
436         }
437 
438         mbedtls_pem_free(&pem);
439         if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
440             return ret;
441         }
442     }
443 #endif /* MBEDTLS_PEM_PARSE_C */
444     return mbedtls_x509_csr_parse_der(csr, buf, buflen);
445 }
446 
447 #if defined(MBEDTLS_FS_IO)
448 /*
449  * Load a CSR into the structure
450  */
mbedtls_x509_csr_parse_file(mbedtls_x509_csr * csr,const char * path)451 int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)
452 {
453     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
454     size_t n;
455     unsigned char *buf;
456 
457     if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
458         return ret;
459     }
460 
461     ret = mbedtls_x509_csr_parse(csr, buf, n);
462 
463     mbedtls_platform_zeroize(buf, n);
464     mbedtls_free(buf);
465 
466     return ret;
467 }
468 #endif /* MBEDTLS_FS_IO */
469 
470 #if !defined(MBEDTLS_X509_REMOVE_INFO)
471 #define BEFORE_COLON    14
472 #define BC              "14"
473 /*
474  * Return an informational string about the CSR.
475  */
mbedtls_x509_csr_info(char * buf,size_t size,const char * prefix,const mbedtls_x509_csr * csr)476 int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,
477                           const mbedtls_x509_csr *csr)
478 {
479     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
480     size_t n;
481     char *p;
482     char key_size_str[BEFORE_COLON];
483 
484     p = buf;
485     n = size;
486 
487     ret = mbedtls_snprintf(p, n, "%sCSR version   : %d",
488                            prefix, csr->version);
489     MBEDTLS_X509_SAFE_SNPRINTF;
490 
491     ret = mbedtls_snprintf(p, n, "\n%ssubject name  : ", prefix);
492     MBEDTLS_X509_SAFE_SNPRINTF;
493     ret = mbedtls_x509_dn_gets(p, n, &csr->subject);
494     MBEDTLS_X509_SAFE_SNPRINTF;
495 
496     ret = mbedtls_snprintf(p, n, "\n%ssigned using  : ", prefix);
497     MBEDTLS_X509_SAFE_SNPRINTF;
498 
499     ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
500                                     csr->sig_opts);
501     MBEDTLS_X509_SAFE_SNPRINTF;
502 
503     if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
504                                             mbedtls_pk_get_name(&csr->pk))) != 0) {
505         return ret;
506     }
507 
508     ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
509                            (int) mbedtls_pk_get_bitlen(&csr->pk));
510     MBEDTLS_X509_SAFE_SNPRINTF;
511 
512     /*
513      * Optional extensions
514      */
515 
516     if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
517         ret = mbedtls_snprintf(p, n, "\n%ssubject alt name  :", prefix);
518         MBEDTLS_X509_SAFE_SNPRINTF;
519 
520         if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,
521                                                       &csr->subject_alt_names,
522                                                       prefix)) != 0) {
523             return ret;
524         }
525     }
526 
527     if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
528         ret = mbedtls_snprintf(p, n, "\n%scert. type        : ", prefix);
529         MBEDTLS_X509_SAFE_SNPRINTF;
530 
531         if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) {
532             return ret;
533         }
534     }
535 
536     if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
537         ret = mbedtls_snprintf(p, n, "\n%skey usage         : ", prefix);
538         MBEDTLS_X509_SAFE_SNPRINTF;
539 
540         if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) {
541             return ret;
542         }
543     }
544 
545     if (csr->ext_types != 0) {
546         ret = mbedtls_snprintf(p, n, "\n");
547         MBEDTLS_X509_SAFE_SNPRINTF;
548     }
549 
550     return (int) (size - n);
551 }
552 #endif /* MBEDTLS_X509_REMOVE_INFO */
553 
554 /*
555  * Initialize a CSR
556  */
mbedtls_x509_csr_init(mbedtls_x509_csr * csr)557 void mbedtls_x509_csr_init(mbedtls_x509_csr *csr)
558 {
559     memset(csr, 0, sizeof(mbedtls_x509_csr));
560 }
561 
562 /*
563  * Unallocate all CSR data
564  */
mbedtls_x509_csr_free(mbedtls_x509_csr * csr)565 void mbedtls_x509_csr_free(mbedtls_x509_csr *csr)
566 {
567     if (csr == NULL) {
568         return;
569     }
570 
571     mbedtls_pk_free(&csr->pk);
572 
573 #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
574     mbedtls_free(csr->sig_opts);
575 #endif
576 
577     mbedtls_asn1_free_named_data_list_shallow(csr->subject.next);
578     mbedtls_asn1_sequence_free(csr->subject_alt_names.next);
579 
580     if (csr->raw.p != NULL) {
581         mbedtls_platform_zeroize(csr->raw.p, csr->raw.len);
582         mbedtls_free(csr->raw.p);
583     }
584 
585     mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));
586 }
587 
588 #endif /* MBEDTLS_X509_CSR_PARSE_C */
589