/src/mbedtls/library/x509.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * X.509 common functions for parsing and verification |
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_USE_C) |
33 | | |
34 | | #include "mbedtls/x509.h" |
35 | | #include "mbedtls/asn1.h" |
36 | | #include "mbedtls/error.h" |
37 | | #include "mbedtls/oid.h" |
38 | | |
39 | | #include <stdio.h> |
40 | | #include <string.h> |
41 | | |
42 | | #if defined(MBEDTLS_PEM_PARSE_C) |
43 | | #include "mbedtls/pem.h" |
44 | | #endif |
45 | | |
46 | | #include "mbedtls/platform.h" |
47 | | |
48 | | #if defined(MBEDTLS_HAVE_TIME) |
49 | | #include "mbedtls/platform_time.h" |
50 | | #endif |
51 | | #if defined(MBEDTLS_HAVE_TIME_DATE) |
52 | | #include "mbedtls/platform_util.h" |
53 | | #include <time.h> |
54 | | #endif |
55 | | |
56 | | #include "mbedtls/legacy_or_psa.h" |
57 | | |
58 | 435k | #define CHECK(code) if ((ret = (code)) != 0) { return ret; } |
59 | | #define CHECK_RANGE(min, max, val) \ |
60 | 309k | do \ |
61 | 309k | { \ |
62 | 309k | if ((val) < (min) || (val) > (max)) \ |
63 | 309k | { \ |
64 | 179 | return ret; \ |
65 | 179 | } \ |
66 | 309k | } while (0) |
67 | | |
68 | | /* |
69 | | * CertificateSerialNumber ::= INTEGER |
70 | | */ |
71 | | int mbedtls_x509_get_serial(unsigned char **p, const unsigned char *end, |
72 | | mbedtls_x509_buf *serial) |
73 | 40.1k | { |
74 | 40.1k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
75 | | |
76 | 40.1k | if ((end - *p) < 1) { |
77 | 18 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, |
78 | 18 | MBEDTLS_ERR_ASN1_OUT_OF_DATA); |
79 | 18 | } |
80 | | |
81 | 40.1k | if (**p != (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2) && |
82 | 40.1k | **p != MBEDTLS_ASN1_INTEGER) { |
83 | 73 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, |
84 | 73 | MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); |
85 | 73 | } |
86 | | |
87 | 40.0k | serial->tag = *(*p)++; |
88 | | |
89 | 40.0k | if ((ret = mbedtls_asn1_get_len(p, end, &serial->len)) != 0) { |
90 | 30 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SERIAL, ret); |
91 | 30 | } |
92 | | |
93 | 40.0k | serial->p = *p; |
94 | 40.0k | *p += serial->len; |
95 | | |
96 | 40.0k | return 0; |
97 | 40.0k | } |
98 | | |
99 | | /* Get an algorithm identifier without parameters (eg for signatures) |
100 | | * |
101 | | * AlgorithmIdentifier ::= SEQUENCE { |
102 | | * algorithm OBJECT IDENTIFIER, |
103 | | * parameters ANY DEFINED BY algorithm OPTIONAL } |
104 | | */ |
105 | | int mbedtls_x509_get_alg_null(unsigned char **p, const unsigned char *end, |
106 | | mbedtls_x509_buf *alg) |
107 | 0 | { |
108 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
109 | |
|
110 | 0 | if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) { |
111 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
112 | 0 | } |
113 | | |
114 | 0 | return 0; |
115 | 0 | } |
116 | | |
117 | | /* |
118 | | * Parse an algorithm identifier with (optional) parameters |
119 | | */ |
120 | | int mbedtls_x509_get_alg(unsigned char **p, const unsigned char *end, |
121 | | mbedtls_x509_buf *alg, mbedtls_x509_buf *params) |
122 | 65.3k | { |
123 | 65.3k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
124 | | |
125 | 65.3k | if ((ret = mbedtls_asn1_get_alg(p, end, alg, params)) != 0) { |
126 | 393 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
127 | 393 | } |
128 | | |
129 | 64.9k | return 0; |
130 | 65.3k | } |
131 | | |
132 | | /* |
133 | | * Convert md type to string |
134 | | */ |
135 | | static inline const char *md_type_to_string(mbedtls_md_type_t md_alg) |
136 | 0 | { |
137 | 0 | switch (md_alg) { |
138 | 0 | #if defined(MBEDTLS_HAS_ALG_MD5_VIA_MD_OR_PSA) |
139 | 0 | case MBEDTLS_MD_MD5: |
140 | 0 | return "MD5"; |
141 | 0 | #endif |
142 | 0 | #if defined(MBEDTLS_HAS_ALG_SHA_1_VIA_MD_OR_PSA) |
143 | 0 | case MBEDTLS_MD_SHA1: |
144 | 0 | return "SHA1"; |
145 | 0 | #endif |
146 | 0 | #if defined(MBEDTLS_HAS_ALG_SHA_224_VIA_MD_OR_PSA) |
147 | 0 | case MBEDTLS_MD_SHA224: |
148 | 0 | return "SHA224"; |
149 | 0 | #endif |
150 | 0 | #if defined(MBEDTLS_HAS_ALG_SHA_256_VIA_MD_OR_PSA) |
151 | 0 | case MBEDTLS_MD_SHA256: |
152 | 0 | return "SHA256"; |
153 | 0 | #endif |
154 | 0 | #if defined(MBEDTLS_HAS_ALG_SHA_384_VIA_MD_OR_PSA) |
155 | 0 | case MBEDTLS_MD_SHA384: |
156 | 0 | return "SHA384"; |
157 | 0 | #endif |
158 | 0 | #if defined(MBEDTLS_HAS_ALG_SHA_512_VIA_MD_OR_PSA) |
159 | 0 | case MBEDTLS_MD_SHA512: |
160 | 0 | return "SHA512"; |
161 | 0 | #endif |
162 | 0 | #if defined(MBEDTLS_HAS_ALG_RIPEMD160_VIA_MD_OR_PSA) |
163 | 0 | case MBEDTLS_MD_RIPEMD160: |
164 | 0 | return "RIPEMD160"; |
165 | 0 | #endif |
166 | 0 | case MBEDTLS_MD_NONE: |
167 | 0 | return NULL; |
168 | 0 | default: |
169 | 0 | return NULL; |
170 | 0 | } |
171 | 0 | } |
172 | | |
173 | | #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
174 | | /* |
175 | | * HashAlgorithm ::= AlgorithmIdentifier |
176 | | * |
177 | | * AlgorithmIdentifier ::= SEQUENCE { |
178 | | * algorithm OBJECT IDENTIFIER, |
179 | | * parameters ANY DEFINED BY algorithm OPTIONAL } |
180 | | * |
181 | | * For HashAlgorithm, parameters MUST be NULL or absent. |
182 | | */ |
183 | | static int x509_get_hash_alg(const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg) |
184 | 0 | { |
185 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
186 | 0 | unsigned char *p; |
187 | 0 | const unsigned char *end; |
188 | 0 | mbedtls_x509_buf md_oid; |
189 | 0 | size_t len; |
190 | | |
191 | | /* Make sure we got a SEQUENCE and setup bounds */ |
192 | 0 | if (alg->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { |
193 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
194 | 0 | MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); |
195 | 0 | } |
196 | | |
197 | 0 | p = alg->p; |
198 | 0 | end = p + alg->len; |
199 | |
|
200 | 0 | if (p >= end) { |
201 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
202 | 0 | MBEDTLS_ERR_ASN1_OUT_OF_DATA); |
203 | 0 | } |
204 | | |
205 | | /* Parse md_oid */ |
206 | 0 | md_oid.tag = *p; |
207 | |
|
208 | 0 | if ((ret = mbedtls_asn1_get_tag(&p, end, &md_oid.len, MBEDTLS_ASN1_OID)) != 0) { |
209 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
210 | 0 | } |
211 | | |
212 | 0 | md_oid.p = p; |
213 | 0 | p += md_oid.len; |
214 | | |
215 | | /* Get md_alg from md_oid */ |
216 | 0 | if ((ret = mbedtls_oid_get_md_alg(&md_oid, md_alg)) != 0) { |
217 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
218 | 0 | } |
219 | | |
220 | | /* Make sure params is absent of NULL */ |
221 | 0 | if (p == end) { |
222 | 0 | return 0; |
223 | 0 | } |
224 | | |
225 | 0 | if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_NULL)) != 0 || len != 0) { |
226 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
227 | 0 | } |
228 | | |
229 | 0 | if (p != end) { |
230 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
231 | 0 | MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); |
232 | 0 | } |
233 | | |
234 | 0 | return 0; |
235 | 0 | } |
236 | | |
237 | | /* |
238 | | * RSASSA-PSS-params ::= SEQUENCE { |
239 | | * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, |
240 | | * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, |
241 | | * saltLength [2] INTEGER DEFAULT 20, |
242 | | * trailerField [3] INTEGER DEFAULT 1 } |
243 | | * -- Note that the tags in this Sequence are explicit. |
244 | | * |
245 | | * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value |
246 | | * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other |
247 | | * option. Enforce this at parsing time. |
248 | | */ |
249 | | int mbedtls_x509_get_rsassa_pss_params(const mbedtls_x509_buf *params, |
250 | | mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, |
251 | | int *salt_len) |
252 | 41 | { |
253 | 41 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
254 | 41 | unsigned char *p; |
255 | 41 | const unsigned char *end, *end2; |
256 | 41 | size_t len; |
257 | 41 | mbedtls_x509_buf alg_id, alg_params; |
258 | | |
259 | | /* First set everything to defaults */ |
260 | 41 | *md_alg = MBEDTLS_MD_SHA1; |
261 | 41 | *mgf_md = MBEDTLS_MD_SHA1; |
262 | 41 | *salt_len = 20; |
263 | | |
264 | | /* Make sure params is a SEQUENCE and setup bounds */ |
265 | 41 | if (params->tag != (MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) { |
266 | 21 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
267 | 21 | MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); |
268 | 21 | } |
269 | | |
270 | 20 | p = (unsigned char *) params->p; |
271 | 20 | end = p + params->len; |
272 | | |
273 | 20 | if (p == end) { |
274 | 20 | return 0; |
275 | 20 | } |
276 | | |
277 | | /* |
278 | | * HashAlgorithm |
279 | | */ |
280 | 0 | if ((ret = mbedtls_asn1_get_tag(&p, end, &len, |
281 | 0 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | |
282 | 0 | 0)) == 0) { |
283 | 0 | end2 = p + len; |
284 | | |
285 | | /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ |
286 | 0 | if ((ret = mbedtls_x509_get_alg_null(&p, end2, &alg_id)) != 0) { |
287 | 0 | return ret; |
288 | 0 | } |
289 | | |
290 | 0 | if ((ret = mbedtls_oid_get_md_alg(&alg_id, md_alg)) != 0) { |
291 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
292 | 0 | } |
293 | | |
294 | 0 | if (p != end2) { |
295 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
296 | 0 | MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); |
297 | 0 | } |
298 | 0 | } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { |
299 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
300 | 0 | } |
301 | | |
302 | 0 | if (p == end) { |
303 | 0 | return 0; |
304 | 0 | } |
305 | | |
306 | | /* |
307 | | * MaskGenAlgorithm |
308 | | */ |
309 | 0 | if ((ret = mbedtls_asn1_get_tag(&p, end, &len, |
310 | 0 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | |
311 | 0 | 1)) == 0) { |
312 | 0 | end2 = p + len; |
313 | | |
314 | | /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ |
315 | 0 | if ((ret = mbedtls_x509_get_alg(&p, end2, &alg_id, &alg_params)) != 0) { |
316 | 0 | return ret; |
317 | 0 | } |
318 | | |
319 | | /* Only MFG1 is recognised for now */ |
320 | 0 | if (MBEDTLS_OID_CMP(MBEDTLS_OID_MGF1, &alg_id) != 0) { |
321 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE, |
322 | 0 | MBEDTLS_ERR_OID_NOT_FOUND); |
323 | 0 | } |
324 | | |
325 | | /* Parse HashAlgorithm */ |
326 | 0 | if ((ret = x509_get_hash_alg(&alg_params, mgf_md)) != 0) { |
327 | 0 | return ret; |
328 | 0 | } |
329 | | |
330 | 0 | if (p != end2) { |
331 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
332 | 0 | MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); |
333 | 0 | } |
334 | 0 | } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { |
335 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
336 | 0 | } |
337 | | |
338 | 0 | if (p == end) { |
339 | 0 | return 0; |
340 | 0 | } |
341 | | |
342 | | /* |
343 | | * salt_len |
344 | | */ |
345 | 0 | if ((ret = mbedtls_asn1_get_tag(&p, end, &len, |
346 | 0 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | |
347 | 0 | 2)) == 0) { |
348 | 0 | end2 = p + len; |
349 | |
|
350 | 0 | if ((ret = mbedtls_asn1_get_int(&p, end2, salt_len)) != 0) { |
351 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
352 | 0 | } |
353 | | |
354 | 0 | if (p != end2) { |
355 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
356 | 0 | MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); |
357 | 0 | } |
358 | 0 | } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { |
359 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
360 | 0 | } |
361 | | |
362 | 0 | if (p == end) { |
363 | 0 | return 0; |
364 | 0 | } |
365 | | |
366 | | /* |
367 | | * trailer_field (if present, must be 1) |
368 | | */ |
369 | 0 | if ((ret = mbedtls_asn1_get_tag(&p, end, &len, |
370 | 0 | MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | |
371 | 0 | 3)) == 0) { |
372 | 0 | int trailer_field; |
373 | |
|
374 | 0 | end2 = p + len; |
375 | |
|
376 | 0 | if ((ret = mbedtls_asn1_get_int(&p, end2, &trailer_field)) != 0) { |
377 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
378 | 0 | } |
379 | | |
380 | 0 | if (p != end2) { |
381 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
382 | 0 | MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); |
383 | 0 | } |
384 | | |
385 | 0 | if (trailer_field != 1) { |
386 | 0 | return MBEDTLS_ERR_X509_INVALID_ALG; |
387 | 0 | } |
388 | 0 | } else if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { |
389 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, ret); |
390 | 0 | } |
391 | | |
392 | 0 | if (p != end) { |
393 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_ALG, |
394 | 0 | MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); |
395 | 0 | } |
396 | | |
397 | 0 | return 0; |
398 | 0 | } |
399 | | #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ |
400 | | |
401 | | /* |
402 | | * AttributeTypeAndValue ::= SEQUENCE { |
403 | | * type AttributeType, |
404 | | * value AttributeValue } |
405 | | * |
406 | | * AttributeType ::= OBJECT IDENTIFIER |
407 | | * |
408 | | * AttributeValue ::= ANY DEFINED BY AttributeType |
409 | | */ |
410 | | static int x509_get_attr_type_value(unsigned char **p, |
411 | | const unsigned char *end, |
412 | | mbedtls_x509_name *cur) |
413 | 186k | { |
414 | 186k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
415 | 186k | size_t len; |
416 | 186k | mbedtls_x509_buf *oid; |
417 | 186k | mbedtls_x509_buf *val; |
418 | | |
419 | 186k | if ((ret = mbedtls_asn1_get_tag(p, end, &len, |
420 | 186k | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { |
421 | 100 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); |
422 | 100 | } |
423 | | |
424 | 186k | end = *p + len; |
425 | | |
426 | 186k | if ((end - *p) < 1) { |
427 | 21 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, |
428 | 21 | MBEDTLS_ERR_ASN1_OUT_OF_DATA); |
429 | 21 | } |
430 | | |
431 | 186k | oid = &cur->oid; |
432 | 186k | oid->tag = **p; |
433 | | |
434 | 186k | if ((ret = mbedtls_asn1_get_tag(p, end, &oid->len, MBEDTLS_ASN1_OID)) != 0) { |
435 | 58 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); |
436 | 58 | } |
437 | | |
438 | 186k | oid->p = *p; |
439 | 186k | *p += oid->len; |
440 | | |
441 | 186k | if ((end - *p) < 1) { |
442 | 23 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, |
443 | 23 | MBEDTLS_ERR_ASN1_OUT_OF_DATA); |
444 | 23 | } |
445 | | |
446 | 186k | if (**p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && |
447 | 186k | **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && |
448 | 186k | **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && |
449 | 186k | **p != MBEDTLS_ASN1_BIT_STRING) { |
450 | 59 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, |
451 | 59 | MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); |
452 | 59 | } |
453 | | |
454 | 186k | val = &cur->val; |
455 | 186k | val->tag = *(*p)++; |
456 | | |
457 | 186k | if ((ret = mbedtls_asn1_get_len(p, end, &val->len)) != 0) { |
458 | 181 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); |
459 | 181 | } |
460 | | |
461 | 185k | val->p = *p; |
462 | 185k | *p += val->len; |
463 | | |
464 | 185k | if (*p != end) { |
465 | 53 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, |
466 | 53 | MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); |
467 | 53 | } |
468 | | |
469 | 185k | cur->next = NULL; |
470 | | |
471 | 185k | return 0; |
472 | 185k | } |
473 | | |
474 | | /* |
475 | | * Name ::= CHOICE { -- only one possibility for now -- |
476 | | * rdnSequence RDNSequence } |
477 | | * |
478 | | * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName |
479 | | * |
480 | | * RelativeDistinguishedName ::= |
481 | | * SET OF AttributeTypeAndValue |
482 | | * |
483 | | * AttributeTypeAndValue ::= SEQUENCE { |
484 | | * type AttributeType, |
485 | | * value AttributeValue } |
486 | | * |
487 | | * AttributeType ::= OBJECT IDENTIFIER |
488 | | * |
489 | | * AttributeValue ::= ANY DEFINED BY AttributeType |
490 | | * |
491 | | * The data structure is optimized for the common case where each RDN has only |
492 | | * one element, which is represented as a list of AttributeTypeAndValue. |
493 | | * For the general case we still use a flat list, but we mark elements of the |
494 | | * same set so that they are "merged" together in the functions that consume |
495 | | * this list, eg mbedtls_x509_dn_gets(). |
496 | | * |
497 | | * On success, this function may allocate a linked list starting at cur->next |
498 | | * that must later be free'd by the caller using mbedtls_free(). In error |
499 | | * cases, this function frees all allocated memory internally and the caller |
500 | | * has no freeing responsibilities. |
501 | | */ |
502 | | int mbedtls_x509_get_name(unsigned char **p, const unsigned char *end, |
503 | | mbedtls_x509_name *cur) |
504 | 62.3k | { |
505 | 62.3k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
506 | 62.3k | size_t set_len; |
507 | 62.3k | const unsigned char *end_set; |
508 | 62.3k | mbedtls_x509_name *head = cur; |
509 | | |
510 | | /* don't use recursion, we'd risk stack overflow if not optimized */ |
511 | 186k | while (1) { |
512 | | /* |
513 | | * parse SET |
514 | | */ |
515 | 186k | if ((ret = mbedtls_asn1_get_tag(p, end, &set_len, |
516 | 186k | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET)) != 0) { |
517 | 154 | ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_NAME, ret); |
518 | 154 | goto error; |
519 | 154 | } |
520 | | |
521 | 186k | end_set = *p + set_len; |
522 | | |
523 | 186k | while (1) { |
524 | 186k | if ((ret = x509_get_attr_type_value(p, end_set, cur)) != 0) { |
525 | 495 | goto error; |
526 | 495 | } |
527 | | |
528 | 185k | if (*p == end_set) { |
529 | 185k | break; |
530 | 185k | } |
531 | | |
532 | | /* Mark this item as being no the only one in a set */ |
533 | 45 | cur->next_merged = 1; |
534 | | |
535 | 45 | cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); |
536 | | |
537 | 45 | if (cur->next == NULL) { |
538 | 0 | ret = MBEDTLS_ERR_X509_ALLOC_FAILED; |
539 | 0 | goto error; |
540 | 0 | } |
541 | | |
542 | 45 | cur = cur->next; |
543 | 45 | } |
544 | | |
545 | | /* |
546 | | * continue until end of SEQUENCE is reached |
547 | | */ |
548 | 185k | if (*p == end) { |
549 | 61.7k | return 0; |
550 | 61.7k | } |
551 | | |
552 | 124k | cur->next = mbedtls_calloc(1, sizeof(mbedtls_x509_name)); |
553 | | |
554 | 124k | if (cur->next == NULL) { |
555 | 0 | ret = MBEDTLS_ERR_X509_ALLOC_FAILED; |
556 | 0 | goto error; |
557 | 0 | } |
558 | | |
559 | 124k | cur = cur->next; |
560 | 124k | } |
561 | | |
562 | 649 | error: |
563 | | /* Skip the first element as we did not allocate it */ |
564 | 649 | mbedtls_asn1_free_named_data_list_shallow(head->next); |
565 | 649 | head->next = NULL; |
566 | | |
567 | 649 | return ret; |
568 | 62.3k | } |
569 | | |
570 | | static int x509_parse_int(unsigned char **p, size_t n, int *res) |
571 | 373k | { |
572 | 373k | *res = 0; |
573 | | |
574 | 1.11M | for (; n > 0; --n) { |
575 | 746k | if ((**p < '0') || (**p > '9')) { |
576 | 369 | return MBEDTLS_ERR_X509_INVALID_DATE; |
577 | 369 | } |
578 | | |
579 | 745k | *res *= 10; |
580 | 745k | *res += (*(*p)++ - '0'); |
581 | 745k | } |
582 | | |
583 | 372k | return 0; |
584 | 373k | } |
585 | | |
586 | | static int x509_date_is_valid(const mbedtls_x509_time *t) |
587 | 61.9k | { |
588 | 61.9k | int ret = MBEDTLS_ERR_X509_INVALID_DATE; |
589 | 61.9k | int month_len; |
590 | | |
591 | 61.9k | CHECK_RANGE(0, 9999, t->year); |
592 | 61.9k | CHECK_RANGE(0, 23, t->hour); |
593 | 61.8k | CHECK_RANGE(0, 59, t->min); |
594 | 61.8k | CHECK_RANGE(0, 59, t->sec); |
595 | | |
596 | 61.8k | switch (t->mon) { |
597 | 11.5k | case 1: case 3: case 5: case 7: case 8: case 10: case 12: |
598 | 11.5k | month_len = 31; |
599 | 11.5k | break; |
600 | 8.36k | case 4: case 6: case 9: case 11: |
601 | 8.36k | month_len = 30; |
602 | 8.36k | break; |
603 | 41.9k | case 2: |
604 | 41.9k | if ((!(t->year % 4) && t->year % 100) || |
605 | 41.9k | !(t->year % 400)) { |
606 | 204 | month_len = 29; |
607 | 41.7k | } else { |
608 | 41.7k | month_len = 28; |
609 | 41.7k | } |
610 | 41.9k | break; |
611 | 28 | default: |
612 | 28 | return ret; |
613 | 61.8k | } |
614 | 61.7k | CHECK_RANGE(1, month_len, t->day); |
615 | | |
616 | 61.7k | return 0; |
617 | 61.7k | } |
618 | | |
619 | | /* |
620 | | * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) |
621 | | * field. |
622 | | */ |
623 | | static int x509_parse_time(unsigned char **p, size_t len, size_t yearlen, |
624 | | mbedtls_x509_time *tm) |
625 | 62.3k | { |
626 | 62.3k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
627 | | |
628 | | /* |
629 | | * Minimum length is 10 or 12 depending on yearlen |
630 | | */ |
631 | 62.3k | if (len < yearlen + 8) { |
632 | 22 | return MBEDTLS_ERR_X509_INVALID_DATE; |
633 | 22 | } |
634 | 62.3k | len -= yearlen + 8; |
635 | | |
636 | | /* |
637 | | * Parse year, month, day, hour, minute |
638 | | */ |
639 | 62.3k | CHECK(x509_parse_int(p, yearlen, &tm->year)); |
640 | 62.2k | if (2 == yearlen) { |
641 | 62.2k | if (tm->year < 50) { |
642 | 61.8k | tm->year += 100; |
643 | 61.8k | } |
644 | | |
645 | 62.2k | tm->year += 1900; |
646 | 62.2k | } |
647 | | |
648 | 62.2k | CHECK(x509_parse_int(p, 2, &tm->mon)); |
649 | 62.2k | CHECK(x509_parse_int(p, 2, &tm->day)); |
650 | 62.1k | CHECK(x509_parse_int(p, 2, &tm->hour)); |
651 | 62.0k | CHECK(x509_parse_int(p, 2, &tm->min)); |
652 | | |
653 | | /* |
654 | | * Parse seconds if present |
655 | | */ |
656 | 62.0k | if (len >= 2) { |
657 | 62.0k | CHECK(x509_parse_int(p, 2, &tm->sec)); |
658 | 61.9k | len -= 2; |
659 | 61.9k | } else { |
660 | 30 | return MBEDTLS_ERR_X509_INVALID_DATE; |
661 | 30 | } |
662 | | |
663 | | /* |
664 | | * Parse trailing 'Z' if present |
665 | | */ |
666 | 61.9k | if (1 == len && 'Z' == **p) { |
667 | 61.8k | (*p)++; |
668 | 61.8k | len--; |
669 | 61.8k | } |
670 | | |
671 | | /* |
672 | | * We should have parsed all characters at this point |
673 | | */ |
674 | 61.9k | if (0 != len) { |
675 | 59 | return MBEDTLS_ERR_X509_INVALID_DATE; |
676 | 59 | } |
677 | | |
678 | 61.9k | CHECK(x509_date_is_valid(tm)); |
679 | | |
680 | 61.7k | return 0; |
681 | 61.9k | } |
682 | | |
683 | | /* |
684 | | * Time ::= CHOICE { |
685 | | * utcTime UTCTime, |
686 | | * generalTime GeneralizedTime } |
687 | | */ |
688 | | int mbedtls_x509_get_time(unsigned char **p, const unsigned char *end, |
689 | | mbedtls_x509_time *tm) |
690 | 62.4k | { |
691 | 62.4k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
692 | 62.4k | size_t len, year_len; |
693 | 62.4k | unsigned char tag; |
694 | | |
695 | 62.4k | if ((end - *p) < 1) { |
696 | 20 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, |
697 | 20 | MBEDTLS_ERR_ASN1_OUT_OF_DATA); |
698 | 20 | } |
699 | | |
700 | 62.4k | tag = **p; |
701 | | |
702 | 62.4k | if (tag == MBEDTLS_ASN1_UTC_TIME) { |
703 | 62.3k | year_len = 2; |
704 | 62.3k | } else if (tag == MBEDTLS_ASN1_GENERALIZED_TIME) { |
705 | 63 | year_len = 4; |
706 | 63 | } else { |
707 | 49 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, |
708 | 49 | MBEDTLS_ERR_ASN1_UNEXPECTED_TAG); |
709 | 49 | } |
710 | | |
711 | 62.4k | (*p)++; |
712 | 62.4k | ret = mbedtls_asn1_get_len(p, end, &len); |
713 | | |
714 | 62.4k | if (ret != 0) { |
715 | 29 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_DATE, ret); |
716 | 29 | } |
717 | | |
718 | 62.3k | return x509_parse_time(p, len, year_len, tm); |
719 | 62.4k | } |
720 | | |
721 | | int mbedtls_x509_get_sig(unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig) |
722 | 24.9k | { |
723 | 24.9k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
724 | 24.9k | size_t len; |
725 | 24.9k | int tag_type; |
726 | | |
727 | 24.9k | if ((end - *p) < 1) { |
728 | 0 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, |
729 | 0 | MBEDTLS_ERR_ASN1_OUT_OF_DATA); |
730 | 0 | } |
731 | | |
732 | 24.9k | tag_type = **p; |
733 | | |
734 | 24.9k | if ((ret = mbedtls_asn1_get_bitstring_null(p, end, &len)) != 0) { |
735 | 56 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_SIGNATURE, ret); |
736 | 56 | } |
737 | | |
738 | 24.8k | sig->tag = tag_type; |
739 | 24.8k | sig->len = len; |
740 | 24.8k | sig->p = *p; |
741 | | |
742 | 24.8k | *p += len; |
743 | | |
744 | 24.8k | return 0; |
745 | 24.9k | } |
746 | | |
747 | | /* |
748 | | * Get signature algorithm from alg OID and optional parameters |
749 | | */ |
750 | | int mbedtls_x509_get_sig_alg(const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, |
751 | | mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, |
752 | | void **sig_opts) |
753 | 39.8k | { |
754 | 39.8k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
755 | | |
756 | 39.8k | if (*sig_opts != NULL) { |
757 | 0 | return MBEDTLS_ERR_X509_BAD_INPUT_DATA; |
758 | 0 | } |
759 | | |
760 | 39.8k | if ((ret = mbedtls_oid_get_sig_alg(sig_oid, md_alg, pk_alg)) != 0) { |
761 | 7.85k | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG, ret); |
762 | 7.85k | } |
763 | | |
764 | 31.9k | #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
765 | 31.9k | if (*pk_alg == MBEDTLS_PK_RSASSA_PSS) { |
766 | 41 | mbedtls_pk_rsassa_pss_options *pss_opts; |
767 | | |
768 | 41 | pss_opts = mbedtls_calloc(1, sizeof(mbedtls_pk_rsassa_pss_options)); |
769 | 41 | if (pss_opts == NULL) { |
770 | 0 | return MBEDTLS_ERR_X509_ALLOC_FAILED; |
771 | 0 | } |
772 | | |
773 | 41 | ret = mbedtls_x509_get_rsassa_pss_params(sig_params, |
774 | 41 | md_alg, |
775 | 41 | &pss_opts->mgf1_hash_id, |
776 | 41 | &pss_opts->expected_salt_len); |
777 | 41 | if (ret != 0) { |
778 | 21 | mbedtls_free(pss_opts); |
779 | 21 | return ret; |
780 | 21 | } |
781 | | |
782 | 20 | *sig_opts = (void *) pss_opts; |
783 | 20 | } else |
784 | 31.9k | #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ |
785 | 31.9k | { |
786 | | /* Make sure parameters are absent or NULL */ |
787 | 31.9k | if ((sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0) || |
788 | 31.9k | sig_params->len != 0) { |
789 | 63 | return MBEDTLS_ERR_X509_INVALID_ALG; |
790 | 63 | } |
791 | 31.9k | } |
792 | | |
793 | 31.8k | return 0; |
794 | 31.9k | } |
795 | | |
796 | | /* |
797 | | * X.509 Extensions (No parsing of extensions, pointer should |
798 | | * be either manually updated or extensions should be parsed!) |
799 | | */ |
800 | | int mbedtls_x509_get_ext(unsigned char **p, const unsigned char *end, |
801 | | mbedtls_x509_buf *ext, int tag) |
802 | 26.5k | { |
803 | 26.5k | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
804 | 26.5k | size_t len; |
805 | | |
806 | | /* Extension structure use EXPLICIT tagging. That is, the actual |
807 | | * `Extensions` structure is wrapped by a tag-length pair using |
808 | | * the respective context-specific tag. */ |
809 | 26.5k | ret = mbedtls_asn1_get_tag(p, end, &ext->len, |
810 | 26.5k | MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag); |
811 | 26.5k | if (ret != 0) { |
812 | 45 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); |
813 | 45 | } |
814 | | |
815 | 26.5k | ext->tag = MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag; |
816 | 26.5k | ext->p = *p; |
817 | 26.5k | end = *p + ext->len; |
818 | | |
819 | | /* |
820 | | * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension |
821 | | */ |
822 | 26.5k | if ((ret = mbedtls_asn1_get_tag(p, end, &len, |
823 | 26.5k | MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) { |
824 | 54 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, ret); |
825 | 54 | } |
826 | | |
827 | 26.4k | if (end != *p + len) { |
828 | 28 | return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_X509_INVALID_EXTENSIONS, |
829 | 28 | MBEDTLS_ERR_ASN1_LENGTH_MISMATCH); |
830 | 28 | } |
831 | | |
832 | 26.4k | return 0; |
833 | 26.4k | } |
834 | | |
835 | | /* |
836 | | * Store the name in printable form into buf; no more |
837 | | * than size characters will be written |
838 | | */ |
839 | | int mbedtls_x509_dn_gets(char *buf, size_t size, const mbedtls_x509_name *dn) |
840 | 0 | { |
841 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
842 | 0 | size_t i, j, n; |
843 | 0 | unsigned char c, merge = 0; |
844 | 0 | const mbedtls_x509_name *name; |
845 | 0 | const char *short_name = NULL; |
846 | 0 | char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; |
847 | |
|
848 | 0 | memset(s, 0, sizeof(s)); |
849 | |
|
850 | 0 | name = dn; |
851 | 0 | p = buf; |
852 | 0 | n = size; |
853 | |
|
854 | 0 | while (name != NULL) { |
855 | 0 | if (!name->oid.p) { |
856 | 0 | name = name->next; |
857 | 0 | continue; |
858 | 0 | } |
859 | | |
860 | 0 | if (name != dn) { |
861 | 0 | ret = mbedtls_snprintf(p, n, merge ? " + " : ", "); |
862 | 0 | MBEDTLS_X509_SAFE_SNPRINTF; |
863 | 0 | } |
864 | | |
865 | 0 | ret = mbedtls_oid_get_attr_short_name(&name->oid, &short_name); |
866 | |
|
867 | 0 | if (ret == 0) { |
868 | 0 | ret = mbedtls_snprintf(p, n, "%s=", short_name); |
869 | 0 | } else { |
870 | 0 | ret = mbedtls_snprintf(p, n, "\?\?="); |
871 | 0 | } |
872 | 0 | MBEDTLS_X509_SAFE_SNPRINTF; |
873 | | |
874 | 0 | for (i = 0, j = 0; i < name->val.len; i++, j++) { |
875 | 0 | if (j >= sizeof(s) - 1) { |
876 | 0 | return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; |
877 | 0 | } |
878 | | |
879 | 0 | c = name->val.p[i]; |
880 | | // Special characters requiring escaping, RFC 1779 |
881 | 0 | if (c && strchr(",=+<>#;\"\\", c)) { |
882 | 0 | if (j + 1 >= sizeof(s) - 1) { |
883 | 0 | return MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; |
884 | 0 | } |
885 | 0 | s[j++] = '\\'; |
886 | 0 | } |
887 | 0 | if (c < 32 || c >= 127) { |
888 | 0 | s[j] = '?'; |
889 | 0 | } else { |
890 | 0 | s[j] = c; |
891 | 0 | } |
892 | 0 | } |
893 | 0 | s[j] = '\0'; |
894 | 0 | ret = mbedtls_snprintf(p, n, "%s", s); |
895 | 0 | MBEDTLS_X509_SAFE_SNPRINTF; |
896 | | |
897 | 0 | merge = name->next_merged; |
898 | 0 | name = name->next; |
899 | 0 | } |
900 | | |
901 | 0 | return (int) (size - n); |
902 | 0 | } |
903 | | |
904 | | /* |
905 | | * Store the serial in printable form into buf; no more |
906 | | * than size characters will be written |
907 | | */ |
908 | | int mbedtls_x509_serial_gets(char *buf, size_t size, const mbedtls_x509_buf *serial) |
909 | 0 | { |
910 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
911 | 0 | size_t i, n, nr; |
912 | 0 | char *p; |
913 | |
|
914 | 0 | p = buf; |
915 | 0 | n = size; |
916 | |
|
917 | 0 | nr = (serial->len <= 32) |
918 | 0 | ? serial->len : 28; |
919 | |
|
920 | 0 | for (i = 0; i < nr; i++) { |
921 | 0 | if (i == 0 && nr > 1 && serial->p[i] == 0x0) { |
922 | 0 | continue; |
923 | 0 | } |
924 | | |
925 | 0 | ret = mbedtls_snprintf(p, n, "%02X%s", |
926 | 0 | serial->p[i], (i < nr - 1) ? ":" : ""); |
927 | 0 | MBEDTLS_X509_SAFE_SNPRINTF; |
928 | 0 | } |
929 | | |
930 | 0 | if (nr != serial->len) { |
931 | 0 | ret = mbedtls_snprintf(p, n, "...."); |
932 | 0 | MBEDTLS_X509_SAFE_SNPRINTF; |
933 | 0 | } |
934 | | |
935 | 0 | return (int) (size - n); |
936 | 0 | } |
937 | | |
938 | | #if !defined(MBEDTLS_X509_REMOVE_INFO) |
939 | | /* |
940 | | * Helper for writing signature algorithms |
941 | | */ |
942 | | int mbedtls_x509_sig_alg_gets(char *buf, size_t size, const mbedtls_x509_buf *sig_oid, |
943 | | mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, |
944 | | const void *sig_opts) |
945 | 0 | { |
946 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
947 | 0 | char *p = buf; |
948 | 0 | size_t n = size; |
949 | 0 | const char *desc = NULL; |
950 | |
|
951 | 0 | ret = mbedtls_oid_get_sig_alg_desc(sig_oid, &desc); |
952 | 0 | if (ret != 0) { |
953 | 0 | ret = mbedtls_snprintf(p, n, "???"); |
954 | 0 | } else { |
955 | 0 | ret = mbedtls_snprintf(p, n, "%s", desc); |
956 | 0 | } |
957 | 0 | MBEDTLS_X509_SAFE_SNPRINTF; |
958 | | |
959 | 0 | #if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) |
960 | 0 | if (pk_alg == MBEDTLS_PK_RSASSA_PSS) { |
961 | 0 | const mbedtls_pk_rsassa_pss_options *pss_opts; |
962 | |
|
963 | 0 | pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; |
964 | |
|
965 | 0 | const char *name = md_type_to_string(md_alg); |
966 | 0 | const char *mgf_name = md_type_to_string(pss_opts->mgf1_hash_id); |
967 | |
|
968 | 0 | ret = mbedtls_snprintf(p, n, " (%s, MGF1-%s, 0x%02X)", |
969 | 0 | name ? name : "???", |
970 | 0 | mgf_name ? mgf_name : "???", |
971 | 0 | (unsigned int) pss_opts->expected_salt_len); |
972 | 0 | MBEDTLS_X509_SAFE_SNPRINTF; |
973 | 0 | } |
974 | | #else |
975 | | ((void) pk_alg); |
976 | | ((void) md_alg); |
977 | | ((void) sig_opts); |
978 | | #endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ |
979 | | |
980 | 0 | return (int) (size - n); |
981 | 0 | } |
982 | | #endif /* MBEDTLS_X509_REMOVE_INFO */ |
983 | | |
984 | | /* |
985 | | * Helper for writing "RSA key size", "EC key size", etc |
986 | | */ |
987 | | int mbedtls_x509_key_size_helper(char *buf, size_t buf_size, const char *name) |
988 | 0 | { |
989 | 0 | char *p = buf; |
990 | 0 | size_t n = buf_size; |
991 | 0 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
992 | |
|
993 | 0 | ret = mbedtls_snprintf(p, n, "%s key size", name); |
994 | 0 | MBEDTLS_X509_SAFE_SNPRINTF; |
995 | | |
996 | 0 | return 0; |
997 | 0 | } |
998 | | |
999 | | #if defined(MBEDTLS_HAVE_TIME_DATE) |
1000 | | /* |
1001 | | * Set the time structure to the current time. |
1002 | | * Return 0 on success, non-zero on failure. |
1003 | | */ |
1004 | | static int x509_get_current_time(mbedtls_x509_time *now) |
1005 | 0 | { |
1006 | 0 | struct tm *lt, tm_buf; |
1007 | 0 | mbedtls_time_t tt; |
1008 | 0 | int ret = 0; |
1009 | |
|
1010 | 0 | tt = mbedtls_time(NULL); |
1011 | 0 | lt = mbedtls_platform_gmtime_r(&tt, &tm_buf); |
1012 | |
|
1013 | 0 | if (lt == NULL) { |
1014 | 0 | ret = -1; |
1015 | 0 | } else { |
1016 | 0 | now->year = lt->tm_year + 1900; |
1017 | 0 | now->mon = lt->tm_mon + 1; |
1018 | 0 | now->day = lt->tm_mday; |
1019 | 0 | now->hour = lt->tm_hour; |
1020 | 0 | now->min = lt->tm_min; |
1021 | 0 | now->sec = lt->tm_sec; |
1022 | 0 | } |
1023 | |
|
1024 | 0 | return ret; |
1025 | 0 | } |
1026 | | |
1027 | | /* |
1028 | | * Return 0 if before <= after, 1 otherwise |
1029 | | */ |
1030 | | static int x509_check_time(const mbedtls_x509_time *before, const mbedtls_x509_time *after) |
1031 | 0 | { |
1032 | 0 | if (before->year > after->year) { |
1033 | 0 | return 1; |
1034 | 0 | } |
1035 | | |
1036 | 0 | if (before->year == after->year && |
1037 | 0 | before->mon > after->mon) { |
1038 | 0 | return 1; |
1039 | 0 | } |
1040 | | |
1041 | 0 | if (before->year == after->year && |
1042 | 0 | before->mon == after->mon && |
1043 | 0 | before->day > after->day) { |
1044 | 0 | return 1; |
1045 | 0 | } |
1046 | | |
1047 | 0 | if (before->year == after->year && |
1048 | 0 | before->mon == after->mon && |
1049 | 0 | before->day == after->day && |
1050 | 0 | before->hour > after->hour) { |
1051 | 0 | return 1; |
1052 | 0 | } |
1053 | | |
1054 | 0 | if (before->year == after->year && |
1055 | 0 | before->mon == after->mon && |
1056 | 0 | before->day == after->day && |
1057 | 0 | before->hour == after->hour && |
1058 | 0 | before->min > after->min) { |
1059 | 0 | return 1; |
1060 | 0 | } |
1061 | | |
1062 | 0 | if (before->year == after->year && |
1063 | 0 | before->mon == after->mon && |
1064 | 0 | before->day == after->day && |
1065 | 0 | before->hour == after->hour && |
1066 | 0 | before->min == after->min && |
1067 | 0 | before->sec > after->sec) { |
1068 | 0 | return 1; |
1069 | 0 | } |
1070 | | |
1071 | 0 | return 0; |
1072 | 0 | } |
1073 | | |
1074 | | int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) |
1075 | 0 | { |
1076 | 0 | mbedtls_x509_time now; |
1077 | |
|
1078 | 0 | if (x509_get_current_time(&now) != 0) { |
1079 | 0 | return 1; |
1080 | 0 | } |
1081 | | |
1082 | 0 | return x509_check_time(&now, to); |
1083 | 0 | } |
1084 | | |
1085 | | int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) |
1086 | 0 | { |
1087 | 0 | mbedtls_x509_time now; |
1088 | |
|
1089 | 0 | if (x509_get_current_time(&now) != 0) { |
1090 | 0 | return 1; |
1091 | 0 | } |
1092 | | |
1093 | 0 | return x509_check_time(from, &now); |
1094 | 0 | } |
1095 | | |
1096 | | #else /* MBEDTLS_HAVE_TIME_DATE */ |
1097 | | |
1098 | | int mbedtls_x509_time_is_past(const mbedtls_x509_time *to) |
1099 | | { |
1100 | | ((void) to); |
1101 | | return 0; |
1102 | | } |
1103 | | |
1104 | | int mbedtls_x509_time_is_future(const mbedtls_x509_time *from) |
1105 | | { |
1106 | | ((void) from); |
1107 | | return 0; |
1108 | | } |
1109 | | #endif /* MBEDTLS_HAVE_TIME_DATE */ |
1110 | | #endif /* MBEDTLS_X509_USE_C */ |