Branch data Line data Source code
1 : : /*
2 : : * X.509 common functions for parsing and verification
3 : : *
4 : : * Copyright The Mbed TLS Contributors
5 : : * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 : : */
7 : : /*
8 : : * The ITU-T X.509 standard defines a certificate format for PKI.
9 : : *
10 : : * 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)
13 : : *
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 : :
18 : : #include "common.h"
19 : :
20 : : #if defined(MBEDTLS_X509_USE_C)
21 : :
22 : : #include "x509_internal.h"
23 : : #include "mbedtls/asn1.h"
24 : : #include "mbedtls/error.h"
25 : : #include "mbedtls/oid.h"
26 : :
27 : : #include <stdio.h>
28 : : #include <string.h>
29 : :
30 : : #if defined(MBEDTLS_PEM_PARSE_C)
31 : : #include "mbedtls/pem.h"
32 : : #endif
33 : :
34 : : #include "mbedtls/asn1write.h"
35 : :
36 : : #include "mbedtls/platform.h"
37 : :
38 : : #if defined(MBEDTLS_HAVE_TIME)
39 : : #include "mbedtls/platform_time.h"
40 : : #endif
41 : : #if defined(MBEDTLS_HAVE_TIME_DATE)
42 : : #include "mbedtls/platform_util.h"
43 : : #include <time.h>
44 : : #endif
45 : :
46 : : #define CHECK(code) \
47 : : do { \
48 : : if ((ret = (code)) != 0) { \
49 : : return ret; \
50 : : } \
51 : : } while (0)
52 : :
53 : : #define CHECK_RANGE(min, max, val) \
54 : : do { \
55 : : if ((val) < (min) || (val) > (max)) { \
56 : : return ret; \
57 : : } \
58 : : } while (0)
59 : :
60 : : /*
61 : : * CertificateSerialNumber ::= INTEGER
62 : : */
63 : 4 : int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end,
64 : : mbedtls_x509_buf *serial)
65 : : {
66 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
67 : :
68 [ - + ]: 4 : if ((end - *p) < 1) {
69 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
70 : : MBEDTLS_ERR_ASN1_OUT_OF_DATA);
71 : : }
72 : :
73 [ - + ]: 4 : if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) &&
74 : : **p != MBEDTLS_ASN1_INTEGER) {
75 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL,
76 : : MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
77 : : }
78 : :
79 : 4 : serial->tag = *(*p)++;
80 : :
81 [ - + ]: 4 : if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) {
82 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret);
83 : : }
84 : :
85 : 4 : serial->p = *p;
86 : 4 : *p += serial->len;
87 : :
88 : 4 : return 0;
89 : : }
90 : :
91 : : /* Get an algorithm identifier without parameters (eg for signatures)
92 : : *
93 : : * AlgorithmIdentifier ::= SEQUENCE {
94 : : * algorithm OBJECT IDENTIFIER,
95 : : * parameters ANY DEFINED BY algorithm OPTIONAL }
96 : : */
97 : 0 : int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end,
98 : : mbedtls_x509_buf *alg)
99 : : {
100 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101 : :
102 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
103 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
104 : : }
105 : :
106 : : return 0;
107 : : }
108 : :
109 : : /*
110 : : * Parse an algorithm identifier with (optional) parameters
111 : : */
112 : 8 : int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end,
113 : : mbedtls_x509_buf *alg, mbedtls_x509_buf *params)
114 : : {
115 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
116 : :
117 [ - + ]: 8 : if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) {
118 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
119 : : }
120 : :
121 : : return 0;
122 : : }
123 : :
124 : : /*
125 : : * Convert md type to string
126 : : */
127 : : #if !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
128 : :
129 : : static inline const char *md_type_to_string(mbedtls_md_type_t md_alg)
130 : : {
131 : : switch (md_alg) {
132 : : #if defined(MBEDTLS_MD_CAN_MD5)
133 : : case MBEDTLS_MD_MD5:
134 : : return "MD5";
135 : : #endif
136 : : #if defined(MBEDTLS_MD_CAN_SHA1)
137 : : case MBEDTLS_MD_SHA1:
138 : : return "SHA1";
139 : : #endif
140 : : #if defined(MBEDTLS_MD_CAN_SHA224)
141 : : case MBEDTLS_MD_SHA224:
142 : : return "SHA224";
143 : : #endif
144 : : #if defined(MBEDTLS_MD_CAN_SHA256)
145 : : case MBEDTLS_MD_SHA256:
146 : : return "SHA256";
147 : : #endif
148 : : #if defined(MBEDTLS_MD_CAN_SHA384)
149 : : case MBEDTLS_MD_SHA384:
150 : : return "SHA384";
151 : : #endif
152 : : #if defined(MBEDTLS_MD_CAN_SHA512)
153 : : case MBEDTLS_MD_SHA512:
154 : : return "SHA512";
155 : : #endif
156 : : #if defined(MBEDTLS_MD_CAN_RIPEMD160)
157 : : case MBEDTLS_MD_RIPEMD160:
158 : : return "RIPEMD160";
159 : : #endif
160 : : case MBEDTLS_MD_NONE:
161 : : return NULL;
162 : : default:
163 : : return NULL;
164 : : }
165 : : }
166 : :
167 : : #endif /* !defined(MBEDTLS_X509_REMOVE_INFO) && defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) */
168 : :
169 : : #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
170 : : /*
171 : : * HashAlgorithm ::= AlgorithmIdentifier
172 : : *
173 : : * AlgorithmIdentifier ::= SEQUENCE {
174 : : * algorithm OBJECT IDENTIFIER,
175 : : * parameters ANY DEFINED BY algorithm OPTIONAL }
176 : : *
177 : : * For HashAlgorithm, parameters MUST be NULL or absent.
178 : : */
179 : : static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg)
180 : : {
181 : : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
182 : : unsigned char *p;
183 : : const unsigned char *end;
184 : : mbedtls_x509_buf md_oid;
185 : : size_t len;
186 : :
187 : : /* Make sure we got a SEQUENCE and setup bounds */
188 : : if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
189 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
190 : : MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
191 : : }
192 : :
193 : : p = alg->p;
194 : : end = p + alg->len;
195 : :
196 : : if (p >= end) {
197 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
198 : : MBEDTLS_ERR_ASN1_OUT_OF_DATA);
199 : : }
200 : :
201 : : /* Parse md_oid */
202 : : md_oid.tag = *p;
203 : :
204 : : if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) {
205 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
206 : : }
207 : :
208 : : md_oid.p = p;
209 : : p += md_oid.len;
210 : :
211 : : /* Get md_alg from md_oid */
212 : : if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) {
213 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
214 : : }
215 : :
216 : : /* Make sure params is absent of NULL */
217 : : if (p == end) {
218 : : return 0;
219 : : }
220 : :
221 : : if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) {
222 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
223 : : }
224 : :
225 : : if (p != end) {
226 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
227 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
228 : : }
229 : :
230 : : return 0;
231 : : }
232 : :
233 : : /*
234 : : * RSASSA-PSS-params ::= SEQUENCE {
235 : : * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier,
236 : : * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier,
237 : : * saltLength [2] INTEGER DEFAULT 20,
238 : : * trailerField [3] INTEGER DEFAULT 1 }
239 : : * -- Note that the tags in this Sequence are explicit.
240 : : *
241 : : * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value
242 : : * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other
243 : : * option. Enforce this at parsing time.
244 : : */
245 : : int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params,
246 : : mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md,
247 : : int *salt_len)
248 : : {
249 : : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
250 : : unsigned char *p;
251 : : const unsigned char *end, *end2;
252 : : size_t len;
253 : : mbedtls_x509_buf alg_id, alg_params;
254 : :
255 : : /* First set everything to defaults */
256 : : *md_alg = MBEDTLS_MD_SHA1;
257 : : *mgf_md = MBEDTLS_MD_SHA1;
258 : : *salt_len = 20;
259 : :
260 : : /* Make sure params is a SEQUENCE and setup bounds */
261 : : if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) {
262 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
263 : : MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
264 : : }
265 : :
266 : : p = (unsigned char *) params->p;
267 : : end = p + params->len;
268 : :
269 : : if (p == end) {
270 : : return 0;
271 : : }
272 : :
273 : : /*
274 : : * HashAlgorithm
275 : : */
276 : : if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
277 : : MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
278 : : 0)) == 0) {
279 : : end2 = p + len;
280 : :
281 : : /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */
282 : : if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) {
283 : : return ret;
284 : : }
285 : :
286 : : if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) {
287 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
288 : : }
289 : :
290 : : if (p != end2) {
291 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
292 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
293 : : }
294 : : } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
295 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
296 : : }
297 : :
298 : : if (p == end) {
299 : : return 0;
300 : : }
301 : :
302 : : /*
303 : : * MaskGenAlgorithm
304 : : */
305 : : if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
306 : : MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
307 : : 1)) == 0) {
308 : : end2 = p + len;
309 : :
310 : : /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */
311 : : if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) {
312 : : return ret;
313 : : }
314 : :
315 : : /* Only MFG1 is recognised for now */
316 : : if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) {
317 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE,
318 : : MBEDTLS_ERR_OID_NOT_FOUND);
319 : : }
320 : :
321 : : /* Parse HashAlgorithm */
322 : : if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) {
323 : : return ret;
324 : : }
325 : :
326 : : if (p != end2) {
327 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
328 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
329 : : }
330 : : } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
331 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
332 : : }
333 : :
334 : : if (p == end) {
335 : : return 0;
336 : : }
337 : :
338 : : /*
339 : : * salt_len
340 : : */
341 : : if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
342 : : MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
343 : : 2)) == 0) {
344 : : end2 = p + len;
345 : :
346 : : if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) {
347 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
348 : : }
349 : :
350 : : if (p != end2) {
351 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
352 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
353 : : }
354 : : } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
355 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
356 : : }
357 : :
358 : : if (p == end) {
359 : : return 0;
360 : : }
361 : :
362 : : /*
363 : : * trailer_field (if present, must be 1)
364 : : */
365 : : if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
366 : : MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED |
367 : : 3)) == 0) {
368 : : int trailer_field;
369 : :
370 : : end2 = p + len;
371 : :
372 : : if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) {
373 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
374 : : }
375 : :
376 : : if (p != end2) {
377 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
378 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
379 : : }
380 : :
381 : : if (trailer_field != 1) {
382 : : return MBEDTLS_ERR_X509_INVALID_ALG;
383 : : }
384 : : } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
385 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret);
386 : : }
387 : :
388 : : if (p != end) {
389 : : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG,
390 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
391 : : }
392 : :
393 : : return 0;
394 : : }
395 : : #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
396 : :
397 : : /*
398 : : * AttributeTypeAndValue ::= SEQUENCE {
399 : : * type AttributeType,
400 : : * value AttributeValue }
401 : : *
402 : : * AttributeType ::= OBJECT IDENTIFIER
403 : : *
404 : : * AttributeValue ::= ANY DEFINED BY AttributeType
405 : : */
406 : 8 : static int x509_get_attr_type_value(unsigned char **p,
407 : : const unsigned char *end,
408 : : mbedtls_x509_name *cur)
409 : : {
410 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
411 : 8 : size_t len;
412 : 8 : mbedtls_x509_buf *oid;
413 : 8 : mbedtls_x509_buf *val;
414 : :
415 [ - + ]: 8 : if ((ret = mbedtls_asn1_get_tag(p, end, &len,
416 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
417 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
418 : : }
419 : :
420 : 8 : end = *p + len;
421 : :
422 [ - + ]: 8 : if ((end - *p) < 1) {
423 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
424 : : MBEDTLS_ERR_ASN1_OUT_OF_DATA);
425 : : }
426 : :
427 : 8 : oid = &cur->oid;
428 : 8 : oid->tag = **p;
429 : :
430 [ - + ]: 8 : if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) {
431 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
432 : : }
433 : :
434 : 8 : oid->p = *p;
435 : 8 : *p += oid->len;
436 : :
437 [ - + ]: 8 : if ((end - *p) < 1) {
438 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
439 : : MBEDTLS_ERR_ASN1_OUT_OF_DATA);
440 : : }
441 : :
442 [ - + ]: 8 : if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING &&
443 : : **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING &&
444 : : **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING &&
445 : : **p != MBEDTLS_ASN1_BIT_STRING) {
446 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
447 : : MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
448 : : }
449 : :
450 : 8 : val = &cur->val;
451 : 8 : val->tag = *(*p)++;
452 : :
453 [ - + ]: 8 : if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) {
454 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
455 : : }
456 : :
457 : 8 : val->p = *p;
458 : 8 : *p += val->len;
459 : :
460 [ - + ]: 8 : if (*p != end) {
461 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME,
462 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
463 : : }
464 : :
465 : 8 : cur->next = NULL;
466 : :
467 : 8 : return 0;
468 : : }
469 : :
470 : : /*
471 : : * Name ::= CHOICE { -- only one possibility for now --
472 : : * rdnSequence RDNSequence }
473 : : *
474 : : * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
475 : : *
476 : : * RelativeDistinguishedName ::=
477 : : * SET OF AttributeTypeAndValue
478 : : *
479 : : * AttributeTypeAndValue ::= SEQUENCE {
480 : : * type AttributeType,
481 : : * value AttributeValue }
482 : : *
483 : : * AttributeType ::= OBJECT IDENTIFIER
484 : : *
485 : : * AttributeValue ::= ANY DEFINED BY AttributeType
486 : : *
487 : : * The data structure is optimized for the common case where each RDN has only
488 : : * one element, which is represented as a list of AttributeTypeAndValue.
489 : : * For the general case we still use a flat list, but we mark elements of the
490 : : * same set so that they are "merged" together in the functions that consume
491 : : * this list, eg mbedtls_x509_dn_gets().
492 : : *
493 : : * On success, this function may allocate a linked list starting at cur->next
494 : : * that must later be free'd by the caller using mbedtls_free(). In error
495 : : * cases, this function frees all allocated memory internally and the caller
496 : : * has no freeing responsibilities.
497 : : */
498 : 8 : int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end,
499 : : mbedtls_x509_name *cur)
500 : : {
501 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
502 : 8 : size_t set_len;
503 : 8 : const unsigned char *end_set;
504 : 8 : mbedtls_x509_name *head = cur;
505 : :
506 : : /* don't use recursion, we'd risk stack overflow if not optimized */
507 : 8 : while (1) {
508 : : /*
509 : : * parse SET
510 : : */
511 [ - + ]: 8 : if ((ret = mbedtls_asn1_get_tag(p, end, &set_len,
512 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) {
513 : 0 : ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret);
514 : 0 : goto error;
515 : : }
516 : :
517 : 8 : end_set = *p + set_len;
518 : :
519 : 8 : while (1) {
520 [ - + ]: 8 : if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) {
521 : 0 : goto error;
522 : : }
523 : :
524 [ - + ]: 8 : if (*p == end_set) {
525 : : break;
526 : : }
527 : :
528 : : /* Mark this item as being no the only one in a set */
529 : 0 : cur->next_merged = 1;
530 : :
531 : 0 : cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
532 : :
533 [ # # ]: 0 : if (cur->next == NULL) {
534 : 0 : ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
535 : 0 : goto error;
536 : : }
537 : :
538 : : cur = cur->next;
539 : : }
540 : :
541 : : /*
542 : : * continue until end of SEQUENCE is reached
543 : : */
544 [ - + ]: 8 : if (*p == end) {
545 : : return 0;
546 : : }
547 : :
548 : 0 : cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name));
549 : :
550 [ # # ]: 0 : if (cur->next == NULL) {
551 : 0 : ret = MBEDTLS_ERR_X509_ALLOC_FAILED;
552 : 0 : goto error;
553 : : }
554 : :
555 : : cur = cur->next;
556 : : }
557 : :
558 : 0 : error:
559 : : /* Skip the first element as we did not allocate it */
560 : 0 : mbedtls_asn1_free_named_data_list_shallow(head->next);
561 : 0 : head->next = NULL;
562 : :
563 : 0 : return ret;
564 : : }
565 : :
566 : 8 : static int x509_date_is_valid(const mbedtls_x509_time *t)
567 : : {
568 : 8 : unsigned int month_days;
569 : 8 : unsigned int year;
570 [ - - + - ]: 8 : switch (t->mon) {
571 : : case 1: case 3: case 5: case 7: case 8: case 10: case 12:
572 : : month_days = 31;
573 : : break;
574 : 0 : case 4: case 6: case 9: case 11:
575 : 0 : month_days = 30;
576 : 0 : break;
577 : 0 : case 2:
578 : 0 : year = (unsigned int) t->year;
579 [ # # ]: 0 : month_days = ((year & 3) || (!(year % 100)
580 [ # # ]: 0 : && (year % 400)))
581 [ # # ]: 0 : ? 28 : 29;
582 : : break;
583 : : default:
584 : : return MBEDTLS_ERR_X509_INVALID_DATE;
585 : : }
586 : :
587 [ + - ]: 8 : if ((unsigned int) (t->day - 1) >= month_days || /* (1 - days in month) */
588 : : /* (unsigned int) (t->mon - 1) >= 12 || */ /* (1 - 12) checked above */
589 [ + - ]: 8 : (unsigned int) t->year > 9999 || /* (0 - 9999) */
590 [ + - ]: 8 : (unsigned int) t->hour > 23 || /* (0 - 23) */
591 [ + - ]: 8 : (unsigned int) t->min > 59 || /* (0 - 59) */
592 [ - + ]: 8 : (unsigned int) t->sec > 59) { /* (0 - 59) */
593 : 0 : return MBEDTLS_ERR_X509_INVALID_DATE;
594 : : }
595 : :
596 : : return 0;
597 : : }
598 : :
599 : 48 : static int x509_parse2_int(const unsigned char *p)
600 : : {
601 : 48 : uint32_t d1 = p[0] - '0';
602 : 48 : uint32_t d2 = p[1] - '0';
603 [ + - ]: 48 : return (d1 < 10 && d2 < 10) ? (int) (d1 * 10 + d2) : -1;
604 : : }
605 : :
606 : : /*
607 : : * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4)
608 : : * field.
609 : : */
610 : 8 : static int x509_parse_time(const unsigned char *p, mbedtls_x509_time *tm,
611 : : size_t yearlen)
612 : : {
613 : 8 : int x;
614 : :
615 : : /*
616 : : * Parse year, month, day, hour, minute, second
617 : : */
618 : 8 : tm->year = x509_parse2_int(p);
619 [ - + ]: 8 : if (tm->year < 0) {
620 : : return MBEDTLS_ERR_X509_INVALID_DATE;
621 : : }
622 : :
623 [ - + ]: 8 : if (4 == yearlen) {
624 : 0 : x = tm->year * 100;
625 : 0 : p += 2;
626 : 0 : tm->year = x509_parse2_int(p);
627 [ # # ]: 0 : if (tm->year < 0) {
628 : : return MBEDTLS_ERR_X509_INVALID_DATE;
629 : : }
630 : : } else {
631 [ - + ]: 8 : x = (tm->year < 50) ? 2000 : 1900;
632 : : }
633 : 8 : tm->year += x;
634 : :
635 : 8 : tm->mon = x509_parse2_int(p + 2);
636 : 8 : tm->day = x509_parse2_int(p + 4);
637 : 8 : tm->hour = x509_parse2_int(p + 6);
638 : 8 : tm->min = x509_parse2_int(p + 8);
639 : 8 : tm->sec = x509_parse2_int(p + 10);
640 : :
641 : 8 : return x509_date_is_valid(tm);
642 : : }
643 : :
644 : : /*
645 : : * Time ::= CHOICE {
646 : : * utcTime UTCTime,
647 : : * generalTime GeneralizedTime }
648 : : */
649 : 8 : int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end,
650 : : mbedtls_x509_time *tm)
651 : : {
652 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
653 : 8 : size_t len, year_len;
654 : 8 : unsigned char tag;
655 : :
656 [ - + ]: 8 : if ((end - *p) < 1) {
657 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
658 : : MBEDTLS_ERR_ASN1_OUT_OF_DATA);
659 : : }
660 : :
661 : 8 : tag = **p;
662 : :
663 [ - + ]: 8 : if (tag == MBEDTLS_ASN1_UTC_TIME) {
664 : : year_len = 2;
665 [ # # ]: 0 : } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) {
666 : : year_len = 4;
667 : : } else {
668 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE,
669 : : MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
670 : : }
671 : :
672 : 8 : (*p)++;
673 : 8 : ret = mbedtls_asn1_get_len(p, end, &len);
674 : :
675 [ - + ]: 8 : if (ret != 0) {
676 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret);
677 : : }
678 : :
679 : : /* len is 12 or 14 depending on year_len, plus optional trailing 'Z' */
680 [ + - ]: 8 : if (len != year_len + 10 &&
681 [ + - + - ]: 8 : !(len == year_len + 11 && (*p)[(len - 1)] == 'Z')) {
682 : : return MBEDTLS_ERR_X509_INVALID_DATE;
683 : : }
684 : :
685 : 8 : (*p) += len;
686 : 8 : return x509_parse_time(*p - len, tm, year_len);
687 : : }
688 : :
689 : 4 : int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig)
690 : : {
691 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
692 : 4 : size_t len;
693 : 4 : int tag_type;
694 : :
695 [ - + ]: 4 : if ((end - *p) < 1) {
696 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE,
697 : : MBEDTLS_ERR_ASN1_OUT_OF_DATA);
698 : : }
699 : :
700 : 4 : tag_type = **p;
701 : :
702 [ - + ]: 4 : if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) {
703 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret);
704 : : }
705 : :
706 : 4 : sig->tag = tag_type;
707 : 4 : sig->len = len;
708 : 4 : sig->p = *p;
709 : :
710 : 4 : *p += len;
711 : :
712 : 4 : return 0;
713 : : }
714 : :
715 : : /*
716 : : * Get signature algorithm from alg OID and optional parameters
717 : : */
718 : 4 : int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params,
719 : : mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg,
720 : : void **sig_opts)
721 : : {
722 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
723 : :
724 [ + - ]: 4 : if (*sig_opts != NULL) {
725 : : return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
726 : : }
727 : :
728 [ - + ]: 4 : if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) {
729 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret);
730 : : }
731 : :
732 : : #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
733 : : if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) {
734 : : mbedtls_pk_rsassa_pss_options *pss_opts;
735 : :
736 : : pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options));
737 : : if (pss_opts == NULL) {
738 : : return MBEDTLS_ERR_X509_ALLOC_FAILED;
739 : : }
740 : :
741 : : ret = mbedtls_x509_get_rsassa_pss_params(sig_params,
742 : : md_alg,
743 : : &pss_opts->mgf1_hash_id,
744 : : &pss_opts->expected_salt_len);
745 : : if (ret != 0) {
746 : : mbedtls_free(pss_opts);
747 : : return ret;
748 : : }
749 : :
750 : : *sig_opts = (void *) pss_opts;
751 : : } else
752 : : #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
753 : : {
754 : : /* Make sure parameters are absent or NULL */
755 [ + - ]: 4 : if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) ||
756 [ - + ]: 4 : sig_params->len != 0) {
757 : 0 : return MBEDTLS_ERR_X509_INVALID_ALG;
758 : : }
759 : : }
760 : :
761 : : return 0;
762 : : }
763 : :
764 : : /*
765 : : * X.509 Extensions (No parsing of extensions, pointer should
766 : : * be either manually updated or extensions should be parsed!)
767 : : */
768 : 0 : int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end,
769 : : mbedtls_x509_buf *ext, int tag)
770 : : {
771 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
772 : 0 : size_t len;
773 : :
774 : : /* Extension structure use EXPLICIT tagging. That is, the actual
775 : : * `Extensions` structure is wrapped by a tag-length pair using
776 : : * the respective context-specific tag. */
777 : 0 : ret = mbedtls_asn1_get_tag(p, end, &ext->len,
778 : : MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag);
779 [ # # ]: 0 : if (ret != 0) {
780 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
781 : : }
782 : :
783 : 0 : ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag;
784 : 0 : ext->p = *p;
785 : 0 : end = *p + ext->len;
786 : :
787 : : /*
788 : : * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
789 : : */
790 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(p, end, &len,
791 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
792 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
793 : : }
794 : :
795 [ # # ]: 0 : if (end != *p + len) {
796 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
797 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
798 : : }
799 : :
800 : : return 0;
801 : : }
802 : :
803 : 0 : static char nibble_to_hex_digit(int i)
804 : : {
805 [ # # ]: 0 : return (i < 10) ? (i + '0') : (i - 10 + 'A');
806 : : }
807 : :
808 : : /*
809 : : * Store the name in printable form into buf; no more
810 : : * than size characters will be written
811 : : */
812 : 0 : int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn)
813 : : {
814 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
815 : 0 : size_t i, j, n, asn1_len_size, asn1_tag_size, asn1_tag_len_buf_start;
816 : : /* 6 is enough as our asn1 write functions only write one byte for the tag and at most five bytes for the length*/
817 : 0 : unsigned char asn1_tag_len_buf[6];
818 : 0 : unsigned char *asn1_len_p;
819 : 0 : unsigned char c, merge = 0;
820 : 0 : const mbedtls_x509_name *name;
821 : 0 : const char *short_name = NULL;
822 : 0 : char lowbits, highbits;
823 : 0 : char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p;
824 : 0 : int print_hexstring;
825 : :
826 : 0 : memset(s, 0, sizeof(s));
827 : :
828 : 0 : name = dn;
829 : 0 : p = buf;
830 : 0 : n = size;
831 : :
832 [ # # ]: 0 : while (name != NULL) {
833 [ # # ]: 0 : if (!name->oid.p) {
834 : 0 : name = name->next;
835 : 0 : continue;
836 : : }
837 : :
838 [ # # ]: 0 : if (name != dn) {
839 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, merge ? " + " : ", ");
840 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
841 : : }
842 : :
843 : 0 : print_hexstring = (name->val.tag != MBEDTLS_ASN1_UTF8_STRING) &&
844 [ # # # # ]: 0 : (name->val.tag != MBEDTLS_ASN1_PRINTABLE_STRING) &&
845 : : (name->val.tag != MBEDTLS_ASN1_IA5_STRING);
846 : :
847 [ # # ]: 0 : if ((ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name)) == 0) {
848 : 0 : ret = mbedtls_snprintf(p, n, "%s=", short_name);
849 : : } else {
850 [ # # ]: 0 : if ((ret = mbedtls_oid_get_numeric_string(p, n, &name->oid)) > 0) {
851 : 0 : n -= ret;
852 : 0 : p += ret;
853 : 0 : ret = mbedtls_snprintf(p, n, "=");
854 : 0 : print_hexstring = 1;
855 [ # # ]: 0 : } else if (ret == MBEDTLS_ERR_OID_BUF_TOO_SMALL) {
856 : : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
857 : : } else {
858 : 0 : ret = mbedtls_snprintf(p, n, "\?\?=");
859 : : }
860 : : }
861 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
862 : :
863 [ # # ]: 0 : if (print_hexstring) {
864 : 0 : s[0] = '#';
865 : :
866 : 0 : asn1_len_p = asn1_tag_len_buf + sizeof(asn1_tag_len_buf);
867 [ # # ]: 0 : if ((ret = mbedtls_asn1_write_len(&asn1_len_p, asn1_tag_len_buf, name->val.len)) < 0) {
868 : : return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
869 : : }
870 : 0 : asn1_len_size = ret;
871 [ # # ]: 0 : if ((ret = mbedtls_asn1_write_tag(&asn1_len_p, asn1_tag_len_buf, name->val.tag)) < 0) {
872 : : return MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
873 : : }
874 : 0 : asn1_tag_size = ret;
875 : 0 : asn1_tag_len_buf_start = sizeof(asn1_tag_len_buf) - asn1_len_size - asn1_tag_size;
876 [ # # ]: 0 : for (i = 0, j = 1; i < asn1_len_size + asn1_tag_size; i++) {
877 : 0 : if (j + 1 >= sizeof(s) - 1) {
878 : : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
879 : : }
880 : 0 : c = asn1_tag_len_buf[asn1_tag_len_buf_start+i];
881 : 0 : lowbits = (c & 0x0F);
882 : 0 : highbits = c >> 4;
883 : 0 : s[j++] = nibble_to_hex_digit(highbits);
884 : 0 : s[j++] = nibble_to_hex_digit(lowbits);
885 : : }
886 [ # # ]: 0 : for (i = 0; i < name->val.len; i++) {
887 [ # # ]: 0 : if (j + 1 >= sizeof(s) - 1) {
888 : : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
889 : : }
890 : 0 : c = name->val.p[i];
891 : 0 : lowbits = (c & 0x0F);
892 : 0 : highbits = c >> 4;
893 : 0 : s[j++] = nibble_to_hex_digit(highbits);
894 : 0 : s[j++] = nibble_to_hex_digit(lowbits);
895 : : }
896 : : } else {
897 [ # # ]: 0 : for (i = 0, j = 0; i < name->val.len; i++, j++) {
898 [ # # ]: 0 : if (j >= sizeof(s) - 1) {
899 : : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
900 : : }
901 : :
902 : 0 : c = name->val.p[i];
903 : : // Special characters requiring escaping, RFC 4514 Section 2.4
904 [ # # ]: 0 : if (c == '\0') {
905 : : return MBEDTLS_ERR_X509_INVALID_NAME;
906 : : } else {
907 [ # # # # ]: 0 : if (strchr(",=+<>;\"\\", c) ||
908 [ # # ]: 0 : ((i == 0) && strchr("# ", c)) ||
909 [ # # # # ]: 0 : ((i == name->val.len-1) && (c == ' '))) {
910 [ # # ]: 0 : if (j + 1 >= sizeof(s) - 1) {
911 : : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
912 : : }
913 : 0 : s[j++] = '\\';
914 : : }
915 : : }
916 [ # # ]: 0 : if (c < 32 || c >= 127) {
917 [ # # ]: 0 : if (j + 3 >= sizeof(s) - 1) {
918 : : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
919 : : }
920 : 0 : s[j++] = '\\';
921 : 0 : lowbits = (c & 0x0F);
922 : 0 : highbits = c >> 4;
923 : 0 : s[j++] = nibble_to_hex_digit(highbits);
924 : 0 : s[j] = nibble_to_hex_digit(lowbits);
925 : : } else {
926 : 0 : s[j] = c;
927 : : }
928 : : }
929 : : }
930 : 0 : s[j] = '\0';
931 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "%s", s);
932 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
933 : :
934 : 0 : merge = name->next_merged;
935 : 0 : name = name->next;
936 : : }
937 : :
938 : 0 : return (int) (size - n);
939 : : }
940 : :
941 : : /*
942 : : * Store the serial in printable form into buf; no more
943 : : * than size characters will be written
944 : : */
945 : 0 : int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial)
946 : : {
947 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
948 : 0 : size_t i, n, nr;
949 : 0 : char *p;
950 : :
951 : 0 : p = buf;
952 : 0 : n = size;
953 : :
954 : 0 : nr = (serial->len <= 32)
955 [ # # ]: 0 : ? serial->len : 28;
956 : :
957 [ # # ]: 0 : for (i = 0; i < nr; i++) {
958 [ # # # # ]: 0 : if (i == 0 && nr > 1 && serial->p[i] == 0x0) {
959 : 0 : continue;
960 : : }
961 : :
962 : 0 : ret = mbedtls_snprintf(p, n, "%02X%s",
963 [ # # # # ]: 0 : serial->p[i], (i < nr - 1) ? ":" : "");
964 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
965 : : }
966 : :
967 [ # # ]: 0 : if (nr != serial->len) {
968 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "....");
969 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
970 : : }
971 : :
972 : 0 : return (int) (size - n);
973 : : }
974 : :
975 : : #if !defined(MBEDTLS_X509_REMOVE_INFO)
976 : : /*
977 : : * Helper for writing signature algorithms
978 : : */
979 : 0 : int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid,
980 : : mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg,
981 : : const void *sig_opts)
982 : : {
983 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
984 : 0 : char *p = buf;
985 : 0 : size_t n = size;
986 : 0 : const char *desc = NULL;
987 : :
988 : 0 : ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc);
989 [ # # ]: 0 : if (ret != 0) {
990 : 0 : ret = mbedtls_snprintf(p, n, "???");
991 : : } else {
992 : 0 : ret = mbedtls_snprintf(p, n, "%s", desc);
993 : : }
994 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
995 : :
996 : : #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT)
997 : : if (pk_alg == MBEDTLS_PK_RSASSA_PSS) {
998 : : const mbedtls_pk_rsassa_pss_options *pss_opts;
999 : :
1000 : : pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts;
1001 : :
1002 : : const char *name = md_type_to_string(md_alg);
1003 : : const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id);
1004 : :
1005 : : ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)",
1006 : : name ? name : "???",
1007 : : mgf_name ? mgf_name : "???",
1008 : : (unsigned int) pss_opts->expected_salt_len);
1009 : : MBEDTLS_X509_SAFE_SNPRINTF;
1010 : : }
1011 : : #else
1012 : 0 : ((void) pk_alg);
1013 : 0 : ((void) md_alg);
1014 : 0 : ((void) sig_opts);
1015 : : #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */
1016 : :
1017 : 0 : return (int) (size - n);
1018 : : }
1019 : : #endif /* MBEDTLS_X509_REMOVE_INFO */
1020 : :
1021 : : /*
1022 : : * Helper for writing "RSA key size", "EC key size", etc
1023 : : */
1024 : 0 : int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name)
1025 : : {
1026 : 0 : char *p = buf;
1027 : 0 : size_t n = buf_size;
1028 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1029 : :
1030 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "%s key size", name);
1031 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1032 : :
1033 : 0 : return 0;
1034 : : }
1035 : :
1036 : 0 : int mbedtls_x509_time_cmp(const mbedtls_x509_time *t1,
1037 : : const mbedtls_x509_time *t2)
1038 : : {
1039 : 0 : int x;
1040 : :
1041 : 0 : x = (((t1->year << 9) | (t1->mon << 5) | (t1->day)) -
1042 : 0 : ((t2->year << 9) | (t2->mon << 5) | (t2->day)));
1043 [ # # ]: 0 : if (x != 0) {
1044 : : return x;
1045 : : }
1046 : :
1047 : 0 : x = (((t1->hour << 12) | (t1->min << 6) | (t1->sec)) -
1048 : 0 : ((t2->hour << 12) | (t2->min << 6) | (t2->sec)));
1049 : 0 : return x;
1050 : : }
1051 : :
1052 : : #if defined(MBEDTLS_HAVE_TIME_DATE)
1053 : : int mbedtls_x509_time_gmtime(mbedtls_time_t tt, mbedtls_x509_time *now)
1054 : : {
1055 : : struct tm tm;
1056 : :
1057 : : if (mbedtls_platform_gmtime_r(&tt, &tm) == NULL) {
1058 : : return -1;
1059 : : }
1060 : :
1061 : : now->year = tm.tm_year + 1900;
1062 : : now->mon = tm.tm_mon + 1;
1063 : : now->day = tm.tm_mday;
1064 : : now->hour = tm.tm_hour;
1065 : : now->min = tm.tm_min;
1066 : : now->sec = tm.tm_sec;
1067 : : return 0;
1068 : : }
1069 : :
1070 : : static int x509_get_current_time(mbedtls_x509_time *now)
1071 : : {
1072 : : return mbedtls_x509_time_gmtime(mbedtls_time(NULL), now);
1073 : : }
1074 : :
1075 : : int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
1076 : : {
1077 : : mbedtls_x509_time now;
1078 : :
1079 : : if (x509_get_current_time(&now) != 0) {
1080 : : return 1;
1081 : : }
1082 : :
1083 : : return mbedtls_x509_time_cmp(to, &now) < 0;
1084 : : }
1085 : :
1086 : : int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
1087 : : {
1088 : : mbedtls_x509_time now;
1089 : :
1090 : : if (x509_get_current_time(&now) != 0) {
1091 : : return 1;
1092 : : }
1093 : :
1094 : : return mbedtls_x509_time_cmp(from, &now) > 0;
1095 : : }
1096 : :
1097 : : #else /* MBEDTLS_HAVE_TIME_DATE */
1098 : :
1099 : 0 : int mbedtls_x509_time_is_past(const mbedtls_x509_time *to)
1100 : : {
1101 : 0 : ((void) to);
1102 : 0 : return 0;
1103 : : }
1104 : :
1105 : 0 : int mbedtls_x509_time_is_future(const mbedtls_x509_time *from)
1106 : : {
1107 : 0 : ((void) from);
1108 : 0 : return 0;
1109 : : }
1110 : : #endif /* MBEDTLS_HAVE_TIME_DATE */
1111 : :
1112 : : /* Common functions for parsing CRT and CSR. */
1113 : : #if defined(MBEDTLS_X509_CRT_PARSE_C) || defined(MBEDTLS_X509_CSR_PARSE_C)
1114 : : /*
1115 : : * OtherName ::= SEQUENCE {
1116 : : * type-id OBJECT IDENTIFIER,
1117 : : * value [0] EXPLICIT ANY DEFINED BY type-id }
1118 : : *
1119 : : * HardwareModuleName ::= SEQUENCE {
1120 : : * hwType OBJECT IDENTIFIER,
1121 : : * hwSerialNum OCTET STRING }
1122 : : *
1123 : : * NOTE: we currently only parse and use otherName of type HwModuleName,
1124 : : * as defined in RFC 4108.
1125 : : */
1126 : 0 : static int x509_get_other_name(const mbedtls_x509_buf *subject_alt_name,
1127 : : mbedtls_x509_san_other_name *other_name)
1128 : : {
1129 : 0 : int ret = 0;
1130 : 0 : size_t len;
1131 : 0 : unsigned char *p = subject_alt_name->p;
1132 : 0 : const unsigned char *end = p + subject_alt_name->len;
1133 : 0 : mbedtls_x509_buf cur_oid;
1134 : :
1135 [ # # ]: 0 : if ((subject_alt_name->tag &
1136 : : (MBEDTLS_ASN1_TAG_CLASS_MASK | MBEDTLS_ASN1_TAG_VALUE_MASK)) !=
1137 : : (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME)) {
1138 : : /*
1139 : : * The given subject alternative name is not of type "othername".
1140 : : */
1141 : : return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1142 : : }
1143 : :
1144 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1145 : : MBEDTLS_ASN1_OID)) != 0) {
1146 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1147 : : }
1148 : :
1149 : 0 : cur_oid.tag = MBEDTLS_ASN1_OID;
1150 : 0 : cur_oid.p = p;
1151 : 0 : cur_oid.len = len;
1152 : :
1153 : : /*
1154 : : * Only HwModuleName is currently supported.
1155 : : */
1156 [ # # # # ]: 0 : if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME, &cur_oid) != 0) {
1157 : : return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1158 : : }
1159 : 0 : other_name->type_id = cur_oid;
1160 : :
1161 : 0 : p += len;
1162 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1163 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC)) !=
1164 : : 0) {
1165 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1166 : : }
1167 : :
1168 [ # # ]: 0 : if (end != p + len) {
1169 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1170 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1171 : : }
1172 : :
1173 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1174 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1175 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1176 : : }
1177 : :
1178 [ # # ]: 0 : if (end != p + len) {
1179 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1180 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1181 : : }
1182 : :
1183 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
1184 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1185 : : }
1186 : :
1187 : 0 : other_name->value.hardware_module_name.oid.tag = MBEDTLS_ASN1_OID;
1188 : 0 : other_name->value.hardware_module_name.oid.p = p;
1189 : 0 : other_name->value.hardware_module_name.oid.len = len;
1190 : :
1191 : 0 : p += len;
1192 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
1193 : : MBEDTLS_ASN1_OCTET_STRING)) != 0) {
1194 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1195 : : }
1196 : :
1197 : 0 : other_name->value.hardware_module_name.val.tag = MBEDTLS_ASN1_OCTET_STRING;
1198 : 0 : other_name->value.hardware_module_name.val.p = p;
1199 : 0 : other_name->value.hardware_module_name.val.len = len;
1200 : 0 : p += len;
1201 [ # # ]: 0 : if (p != end) {
1202 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1203 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1204 : : }
1205 : : return 0;
1206 : : }
1207 : :
1208 : : /* Check mbedtls_x509_get_subject_alt_name for detailed description.
1209 : : *
1210 : : * In some cases while parsing subject alternative names the sequence tag is optional
1211 : : * (e.g. CertSerialNumber). This function is designed to handle such case.
1212 : : */
1213 : 0 : int mbedtls_x509_get_subject_alt_name_ext(unsigned char **p,
1214 : : const unsigned char *end,
1215 : : mbedtls_x509_sequence *subject_alt_name)
1216 : : {
1217 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1218 : 0 : size_t tag_len;
1219 : 0 : mbedtls_asn1_sequence *cur = subject_alt_name;
1220 : :
1221 [ # # ]: 0 : while (*p < end) {
1222 : 0 : mbedtls_x509_subject_alternative_name tmp_san_name;
1223 : 0 : mbedtls_x509_buf tmp_san_buf;
1224 : 0 : memset(&tmp_san_name, 0, sizeof(tmp_san_name));
1225 : :
1226 : 0 : tmp_san_buf.tag = **p;
1227 : 0 : (*p)++;
1228 : :
1229 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_len(p, end, &tag_len)) != 0) {
1230 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1231 : : }
1232 : :
1233 : 0 : tmp_san_buf.p = *p;
1234 : 0 : tmp_san_buf.len = tag_len;
1235 : :
1236 [ # # ]: 0 : if ((tmp_san_buf.tag & MBEDTLS_ASN1_TAG_CLASS_MASK) !=
1237 : : MBEDTLS_ASN1_CONTEXT_SPECIFIC) {
1238 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1239 : : MBEDTLS_ERR_ASN1_UNEXPECTED_TAG);
1240 : : }
1241 : :
1242 : : /*
1243 : : * Check that the SAN is structured correctly by parsing it.
1244 : : * The SAN structure is discarded afterwards.
1245 : : */
1246 : 0 : ret = mbedtls_x509_parse_subject_alt_name(&tmp_san_buf, &tmp_san_name);
1247 : : /*
1248 : : * In case the extension is malformed, return an error,
1249 : : * and clear the allocated sequences.
1250 : : */
1251 [ # # ]: 0 : if (ret != 0 && ret != MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1252 : 0 : mbedtls_asn1_sequence_free(subject_alt_name->next);
1253 : 0 : subject_alt_name->next = NULL;
1254 : 0 : return ret;
1255 : : }
1256 : :
1257 : 0 : mbedtls_x509_free_subject_alt_name(&tmp_san_name);
1258 : : /* Allocate and assign next pointer */
1259 [ # # ]: 0 : if (cur->buf.p != NULL) {
1260 [ # # ]: 0 : if (cur->next != NULL) {
1261 : : return MBEDTLS_ERR_X509_INVALID_EXTENSIONS;
1262 : : }
1263 : :
1264 : 0 : cur->next = mbedtls_calloc(1, sizeof(mbedtls_asn1_sequence));
1265 : :
1266 [ # # ]: 0 : if (cur->next == NULL) {
1267 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1268 : : MBEDTLS_ERR_ASN1_ALLOC_FAILED);
1269 : : }
1270 : :
1271 : : cur = cur->next;
1272 : : }
1273 : :
1274 : 0 : cur->buf = tmp_san_buf;
1275 : 0 : *p += tmp_san_buf.len;
1276 : : }
1277 : :
1278 : : /* Set final sequence entry's next pointer to NULL */
1279 : 0 : cur->next = NULL;
1280 : :
1281 [ # # ]: 0 : if (*p != end) {
1282 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1283 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1284 : : }
1285 : :
1286 : : return 0;
1287 : : }
1288 : :
1289 : : /*
1290 : : * SubjectAltName ::= GeneralNames
1291 : : *
1292 : : * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
1293 : : *
1294 : : * GeneralName ::= CHOICE {
1295 : : * otherName [0] OtherName,
1296 : : * rfc822Name [1] IA5String,
1297 : : * dNSName [2] IA5String,
1298 : : * x400Address [3] ORAddress,
1299 : : * directoryName [4] Name,
1300 : : * ediPartyName [5] EDIPartyName,
1301 : : * uniformResourceIdentifier [6] IA5String,
1302 : : * iPAddress [7] OCTET STRING,
1303 : : * registeredID [8] OBJECT IDENTIFIER }
1304 : : *
1305 : : * OtherName ::= SEQUENCE {
1306 : : * type-id OBJECT IDENTIFIER,
1307 : : * value [0] EXPLICIT ANY DEFINED BY type-id }
1308 : : *
1309 : : * EDIPartyName ::= SEQUENCE {
1310 : : * nameAssigner [0] DirectoryString OPTIONAL,
1311 : : * partyName [1] DirectoryString }
1312 : : *
1313 : : * We list all types, but use the following GeneralName types from RFC 5280:
1314 : : * "dnsName", "uniformResourceIdentifier" and "hardware_module_name"
1315 : : * of type "otherName", as defined in RFC 4108.
1316 : : */
1317 : 0 : int mbedtls_x509_get_subject_alt_name(unsigned char **p,
1318 : : const unsigned char *end,
1319 : : mbedtls_x509_sequence *subject_alt_name)
1320 : : {
1321 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1322 : 0 : size_t len;
1323 : :
1324 : : /* Get main sequence tag */
1325 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_tag(p, end, &len,
1326 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
1327 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1328 : : }
1329 : :
1330 [ # # ]: 0 : if (*p + len != end) {
1331 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1332 : : MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
1333 : : }
1334 : :
1335 : 0 : return mbedtls_x509_get_subject_alt_name_ext(p, end, subject_alt_name);
1336 : : }
1337 : :
1338 : 0 : int mbedtls_x509_get_ns_cert_type(unsigned char **p,
1339 : : const unsigned char *end,
1340 : : unsigned char *ns_cert_type)
1341 : : {
1342 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1343 : 0 : mbedtls_x509_bitstring bs = { 0, 0, NULL };
1344 : :
1345 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
1346 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1347 : : }
1348 : :
1349 : : /* A bitstring with no flags set is still technically valid, as it will mean
1350 : : that the certificate has no designated purpose at the time of creation. */
1351 [ # # ]: 0 : if (bs.len == 0) {
1352 : 0 : *ns_cert_type = 0;
1353 : 0 : return 0;
1354 : : }
1355 : :
1356 [ # # ]: 0 : if (bs.len != 1) {
1357 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS,
1358 : : MBEDTLS_ERR_ASN1_INVALID_LENGTH);
1359 : : }
1360 : :
1361 : : /* Get actual bitstring */
1362 : 0 : *ns_cert_type = *bs.p;
1363 : 0 : return 0;
1364 : : }
1365 : :
1366 : 0 : int mbedtls_x509_get_key_usage(unsigned char **p,
1367 : : const unsigned char *end,
1368 : : unsigned int *key_usage)
1369 : : {
1370 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1371 : 0 : size_t i;
1372 : 0 : mbedtls_x509_bitstring bs = { 0, 0, NULL };
1373 : :
1374 [ # # ]: 0 : if ((ret = mbedtls_asn1_get_bitstring(p, end, &bs)) != 0) {
1375 : 0 : return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret);
1376 : : }
1377 : :
1378 : : /* A bitstring with no flags set is still technically valid, as it will mean
1379 : : that the certificate has no designated purpose at the time of creation. */
1380 [ # # ]: 0 : if (bs.len == 0) {
1381 : 0 : *key_usage = 0;
1382 : 0 : return 0;
1383 : : }
1384 : :
1385 : : /* Get actual bitstring */
1386 : 0 : *key_usage = 0;
1387 [ # # # # ]: 0 : for (i = 0; i < bs.len && i < sizeof(unsigned int); i++) {
1388 : 0 : *key_usage |= (unsigned int) bs.p[i] << (8*i);
1389 : : }
1390 : :
1391 : : return 0;
1392 : : }
1393 : :
1394 : 0 : int mbedtls_x509_parse_subject_alt_name(const mbedtls_x509_buf *san_buf,
1395 : : mbedtls_x509_subject_alternative_name *san)
1396 : : {
1397 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1398 [ # # # # : 0 : switch (san_buf->tag &
# # # ]
1399 : : (MBEDTLS_ASN1_TAG_CLASS_MASK |
1400 : : MBEDTLS_ASN1_TAG_VALUE_MASK)) {
1401 : : /*
1402 : : * otherName
1403 : : */
1404 : 0 : case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_OTHER_NAME):
1405 : : {
1406 : 0 : mbedtls_x509_san_other_name other_name;
1407 : :
1408 : 0 : ret = x509_get_other_name(san_buf, &other_name);
1409 [ # # ]: 0 : if (ret != 0) {
1410 : 0 : return ret;
1411 : : }
1412 : :
1413 : 0 : memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1414 : 0 : san->type = MBEDTLS_X509_SAN_OTHER_NAME;
1415 : 0 : memcpy(&san->san.other_name,
1416 : : &other_name, sizeof(other_name));
1417 : :
1418 : : }
1419 : 0 : break;
1420 : : /*
1421 : : * uniformResourceIdentifier
1422 : : */
1423 : : case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER):
1424 : : {
1425 : 0 : memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1426 : 0 : san->type = MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER;
1427 : :
1428 : 0 : memcpy(&san->san.unstructured_name,
1429 : : san_buf, sizeof(*san_buf));
1430 : :
1431 : : }
1432 : 0 : break;
1433 : : /*
1434 : : * dNSName
1435 : : */
1436 : : case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DNS_NAME):
1437 : : {
1438 : 0 : memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1439 : 0 : san->type = MBEDTLS_X509_SAN_DNS_NAME;
1440 : :
1441 : 0 : memcpy(&san->san.unstructured_name,
1442 : : san_buf, sizeof(*san_buf));
1443 : : }
1444 : 0 : break;
1445 : : /*
1446 : : * IP address
1447 : : */
1448 : : case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_IP_ADDRESS):
1449 : : {
1450 [ # # ]: 0 : memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1451 : 0 : san->type = MBEDTLS_X509_SAN_IP_ADDRESS;
1452 : : // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
1453 [ # # ]: 0 : if (san_buf->len == 4 || san_buf->len == 16) {
1454 : 0 : memcpy(&san->san.unstructured_name,
1455 : : san_buf, sizeof(*san_buf));
1456 : : } else {
1457 : : return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1458 : : }
1459 : : }
1460 : 0 : break;
1461 : : /*
1462 : : * rfc822Name
1463 : : */
1464 : : case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_RFC822_NAME):
1465 : : {
1466 : 0 : memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1467 : 0 : san->type = MBEDTLS_X509_SAN_RFC822_NAME;
1468 : 0 : memcpy(&san->san.unstructured_name, san_buf, sizeof(*san_buf));
1469 : : }
1470 : 0 : break;
1471 : : /*
1472 : : * directoryName
1473 : : */
1474 : 0 : case (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_X509_SAN_DIRECTORY_NAME):
1475 : : {
1476 : 0 : size_t name_len;
1477 : 0 : unsigned char *p = san_buf->p;
1478 : 0 : memset(san, 0, sizeof(mbedtls_x509_subject_alternative_name));
1479 : 0 : san->type = MBEDTLS_X509_SAN_DIRECTORY_NAME;
1480 : :
1481 : 0 : ret = mbedtls_asn1_get_tag(&p, p + san_buf->len, &name_len,
1482 : : MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
1483 : :
1484 [ # # ]: 0 : if (ret != 0) {
1485 : 0 : return ret;
1486 : : }
1487 : :
1488 [ # # ]: 0 : if ((ret = mbedtls_x509_get_name(&p, p + name_len,
1489 : : &san->san.directory_name)) != 0) {
1490 : : return ret;
1491 : : }
1492 : : }
1493 : 0 : break;
1494 : : /*
1495 : : * Type not supported
1496 : : */
1497 : : default:
1498 : : return MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
1499 : : }
1500 : : return 0;
1501 : : }
1502 : :
1503 : 0 : void mbedtls_x509_free_subject_alt_name(mbedtls_x509_subject_alternative_name *san)
1504 : : {
1505 [ # # ]: 0 : if (san->type == MBEDTLS_X509_SAN_DIRECTORY_NAME) {
1506 : 0 : mbedtls_asn1_free_named_data_list_shallow(san->san.directory_name.next);
1507 : : }
1508 : 0 : }
1509 : :
1510 : : #if !defined(MBEDTLS_X509_REMOVE_INFO)
1511 : 0 : int mbedtls_x509_info_subject_alt_name(char **buf, size_t *size,
1512 : : const mbedtls_x509_sequence
1513 : : *subject_alt_name,
1514 : : const char *prefix)
1515 : : {
1516 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1517 : 0 : size_t i;
1518 : 0 : size_t n = *size;
1519 : 0 : char *p = *buf;
1520 : 0 : const mbedtls_x509_sequence *cur = subject_alt_name;
1521 : 0 : mbedtls_x509_subject_alternative_name san;
1522 : 0 : int parse_ret;
1523 : :
1524 [ # # ]: 0 : while (cur != NULL) {
1525 : 0 : memset(&san, 0, sizeof(san));
1526 : 0 : parse_ret = mbedtls_x509_parse_subject_alt_name(&cur->buf, &san);
1527 [ # # ]: 0 : if (parse_ret != 0) {
1528 [ # # ]: 0 : if (parse_ret == MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) {
1529 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix);
1530 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1531 : : } else {
1532 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "\n%s <malformed>", prefix);
1533 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1534 : : }
1535 : 0 : cur = cur->next;
1536 : 0 : continue;
1537 : : }
1538 : :
1539 [ # # # # : 0 : switch (san.type) {
# # ]
1540 : : /*
1541 : : * otherName
1542 : : */
1543 : 0 : case MBEDTLS_X509_SAN_OTHER_NAME:
1544 : : {
1545 : 0 : mbedtls_x509_san_other_name *other_name = &san.san.other_name;
1546 : :
1547 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "\n%s otherName :", prefix);
1548 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1549 : :
1550 [ # # # # ]: 0 : if (MBEDTLS_OID_CMP(MBEDTLS_OID_ON_HW_MODULE_NAME,
1551 : : &other_name->type_id) == 0) {
1552 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "\n%s hardware module name :", prefix);
1553 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1554 [ # # ]: 0 : ret =
1555 : 0 : mbedtls_snprintf(p, n, "\n%s hardware type : ", prefix);
1556 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1557 : :
1558 : 0 : ret = mbedtls_oid_get_numeric_string(p,
1559 : : n,
1560 : : &other_name->value.hardware_module_name.oid);
1561 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1562 : :
1563 [ # # ]: 0 : ret =
1564 : 0 : mbedtls_snprintf(p, n, "\n%s hardware serial number : ", prefix);
1565 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1566 : :
1567 [ # # ]: 0 : for (i = 0; i < other_name->value.hardware_module_name.val.len; i++) {
1568 : 0 : ret = mbedtls_snprintf(p,
1569 : : n,
1570 : : "%02X",
1571 [ # # ]: 0 : other_name->value.hardware_module_name.val.p[i]);
1572 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1573 : : }
1574 : : }/* MBEDTLS_OID_ON_HW_MODULE_NAME */
1575 : : }
1576 : : break;
1577 : : /*
1578 : : * uniformResourceIdentifier
1579 : : */
1580 : : case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER:
1581 : : {
1582 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "\n%s uniformResourceIdentifier : ", prefix);
1583 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1584 [ # # ]: 0 : if (san.san.unstructured_name.len >= n) {
1585 : 0 : if (n > 0) {
1586 : 0 : *p = '\0';
1587 : : }
1588 : 0 : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1589 : : }
1590 : :
1591 : 0 : memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
1592 : 0 : p += san.san.unstructured_name.len;
1593 : 0 : n -= san.san.unstructured_name.len;
1594 : : }
1595 : 0 : break;
1596 : : /*
1597 : : * dNSName
1598 : : * RFC822 Name
1599 : : */
1600 : 0 : case MBEDTLS_X509_SAN_DNS_NAME:
1601 : : case MBEDTLS_X509_SAN_RFC822_NAME:
1602 : : {
1603 : 0 : const char *dns_name = "dNSName";
1604 : 0 : const char *rfc822_name = "rfc822Name";
1605 : :
1606 [ # # ]: 0 : ret = mbedtls_snprintf(p, n,
1607 : : "\n%s %s : ",
1608 : : prefix,
1609 : : san.type ==
1610 : : MBEDTLS_X509_SAN_DNS_NAME ? dns_name : rfc822_name);
1611 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1612 [ # # ]: 0 : if (san.san.unstructured_name.len >= n) {
1613 : 0 : if (n > 0) {
1614 : 0 : *p = '\0';
1615 : : }
1616 : 0 : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1617 : : }
1618 : :
1619 : 0 : memcpy(p, san.san.unstructured_name.p, san.san.unstructured_name.len);
1620 : 0 : p += san.san.unstructured_name.len;
1621 : 0 : n -= san.san.unstructured_name.len;
1622 : : }
1623 : 0 : break;
1624 : : /*
1625 : : * iPAddress
1626 : : */
1627 : : case MBEDTLS_X509_SAN_IP_ADDRESS:
1628 : : {
1629 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "\n%s %s : ",
1630 : : prefix, "iPAddress");
1631 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1632 [ # # ]: 0 : if (san.san.unstructured_name.len >= n) {
1633 : 0 : if (n > 0) {
1634 : 0 : *p = '\0';
1635 : : }
1636 : 0 : return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL;
1637 : : }
1638 : :
1639 : 0 : unsigned char *ip = san.san.unstructured_name.p;
1640 : : // Only IPv6 (16 bytes) and IPv4 (4 bytes) types are supported
1641 [ # # ]: 0 : if (san.san.unstructured_name.len == 4) {
1642 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "%u.%u.%u.%u", ip[0], ip[1], ip[2], ip[3]);
1643 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1644 [ # # ]: 0 : } else if (san.san.unstructured_name.len == 16) {
1645 : 0 : ret = mbedtls_snprintf(p, n,
1646 : : "%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X:%X%X",
1647 : 0 : ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6],
1648 : 0 : ip[7], ip[8], ip[9], ip[10], ip[11], ip[12], ip[13],
1649 [ # # ]: 0 : ip[14], ip[15]);
1650 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1651 : : } else {
1652 : 0 : if (n > 0) {
1653 : 0 : *p = '\0';
1654 : : }
1655 : 0 : return MBEDTLS_ERR_X509_BAD_INPUT_DATA;
1656 : : }
1657 : : }
1658 : : break;
1659 : : /*
1660 : : * directoryName
1661 : : */
1662 : : case MBEDTLS_X509_SAN_DIRECTORY_NAME:
1663 : : {
1664 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "\n%s directoryName : ", prefix);
1665 [ # # ]: 0 : if (ret < 0 || (size_t) ret >= n) {
1666 : 0 : mbedtls_x509_free_subject_alt_name(&san);
1667 : : }
1668 : :
1669 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1670 : 0 : ret = mbedtls_x509_dn_gets(p, n, &san.san.directory_name);
1671 : :
1672 [ # # ]: 0 : if (ret < 0) {
1673 : 0 : mbedtls_x509_free_subject_alt_name(&san);
1674 : 0 : if (n > 0) {
1675 : 0 : *p = '\0';
1676 : : }
1677 : 0 : return ret;
1678 : : }
1679 : :
1680 : 0 : p += ret;
1681 : 0 : n -= ret;
1682 : : }
1683 : 0 : break;
1684 : : /*
1685 : : * Type not supported, skip item.
1686 : : */
1687 : : default:
1688 [ # # ]: 0 : ret = mbedtls_snprintf(p, n, "\n%s <unsupported>", prefix);
1689 [ # # ]: 0 : MBEDTLS_X509_SAFE_SNPRINTF;
1690 : 0 : break;
1691 : : }
1692 : :
1693 : : /* So far memory is freed only in the case of directoryName
1694 : : * parsing succeeding, as mbedtls_x509_get_name allocates memory. */
1695 : 0 : mbedtls_x509_free_subject_alt_name(&san);
1696 : 0 : cur = cur->next;
1697 : : }
1698 : :
1699 : 0 : *p = '\0';
1700 : :
1701 : 0 : *size = n;
1702 : 0 : *buf = p;
1703 : :
1704 : 0 : return 0;
1705 : : }
1706 : :
1707 : : #define PRINT_ITEM(i) \
1708 : : do { \
1709 : : ret = mbedtls_snprintf(p, n, "%s" i, sep); \
1710 : : MBEDTLS_X509_SAFE_SNPRINTF; \
1711 : : sep = ", "; \
1712 : : } while (0)
1713 : :
1714 : : #define CERT_TYPE(type, name) \
1715 : : do { \
1716 : : if (ns_cert_type & (type)) { \
1717 : : PRINT_ITEM(name); \
1718 : : } \
1719 : : } while (0)
1720 : :
1721 : 0 : int mbedtls_x509_info_cert_type(char **buf, size_t *size,
1722 : : unsigned char ns_cert_type)
1723 : : {
1724 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1725 : 0 : size_t n = *size;
1726 : 0 : char *p = *buf;
1727 : 0 : const char *sep = "";
1728 : :
1729 [ # # # # ]: 0 : CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client");
1730 [ # # # # ]: 0 : CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server");
1731 [ # # # # ]: 0 : CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email");
1732 [ # # # # ]: 0 : CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing");
1733 [ # # # # ]: 0 : CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved");
1734 [ # # # # ]: 0 : CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA");
1735 [ # # # # ]: 0 : CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA");
1736 [ # # # # ]: 0 : CERT_TYPE(MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA");
1737 : :
1738 : 0 : *size = n;
1739 : 0 : *buf = p;
1740 : :
1741 : 0 : return 0;
1742 : : }
1743 : :
1744 : : #define KEY_USAGE(code, name) \
1745 : : do { \
1746 : : if ((key_usage) & (code)) { \
1747 : : PRINT_ITEM(name); \
1748 : : } \
1749 : : } while (0)
1750 : :
1751 : 0 : int mbedtls_x509_info_key_usage(char **buf, size_t *size,
1752 : : unsigned int key_usage)
1753 : : {
1754 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
1755 : 0 : size_t n = *size;
1756 : 0 : char *p = *buf;
1757 : 0 : const char *sep = "";
1758 : :
1759 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature");
1760 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation");
1761 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment");
1762 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment");
1763 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement");
1764 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign");
1765 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign");
1766 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only");
1767 [ # # # # ]: 0 : KEY_USAGE(MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only");
1768 : :
1769 : 0 : *size = n;
1770 : 0 : *buf = p;
1771 : :
1772 : 0 : return 0;
1773 : : }
1774 : : #endif /* MBEDTLS_X509_REMOVE_INFO */
1775 : : #endif /* MBEDTLS_X509_CRT_PARSE_C || MBEDTLS_X509_CSR_PARSE_C */
1776 : : #endif /* MBEDTLS_X509_USE_C */
|