1 /*
2 * Copyright The Mbed TLS Contributors
3 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
4 */
5 #include "common.h"
6
7 #include "mbedtls/build_info.h"
8 #if defined(MBEDTLS_PKCS7_C)
9 #include "mbedtls/pkcs7.h"
10 #include "x509_internal.h"
11 #include "mbedtls/asn1.h"
12 #include "mbedtls/x509_crt.h"
13 #include "mbedtls/x509_crl.h"
14 #include "mbedtls/oid.h"
15 #include "mbedtls/error.h"
16
17 #if defined(MBEDTLS_FS_IO)
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #endif
21
22 #include "mbedtls/platform.h"
23 #include "mbedtls/platform_util.h"
24
25 #if defined(MBEDTLS_HAVE_TIME)
26 #include "mbedtls/platform_time.h"
27 #endif
28 #if defined(MBEDTLS_HAVE_TIME_DATE)
29 #include <time.h>
30 #endif
31
32 enum OID {
33 /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */
34 MBEDTLS_OID_DATA = 13, /* 1.2.840.113549.1.7.1 */
35 /* Microsoft Authenticode & Software Publishing */
36 MBEDTLS_OID_MS_INDIRECTDATA = 24, /* 1.3.6.1.4.1.311.2.1.4 */
37 };
38
39 /**
40 * Initializes the mbedtls_pkcs7 structure.
41 */
mbedtls_pkcs7_init(mbedtls_pkcs7 * pkcs7)42 void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7)
43 {
44 memset(pkcs7, 0, sizeof(*pkcs7));
45 }
46
pkcs7_get_next_content_len(unsigned char ** p,unsigned char * end,size_t * len)47 static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end,
48 size_t *len)
49 {
50 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
51
52 ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED
53 | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
54 if (ret != 0) {
55 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
56 } else if ((size_t) (end - *p) != *len) {
57 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
58 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
59 }
60
61 return ret;
62 }
63
64 /**
65 * Get and decode one cert from a sequence.
66 * Return 0 for success,
67 * Return negative error code for failure.
68 **/
pkcs7_get_one_cert(unsigned char ** p,unsigned char * end,mbedtls_x509_crt * certs)69 static int pkcs7_get_one_cert(unsigned char **p, unsigned char *end,
70 mbedtls_x509_crt *certs)
71 {
72 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
73 size_t len = 0;
74 unsigned char *start = *p;
75 unsigned char *end_cert;
76
77 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
78 | MBEDTLS_ASN1_SEQUENCE);
79 if (ret != 0) {
80 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);
81 }
82
83 end_cert = *p + len;
84
85 if ((ret = mbedtls_x509_crt_parse_der(certs, start, end_cert - start)) < 0) {
86 return MBEDTLS_ERR_PKCS7_INVALID_CERT;
87 }
88
89 *p = end_cert;
90
91 return 0;
92 }
93
94 /**
95 * version Version
96 * Version ::= INTEGER
97 **/
pkcs7_get_version(unsigned char ** p,unsigned char * end,int * ver)98 static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver)
99 {
100 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101
102 ret = mbedtls_asn1_get_int(p, end, ver);
103 if (ret != 0) {
104 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret);
105 }
106
107 /* If version != 1, return invalid version */
108 if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) {
109 ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
110 }
111
112 return ret;
113 }
114
115 /**
116 * ContentInfo ::= SEQUENCE {
117 * contentType ContentType,
118 * content
119 * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
120 **/
pkcs7_get_content_info_type(unsigned char ** p,unsigned char * end,unsigned char ** seq_end,mbedtls_pkcs7_buf * pkcs7)121 static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end,
122 unsigned char **seq_end,
123 mbedtls_pkcs7_buf *pkcs7)
124 {
125 size_t len = 0;
126 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
127 unsigned char *start = *p;
128
129 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
130 | MBEDTLS_ASN1_SEQUENCE);
131 if (ret != 0) {
132 *p = start;
133 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
134 }
135 *seq_end = *p + len;
136 ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID);
137 if (ret != 0) {
138 *p = start;
139 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
140 }
141
142 pkcs7->tag = MBEDTLS_ASN1_OID;
143 pkcs7->len = len;
144 pkcs7->p = *p;
145 *p += len;
146
147 return ret;
148 }
149
150 /**
151 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
152 *
153 * This is from x509.h
154 **/
pkcs7_get_digest_algorithm(unsigned char ** p,unsigned char * end,mbedtls_x509_buf * alg)155 static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end,
156 mbedtls_x509_buf *alg)
157 {
158 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
159
160 if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
161 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
162 }
163
164 return ret;
165 }
166
167 /**
168 * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
169 **/
pkcs7_get_digest_algorithm_set(unsigned char ** p,unsigned char * end,mbedtls_x509_buf * alg)170 static int pkcs7_get_digest_algorithm_set(unsigned char **p,
171 unsigned char *end,
172 mbedtls_x509_buf *alg)
173 {
174 size_t len = 0;
175 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
176
177 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
178 | MBEDTLS_ASN1_SET);
179 if (ret != 0) {
180 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
181 }
182
183 end = *p + len;
184
185 ret = mbedtls_asn1_get_alg_null(p, end, alg);
186 if (ret != 0) {
187 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
188 }
189
190 /** For now, it assumes there is only one digest algorithm specified **/
191 if (*p != end) {
192 return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
193 }
194
195 return 0;
196 }
197
198 /**
199 * certificates :: SET OF ExtendedCertificateOrCertificate,
200 * ExtendedCertificateOrCertificate ::= CHOICE {
201 * certificate Certificate -- x509,
202 * extendedCertificate[0] IMPLICIT ExtendedCertificate }
203 * Return number of certificates added to the signed data,
204 * 0 or higher is valid.
205 * Return negative error code for failure.
206 **/
pkcs7_get_certificates(unsigned char ** p,unsigned char * end,mbedtls_x509_crt * certs)207 static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
208 mbedtls_x509_crt *certs)
209 {
210 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
211 size_t len = 0;
212 unsigned char *end_set;
213 int num_of_certs = 0;
214
215 /* Get the set of certs */
216 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
217 | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
218 if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
219 return 0;
220 }
221 if (ret != 0) {
222 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
223 }
224 end_set = *p + len;
225
226 ret = pkcs7_get_one_cert(p, end_set, certs);
227 if (ret != 0) {
228 return ret;
229 }
230
231 num_of_certs++;
232
233 while (*p != end_set) {
234 ret = pkcs7_get_one_cert(p, end_set, certs);
235 if (ret != 0) {
236 return ret;
237 }
238 num_of_certs++;
239 }
240
241 *p = end_set;
242
243 return num_of_certs;
244 }
245
246 /**
247 * EncryptedDigest ::= OCTET STRING
248 **/
pkcs7_get_signature(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_buf * signature)249 static int pkcs7_get_signature(unsigned char **p, unsigned char *end,
250 mbedtls_pkcs7_buf *signature)
251 {
252 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253 size_t len = 0;
254
255 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
256 if (ret != 0) {
257 return ret;
258 }
259
260 signature->tag = MBEDTLS_ASN1_OCTET_STRING;
261 signature->len = len;
262 signature->p = *p;
263
264 *p = *p + len;
265
266 return 0;
267 }
268
pkcs7_free_signer_info(mbedtls_pkcs7_signer_info * signer)269 static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)
270 {
271 mbedtls_x509_name *name_cur;
272 mbedtls_x509_name *name_prv;
273
274 if (signer == NULL) {
275 return;
276 }
277
278 name_cur = signer->issuer.next;
279 while (name_cur != NULL) {
280 name_prv = name_cur;
281 name_cur = name_cur->next;
282 mbedtls_free(name_prv);
283 }
284 signer->issuer.next = NULL;
285 }
286
287 /**
288 * SignerInfo ::= SEQUENCE {
289 * version Version;
290 * issuerAndSerialNumber IssuerAndSerialNumber,
291 * digestAlgorithm DigestAlgorithmIdentifier,
292 * authenticatedAttributes
293 * [0] IMPLICIT Attributes OPTIONAL,
294 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
295 * encryptedDigest EncryptedDigest,
296 * unauthenticatedAttributes
297 * [1] IMPLICIT Attributes OPTIONAL,
298 * Returns 0 if the signerInfo is valid.
299 * Return negative error code for failure.
300 * Structure must not contain vales for authenticatedAttributes
301 * and unauthenticatedAttributes.
302 **/
pkcs7_get_signer_info(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_signer_info * signer,mbedtls_x509_buf * alg)303 static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
304 mbedtls_pkcs7_signer_info *signer,
305 mbedtls_x509_buf *alg)
306 {
307 unsigned char *end_signer, *end_issuer_and_sn;
308 int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
309 size_t len = 0;
310 unsigned char *tmp_p;
311
312 asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
313 | MBEDTLS_ASN1_SEQUENCE);
314 if (asn1_ret != 0) {
315 goto out;
316 }
317
318 end_signer = *p + len;
319
320 ret = pkcs7_get_version(p, end_signer, &signer->version);
321 if (ret != 0) {
322 goto out;
323 }
324
325 asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len,
326 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
327 if (asn1_ret != 0) {
328 goto out;
329 }
330
331 end_issuer_and_sn = *p + len;
332 /* Parsing IssuerAndSerialNumber */
333 signer->issuer_raw.p = *p;
334
335 asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len,
336 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
337 if (asn1_ret != 0) {
338 goto out;
339 }
340
341 ret = mbedtls_x509_get_name(p, *p + len, &signer->issuer);
342 if (ret != 0) {
343 goto out;
344 }
345
346 signer->issuer_raw.len = (size_t) (*p - signer->issuer_raw.p);
347
348 ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial);
349 if (ret != 0) {
350 goto out;
351 }
352
353 /* ensure no extra or missing bytes */
354 if (*p != end_issuer_and_sn) {
355 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
356 goto out;
357 }
358
359 ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier);
360 if (ret != 0) {
361 goto out;
362 }
363
364 /* Check that the digest algorithm used matches the one provided earlier */
365 if (signer->alg_identifier.tag != alg->tag ||
366 signer->alg_identifier.len != alg->len ||
367 memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) {
368 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
369 goto out;
370 }
371
372 /* Save authenticatedAttributes if present */
373 if (*p < end_signer &&
374 **p == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) {
375 tmp_p = *p;
376
377 ret = mbedtls_asn1_get_tag(p, end_signer, &len,
378 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
379 MBEDTLS_ASN1_CONSTRUCTED | 0);
380 if (ret != 0) {
381 goto out;
382 }
383
384 signer->authattrs.data = tmp_p;
385 signer->authattrs.data_len = len + *p - tmp_p;
386 *p += len;
387 }
388
389 ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier);
390 if (ret != 0) {
391 goto out;
392 }
393
394 ret = pkcs7_get_signature(p, end_signer, &signer->sig);
395 if (ret != 0) {
396 goto out;
397 }
398
399 /* Do not permit any unauthenticated attributes */
400 if (*p != end_signer) {
401 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
402 }
403
404 out:
405 if (asn1_ret != 0 || ret != 0) {
406 pkcs7_free_signer_info(signer);
407 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
408 asn1_ret);
409 }
410
411 return ret;
412 }
413
414 /**
415 * SignerInfos ::= SET of SignerInfo
416 * Return number of signers added to the signed data,
417 * 0 or higher is valid.
418 * Return negative error code for failure.
419 **/
pkcs7_get_signers_info_set(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_signer_info * signers_set,mbedtls_x509_buf * digest_alg)420 static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end,
421 mbedtls_pkcs7_signer_info *signers_set,
422 mbedtls_x509_buf *digest_alg)
423 {
424 unsigned char *end_set;
425 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
426 int count = 0;
427 size_t len = 0;
428
429 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
430 | MBEDTLS_ASN1_SET);
431 if (ret != 0) {
432 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret);
433 }
434
435 /* Detect zero signers */
436 if (len == 0) {
437 return 0;
438 }
439
440 end_set = *p + len;
441
442 ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg);
443 if (ret != 0) {
444 return ret;
445 }
446 count++;
447
448 mbedtls_pkcs7_signer_info *prev = signers_set;
449 while (*p != end_set) {
450 mbedtls_pkcs7_signer_info *signer =
451 mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info));
452 if (!signer) {
453 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
454 goto cleanup;
455 }
456
457 ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg);
458 if (ret != 0) {
459 mbedtls_free(signer);
460 goto cleanup;
461 }
462 prev->next = signer;
463 prev = signer;
464 count++;
465 }
466
467 return count;
468
469 cleanup:
470 pkcs7_free_signer_info(signers_set);
471 mbedtls_pkcs7_signer_info *signer = signers_set->next;
472 while (signer != NULL) {
473 prev = signer;
474 signer = signer->next;
475 pkcs7_free_signer_info(prev);
476 mbedtls_free(prev);
477 }
478 signers_set->next = NULL;
479 return ret;
480 }
481
482 /**
483 * SignedData ::= SEQUENCE {
484 * version Version,
485 * digestAlgorithms DigestAlgorithmIdentifiers,
486 * contentInfo ContentInfo,
487 * certificates
488 * [0] IMPLICIT ExtendedCertificatesAndCertificates
489 * OPTIONAL,
490 * crls
491 * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
492 * signerInfos SignerInfos }
493 */
pkcs7_get_signed_data(unsigned char * buf,size_t buflen,mbedtls_pkcs7 * pkcs7)494 static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen,
495 mbedtls_pkcs7 *pkcs7)
496 {
497 unsigned char *p = buf;
498 unsigned char *end = buf + buflen;
499 unsigned char *end_content_info = NULL;
500 size_t len = 0;
501 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
502 mbedtls_md_type_t md_alg;
503 mbedtls_pkcs7_signed_data *signed_data = &pkcs7->signed_data;
504
505 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
506 | MBEDTLS_ASN1_SEQUENCE);
507 if (ret != 0) {
508 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
509 }
510
511 if (p + len != end) {
512 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
513 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
514 }
515
516 /* Get version of signed data */
517 ret = pkcs7_get_version(&p, end, &signed_data->version);
518 if (ret != 0) {
519 return ret;
520 }
521
522 /* Get digest algorithm */
523 ret = pkcs7_get_digest_algorithm_set(&p, end,
524 &signed_data->digest_alg_identifiers);
525 if (ret != 0) {
526 return ret;
527 }
528
529 ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg);
530 if (ret != 0) {
531 return MBEDTLS_ERR_PKCS7_INVALID_ALG;
532 }
533
534 mbedtls_pkcs7_buf content_type;
535 memset(&content_type, 0, sizeof(content_type));
536 ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type);
537 if (ret != 0) {
538 return ret;
539 }
540
541 /*
542 * We should only support 1.2.840.113549.1.7.1 (PKCS7 DATA) and
543 * 1.3.6.1.4.1.311.2.1.4 (MicroSoft Authentication Code) that is for
544 * U-Boot Secure Boot
545 */
546 if (!MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) {
547 pkcs7->content_data.data_type = MBEDTLS_OID_DATA;
548 } else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_MICROSOFT_INDIRECTDATA,
549 &content_type)) {
550 pkcs7->content_data.data_type = MBEDTLS_OID_MS_INDIRECTDATA;
551 } else {
552 return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
553 }
554
555 if (p != end_content_info) {
556 unsigned char *tmp_p = p;
557
558 /* Determine if valid content is present */
559 ret = mbedtls_asn1_get_tag(&p,
560 end_content_info,
561 &len,
562 MBEDTLS_ASN1_CONSTRUCTED |
563 MBEDTLS_ASN1_CONTEXT_SPECIFIC);
564 if (ret != 0 || p + len != end_content_info) {
565 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
566 ret);
567 }
568
569 /*
570 * U-Boot Secure Boot needs to calculate the digest of MicroSoft
571 * Authentication Code during verifying an EFI image.
572 * Thus we need to save the context of Content Data.
573 */
574 pkcs7->content_data.data_hdrlen = p - tmp_p;
575 /* Parse the content data from a sequence */
576 ret = mbedtls_asn1_get_tag(&p, end_content_info, &len,
577 MBEDTLS_ASN1_CONSTRUCTED |
578 MBEDTLS_ASN1_SEQUENCE);
579 if (ret != 0) {
580 /* TODO: Other Content Data formats are not supported at the moment */
581 return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
582 } else if (p + len != end_content_info) {
583 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
584 ret);
585 }
586
587 pkcs7->content_data.data = p;
588 pkcs7->content_data.data_len = len;
589
590 p += len;
591 }
592
593 /* Look for certificates, there may or may not be any */
594 mbedtls_x509_crt_init(&signed_data->certs);
595 ret = pkcs7_get_certificates(&p, end, &signed_data->certs);
596 if (ret < 0) {
597 return ret;
598 }
599
600 signed_data->no_of_certs = ret;
601
602 /*
603 * Currently CRLs are not supported. If CRL exist, the parsing will fail
604 * at next step of getting signers info and return error as invalid
605 * signer info.
606 */
607
608 signed_data->no_of_crls = 0;
609
610 /* Get signers info */
611 ret = pkcs7_get_signers_info_set(&p,
612 end,
613 &signed_data->signers,
614 &signed_data->digest_alg_identifiers);
615 if (ret < 0) {
616 return ret;
617 }
618
619 signed_data->no_of_signers = ret;
620
621 /* Don't permit trailing data */
622 if (p != end) {
623 return MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
624 }
625
626 return 0;
627 }
628
mbedtls_pkcs7_parse_der(mbedtls_pkcs7 * pkcs7,const unsigned char * buf,const size_t buflen)629 int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
630 const size_t buflen)
631 {
632 unsigned char *p;
633 unsigned char *end;
634 size_t len = 0;
635 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
636
637 if (pkcs7 == NULL) {
638 return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
639 }
640
641 /* make an internal copy of the buffer for parsing */
642 pkcs7->raw.p = p = mbedtls_calloc(1, buflen);
643 if (pkcs7->raw.p == NULL) {
644 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
645 goto out;
646 }
647 memcpy(p, buf, buflen);
648 pkcs7->raw.len = buflen;
649 end = p + buflen;
650
651 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
652 | MBEDTLS_ASN1_SEQUENCE);
653 if (ret != 0) {
654 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
655 goto out;
656 }
657
658 if ((size_t) (end - p) != len) {
659 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
660 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
661 goto out;
662 }
663
664 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
665 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
666 goto out;
667 }
668 p = pkcs7->raw.p;
669 len = buflen;
670 goto try_data;
671 }
672
673 if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) {
674 /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */
675 if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len)
676 || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len)
677 || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len)
678 || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len)
679 || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) {
680 /* OID is valid according to the spec, but unsupported */
681 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
682 } else {
683 /* OID is invalid according to the spec */
684 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
685 }
686 goto out;
687 }
688
689 p += len;
690
691 ret = pkcs7_get_next_content_len(&p, end, &len);
692 if (ret != 0) {
693 goto out;
694 }
695
696 /* ensure no extra/missing data */
697 if (p + len != end) {
698 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
699 goto out;
700 }
701
702 try_data:
703 ret = pkcs7_get_signed_data(p, len, pkcs7);
704 if (ret != 0) {
705 goto out;
706 }
707
708 ret = MBEDTLS_PKCS7_SIGNED_DATA;
709
710 out:
711 if (ret < 0) {
712 mbedtls_pkcs7_free(pkcs7);
713 }
714
715 return ret;
716 }
717
mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 * pkcs7,const mbedtls_x509_crt * cert,const unsigned char * data,size_t datalen,const int is_data_hash)718 static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
719 const mbedtls_x509_crt *cert,
720 const unsigned char *data,
721 size_t datalen,
722 const int is_data_hash)
723 {
724 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
725 unsigned char *hash;
726 mbedtls_pk_context pk_cxt = cert->pk;
727 const mbedtls_md_info_t *md_info;
728 mbedtls_md_type_t md_alg;
729 mbedtls_pkcs7_signer_info *signer;
730
731 if (pkcs7->signed_data.no_of_signers == 0) {
732 return MBEDTLS_ERR_PKCS7_INVALID_CERT;
733 }
734
735 if (mbedtls_x509_time_is_past(&cert->valid_to) ||
736 mbedtls_x509_time_is_future(&cert->valid_from)) {
737 return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
738 }
739
740 ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg);
741 if (ret != 0) {
742 return ret;
743 }
744
745 md_info = mbedtls_md_info_from_type(md_alg);
746 if (md_info == NULL) {
747 return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
748 }
749
750 hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);
751 if (hash == NULL) {
752 return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
753 }
754
755 /* BEGIN must free hash before jumping out */
756 if (is_data_hash) {
757 if (datalen != mbedtls_md_get_size(md_info)) {
758 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
759 } else {
760 memcpy(hash, data, datalen);
761 }
762 } else {
763 ret = mbedtls_md(md_info, data, datalen, hash);
764 }
765 if (ret != 0) {
766 mbedtls_free(hash);
767 return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
768 }
769
770 /* assume failure */
771 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
772
773 /*
774 * Potential TODOs
775 * Currently we iterate over all signers and return success if any of them
776 * verify.
777 *
778 * However, we could make this better by checking against the certificate's
779 * identification and SignerIdentifier fields first. That would also allow
780 * us to distinguish between 'no signature for key' and 'signature for key
781 * failed to validate'.
782 */
783 for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) {
784 ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash,
785 mbedtls_md_get_size(md_info),
786 signer->sig.p, signer->sig.len);
787
788 if (ret == 0) {
789 break;
790 }
791 }
792
793 mbedtls_free(hash);
794 /* END must free hash before jumping out */
795 return ret;
796 }
797
mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 * pkcs7,const mbedtls_x509_crt * cert,const unsigned char * data,size_t datalen)798 int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
799 const mbedtls_x509_crt *cert,
800 const unsigned char *data,
801 size_t datalen)
802 {
803 if (data == NULL) {
804 return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
805 }
806 return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);
807 }
808
mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 * pkcs7,const mbedtls_x509_crt * cert,const unsigned char * hash,size_t hashlen)809 int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,
810 const mbedtls_x509_crt *cert,
811 const unsigned char *hash,
812 size_t hashlen)
813 {
814 if (hash == NULL) {
815 return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
816 }
817 return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1);
818 }
819
820 /*
821 * Unallocate all pkcs7 data
822 */
mbedtls_pkcs7_free(mbedtls_pkcs7 * pkcs7)823 void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7)
824 {
825 mbedtls_pkcs7_signer_info *signer_cur;
826 mbedtls_pkcs7_signer_info *signer_prev;
827
828 if (pkcs7 == NULL || pkcs7->raw.p == NULL) {
829 return;
830 }
831
832 mbedtls_free(pkcs7->raw.p);
833
834 mbedtls_x509_crt_free(&pkcs7->signed_data.certs);
835 mbedtls_x509_crl_free(&pkcs7->signed_data.crl);
836
837 signer_cur = pkcs7->signed_data.signers.next;
838 pkcs7_free_signer_info(&pkcs7->signed_data.signers);
839 while (signer_cur != NULL) {
840 signer_prev = signer_cur;
841 signer_cur = signer_prev->next;
842 pkcs7_free_signer_info(signer_prev);
843 mbedtls_free(signer_prev);
844 }
845
846 pkcs7->raw.p = NULL;
847 }
848
849 #endif
850