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