blob: cfe570a78838d81ea3f63040e964dc2b7265b08a [file] [log] [blame]
Nick Child5d881c32022-02-28 10:09:16 -06001/*
2 * Copyright The Mbed TLS Contributors
Dave Rodgman16799db2023-11-02 19:47:20 +00003 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Nayna Jainc9deb182020-11-16 19:03:12 +00004 */
Harry Ramsey0f6bc412024-10-04 10:36:54 +01005#include "x509_internal.h"
Nayna Jainc9deb182020-11-16 19:03:12 +00006
Nayna Jainc9deb182020-11-16 19:03:12 +00007#if defined(MBEDTLS_PKCS7_C)
8#include "mbedtls/pkcs7.h"
Nayna Jainc9deb182020-11-16 19:03:12 +00009#include "mbedtls/asn1.h"
10#include "mbedtls/x509_crt.h"
11#include "mbedtls/x509_crl.h"
Gilles Peskine86a47f82025-05-07 20:20:12 +020012#include "x509_oid.h"
Nick Child9f4fb3e2022-09-12 16:21:02 -050013#include "mbedtls/error.h"
Nayna Jainc9deb182020-11-16 19:03:12 +000014
Nayna Jainc9deb182020-11-16 19:03:12 +000015#if defined(MBEDTLS_FS_IO)
16#include <sys/types.h>
17#include <sys/stat.h>
18#endif
19
Nayna Jainc9deb182020-11-16 19:03:12 +000020#include "mbedtls/platform.h"
21#include "mbedtls/platform_util.h"
Nayna Jainc9deb182020-11-16 19:03:12 +000022
23#if defined(MBEDTLS_HAVE_TIME)
24#include "mbedtls/platform_time.h"
25#endif
26#if defined(MBEDTLS_HAVE_TIME_DATE)
27#include <time.h>
28#endif
29
30/**
Dave Rodgmanefbc5f72023-03-13 12:15:49 +000031 * Initializes the mbedtls_pkcs7 structure.
Nayna Jainc9deb182020-11-16 19:03:12 +000032 */
Gilles Peskine449bd832023-01-11 14:50:10 +010033void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7)
Nayna Jainc9deb182020-11-16 19:03:12 +000034{
Gilles Peskine449bd832023-01-11 14:50:10 +010035 memset(pkcs7, 0, sizeof(*pkcs7));
Nayna Jainc9deb182020-11-16 19:03:12 +000036}
37
Gilles Peskine449bd832023-01-11 14:50:10 +010038static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end,
39 size_t *len)
Nayna Jainc9deb182020-11-16 19:03:12 +000040{
Nick Child9f4fb3e2022-09-12 16:21:02 -050041 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +000042
Gilles Peskine449bd832023-01-11 14:50:10 +010043 ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED
44 | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
45 if (ret != 0) {
Demi Marie Obenour6cfc4692022-11-28 00:46:00 -050046 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
Demi Marie Obenour512818b2022-11-27 22:48:55 -050047 } else if ((size_t) (end - *p) != *len) {
Demi Marie Obenour6cfc4692022-11-28 00:46:00 -050048 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
Demi Marie Obenour512818b2022-11-27 22:48:55 -050049 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Nayna Jainc9deb182020-11-16 19:03:12 +000050 }
51
Gilles Peskine449bd832023-01-11 14:50:10 +010052 return ret;
Nayna Jainc9deb182020-11-16 19:03:12 +000053}
54
55/**
56 * version Version
57 * Version ::= INTEGER
58 **/
Gilles Peskine449bd832023-01-11 14:50:10 +010059static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver)
Nayna Jainc9deb182020-11-16 19:03:12 +000060{
Nick Child9f4fb3e2022-09-12 16:21:02 -050061 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +000062
Gilles Peskine449bd832023-01-11 14:50:10 +010063 ret = mbedtls_asn1_get_int(p, end, ver);
64 if (ret != 0) {
65 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret);
66 }
Nayna Jainc9deb182020-11-16 19:03:12 +000067
68 /* If version != 1, return invalid version */
Gilles Peskine449bd832023-01-11 14:50:10 +010069 if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) {
Nick Child9f4fb3e2022-09-12 16:21:02 -050070 ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
Gilles Peskine449bd832023-01-11 14:50:10 +010071 }
Nayna Jainc9deb182020-11-16 19:03:12 +000072
Gilles Peskine449bd832023-01-11 14:50:10 +010073 return ret;
Nayna Jainc9deb182020-11-16 19:03:12 +000074}
75
76/**
77 * ContentInfo ::= SEQUENCE {
78 * contentType ContentType,
79 * content
80 * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
81 **/
Gilles Peskine449bd832023-01-11 14:50:10 +010082static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end,
Nick Childec817092022-12-15 15:54:03 -060083 unsigned char **seq_end,
Gilles Peskine449bd832023-01-11 14:50:10 +010084 mbedtls_pkcs7_buf *pkcs7)
Nayna Jainc9deb182020-11-16 19:03:12 +000085{
86 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -050087 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jain673a2262020-12-14 22:44:49 +000088 unsigned char *start = *p;
Nayna Jainc9deb182020-11-16 19:03:12 +000089
Gilles Peskine449bd832023-01-11 14:50:10 +010090 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
91 | MBEDTLS_ASN1_SEQUENCE);
92 if (ret != 0) {
Nick Childc448c942021-07-01 15:29:50 -040093 *p = start;
Gilles Peskine449bd832023-01-11 14:50:10 +010094 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
Nick Childc448c942021-07-01 15:29:50 -040095 }
Nick Childec817092022-12-15 15:54:03 -060096 *seq_end = *p + len;
97 ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID);
Gilles Peskine449bd832023-01-11 14:50:10 +010098 if (ret != 0) {
Nayna Jain673a2262020-12-14 22:44:49 +000099 *p = start;
Gilles Peskine449bd832023-01-11 14:50:10 +0100100 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
Nayna Jain673a2262020-12-14 22:44:49 +0000101 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000102
103 pkcs7->tag = MBEDTLS_ASN1_OID;
104 pkcs7->len = len;
105 pkcs7->p = *p;
Nick Childbb82ab72022-10-28 12:28:54 -0500106 *p += len;
Nayna Jainc9deb182020-11-16 19:03:12 +0000107
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 return ret;
Nayna Jainc9deb182020-11-16 19:03:12 +0000109}
110
111/**
112 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
113 *
114 * This is from x509.h
115 **/
Gilles Peskine449bd832023-01-11 14:50:10 +0100116static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end,
117 mbedtls_x509_buf *alg)
Nayna Jainc9deb182020-11-16 19:03:12 +0000118{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500119 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000120
Gilles Peskine449bd832023-01-11 14:50:10 +0100121 if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
122 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
123 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000124
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 return ret;
Nayna Jainc9deb182020-11-16 19:03:12 +0000126}
127
128/**
129 * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
130 **/
Gilles Peskine449bd832023-01-11 14:50:10 +0100131static int pkcs7_get_digest_algorithm_set(unsigned char **p,
132 unsigned char *end,
133 mbedtls_x509_buf *alg)
Nayna Jainc9deb182020-11-16 19:03:12 +0000134{
135 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500136 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000137
Gilles Peskine449bd832023-01-11 14:50:10 +0100138 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
139 | MBEDTLS_ASN1_SET);
140 if (ret != 0) {
141 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
Nick Child9f4fb3e2022-09-12 16:21:02 -0500142 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000143
144 end = *p + len;
145
Gilles Peskine449bd832023-01-11 14:50:10 +0100146 ret = mbedtls_asn1_get_alg_null(p, end, alg);
147 if (ret != 0) {
148 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
Nick Child9f4fb3e2022-09-12 16:21:02 -0500149 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000150
Nick Child34d5e932022-09-14 14:44:03 -0500151 /** For now, it assumes there is only one digest algorithm specified **/
Gilles Peskine449bd832023-01-11 14:50:10 +0100152 if (*p != end) {
153 return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
154 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000155
Gilles Peskine449bd832023-01-11 14:50:10 +0100156 return 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000157}
158
159/**
160 * certificates :: SET OF ExtendedCertificateOrCertificate,
161 * ExtendedCertificateOrCertificate ::= CHOICE {
162 * certificate Certificate -- x509,
163 * extendedCertificate[0] IMPLICIT ExtendedCertificate }
164 * Return number of certificates added to the signed data,
165 * 0 or higher is valid.
166 * Return negative error code for failure.
167 **/
Gilles Peskine449bd832023-01-11 14:50:10 +0100168static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
169 mbedtls_x509_crt *certs)
Nayna Jainc9deb182020-11-16 19:03:12 +0000170{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500171 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000172 size_t len1 = 0;
173 size_t len2 = 0;
Nick Childbb82ab72022-10-28 12:28:54 -0500174 unsigned char *end_set, *end_cert, *start;
Nayna Jainc9deb182020-11-16 19:03:12 +0000175
Demi Marie Obenour6cfc4692022-11-28 00:46:00 -0500176 ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
177 | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
178 if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
179 return 0;
180 }
181 if (ret != 0) {
182 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
Nayna Jainc9deb182020-11-16 19:03:12 +0000183 }
184 start = *p;
185 end_set = *p + len1;
186
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
188 | MBEDTLS_ASN1_SEQUENCE);
189 if (ret != 0) {
190 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);
Nick Child9f4fb3e2022-09-12 16:21:02 -0500191 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000192
193 end_cert = *p + len2;
194
195 /*
196 * This is to verify that there is only one signer certificate. It seems it is
197 * not easy to differentiate between the chain vs different signer's certificate.
198 * So, we support only the root certificate and the single signer.
199 * The behaviour would be improved with addition of multiple signer support.
200 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100201 if (end_cert != end_set) {
202 return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500203 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000204
Demi Marie Obenour55d9df22022-11-28 00:29:32 -0500205 if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100206 return MBEDTLS_ERR_PKCS7_INVALID_CERT;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500207 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000208
Demi Marie Obenour55d9df22022-11-28 00:29:32 -0500209 *p = end_cert;
Nayna Jainc9deb182020-11-16 19:03:12 +0000210
Nick Child5f9456f2022-09-19 10:01:25 -0500211 /*
Nick Child9f4fb3e2022-09-12 16:21:02 -0500212 * Since in this version we strictly support single certificate, and reaching
Nick Child5f9456f2022-09-19 10:01:25 -0500213 * here implies we have parsed successfully, we return 1.
Nick Child9f4fb3e2022-09-12 16:21:02 -0500214 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100215 return 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000216}
217
218/**
219 * EncryptedDigest ::= OCTET STRING
220 **/
Gilles Peskine449bd832023-01-11 14:50:10 +0100221static int pkcs7_get_signature(unsigned char **p, unsigned char *end,
222 mbedtls_pkcs7_buf *signature)
Nayna Jainc9deb182020-11-16 19:03:12 +0000223{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500224 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000225 size_t len = 0;
226
Gilles Peskine449bd832023-01-11 14:50:10 +0100227 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
228 if (ret != 0) {
229 return ret;
230 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000231
232 signature->tag = MBEDTLS_ASN1_OCTET_STRING;
233 signature->len = len;
234 signature->p = *p;
235
236 *p = *p + len;
237
Gilles Peskine449bd832023-01-11 14:50:10 +0100238 return 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000239}
240
Gilles Peskine449bd832023-01-11 14:50:10 +0100241static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)
Bence Szépkútif7641542022-12-12 21:37:36 +0100242{
243 mbedtls_x509_name *name_cur;
244 mbedtls_x509_name *name_prv;
245
Gilles Peskine449bd832023-01-11 14:50:10 +0100246 if (signer == NULL) {
Bence Szépkútif7641542022-12-12 21:37:36 +0100247 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100248 }
Bence Szépkútif7641542022-12-12 21:37:36 +0100249
250 name_cur = signer->issuer.next;
Gilles Peskine449bd832023-01-11 14:50:10 +0100251 while (name_cur != NULL) {
Bence Szépkútif7641542022-12-12 21:37:36 +0100252 name_prv = name_cur;
253 name_cur = name_cur->next;
Gilles Peskine449bd832023-01-11 14:50:10 +0100254 mbedtls_free(name_prv);
Bence Szépkútif7641542022-12-12 21:37:36 +0100255 }
256 signer->issuer.next = NULL;
257}
258
Nayna Jainc9deb182020-11-16 19:03:12 +0000259/**
Nayna Jainc9deb182020-11-16 19:03:12 +0000260 * SignerInfo ::= SEQUENCE {
261 * version Version;
262 * issuerAndSerialNumber IssuerAndSerialNumber,
263 * digestAlgorithm DigestAlgorithmIdentifier,
264 * authenticatedAttributes
265 * [0] IMPLICIT Attributes OPTIONAL,
266 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
267 * encryptedDigest EncryptedDigest,
268 * unauthenticatedAttributes
269 * [1] IMPLICIT Attributes OPTIONAL,
Daniel Axtens35384792020-09-02 14:48:45 +1000270 * Returns 0 if the signerInfo is valid.
271 * Return negative error code for failure.
Nick Childbb82ab72022-10-28 12:28:54 -0500272 * Structure must not contain vales for authenticatedAttributes
273 * and unauthenticatedAttributes.
Daniel Axtens35384792020-09-02 14:48:45 +1000274 **/
Gilles Peskine449bd832023-01-11 14:50:10 +0100275static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500276 mbedtls_pkcs7_signer_info *signer,
277 mbedtls_x509_buf *alg)
Daniel Axtens35384792020-09-02 14:48:45 +1000278{
Nick Childec817092022-12-15 15:54:03 -0600279 unsigned char *end_signer, *end_issuer_and_sn;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500280 int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000281 size_t len = 0;
282
Gilles Peskine449bd832023-01-11 14:50:10 +0100283 asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
284 | MBEDTLS_ASN1_SEQUENCE);
285 if (asn1_ret != 0) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500286 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 }
Daniel Axtens35384792020-09-02 14:48:45 +1000288
289 end_signer = *p + len;
290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 ret = pkcs7_get_version(p, end_signer, &signer->version);
292 if (ret != 0) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500293 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 }
Daniel Axtens35384792020-09-02 14:48:45 +1000295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len,
297 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
298 if (asn1_ret != 0) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500299 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 }
Daniel Axtens35384792020-09-02 14:48:45 +1000301
Nick Childec817092022-12-15 15:54:03 -0600302 end_issuer_and_sn = *p + len;
Daniel Axtens35384792020-09-02 14:48:45 +1000303 /* Parsing IssuerAndSerialNumber */
304 signer->issuer_raw.p = *p;
305
Nick Child3bd17f22023-01-31 20:42:26 +0000306 asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len,
Gilles Peskine449bd832023-01-11 14:50:10 +0100307 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
308 if (asn1_ret != 0) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500309 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 }
Daniel Axtens35384792020-09-02 14:48:45 +1000311
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 ret = mbedtls_x509_get_name(p, *p + len, &signer->issuer);
313 if (ret != 0) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500314 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100315 }
Daniel Axtens35384792020-09-02 14:48:45 +1000316
Dave Rodgmane4a6f5a2023-11-04 12:20:09 +0000317 signer->issuer_raw.len = (size_t) (*p - signer->issuer_raw.p);
Daniel Axtens35384792020-09-02 14:48:45 +1000318
Nick Child3bd17f22023-01-31 20:42:26 +0000319 ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial);
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 if (ret != 0) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500321 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100322 }
Daniel Axtens35384792020-09-02 14:48:45 +1000323
Nick Childec817092022-12-15 15:54:03 -0600324 /* ensure no extra or missing bytes */
325 if (*p != end_issuer_and_sn) {
326 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
327 goto out;
328 }
329
Gilles Peskine449bd832023-01-11 14:50:10 +0100330 ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier);
331 if (ret != 0) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500332 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100333 }
Daniel Axtens35384792020-09-02 14:48:45 +1000334
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500335 /* Check that the digest algorithm used matches the one provided earlier */
336 if (signer->alg_identifier.tag != alg->tag ||
337 signer->alg_identifier.len != alg->len ||
338 memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) {
339 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
340 goto out;
341 }
Nick Childbb82ab72022-10-28 12:28:54 -0500342
Tom Cosgrove5c8505f2023-03-07 11:39:52 +0000343 /* Assume authenticatedAttributes is nonexistent */
Gilles Peskine449bd832023-01-11 14:50:10 +0100344 ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier);
345 if (ret != 0) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500346 goto out;
Bence Szépkútif7641542022-12-12 21:37:36 +0100347 }
Nick Child9f4fb3e2022-09-12 16:21:02 -0500348
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 ret = pkcs7_get_signature(p, end_signer, &signer->sig);
350 if (ret != 0) {
351 goto out;
352 }
353
354 /* Do not permit any unauthenticated attributes */
355 if (*p != end_signer) {
356 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
357 }
358
359out:
360 if (asn1_ret != 0 || ret != 0) {
361 pkcs7_free_signer_info(signer);
362 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
363 asn1_ret);
364 }
365
366 return ret;
Daniel Axtens35384792020-09-02 14:48:45 +1000367}
368
Daniel Axtens35384792020-09-02 14:48:45 +1000369/**
370 * SignerInfos ::= SET of SignerInfo
Nayna Jainc9deb182020-11-16 19:03:12 +0000371 * Return number of signers added to the signed data,
372 * 0 or higher is valid.
373 * Return negative error code for failure.
374 **/
Gilles Peskine449bd832023-01-11 14:50:10 +0100375static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end,
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500376 mbedtls_pkcs7_signer_info *signers_set,
377 mbedtls_x509_buf *digest_alg)
Nayna Jainc9deb182020-11-16 19:03:12 +0000378{
Daniel Axtens35384792020-09-02 14:48:45 +1000379 unsigned char *end_set;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500380 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000381 int count = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000382 size_t len = 0;
383
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
385 | MBEDTLS_ASN1_SET);
386 if (ret != 0) {
387 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret);
Nick Child9f4fb3e2022-09-12 16:21:02 -0500388 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000389
Daniel Axtens35384792020-09-02 14:48:45 +1000390 /* Detect zero signers */
Gilles Peskine449bd832023-01-11 14:50:10 +0100391 if (len == 0) {
392 return 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500393 }
Daniel Axtens35384792020-09-02 14:48:45 +1000394
Nayna Jainc9deb182020-11-16 19:03:12 +0000395 end_set = *p + len;
396
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500397 ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg);
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 if (ret != 0) {
399 return ret;
400 }
Daniel Axtens35384792020-09-02 14:48:45 +1000401 count++;
Nayna Jainc9deb182020-11-16 19:03:12 +0000402
Gilles Peskine47a73262022-11-27 21:46:56 +0100403 mbedtls_pkcs7_signer_info *prev = signers_set;
Gilles Peskine449bd832023-01-11 14:50:10 +0100404 while (*p != end_set) {
Gilles Peskine47a73262022-11-27 21:46:56 +0100405 mbedtls_pkcs7_signer_info *signer =
Gilles Peskine449bd832023-01-11 14:50:10 +0100406 mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info));
407 if (!signer) {
Daniel Axtens35384792020-09-02 14:48:45 +1000408 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
409 goto cleanup;
410 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000411
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500412 ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg);
Gilles Peskine449bd832023-01-11 14:50:10 +0100413 if (ret != 0) {
414 mbedtls_free(signer);
Daniel Axtens35384792020-09-02 14:48:45 +1000415 goto cleanup;
416 }
417 prev->next = signer;
418 prev = signer;
419 count++;
420 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000421
Gilles Peskine449bd832023-01-11 14:50:10 +0100422 return count;
Nayna Jainc9deb182020-11-16 19:03:12 +0000423
Daniel Axtens35384792020-09-02 14:48:45 +1000424cleanup:
Gilles Peskine449bd832023-01-11 14:50:10 +0100425 pkcs7_free_signer_info(signers_set);
Gilles Peskine47a73262022-11-27 21:46:56 +0100426 mbedtls_pkcs7_signer_info *signer = signers_set->next;
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 while (signer != NULL) {
Daniel Axtens35384792020-09-02 14:48:45 +1000428 prev = signer;
429 signer = signer->next;
Gilles Peskine449bd832023-01-11 14:50:10 +0100430 pkcs7_free_signer_info(prev);
431 mbedtls_free(prev);
Daniel Axtens35384792020-09-02 14:48:45 +1000432 }
Gilles Peskine290f01b2022-11-27 21:28:31 +0100433 signers_set->next = NULL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100434 return ret;
Nayna Jainc9deb182020-11-16 19:03:12 +0000435}
436
437/**
438 * SignedData ::= SEQUENCE {
439 * version Version,
440 * digestAlgorithms DigestAlgorithmIdentifiers,
441 * contentInfo ContentInfo,
442 * certificates
443 * [0] IMPLICIT ExtendedCertificatesAndCertificates
444 * OPTIONAL,
445 * crls
446 * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
447 * signerInfos SignerInfos }
448 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100449static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen,
450 mbedtls_pkcs7_signed_data *signed_data)
Nayna Jainc9deb182020-11-16 19:03:12 +0000451{
452 unsigned char *p = buf;
453 unsigned char *end = buf + buflen;
Dave Rodgmanf6912682023-02-09 17:55:41 +0000454 unsigned char *end_content_info = NULL;
Nayna Jainc9deb182020-11-16 19:03:12 +0000455 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500456 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000457 mbedtls_md_type_t md_alg;
458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
460 | MBEDTLS_ASN1_SEQUENCE);
461 if (ret != 0) {
462 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
Nick Child9f4fb3e2022-09-12 16:21:02 -0500463 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000464
Demi Marie Obenour4ec83552022-11-28 00:23:00 -0500465 if (p + len != end) {
466 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
467 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
468 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000469
470 /* Get version of signed data */
Demi Marie Obenour4ec83552022-11-28 00:23:00 -0500471 ret = pkcs7_get_version(&p, end, &signed_data->version);
Gilles Peskine449bd832023-01-11 14:50:10 +0100472 if (ret != 0) {
473 return ret;
474 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000475
476 /* Get digest algorithm */
Demi Marie Obenour4ec83552022-11-28 00:23:00 -0500477 ret = pkcs7_get_digest_algorithm_set(&p, end,
Gilles Peskine449bd832023-01-11 14:50:10 +0100478 &signed_data->digest_alg_identifiers);
479 if (ret != 0) {
480 return ret;
481 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000482
Gilles Peskine532e3ee2025-05-07 20:37:15 +0200483 ret = mbedtls_x509_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg);
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 if (ret != 0) {
485 return MBEDTLS_ERR_PKCS7_INVALID_ALG;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500486 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000487
Demi Marie Obenoure373a252022-12-13 23:50:03 -0500488 mbedtls_pkcs7_buf content_type;
Dave Rodgmanf6912682023-02-09 17:55:41 +0000489 memset(&content_type, 0, sizeof(content_type));
Demi Marie Obenoure373a252022-12-13 23:50:03 -0500490 ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type);
Gilles Peskine449bd832023-01-11 14:50:10 +0100491 if (ret != 0) {
492 return ret;
493 }
Demi Marie Obenoure373a252022-12-13 23:50:03 -0500494 if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) {
495 return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
496 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000497
Nick Child3dafc6c2023-02-07 19:59:58 +0000498 if (p != end_content_info) {
499 /* Determine if valid content is present */
Dave Rodgman78c6f402023-02-09 09:21:14 +0000500 ret = mbedtls_asn1_get_tag(&p,
501 end_content_info,
502 &len,
503 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
Nick Child3dafc6c2023-02-07 19:59:58 +0000504 if (ret != 0) {
505 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
506 }
507 p += len;
508 if (p != end_content_info) {
509 return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
510 }
511 /* Valid content is present - this is not supported */
512 return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
Nick Childec817092022-12-15 15:54:03 -0600513 }
514
Nayna Jainc9deb182020-11-16 19:03:12 +0000515 /* Look for certificates, there may or may not be any */
Gilles Peskine449bd832023-01-11 14:50:10 +0100516 mbedtls_x509_crt_init(&signed_data->certs);
Demi Marie Obenour4ec83552022-11-28 00:23:00 -0500517 ret = pkcs7_get_certificates(&p, end, &signed_data->certs);
Gilles Peskine449bd832023-01-11 14:50:10 +0100518 if (ret < 0) {
519 return ret;
520 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000521
522 signed_data->no_of_certs = ret;
523
524 /*
525 * Currently CRLs are not supported. If CRL exist, the parsing will fail
526 * at next step of getting signers info and return error as invalid
527 * signer info.
528 */
529
530 signed_data->no_of_crls = 0;
531
532 /* Get signers info */
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500533 ret = pkcs7_get_signers_info_set(&p,
534 end,
535 &signed_data->signers,
536 &signed_data->digest_alg_identifiers);
Gilles Peskine449bd832023-01-11 14:50:10 +0100537 if (ret < 0) {
538 return ret;
539 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000540
541 signed_data->no_of_signers = ret;
542
Daniel Axtens35384792020-09-02 14:48:45 +1000543 /* Don't permit trailing data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100544 if (p != end) {
545 return MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
546 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000547
Gilles Peskine449bd832023-01-11 14:50:10 +0100548 return 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000549}
550
Gilles Peskine449bd832023-01-11 14:50:10 +0100551int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
552 const size_t buflen)
Nayna Jainc9deb182020-11-16 19:03:12 +0000553{
Nick Childbb82ab72022-10-28 12:28:54 -0500554 unsigned char *p;
Demi Marie Obenour4ec83552022-11-28 00:23:00 -0500555 unsigned char *end;
Nayna Jainc9deb182020-11-16 19:03:12 +0000556 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500557 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000558
Gilles Peskine449bd832023-01-11 14:50:10 +0100559 if (pkcs7 == NULL) {
560 return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500561 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000562
563 /* make an internal copy of the buffer for parsing */
Gilles Peskine449bd832023-01-11 14:50:10 +0100564 pkcs7->raw.p = p = mbedtls_calloc(1, buflen);
565 if (pkcs7->raw.p == NULL) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500566 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
567 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000568 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100569 memcpy(p, buf, buflen);
Nayna Jainc9deb182020-11-16 19:03:12 +0000570 pkcs7->raw.len = buflen;
Nick Childbb82ab72022-10-28 12:28:54 -0500571 end = p + buflen;
Nayna Jainc9deb182020-11-16 19:03:12 +0000572
Demi Marie Obenouraaf3c002022-11-28 00:20:42 -0500573 ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
574 | MBEDTLS_ASN1_SEQUENCE);
Gilles Peskine449bd832023-01-11 14:50:10 +0100575 if (ret != 0) {
Demi Marie Obenouraaf3c002022-11-28 00:20:42 -0500576 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
577 goto out;
578 }
579
580 if ((size_t) (end - p) != len) {
581 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
582 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
583 goto out;
584 }
585
586 if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
587 if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
588 goto out;
589 }
590 p = pkcs7->raw.p;
Nayna Jain673a2262020-12-14 22:44:49 +0000591 len = buflen;
592 goto try_data;
593 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000594
Demi Marie Obenouraaf3c002022-11-28 00:20:42 -0500595 if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) {
Dave Rodgmana1b2bff2023-02-20 14:45:09 +0000596 /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */
Demi Marie Obenouraaf3c002022-11-28 00:20:42 -0500597 if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len)
598 || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len)
599 || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len)
600 || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len)
601 || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) {
Dave Rodgmana1b2bff2023-02-20 14:45:09 +0000602 /* OID is valid according to the spec, but unsupported */
Demi Marie Obenouraaf3c002022-11-28 00:20:42 -0500603 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
604 } else {
Dave Rodgmana1b2bff2023-02-20 14:45:09 +0000605 /* OID is invalid according to the spec */
Demi Marie Obenouraaf3c002022-11-28 00:20:42 -0500606 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
607 }
Nick Childec817092022-12-15 15:54:03 -0600608 goto out;
609 }
610
Demi Marie Obenouraaf3c002022-11-28 00:20:42 -0500611 p += len;
Nayna Jainc9deb182020-11-16 19:03:12 +0000612
Gilles Peskine449bd832023-01-11 14:50:10 +0100613 ret = pkcs7_get_next_content_len(&p, end, &len);
614 if (ret != 0) {
Nayna Jainc9deb182020-11-16 19:03:12 +0000615 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100616 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000617
Nick Childec817092022-12-15 15:54:03 -0600618 /* ensure no extra/missing data */
619 if (p + len != end) {
620 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
621 goto out;
622 }
623
Nayna Jain673a2262020-12-14 22:44:49 +0000624try_data:
Gilles Peskine449bd832023-01-11 14:50:10 +0100625 ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data);
626 if (ret != 0) {
Nayna Jain673a2262020-12-14 22:44:49 +0000627 goto out;
Gilles Peskine449bd832023-01-11 14:50:10 +0100628 }
Nayna Jain673a2262020-12-14 22:44:49 +0000629
Nayna Jain673a2262020-12-14 22:44:49 +0000630 ret = MBEDTLS_PKCS7_SIGNED_DATA;
Nayna Jainc9deb182020-11-16 19:03:12 +0000631
632out:
Gilles Peskine449bd832023-01-11 14:50:10 +0100633 if (ret < 0) {
634 mbedtls_pkcs7_free(pkcs7);
635 }
Nayna Jain673a2262020-12-14 22:44:49 +0000636
Gilles Peskine449bd832023-01-11 14:50:10 +0100637 return ret;
Nayna Jainc9deb182020-11-16 19:03:12 +0000638}
639
Gilles Peskine449bd832023-01-11 14:50:10 +0100640static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
Nick Child73621ef2022-10-28 11:23:15 -0500641 const mbedtls_x509_crt *cert,
642 const unsigned char *data,
643 size_t datalen,
Gilles Peskine449bd832023-01-11 14:50:10 +0100644 const int is_data_hash)
Nayna Jainc9deb182020-11-16 19:03:12 +0000645{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500646 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000647 unsigned char *hash;
648 mbedtls_pk_context pk_cxt = cert->pk;
649 const mbedtls_md_info_t *md_info;
650 mbedtls_md_type_t md_alg;
Daniel Axtens35384792020-09-02 14:48:45 +1000651 mbedtls_pkcs7_signer_info *signer;
Nayna Jainc9deb182020-11-16 19:03:12 +0000652
Gilles Peskine449bd832023-01-11 14:50:10 +0100653 if (pkcs7->signed_data.no_of_signers == 0) {
654 return MBEDTLS_ERR_PKCS7_INVALID_CERT;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500655 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000656
Gilles Peskine449bd832023-01-11 14:50:10 +0100657 if (mbedtls_x509_time_is_past(&cert->valid_to) ||
658 mbedtls_x509_time_is_future(&cert->valid_from)) {
659 return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
Nick Child73621ef2022-10-28 11:23:15 -0500660 }
661
Gilles Peskine532e3ee2025-05-07 20:37:15 +0200662 ret = mbedtls_x509_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg);
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500663 if (ret != 0) {
664 return ret;
665 }
666
667 md_info = mbedtls_md_info_from_type(md_alg);
668 if (md_info == NULL) {
669 return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
670 }
671
672 hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);
673 if (hash == NULL) {
674 return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
675 }
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500676
Dave Rodgmanfc643522023-02-16 16:23:09 +0000677 /* BEGIN must free hash before jumping out */
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500678 if (is_data_hash) {
679 if (datalen != mbedtls_md_get_size(md_info)) {
680 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
681 } else {
682 memcpy(hash, data, datalen);
683 }
684 } else {
685 ret = mbedtls_md(md_info, data, datalen, hash);
686 }
687 if (ret != 0) {
688 mbedtls_free(hash);
689 return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
690 }
691
692 /* assume failure */
693 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
694
Daniel Axtens35384792020-09-02 14:48:45 +1000695 /*
696 * Potential TODOs
697 * Currently we iterate over all signers and return success if any of them
698 * verify.
699 *
700 * However, we could make this better by checking against the certificate's
701 * identification and SignerIdentifier fields first. That would also allow
702 * us to distinguish between 'no signature for key' and 'signature for key
703 * failed to validate'.
Daniel Axtens35384792020-09-02 14:48:45 +1000704 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100705 for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) {
Gilles Peskine449bd832023-01-11 14:50:10 +0100706 ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash,
707 mbedtls_md_get_size(md_info),
708 signer->sig.p, signer->sig.len);
Daniel Axtens35384792020-09-02 14:48:45 +1000709
Gilles Peskine449bd832023-01-11 14:50:10 +0100710 if (ret == 0) {
Daniel Axtens35384792020-09-02 14:48:45 +1000711 break;
Gilles Peskine449bd832023-01-11 14:50:10 +0100712 }
Daniel Axtens35384792020-09-02 14:48:45 +1000713 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000714
Demi Marie Obenour35598ad2022-11-30 02:06:07 -0500715 mbedtls_free(hash);
716 /* END must free hash before jumping out */
Gilles Peskine449bd832023-01-11 14:50:10 +0100717 return ret;
Nayna Jainc9deb182020-11-16 19:03:12 +0000718}
Demi Marie Obenour6cfc4692022-11-28 00:46:00 -0500719
Gilles Peskine449bd832023-01-11 14:50:10 +0100720int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
721 const mbedtls_x509_crt *cert,
722 const unsigned char *data,
723 size_t datalen)
Nick Child73621ef2022-10-28 11:23:15 -0500724{
Demi Marie Obenour6cfc4692022-11-28 00:46:00 -0500725 if (data == NULL) {
726 return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
727 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);
Nick Child73621ef2022-10-28 11:23:15 -0500729}
Nayna Jainc9deb182020-11-16 19:03:12 +0000730
Gilles Peskine449bd832023-01-11 14:50:10 +0100731int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,
732 const mbedtls_x509_crt *cert,
733 const unsigned char *hash,
734 size_t hashlen)
Nayna Jainc9deb182020-11-16 19:03:12 +0000735{
Demi Marie Obenour6cfc4692022-11-28 00:46:00 -0500736 if (hash == NULL) {
737 return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
738 }
Gilles Peskine449bd832023-01-11 14:50:10 +0100739 return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1);
Nayna Jainc9deb182020-11-16 19:03:12 +0000740}
741
742/*
743 * Unallocate all pkcs7 data
744 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100745void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7)
Nayna Jainc9deb182020-11-16 19:03:12 +0000746{
Daniel Axtens35384792020-09-02 14:48:45 +1000747 mbedtls_pkcs7_signer_info *signer_cur;
748 mbedtls_pkcs7_signer_info *signer_prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000749
Gilles Peskine449bd832023-01-11 14:50:10 +0100750 if (pkcs7 == NULL || pkcs7->raw.p == NULL) {
Nayna Jainc9deb182020-11-16 19:03:12 +0000751 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100752 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000753
Gilles Peskine449bd832023-01-11 14:50:10 +0100754 mbedtls_free(pkcs7->raw.p);
Nayna Jainc9deb182020-11-16 19:03:12 +0000755
Gilles Peskine449bd832023-01-11 14:50:10 +0100756 mbedtls_x509_crt_free(&pkcs7->signed_data.certs);
757 mbedtls_x509_crl_free(&pkcs7->signed_data.crl);
Nayna Jainc9deb182020-11-16 19:03:12 +0000758
Daniel Axtens35384792020-09-02 14:48:45 +1000759 signer_cur = pkcs7->signed_data.signers.next;
Gilles Peskine449bd832023-01-11 14:50:10 +0100760 pkcs7_free_signer_info(&pkcs7->signed_data.signers);
761 while (signer_cur != NULL) {
Daniel Axtens35384792020-09-02 14:48:45 +1000762 signer_prev = signer_cur;
763 signer_cur = signer_prev->next;
Gilles Peskine449bd832023-01-11 14:50:10 +0100764 pkcs7_free_signer_info(signer_prev);
765 mbedtls_free(signer_prev);
Nayna Jainc9deb182020-11-16 19:03:12 +0000766 }
767
768 pkcs7->raw.p = NULL;
769}
770
771#endif