blob: 813d64466cc140a3d5e3418137b425377d909c52 [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"
Valerio Setti25b282e2024-01-17 10:55:32 +010023#include "x509_internal.h"
Janos Follath73c616b2019-12-18 15:07:04 +000024#include "mbedtls/error.h"
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000025#include "mbedtls/oid.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050026#include "mbedtls/platform_util.h"
Rich Evans00ab4702015-02-06 13:43:58 +000027
28#include <string.h>
29
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020030#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000031#include "mbedtls/pem.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020032#endif
Paul Bakker7c6b2c32013-09-16 13:49:26 +020033
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000034#include "mbedtls/platform.h"
Paul Bakker7c6b2c32013-09-16 13:49:26 +020035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020036#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020037#include <stdio.h>
38#endif
39
40/*
41 * Version ::= INTEGER { v1(0) }
42 */
Gilles Peskine449bd832023-01-11 14:50:10 +010043static int x509_csr_get_version(unsigned char **p,
44 const unsigned char *end,
45 int *ver)
Paul Bakker7c6b2c32013-09-16 13:49:26 +020046{
Janos Follath865b3eb2019-12-16 11:46:15 +000047 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020048
Gilles Peskine449bd832023-01-11 14:50:10 +010049 if ((ret = mbedtls_asn1_get_int(p, end, ver)) != 0) {
50 if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
Paul Bakker7c6b2c32013-09-16 13:49:26 +020051 *ver = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +010052 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020053 }
54
Gilles Peskine449bd832023-01-11 14:50:10 +010055 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_VERSION, ret);
Paul Bakker7c6b2c32013-09-16 13:49:26 +020056 }
57
Gilles Peskine449bd832023-01-11 14:50:10 +010058 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +020059}
60
61/*
Jens Alfke2d9e3592019-10-29 15:03:37 -070062 * Parse CSR extension requests in DER format
63 */
64static int x509_csr_parse_extensions(mbedtls_x509_csr *csr,
Matthias Schulzab408222023-10-18 13:20:59 +020065 unsigned char **p, const unsigned char *end,
66 mbedtls_x509_csr_ext_cb_t cb,
67 void *p_ctx)
Jens Alfke2d9e3592019-10-29 15:03:37 -070068{
Matthias Schulz873a2022023-10-17 16:02:20 +020069 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Alfke2d9e3592019-10-29 15:03:37 -070070 size_t len;
Matthias Schulzab408222023-10-18 13:20:59 +020071 unsigned char *end_ext_data, *end_ext_octet;
Matthias Schulzcc923f32023-10-17 12:36:23 +020072
Jens Alfke2d9e3592019-10-29 15:03:37 -070073 while (*p < end) {
74 mbedtls_x509_buf extn_oid = { 0, 0, NULL };
Matthias Schulz873a2022023-10-17 16:02:20 +020075 int is_critical = 0; /* DEFAULT FALSE */
Jens Alfke2d9e3592019-10-29 15:03:37 -070076 int ext_type = 0;
77
78 /* Read sequence tag */
79 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
80 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +010081 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -070082 }
83
84 end_ext_data = *p + len;
85
86 /* Get extension ID */
87 if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &extn_oid.len,
88 MBEDTLS_ASN1_OID)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +010089 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -070090 }
91
92 extn_oid.tag = MBEDTLS_ASN1_OID;
93 extn_oid.p = *p;
94 *p += extn_oid.len;
95
Matthias Schulz873a2022023-10-17 16:02:20 +020096 /* Get optional critical */
97 if ((ret = mbedtls_asn1_get_bool(p, end_ext_data, &is_critical)) != 0 &&
98 (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
99 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
100 }
Matthias Schulzadb3cc42023-10-17 11:50:50 +0200101
Jens Alfke2d9e3592019-10-29 15:03:37 -0700102 /* Data should be octet string type */
103 if ((ret = mbedtls_asn1_get_tag(p, end_ext_data, &len,
104 MBEDTLS_ASN1_OCTET_STRING)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100105 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700106 }
Przemek Stekiel86d19462023-01-24 09:45:19 +0100107
Matthias Schulzab408222023-10-18 13:20:59 +0200108 end_ext_octet = *p + len;
109
110 if (end_ext_octet != end_ext_data) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100111 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
112 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700113 }
114
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100115 /*
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100116 * Detect supported extensions and skip unsupported extensions
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100117 */
118 ret = mbedtls_oid_get_x509_ext_type(&extn_oid, &ext_type);
119
Matthias Schulzab408222023-10-18 13:20:59 +0200120 if (ret != 0) {
121 /* Give the callback (if any) a chance to handle the extension */
122 if (cb != NULL) {
123 ret = cb(p_ctx, csr, &extn_oid, is_critical, *p, end_ext_octet);
124 if (ret != 0 && is_critical) {
125 return ret;
126 }
127 *p = end_ext_octet;
128 continue;
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100129 }
130
Matthias Schulzab408222023-10-18 13:20:59 +0200131 /* No parser found, skip extension */
132 *p = end_ext_octet;
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100133
Matthias Schulz873a2022023-10-17 16:02:20 +0200134 if (is_critical) {
135 /* Data is marked as critical: fail */
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100136 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
Matthias Schulz873a2022023-10-17 16:02:20 +0200137 MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
Przemek Stekiel94e21e12023-01-25 11:08:32 +0100138 }
Matthias Schulzab408222023-10-18 13:20:59 +0200139 continue;
Przemek Stekiel86d19462023-01-24 09:45:19 +0100140 }
Matthias Schulzab408222023-10-18 13:20:59 +0200141
142 /* Forbid repeated extensions */
143 if ((csr->ext_types & ext_type) != 0) {
144 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200145 MBEDTLS_ERR_ASN1_INVALID_DATA);
Matthias Schulzab408222023-10-18 13:20:59 +0200146 }
147
148 csr->ext_types |= ext_type;
149
150 switch (ext_type) {
151 case MBEDTLS_X509_EXT_KEY_USAGE:
152 /* Parse key usage */
153 if ((ret = mbedtls_x509_get_key_usage(p, end_ext_data,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200154 &csr->key_usage)) != 0) {
Matthias Schulzab408222023-10-18 13:20:59 +0200155 return ret;
156 }
157 break;
158
159 case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME:
160 /* Parse subject alt name */
161 if ((ret = mbedtls_x509_get_subject_alt_name(p, end_ext_data,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200162 &csr->subject_alt_names)) != 0) {
Matthias Schulzab408222023-10-18 13:20:59 +0200163 return ret;
164 }
165 break;
166
167 case MBEDTLS_X509_EXT_NS_CERT_TYPE:
168 /* Parse netscape certificate type */
169 if ((ret = mbedtls_x509_get_ns_cert_type(p, end_ext_data,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200170 &csr->ns_cert_type)) != 0) {
Matthias Schulzab408222023-10-18 13:20:59 +0200171 return ret;
172 }
173 break;
174 default:
175 /*
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200176 * If this is a non-critical extension, which the oid layer
177 * supports, but there isn't an x509 parser for it,
178 * skip the extension.
179 */
Matthias Schulzab408222023-10-18 13:20:59 +0200180 if (is_critical) {
181 return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
182 } else {
183 *p = end_ext_octet;
184 }
185 }
Jens Alfke2d9e3592019-10-29 15:03:37 -0700186 }
187
188 if (*p != end) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100189 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
190 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700191 }
192
193 return 0;
194}
195
196/*
197 * Parse CSR attributes in DER format
198 */
199static int x509_csr_parse_attributes(mbedtls_x509_csr *csr,
Matthias Schulzab408222023-10-18 13:20:59 +0200200 const unsigned char *start, const unsigned char *end,
201 mbedtls_x509_csr_ext_cb_t cb,
202 void *p_ctx)
Jens Alfke2d9e3592019-10-29 15:03:37 -0700203{
204 int ret;
205 size_t len;
206 unsigned char *end_attr_data;
207 unsigned char **p = (unsigned char **) &start;
208
209 while (*p < end) {
210 mbedtls_x509_buf attr_oid = { 0, 0, NULL };
211
212 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
213 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100214 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700215 }
216 end_attr_data = *p + len;
217
218 /* Get attribute ID */
219 if ((ret = mbedtls_asn1_get_tag(p, end_attr_data, &attr_oid.len,
220 MBEDTLS_ASN1_OID)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100221 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700222 }
223
224 attr_oid.tag = MBEDTLS_ASN1_OID;
225 attr_oid.p = *p;
226 *p += attr_oid.len;
227
228 /* Check that this is an extension-request attribute */
229 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_CSR_EXT_REQ, &attr_oid) == 0) {
230 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
231 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100232 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700233 }
234
235 if ((ret = mbedtls_asn1_get_tag(p, end, &len,
236 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) !=
237 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100238 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700239 }
240
Matthias Schulzab408222023-10-18 13:20:59 +0200241 if ((ret = x509_csr_parse_extensions(csr, p, *p + len, cb, p_ctx)) != 0) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100242 return ret;
Jens Alfke2d9e3592019-10-29 15:03:37 -0700243 }
244
245 if (*p != end_attr_data) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100246 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
247 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700248 }
249 }
250
251 *p = end_attr_data;
252 }
253
254 if (*p != end) {
Przemek Stekiel86d19462023-01-24 09:45:19 +0100255 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
Przemek Stekiel36ad5e72023-01-26 22:30:45 +0100256 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Alfke2d9e3592019-10-29 15:03:37 -0700257 }
258
259 return 0;
260}
261
262/*
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200263 * Parse a CSR in DER format
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200264 */
Matthias Schulzab408222023-10-18 13:20:59 +0200265static int mbedtls_x509_csr_parse_der_internal(mbedtls_x509_csr *csr,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200266 const unsigned char *buf, size_t buflen,
267 mbedtls_x509_csr_ext_cb_t cb,
268 void *p_ctx)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200269{
Janos Follath865b3eb2019-12-16 11:46:15 +0000270 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200271 size_t len;
272 unsigned char *p, *end;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200273 mbedtls_x509_buf sig_params;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200274
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 memset(&sig_params, 0, sizeof(mbedtls_x509_buf));
Manuel Pégourié-Gonnarddddbb1d2014-06-05 17:02:24 +0200276
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200277 /*
278 * Check for valid input
279 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100280 if (csr == NULL || buf == NULL || buflen == 0) {
281 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
282 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200283
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 mbedtls_x509_csr_init(csr);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200285
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200286 /*
287 * first copy the raw DER data
288 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100289 p = mbedtls_calloc(1, len = buflen);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 if (p == NULL) {
292 return MBEDTLS_ERR_X509_ALLOC_FAILED;
293 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200294
Gilles Peskine449bd832023-01-11 14:50:10 +0100295 memcpy(p, buf, buflen);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200296
297 csr->raw.p = p;
298 csr->raw.len = len;
299 end = p + len;
300
301 /*
302 * CertificationRequest ::= SEQUENCE {
303 * certificationRequestInfo CertificationRequestInfo,
304 * signatureAlgorithm AlgorithmIdentifier,
305 * signature BIT STRING
306 * }
307 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100308 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
309 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
310 mbedtls_x509_csr_free(csr);
311 return MBEDTLS_ERR_X509_INVALID_FORMAT;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200312 }
313
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 if (len != (size_t) (end - p)) {
315 mbedtls_x509_csr_free(csr);
316 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
317 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200318 }
319
320 /*
321 * CertificationRequestInfo ::= SEQUENCE {
322 */
323 csr->cri.p = p;
324
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
326 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
327 mbedtls_x509_csr_free(csr);
328 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200329 }
330
331 end = p + len;
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000332 csr->cri.len = (size_t) (end - csr->cri.p);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200333
334 /*
335 * Version ::= INTEGER { v1(0) }
336 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100337 if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) {
338 mbedtls_x509_csr_free(csr);
339 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200340 }
341
Gilles Peskine449bd832023-01-11 14:50:10 +0100342 if (csr->version != 0) {
343 mbedtls_x509_csr_free(csr);
344 return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200345 }
346
Andres AG2e3ddfa2017-02-17 13:54:43 +0000347 csr->version++;
348
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200349 /*
350 * subject Name
351 */
352 csr->subject_raw.p = p;
353
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
355 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
356 mbedtls_x509_csr_free(csr);
357 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200358 }
359
Gilles Peskine449bd832023-01-11 14:50:10 +0100360 if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) {
361 mbedtls_x509_csr_free(csr);
362 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200363 }
364
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000365 csr->subject_raw.len = (size_t) (p - csr->subject_raw.p);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200366
367 /*
368 * subjectPKInfo SubjectPublicKeyInfo
369 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) {
371 mbedtls_x509_csr_free(csr);
372 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200373 }
374
375 /*
376 * attributes [0] Attributes
Manuel Pégourié-Gonnard986bbf22016-02-24 14:36:05 +0000377 *
378 * The list of possible attributes is open-ended, though RFC 2985
379 * (PKCS#9) defines a few in section 5.4. We currently don't support any,
380 * so we just ignore them. This is a safe thing to do as the worst thing
381 * that could happen is that we issue a certificate that does not match
382 * the requester's expectations - this cannot cause a violation of our
383 * signature policies.
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200384 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100385 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
386 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
387 0) {
388 mbedtls_x509_csr_free(csr);
389 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200390 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200391
Matthias Schulzab408222023-10-18 13:20:59 +0200392 if ((ret = x509_csr_parse_attributes(csr, p, p + len, cb, p_ctx)) != 0) {
Jens Alfke2d9e3592019-10-29 15:03:37 -0700393 mbedtls_x509_csr_free(csr);
394 return ret;
395 }
396
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200397 p += len;
398
399 end = csr->raw.p + csr->raw.len;
400
401 /*
402 * signatureAlgorithm AlgorithmIdentifier,
403 * signature BIT STRING
404 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) {
406 mbedtls_x509_csr_free(csr);
407 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200408 }
409
Gilles Peskine449bd832023-01-11 14:50:10 +0100410 if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params,
411 &csr->sig_md, &csr->sig_pk,
412 &csr->sig_opts)) != 0) {
413 mbedtls_x509_csr_free(csr);
414 return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200415 }
416
Gilles Peskine449bd832023-01-11 14:50:10 +0100417 if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) {
418 mbedtls_x509_csr_free(csr);
419 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200420 }
421
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 if (p != end) {
423 mbedtls_x509_csr_free(csr);
424 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
425 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200426 }
427
Gilles Peskine449bd832023-01-11 14:50:10 +0100428 return 0;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200429}
430
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200431/*
Matthias Schulzab408222023-10-18 13:20:59 +0200432 * Parse a CSR in DER format
433 */
434int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
435 const unsigned char *buf, size_t buflen)
436{
437 return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, NULL, NULL);
438}
439
440/*
441 * Parse a CSR in DER format with callback for unknown extensions
442 */
443int mbedtls_x509_csr_parse_der_with_ext_cb(mbedtls_x509_csr *csr,
Matthias Schulzedc32ea2023-10-19 16:09:08 +0200444 const unsigned char *buf, size_t buflen,
445 mbedtls_x509_csr_ext_cb_t cb,
446 void *p_ctx)
Matthias Schulzab408222023-10-18 13:20:59 +0200447{
448 return mbedtls_x509_csr_parse_der_internal(csr, buf, buflen, cb, p_ctx);
449}
450
451/*
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200452 * Parse a CSR, allowing for PEM or raw DER encoding
453 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100454int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen)
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200455{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200456#if defined(MBEDTLS_PEM_PARSE_C)
Janos Follath865b3eb2019-12-16 11:46:15 +0000457 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200458 size_t use_len;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200459 mbedtls_pem_context pem;
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200460#endif
461
462 /*
463 * Check for valid input
464 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 if (csr == NULL || buf == NULL || buflen == 0) {
466 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
467 }
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200468
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200469#if defined(MBEDTLS_PEM_PARSE_C)
Manuel Pégourié-Gonnard43b37cb2015-05-12 11:20:10 +0200470 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 if (buf[buflen - 1] == '\0') {
472 mbedtls_pem_init(&pem);
473 ret = mbedtls_pem_read_buffer(&pem,
474 "-----BEGIN CERTIFICATE REQUEST-----",
475 "-----END CERTIFICATE REQUEST-----",
476 buf, NULL, 0, &use_len);
477 if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
478 ret = mbedtls_pem_read_buffer(&pem,
479 "-----BEGIN NEW CERTIFICATE REQUEST-----",
480 "-----END NEW CERTIFICATE REQUEST-----",
481 buf, NULL, 0, &use_len);
Simon Butcher0488ce62018-09-30 15:36:50 +0100482 }
Simon Butchere1660af2018-10-07 17:48:37 +0100483
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 if (ret == 0) {
Philippe Antoinec03059d2018-06-14 07:35:11 +0200485 /*
486 * Was PEM encoded, parse the result
487 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100488 ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen);
Simon Butcher0488ce62018-09-30 15:36:50 +0100489 }
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200490
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 mbedtls_pem_free(&pem);
492 if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
493 return ret;
494 }
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200495 }
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200496#endif /* MBEDTLS_PEM_PARSE_C */
Gilles Peskine449bd832023-01-11 14:50:10 +0100497 return mbedtls_x509_csr_parse_der(csr, buf, buflen);
Manuel Pégourié-Gonnardf3b47242014-06-16 18:06:48 +0200498}
499
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200500#if defined(MBEDTLS_FS_IO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200501/*
502 * Load a CSR into the structure
503 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100504int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200505{
Janos Follath865b3eb2019-12-16 11:46:15 +0000506 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200507 size_t n;
508 unsigned char *buf;
509
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
511 return ret;
512 }
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200513
Gilles Peskine449bd832023-01-11 14:50:10 +0100514 ret = mbedtls_x509_csr_parse(csr, buf, n);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200515
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100516 mbedtls_zeroize_and_free(buf, n);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200517
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200519}
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200520#endif /* MBEDTLS_FS_IO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200521
Hanno Becker612a2f12020-10-09 09:19:39 +0100522#if !defined(MBEDTLS_X509_REMOVE_INFO)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200523#define BEFORE_COLON 14
524#define BC "14"
525/*
526 * Return an informational string about the CSR.
527 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100528int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,
529 const mbedtls_x509_csr *csr)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200530{
Janos Follath865b3eb2019-12-16 11:46:15 +0000531 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200532 size_t n;
533 char *p;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200534 char key_size_str[BEFORE_COLON];
535
536 p = buf;
537 n = size;
538
Gilles Peskine449bd832023-01-11 14:50:10 +0100539 ret = mbedtls_snprintf(p, n, "%sCSR version : %d",
540 prefix, csr->version);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200541 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200542
Gilles Peskine449bd832023-01-11 14:50:10 +0100543 ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200544 MBEDTLS_X509_SAFE_SNPRINTF;
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 ret = mbedtls_x509_dn_gets(p, n, &csr->subject);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200546 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200547
Gilles Peskine449bd832023-01-11 14:50:10 +0100548 ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200549 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200550
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
552 csr->sig_opts);
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200553 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200554
Gilles Peskine449bd832023-01-11 14:50:10 +0100555 if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
556 mbedtls_pk_get_name(&csr->pk))) != 0) {
557 return ret;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200558 }
559
Gilles Peskine449bd832023-01-11 14:50:10 +0100560 ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
561 (int) mbedtls_pk_get_bitlen(&csr->pk));
Manuel Pégourié-Gonnard16853682015-06-22 11:12:02 +0200562 MBEDTLS_X509_SAFE_SNPRINTF;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200563
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100564 /*
565 * Optional extensions
566 */
567
568 if (csr->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
569 ret = mbedtls_snprintf(p, n, "\n%ssubject alt name :", prefix);
570 MBEDTLS_X509_SAFE_SNPRINTF;
571
Przemek Stekiel21c37282023-01-16 08:47:49 +0100572 if ((ret = mbedtls_x509_info_subject_alt_name(&p, &n,
573 &csr->subject_alt_names,
574 prefix)) != 0) {
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100575 return ret;
576 }
577 }
578
579 if (csr->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE) {
580 ret = mbedtls_snprintf(p, n, "\n%scert. type : ", prefix);
581 MBEDTLS_X509_SAFE_SNPRINTF;
582
Przemek Stekiel21c37282023-01-16 08:47:49 +0100583 if ((ret = mbedtls_x509_info_cert_type(&p, &n, csr->ns_cert_type)) != 0) {
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100584 return ret;
585 }
586 }
587
588 if (csr->ext_types & MBEDTLS_X509_EXT_KEY_USAGE) {
589 ret = mbedtls_snprintf(p, n, "\n%skey usage : ", prefix);
590 MBEDTLS_X509_SAFE_SNPRINTF;
591
Przemek Stekiel21c37282023-01-16 08:47:49 +0100592 if ((ret = mbedtls_x509_info_key_usage(&p, &n, csr->key_usage)) != 0) {
Przemek Stekielcbaf3162023-01-12 12:58:02 +0100593 return ret;
594 }
595 }
596
597 if (csr->ext_types != 0) {
598 ret = mbedtls_snprintf(p, n, "\n");
599 MBEDTLS_X509_SAFE_SNPRINTF;
600 }
601
Gilles Peskine449bd832023-01-11 14:50:10 +0100602 return (int) (size - n);
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200603}
Hanno Becker612a2f12020-10-09 09:19:39 +0100604#endif /* MBEDTLS_X509_REMOVE_INFO */
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200605
606/*
Paul Bakker369d2eb2013-09-18 11:58:25 +0200607 * Initialize a CSR
608 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100609void mbedtls_x509_csr_init(mbedtls_x509_csr *csr)
Paul Bakker369d2eb2013-09-18 11:58:25 +0200610{
Gilles Peskine449bd832023-01-11 14:50:10 +0100611 memset(csr, 0, sizeof(mbedtls_x509_csr));
Paul Bakker369d2eb2013-09-18 11:58:25 +0200612}
613
614/*
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200615 * Unallocate all CSR data
616 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100617void mbedtls_x509_csr_free(mbedtls_x509_csr *csr)
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200618{
Gilles Peskine449bd832023-01-11 14:50:10 +0100619 if (csr == NULL) {
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200620 return;
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200621 }
622
Gilles Peskine449bd832023-01-11 14:50:10 +0100623 mbedtls_pk_free(&csr->pk);
624
625#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
626 mbedtls_free(csr->sig_opts);
627#endif
628
629 mbedtls_asn1_free_named_data_list_shallow(csr->subject.next);
Przemek Stekiela4687682023-01-24 15:19:47 +0100630 mbedtls_asn1_sequence_free(csr->subject_alt_names.next);
Gilles Peskine449bd832023-01-11 14:50:10 +0100631
632 if (csr->raw.p != NULL) {
Tom Cosgroveca8c61b2023-07-17 15:17:40 +0100633 mbedtls_zeroize_and_free(csr->raw.p, csr->raw.len);
Gilles Peskine449bd832023-01-11 14:50:10 +0100634 }
635
636 mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));
Paul Bakker7c6b2c32013-09-16 13:49:26 +0200637}
638
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200639#endif /* MBEDTLS_X509_CSR_PARSE_C */