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 */
54static 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 a CSR in DER format
74 */
75int mbedtls_x509_csr_parse_der(mbedtls_x509_csr *csr,
76 const unsigned char *buf, size_t buflen)
77{
78 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
79 size_t len;
80 unsigned char *p, *end;
81 mbedtls_x509_buf sig_params;
82
83 memset(&sig_params, 0, sizeof(mbedtls_x509_buf));
84
85 /*
86 * Check for valid input
87 */
88 if (csr == NULL || buf == NULL || buflen == 0) {
89 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
90 }
91
92 mbedtls_x509_csr_init(csr);
93
94 /*
95 * first copy the raw DER data
96 */
97 p = mbedtls_calloc(1, len = buflen);
98
99 if (p == NULL) {
100 return MBEDTLS_ERR_X509_ALLOC_FAILED;
101 }
102
103 memcpy(p, buf, buflen);
104
105 csr->raw.p = p;
106 csr->raw.len = len;
107 end = p + len;
108
109 /*
110 * CertificationRequest ::= SEQUENCE {
111 * certificationRequestInfo CertificationRequestInfo,
112 * signatureAlgorithm AlgorithmIdentifier,
113 * signature BIT STRING
114 * }
115 */
116 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
117 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
118 mbedtls_x509_csr_free(csr);
119 return MBEDTLS_ERR_X509_INVALID_FORMAT;
120 }
121
122 if (len != (size_t) (end - p)) {
123 mbedtls_x509_csr_free(csr);
124 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
125 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
126 }
127
128 /*
129 * CertificationRequestInfo ::= SEQUENCE {
130 */
131 csr->cri.p = p;
132
133 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
134 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
135 mbedtls_x509_csr_free(csr);
136 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
137 }
138
139 end = p + len;
140 csr->cri.len = end - csr->cri.p;
141
142 /*
143 * Version ::= INTEGER { v1(0) }
144 */
145 if ((ret = x509_csr_get_version(&p, end, &csr->version)) != 0) {
146 mbedtls_x509_csr_free(csr);
147 return ret;
148 }
149
150 if (csr->version != 0) {
151 mbedtls_x509_csr_free(csr);
152 return MBEDTLS_ERR_X509_UNKNOWN_VERSION;
153 }
154
155 csr->version++;
156
157 /*
158 * subject Name
159 */
160 csr->subject_raw.p = p;
161
162 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
163 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
164 mbedtls_x509_csr_free(csr);
165 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
166 }
167
168 if ((ret = mbedtls_x509_get_name(&p, p + len, &csr->subject)) != 0) {
169 mbedtls_x509_csr_free(csr);
170 return ret;
171 }
172
173 csr->subject_raw.len = p - csr->subject_raw.p;
174
175 /*
176 * subjectPKInfo SubjectPublicKeyInfo
177 */
178 if ((ret = mbedtls_pk_parse_subpubkey(&p, end, &csr->pk)) != 0) {
179 mbedtls_x509_csr_free(csr);
180 return ret;
181 }
182
183 /*
184 * attributes [0] Attributes
185 *
186 * The list of possible attributes is open-ended, though RFC 2985
187 * (PKCS#9) defines a few in section 5.4. We currently don't support any,
188 * so we just ignore them. This is a safe thing to do as the worst thing
189 * that could happen is that we issue a certificate that does not match
190 * the requester's expectations - this cannot cause a violation of our
191 * signature policies.
192 */
193 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
194 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
195 0) {
196 mbedtls_x509_csr_free(csr);
197 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT, ret);
198 }
199
200 p += len;
201
202 end = csr->raw.p + csr->raw.len;
203
204 /*
205 * signatureAlgorithm AlgorithmIdentifier,
206 * signature BIT STRING
207 */
208 if ((ret = mbedtls_x509_get_alg(&p, end, &csr->sig_oid, &sig_params)) != 0) {
209 mbedtls_x509_csr_free(csr);
210 return ret;
211 }
212
213 if ((ret = mbedtls_x509_get_sig_alg(&csr->sig_oid, &sig_params,
214 &csr->sig_md, &csr->sig_pk,
215 &csr->sig_opts)) != 0) {
216 mbedtls_x509_csr_free(csr);
217 return MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG;
218 }
219
220 if ((ret = mbedtls_x509_get_sig(&p, end, &csr->sig)) != 0) {
221 mbedtls_x509_csr_free(csr);
222 return ret;
223 }
224
225 if (p != end) {
226 mbedtls_x509_csr_free(csr);
227 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_FORMAT,
228 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
229 }
230
231 return 0;
232}
233
234/*
235 * Parse a CSR, allowing for PEM or raw DER encoding
236 */
237int mbedtls_x509_csr_parse(mbedtls_x509_csr *csr, const unsigned char *buf, size_t buflen)
238{
239#if defined(MBEDTLS_PEM_PARSE_C)
240 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
241 size_t use_len;
242 mbedtls_pem_context pem;
243#endif
244
245 /*
246 * Check for valid input
247 */
248 if (csr == NULL || buf == NULL || buflen == 0) {
249 return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
250 }
251
252#if defined(MBEDTLS_PEM_PARSE_C)
253 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
254 if (buf[buflen - 1] == '\0') {
255 mbedtls_pem_init(&pem);
256 ret = mbedtls_pem_read_buffer(&pem,
257 "-----BEGIN CERTIFICATE REQUEST-----",
258 "-----END CERTIFICATE REQUEST-----",
259 buf, NULL, 0, &use_len);
260 if (ret == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
261 ret = mbedtls_pem_read_buffer(&pem,
262 "-----BEGIN NEW CERTIFICATE REQUEST-----",
263 "-----END NEW CERTIFICATE REQUEST-----",
264 buf, NULL, 0, &use_len);
265 }
266
267 if (ret == 0) {
268 /*
269 * Was PEM encoded, parse the result
270 */
271 ret = mbedtls_x509_csr_parse_der(csr, pem.buf, pem.buflen);
272 }
273
274 mbedtls_pem_free(&pem);
275 if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
276 return ret;
277 }
278 }
279#endif /* MBEDTLS_PEM_PARSE_C */
280 return mbedtls_x509_csr_parse_der(csr, buf, buflen);
281}
282
283#if defined(MBEDTLS_FS_IO)
284/*
285 * Load a CSR into the structure
286 */
287int mbedtls_x509_csr_parse_file(mbedtls_x509_csr *csr, const char *path)
288{
289 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
290 size_t n;
291 unsigned char *buf;
292
293 if ((ret = mbedtls_pk_load_file(path, &buf, &n)) != 0) {
294 return ret;
295 }
296
297 ret = mbedtls_x509_csr_parse(csr, buf, n);
298
299 mbedtls_platform_zeroize(buf, n);
300 mbedtls_free(buf);
301
302 return ret;
303}
304#endif /* MBEDTLS_FS_IO */
305
306#define BEFORE_COLON 14
307#define BC "14"
308/*
309 * Return an informational string about the CSR.
310 */
311int mbedtls_x509_csr_info(char *buf, size_t size, const char *prefix,
312 const mbedtls_x509_csr *csr)
313{
314 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
315 size_t n;
316 char *p;
317 char key_size_str[BEFORE_COLON];
318
319 p = buf;
320 n = size;
321
322 ret = mbedtls_snprintf(p, n, "%sCSR version : %d",
323 prefix, csr->version);
324 MBEDTLS_X509_SAFE_SNPRINTF;
325
326 ret = mbedtls_snprintf(p, n, "\n%ssubject name : ", prefix);
327 MBEDTLS_X509_SAFE_SNPRINTF;
328 ret = mbedtls_x509_dn_gets(p, n, &csr->subject);
329 MBEDTLS_X509_SAFE_SNPRINTF;
330
331 ret = mbedtls_snprintf(p, n, "\n%ssigned using : ", prefix);
332 MBEDTLS_X509_SAFE_SNPRINTF;
333
334 ret = mbedtls_x509_sig_alg_gets(p, n, &csr->sig_oid, csr->sig_pk, csr->sig_md,
335 csr->sig_opts);
336 MBEDTLS_X509_SAFE_SNPRINTF;
337
338 if ((ret = mbedtls_x509_key_size_helper(key_size_str, BEFORE_COLON,
339 mbedtls_pk_get_name(&csr->pk))) != 0) {
340 return ret;
341 }
342
343 ret = mbedtls_snprintf(p, n, "\n%s%-" BC "s: %d bits\n", prefix, key_size_str,
344 (int) mbedtls_pk_get_bitlen(&csr->pk));
345 MBEDTLS_X509_SAFE_SNPRINTF;
346
347 return (int) (size - n);
348}
349
350/*
351 * Initialize a CSR
352 */
353void mbedtls_x509_csr_init(mbedtls_x509_csr *csr)
354{
355 memset(csr, 0, sizeof(mbedtls_x509_csr));
356}
357
358/*
359 * Unallocate all CSR data
360 */
361void mbedtls_x509_csr_free(mbedtls_x509_csr *csr)
362{
363 mbedtls_x509_name *name_cur;
364 mbedtls_x509_name *name_prv;
365
366 if (csr == NULL) {
367 return;
368 }
369
370 mbedtls_pk_free(&csr->pk);
371
372#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
373 mbedtls_free(csr->sig_opts);
374#endif
375
376 name_cur = csr->subject.next;
377 while (name_cur != NULL) {
378 name_prv = name_cur;
379 name_cur = name_cur->next;
380 mbedtls_platform_zeroize(name_prv, sizeof(mbedtls_x509_name));
381 mbedtls_free(name_prv);
382 }
383
384 if (csr->raw.p != NULL) {
385 mbedtls_platform_zeroize(csr->raw.p, csr->raw.len);
386 mbedtls_free(csr->raw.p);
387 }
388
389 mbedtls_platform_zeroize(csr, sizeof(mbedtls_x509_csr));
390}
391
392#endif /* MBEDTLS_X509_CSR_PARSE_C */
393