blob: 79b1589644eab4a7f5b7f750aecebcb9df6fe7e1 [file] [log] [blame]
Paul Bakker7c6b2c32013-09-16 13:49:26 +02001/*
2 * X.509 Certificate Signing Request (CSR) parsing
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker7c6b2c32013-09-16 13:49:26 +02006 */
7/*
8 * The ITU-T X.509 standard defines a certificate format for PKI.
9 *
Manuel Pégourié-Gonnard1c082f32014-06-12 22:34:55 +020010 * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs)
11 * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs)
12 * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020013 *
14 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf
15 * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf
16 */
17
Gilles Peskinedb09ef62020-06-03 01:43:33 +020018#include "common.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020019
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020020#if defined(MBEDTLS_X509_CSR_PARSE_C)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020021
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000022#include "mbedtls/x509_csr.h"
Janos Follath73c616b2019-12-18 15:07:04 +000023#include "mbedtls/error.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000024#include "mbedtls/oid.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050025#include "mbedtls/platform_util.h"
Rich Evans00ab4702015-02-06 13:43:58 +000026
27#include <string.h>
28
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020029#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000030#include "mbedtls/pem.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020031#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020032
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000033#include "mbedtls/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020034
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020035#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020036#include <stdio.h>
37#endif
38
39/*
40 * Version ::= INTEGER { v1(0) }
41 */
Gilles Peskine449bd832023-01-11 14:50:10 +010042static int x509_csr_get_version(unsigned char **p,
43 const unsigned char *end,
44 int *ver)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020045{
Janos Follath865b3eb2019-12-16 11:46:15 +000046 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020047
Gilles Peskine449bd832023-01-11 14:50:10 +010048 if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
49 if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
Paul Bakker7c6b2c32013-09-16 13:49:26 +020050 *ver = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +010051 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020052 }
53
Gilles Peskine449bd832023-01-11 14:50:10 +010054 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
Paul Bakker7c6b2c32013-09-16 13:49:26 +020055 }
56
Gilles Peskine449bd832023-01-11 14:50:10 +010057 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020058}
59
60/*
Jens Alfke2d9e3592019-10-29 15:03:37 -070061 * Parse CSR extension requests in DER format
62 */
63static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
Matthias Schulzab408222023-10-18 13:20:59 +020064 unsigned char **p, const unsigned char *end,
65 mbedtls_x509_csr_ext_cb_t cb,
66 void *p_ctx)
Jens Alfke2d9e3592019-10-29 15:03:37 -070067{
Matthias Schulz873a2022023-10-17 16:02:20 +020068 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Alfke2d9e3592019-10-29 15:03:37 -070069 size_t len;
Matthias Schulzab408222023-10-18 13:20:59 +020070 unsigned char *end_ext_data, *end_ext_octet;
Matthias Schulzcc923f32023-10-17 12:36:23 +020071
Jens Alfke2d9e3592019-10-29 15:03:37 -070072 while (*p < end) {
73 mbedtls_x509_buf extn_oid = { 0, 0, NULL };
Matthias Schulz873a2022023-10-17 16:02:20 +020074 int is_critical = 0; /* DEFAULT FALSE */
Jens Alfke2d9e3592019-10-29 15:03:37 -070075 int ext_type = 0;
76
77 /* Read sequence tag */
78 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
79 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +010080 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -070081 }
82
83 end_ext_data = *p + len;
84
85 /* Get extension ID */
86 if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
87 MBEDTLS_ASN1_OID)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +010088 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -070089 }
90
91 extn_oid.tag = MBEDTLS_ASN1_OID;
92 extn_oid.p = *p;
93 *p += extn_oid.len;
94
Matthias Schulz873a2022023-10-17 16:02:20 +020095 /* Get optional critical */
96 if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 &&
97 (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
98 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
99 }
Matthias Schulzadb3cc42023-10-17 11:50:50 +0200100
Jens Alfke2d9e3592019-10-29 15:03:37 -0700101 /* Data should be octet string type */
102 if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
103 MBEDTLS_ASN1_OCTET_STRING)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100104 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700105 }
Przemek Stekiel86d19462023-01-24 09:45:19 +0100106
Matthias Schulzab408222023-10-18 13:20:59 +0200107 end_ext_octet = *p + len;
108
109 if (end_ext_octet != end_ext_data) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100110 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
111 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700112 }
113
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100114 /*
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100115 * Detect supported extensions and skip unsupported extensions
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100116 */
117 ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
118
Matthias Schulzab408222023-10-18 13:20:59 +0200119 if (ret != 0) {
120 /* Give the callback (if any) a chance to handle the extension */
121 if (cb != NULL) {
122 ret = cb(p_ctx, csr, &extn_oid, is_critical, *p, end_ext_octet);
123 if (ret != 0 && is_critical) {
124 return ret;
125 }
126 *p = end_ext_octet;
127 continue;
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100128 }
129
Matthias Schulzab408222023-10-18 13:20:59 +0200130 /* No parser found, skip extension */
131 *p = end_ext_octet;
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100132
Matthias Schulz873a2022023-10-17 16:02:20 +0200133 if (is_critical) {
134 /* Data is marked as critical: fail */
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100135 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
Matthias Schulz873a2022023-10-17 16:02:20 +0200136 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100137 }
Matthias Schulzab408222023-10-18 13:20:59 +0200138 continue;
Przemek Stekiel86d19462023-01-24 09:45:19 +0100139 }
Matthias Schulzab408222023-10-18 13:20:59 +0200140
141 /* Forbid repeated extensions */
142 if ((csr->ext_types & ext_type) != 0) {
143 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200144 MBEDTLS_ERR_ASN1_INVALID_DATA);
Matthias Schulzab408222023-10-18 13:20:59 +0200145 }
146
147 csr->ext_types |= ext_type;
148
149 switch (ext_type) {
150 case MBEDTLS_X509_EXT_KEY_USAGE:
151 /* Parse key usage */
152 if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200153 &csr->key_usage)) != 0) {
Matthias Schulzab408222023-10-18 13:20:59 +0200154 return ret;
155 }
156 break;
157
158 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
159 /* Parse subject alt name */
160 if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200161 &csr->subject_alt_names)) != 0) {
Matthias Schulzab408222023-10-18 13:20:59 +0200162 return ret;
163 }
164 break;
165
166 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
167 /* Parse netscape certificate type */
168 if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200169 &csr->ns_cert_type)) != 0) {
Matthias Schulzab408222023-10-18 13:20:59 +0200170 return ret;
171 }
172 break;
173 default:
174 /*
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200175 * If this is a non-critical extension, which the oid layer
176 * supports, but there isn't an x509 parser for it,
177 * skip the extension.
178 */
Matthias Schulzab408222023-10-18 13:20:59 +0200179 if (is_critical) {
180 return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
181 } else {
182 *p = end_ext_octet;
183 }
184 }
Jens Alfke2d9e3592019-10-29 15:03:37 -0700185 }
186
187 if (*p != end) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100188 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
189 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700190 }
191
192 return 0;
193}
194
195/*
196 * Parse CSR attributes in DER format
197 */
198static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
Matthias Schulzab408222023-10-18 13:20:59 +0200199 const unsigned char *start, const unsigned char *end,
200 mbedtls_x509_csr_ext_cb_t cb,
201 void *p_ctx)
Jens Alfke2d9e3592019-10-29 15:03:37 -0700202{
203 int ret;
204 size_t len;
205 unsigned char *end_attr_data;
206 unsigned char **p = (unsigned char **) &start;
207
208 while (*p < end) {
209 mbedtls_x509_buf attr_oid = { 0, 0, NULL };
210
211 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
212 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100213 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700214 }
215 end_attr_data = *p + len;
216
217 /* Get attribute ID */
218 if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len,
219 MBEDTLS_ASN1_OID)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100220 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700221 }
222
223 attr_oid.tag = MBEDTLS_ASN1_OID;
224 attr_oid.p = *p;
225 *p += attr_oid.len;
226
227 /* Check that this is an extension-request attribute */
228 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) {
229 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
230 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100231 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700232 }
233
234 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
235 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
236 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100237 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700238 }
239
Matthias Schulzab408222023-10-18 13:20:59 +0200240 if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100241 return ret;
Jens Alfke2d9e3592019-10-29 15:03:37 -0700242 }
243
244 if (*p != end_attr_data) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100245 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
246 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700247 }
248 }
249
250 *p = end_attr_data;
251 }
252
253 if (*p != end) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100254 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
Przemek Stekiel36ad5e72023-01-26 22:30:45 +0100255 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700256 }
257
258 return 0;
259}
260
261/*
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200262 * Parse a CSR in DER format
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200263 */
Matthias Schulzab408222023-10-18 13:20:59 +0200264static int mbedtls_x509_csr_parse_der_internal(mbedtls_x509_csr *csr,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200265 const unsigned char *buf, size_t buflen,
266 mbedtls_x509_csr_ext_cb_t cb,
267 void *p_ctx)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200268{
Janos Follath865b3eb2019-12-16 11:46:15 +0000269 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200270 size_t len;
271 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200272 mbedtls_x509_buf sig_params;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200273
Gilles Peskine449bd832023-01-11 14:50:10 +0100274 memset(&sig_params, 0, sizeof(mbedtls_x509_buf));
Manuel Pégourié-Gonnarddddbb1d2014-06-05 17:02:24 +0200275
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200276 /*
277 * Check for valid input
278 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 if (csr == NULL || buf == NULL || buflen == 0) {
280 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
281 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200282
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 mbedtls_x509_csr_init(csr);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200284
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200285 /*
286 * first copy the raw DER data
287 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100288 p = mbedtls_calloc(1, len = buflen);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200289
Gilles Peskine449bd832023-01-11 14:50:10 +0100290 if (p == NULL) {
291 return MBEDTLS_ERR_X509_ALLOC_FAILED;
292 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200293
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 memcpy(p, buf, buflen);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200295
296 csr->raw.p = p;
297 csr->raw.len = len;
298 end = p + len;
299
300 /*
301 * CertificationRequest ::= SEQUENCE {
302 * certificationRequestInfo CertificationRequestInfo,
303 * signatureAlgorithm AlgorithmIdentifier,
304 * signature BIT STRING
305 * }
306 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
308 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
309 mbedtls_x509_csr_free(csr);
310 return MBEDTLS_ERR_X509_INVALID_FORMAT;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200311 }
312
Gilles Peskine449bd832023-01-11 14:50:10 +0100313 if (len != (size_t) (end - p)) {
314 mbedtls_x509_csr_free(csr);
315 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
316 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200317 }
318
319 /*
320 * CertificationRequestInfo ::= SEQUENCE {
321 */
322 csr->cri.p = p;
323
Gilles Peskine449bd832023-01-11 14:50:10 +0100324 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
325 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
326 mbedtls_x509_csr_free(csr);
327 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200328 }
329
330 end = p + len;
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000331 csr->cri.len = (size_t) (end - csr->cri.p);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200332
333 /*
334 * Version ::= INTEGER { v1(0) }
335 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) {
337 mbedtls_x509_csr_free(csr);
338 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200339 }
340
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 if (csr->version != 0) {
342 mbedtls_x509_csr_free(csr);
343 return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200344 }
345
Andres AG2e3ddfa2017-02-17 13:54:43 +0000346 csr->version++;
347
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200348 /*
349 * subject Name
350 */
351 csr->subject_raw.p = p;
352
Gilles Peskine449bd832023-01-11 14:50:10 +0100353 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
354 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
355 mbedtls_x509_csr_free(csr);
356 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200357 }
358
Gilles Peskine449bd832023-01-11 14:50:10 +0100359 if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) {
360 mbedtls_x509_csr_free(csr);
361 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200362 }
363
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000364 csr->subject_raw.len = (size_t) (p - csr->subject_raw.p);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200365
366 /*
367 * subjectPKInfo SubjectPublicKeyInfo
368 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100369 if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) {
370 mbedtls_x509_csr_free(csr);
371 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200372 }
373
374 /*
375 * attributes [0] Attributes
Manuel Pégourié-Gonnard986bbf22016-02-24 14:36:05 +0000376 *
377 * The list of possible attributes is open-ended, though RFC 2985
378 * (PKCS#9) defines a few in section 5.4. We currently don't support any,
379 * so we just ignore them. This is a safe thing to do as the worst thing
380 * that could happen is that we issue a certificate that does not match
381 * the requester's expectations - this cannot cause a violation of our
382 * signature policies.
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200383 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
385 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
386 0) {
387 mbedtls_x509_csr_free(csr);
388 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200389 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200390
Matthias Schulzab408222023-10-18 13:20:59 +0200391 if ((ret = x509_csr_parse_attributes(csr, p, p + len, cb, p_ctx)) != 0) {
Jens Alfke2d9e3592019-10-29 15:03:37 -0700392 mbedtls_x509_csr_free(csr);
393 return ret;
394 }
395
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200396 p += len;
397
398 end = csr->raw.p + csr->raw.len;
399
400 /*
401 * signatureAlgorithm AlgorithmIdentifier,
402 * signature BIT STRING
403 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) {
405 mbedtls_x509_csr_free(csr);
406 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200407 }
408
Gilles Peskine449bd832023-01-11 14:50:10 +0100409 if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params,
410 &csr->sig_md, &csr->sig_pk,
411 &csr->sig_opts)) != 0) {
412 mbedtls_x509_csr_free(csr);
413 return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200414 }
415
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) {
417 mbedtls_x509_csr_free(csr);
418 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200419 }
420
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 if (p != end) {
422 mbedtls_x509_csr_free(csr);
423 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
424 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200425 }
426
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200428}
429
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200430/*
Matthias Schulzab408222023-10-18 13:20:59 +0200431 * Parse a CSR in DER format
432 */
433int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
434 const unsigned char *buf, size_t buflen)
435{
436 return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, NULL, NULL);
437}
438
439/*
440 * Parse a CSR in DER format with callback for unknown extensions
441 */
442int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200443 const unsigned char *buf, size_t buflen,
444 mbedtls_x509_csr_ext_cb_t cb,
445 void *p_ctx)
Matthias Schulzab408222023-10-18 13:20:59 +0200446{
447 return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, cb, p_ctx);
448}
449
450/*
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200451 * Parse a CSR, allowing for PEM or raw DER encoding
452 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100453int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen)
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200454{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200455#if defined(MBEDTLS_PEM_PARSE_C)
Janos Follath865b3eb2019-12-16 11:46:15 +0000456 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200457 size_t use_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200458 mbedtls_pem_context pem;
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200459#endif
460
461 /*
462 * Check for valid input
463 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 if (csr == NULL || buf == NULL || buflen == 0) {
465 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
466 }
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200467
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200468#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200469 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +0100470 if (buf[buflen - 1] == '\0') {
471 mbedtls_pem_init(&pem);
472 ret = mbedtls_pem_read_buffer(&pem,
473 "-----BEGIN CERTIFICATE REQUEST-----",
474 "-----END CERTIFICATE REQUEST-----",
475 buf, NULL, 0, &use_len);
476 if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
477 ret = mbedtls_pem_read_buffer(&pem,
478 "-----BEGIN NEW CERTIFICATE REQUEST-----",
479 "-----END NEW CERTIFICATE REQUEST-----",
480 buf, NULL, 0, &use_len);
Simon Butcher0488ce62018-09-30 15:36:50 +0100481 }
Simon Butchere1660af2018-10-07 17:48:37 +0100482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 if (ret == 0) {
Philippe Antoinec03059d2018-06-14 07:35:11 +0200484 /*
485 * Was PEM encoded, parse the result
486 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100487 ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen);
Simon Butcher0488ce62018-09-30 15:36:50 +0100488 }
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200489
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 mbedtls_pem_free(&pem);
491 if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
492 return ret;
493 }
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200494 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200495#endif /* MBEDTLS_PEM_PARSE_C */
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 return mbedtls_x509_csr_parse_der(csr, buf, buflen);
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200497}
498
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200499#if defined(MBEDTLS_FS_IO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200500/*
501 * Load a CSR into the structure
502 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100503int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200504{
Janos Follath865b3eb2019-12-16 11:46:15 +0000505 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200506 size_t n;
507 unsigned char *buf;
508
Gilles Peskine449bd832023-01-11 14:50:10 +0100509 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
510 return ret;
511 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200512
Gilles Peskine449bd832023-01-11 14:50:10 +0100513 ret = mbedtls_x509_csr_parse(csr, buf, n);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200514
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100515 mbedtls_zeroize_and_free(buf, n);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200516
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200518}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200519#endif /* MBEDTLS_FS_IO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200520
Hanno Becker612a2f12020-10-09 09:19:39 +0100521#if !defined(MBEDTLS_X509_REMOVE_INFO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200522#define BEFORE_COLON 14
523#define BC "14"
524/*
525 * Return an informational string about the CSR.
526 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100527int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,
528 const mbedtls_x509_csr *csr)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200529{
Janos Follath865b3eb2019-12-16 11:46:15 +0000530 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200531 size_t n;
532 char *p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200533 char key_size_str[BEFORE_COLON];
534
535 p = buf;
536 n = size;
537
Gilles Peskine449bd832023-01-11 14:50:10 +0100538 ret = mbedtls_snprintf(p, n, "%sCSR version : %d",
539 prefix, csr->version);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200540 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200541
Gilles Peskine449bd832023-01-11 14:50:10 +0100542 ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200543 MBEDTLS_X509_SAFE_SNPRINTF;
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 ret = mbedtls_x509_dn_gets(p, n, &csr->subject);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200545 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200546
Gilles Peskine449bd832023-01-11 14:50:10 +0100547 ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200548 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200549
Gilles Peskine449bd832023-01-11 14:50:10 +0100550 ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
551 csr->sig_opts);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200552 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200553
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
555 mbedtls_pk_get_name(&csr->pk))) != 0) {
556 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200557 }
558
Gilles Peskine449bd832023-01-11 14:50:10 +0100559 ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
560 (int) mbedtls_pk_get_bitlen(&csr->pk));
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200561 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200562
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100563 /*
564 * Optional extensions
565 */
566
567 if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
568 ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix);
569 MBEDTLS_X509_SAFE_SNPRINTF;
570
Przemek Stekiel21c37282023-01-16 08:47:49 +0100571 if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,
572 &csr->subject_alt_names,
573 prefix)) != 0) {
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100574 return ret;
575 }
576 }
577
578 if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
579 ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix);
580 MBEDTLS_X509_SAFE_SNPRINTF;
581
Przemek Stekiel21c37282023-01-16 08:47:49 +0100582 if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) {
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100583 return ret;
584 }
585 }
586
587 if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
588 ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix);
589 MBEDTLS_X509_SAFE_SNPRINTF;
590
Przemek Stekiel21c37282023-01-16 08:47:49 +0100591 if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) {
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100592 return ret;
593 }
594 }
595
596 if (csr->ext_types != 0) {
597 ret = mbedtls_snprintf(p, n, "\n");
598 MBEDTLS_X509_SAFE_SNPRINTF;
599 }
600
Gilles Peskine449bd832023-01-11 14:50:10 +0100601 return (int) (size - n);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200602}
Hanno Becker612a2f12020-10-09 09:19:39 +0100603#endif /* MBEDTLS_X509_REMOVE_INFO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200604
605/*
Paul Bakker369d2eb2013-09-18 11:58:25 +0200606 * Initialize a CSR
607 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100608void mbedtls_x509_csr_init(mbedtls_x509_csr *csr)
Paul Bakker369d2eb2013-09-18 11:58:25 +0200609{
Gilles Peskine449bd832023-01-11 14:50:10 +0100610 memset(csr, 0, sizeof(mbedtls_x509_csr));
Paul Bakker369d2eb2013-09-18 11:58:25 +0200611}
612
613/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200614 * Unallocate all CSR data
615 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100616void mbedtls_x509_csr_free(mbedtls_x509_csr *csr)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200617{
Gilles Peskine449bd832023-01-11 14:50:10 +0100618 if (csr == NULL) {
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200619 return;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200620 }
621
Gilles Peskine449bd832023-01-11 14:50:10 +0100622 mbedtls_pk_free(&csr->pk);
623
624#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
625 mbedtls_free(csr->sig_opts);
626#endif
627
628 mbedtls_asn1_free_named_data_list_shallow(csr->subject.next);
Przemek Stekiela4687682023-01-24 15:19:47 +0100629 mbedtls_asn1_sequence_free(csr->subject_alt_names.next);
Gilles Peskine449bd832023-01-11 14:50:10 +0100630
631 if (csr->raw.p != NULL) {
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100632 mbedtls_zeroize_and_free(csr->raw.p, csr->raw.len);
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 }
634
635 mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200636}
637
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200638#endif /* MBEDTLS_X509_CSR_PARSE_C */