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