blob: fc6dd33f3d8ce4a526ffb6f23c25c8bbd34a7ddc [file] [log] [blame]
Nick Child5d881c32022-02-28 10:09:16 -06001/*
2 * Copyright The Mbed TLS Contributors
3 * SPDX-License-Identifier: Apache-2.0
Nayna Jainc9deb182020-11-16 19:03:12 +00004 *
Nick Child5d881c32022-02-28 10:09:16 -06005 * 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
Nayna Jainc9deb182020-11-16 19:03:12 +00008 *
Nick Child5d881c32022-02-28 10:09:16 -06009 * http://www.apache.org/licenses/LICENSE-2.0
Nayna Jainc9deb182020-11-16 19:03:12 +000010 *
Nick Child5d881c32022-02-28 10:09:16 -060011 * 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.
Nayna Jainc9deb182020-11-16 19:03:12 +000016 */
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"
Nick Child9f4fb3e2022-09-12 16:21:02 -050027#include "mbedtls/error.h"
Nayna Jainc9deb182020-11-16 19:03:12 +000028
29#include <stdlib.h>
30#include <stdio.h>
31#include <string.h>
32#if defined(MBEDTLS_FS_IO)
33#include <sys/types.h>
34#include <sys/stat.h>
35#endif
36
Nayna Jainc9deb182020-11-16 19:03:12 +000037#include "mbedtls/platform.h"
38#include "mbedtls/platform_util.h"
Nayna Jainc9deb182020-11-16 19:03:12 +000039
40#if defined(MBEDTLS_HAVE_TIME)
41#include "mbedtls/platform_time.h"
42#endif
43#if defined(MBEDTLS_HAVE_TIME_DATE)
44#include <time.h>
45#endif
46
47/**
48 * Initializes the pkcs7 structure.
49 */
50void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 )
51{
Nick Child8ce1b1a2022-09-14 14:51:23 -050052 memset( pkcs7, 0, sizeof( *pkcs7 ) );
Nayna Jainc9deb182020-11-16 19:03:12 +000053}
54
55static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end,
56 size_t *len )
57{
Nick Child9f4fb3e2022-09-12 16:21:02 -050058 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +000059
Nick Child9f4fb3e2022-09-12 16:21:02 -050060 ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED
61 | MBEDTLS_ASN1_CONTEXT_SPECIFIC );
62 if( ret != 0 )
Nayna Jainc9deb182020-11-16 19:03:12 +000063 {
Nick Child9f4fb3e2022-09-12 16:21:02 -050064 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000065 }
66
Nick Child9f4fb3e2022-09-12 16:21:02 -050067 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000068}
69
70/**
71 * version Version
72 * Version ::= INTEGER
73 **/
74static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver )
75{
Nick Child9f4fb3e2022-09-12 16:21:02 -050076 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +000077
Nick Child9f4fb3e2022-09-12 16:21:02 -050078 ret = mbedtls_asn1_get_int( p, end, ver );
79 if( ret != 0 )
80 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000081
82 /* If version != 1, return invalid version */
83 if( *ver != MBEDTLS_PKCS7_SUPPORTED_VERSION )
Nick Child9f4fb3e2022-09-12 16:21:02 -050084 ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
Nayna Jainc9deb182020-11-16 19:03:12 +000085
Nick Child9f4fb3e2022-09-12 16:21:02 -050086 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000087}
88
89/**
90 * ContentInfo ::= SEQUENCE {
91 * contentType ContentType,
92 * content
93 * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
94 **/
95static int pkcs7_get_content_info_type( unsigned char **p, unsigned char *end,
96 mbedtls_pkcs7_buf *pkcs7 )
97{
98 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -050099 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jain673a2262020-12-14 22:44:49 +0000100 unsigned char *start = *p;
Nayna Jainc9deb182020-11-16 19:03:12 +0000101
102 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
103 | MBEDTLS_ASN1_SEQUENCE );
Nick Childc448c942021-07-01 15:29:50 -0400104 if( ret != 0 ) {
105 *p = start;
Gilles Peskine47a73262022-11-27 21:46:56 +0100106 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret ) );
Nick Childc448c942021-07-01 15:29:50 -0400107 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000108
109 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
Nayna Jain673a2262020-12-14 22:44:49 +0000110 if( ret != 0 ) {
111 *p = start;
Gilles Peskine47a73262022-11-27 21:46:56 +0100112 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret ) );
Nayna Jain673a2262020-12-14 22:44:49 +0000113 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000114
115 pkcs7->tag = MBEDTLS_ASN1_OID;
116 pkcs7->len = len;
117 pkcs7->p = *p;
Nick Childbb82ab72022-10-28 12:28:54 -0500118 *p += len;
Nayna Jainc9deb182020-11-16 19:03:12 +0000119
120 return( ret );
121}
122
123/**
124 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
125 *
126 * This is from x509.h
127 **/
128static int pkcs7_get_digest_algorithm( unsigned char **p, unsigned char *end,
129 mbedtls_x509_buf *alg )
130{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500131 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000132
133 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500134 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000135
Nick Child9f4fb3e2022-09-12 16:21:02 -0500136 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000137}
138
139/**
140 * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
141 **/
142static int pkcs7_get_digest_algorithm_set( unsigned char **p,
143 unsigned char *end,
144 mbedtls_x509_buf *alg )
145{
146 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500147 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000148
149 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
150 | MBEDTLS_ASN1_SET );
151 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500152 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100153 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret ) );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500154 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000155
156 end = *p + len;
157
Nayna Jainc9deb182020-11-16 19:03:12 +0000158 ret = mbedtls_asn1_get_alg_null( p, end, alg );
159 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500160 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100161 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret ) );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500162 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000163
Nick Child34d5e932022-09-14 14:44:03 -0500164 /** For now, it assumes there is only one digest algorithm specified **/
Nayna Jainc9deb182020-11-16 19:03:12 +0000165 if ( *p != end )
Gilles Peskine47a73262022-11-27 21:46:56 +0100166 return( MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE );
Nayna Jainc9deb182020-11-16 19:03:12 +0000167
Gilles Peskine47a73262022-11-27 21:46:56 +0100168 return( 0 );
Nayna Jainc9deb182020-11-16 19:03:12 +0000169}
170
171/**
172 * certificates :: SET OF ExtendedCertificateOrCertificate,
173 * ExtendedCertificateOrCertificate ::= CHOICE {
174 * certificate Certificate -- x509,
175 * extendedCertificate[0] IMPLICIT ExtendedCertificate }
176 * Return number of certificates added to the signed data,
177 * 0 or higher is valid.
178 * Return negative error code for failure.
179 **/
180static int pkcs7_get_certificates( unsigned char **p, unsigned char *end,
181 mbedtls_x509_crt *certs )
182{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500183 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000184 size_t len1 = 0;
185 size_t len2 = 0;
Nick Childbb82ab72022-10-28 12:28:54 -0500186 unsigned char *end_set, *end_cert, *start;
Nayna Jainc9deb182020-11-16 19:03:12 +0000187
188 if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
189 | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
190 {
191 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Gilles Peskine47a73262022-11-27 21:46:56 +0100192 return( 0 );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500193 else
Gilles Peskine47a73262022-11-27 21:46:56 +0100194 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret ) );
Nayna Jainc9deb182020-11-16 19:03:12 +0000195 }
196 start = *p;
197 end_set = *p + len1;
198
199 ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
200 | MBEDTLS_ASN1_SEQUENCE );
201 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500202 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100203 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CERT, ret ) );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500204 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000205
206 end_cert = *p + len2;
207
208 /*
209 * This is to verify that there is only one signer certificate. It seems it is
210 * not easy to differentiate between the chain vs different signer's certificate.
211 * So, we support only the root certificate and the single signer.
212 * The behaviour would be improved with addition of multiple signer support.
213 */
Nick Child8ce1b1a2022-09-14 14:51:23 -0500214 if ( end_cert != end_set )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500215 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100216 return( MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500217 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000218
219 *p = start;
Nick Childbb82ab72022-10-28 12:28:54 -0500220 if( ( ret = mbedtls_x509_crt_parse_der( certs, *p, len1 ) ) < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500221 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100222 return( MBEDTLS_ERR_PKCS7_INVALID_CERT );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500223 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000224
225 *p = *p + len1;
226
Nick Child5f9456f2022-09-19 10:01:25 -0500227 /*
Nick Child9f4fb3e2022-09-12 16:21:02 -0500228 * Since in this version we strictly support single certificate, and reaching
Nick Child5f9456f2022-09-19 10:01:25 -0500229 * here implies we have parsed successfully, we return 1.
Nick Child9f4fb3e2022-09-12 16:21:02 -0500230 */
Gilles Peskine47a73262022-11-27 21:46:56 +0100231 return( 1 );
Nayna Jainc9deb182020-11-16 19:03:12 +0000232}
233
234/**
235 * EncryptedDigest ::= OCTET STRING
236 **/
237static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
238 mbedtls_pkcs7_buf *signature )
239{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500240 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000241 size_t len = 0;
242
243 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING );
244 if( ret != 0 )
Gilles Peskine47a73262022-11-27 21:46:56 +0100245 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000246
247 signature->tag = MBEDTLS_ASN1_OCTET_STRING;
248 signature->len = len;
249 signature->p = *p;
250
251 *p = *p + len;
252
Gilles Peskine47a73262022-11-27 21:46:56 +0100253 return( 0 );
Nayna Jainc9deb182020-11-16 19:03:12 +0000254}
255
256/**
Nayna Jainc9deb182020-11-16 19:03:12 +0000257 * SignerInfo ::= SEQUENCE {
258 * version Version;
259 * issuerAndSerialNumber IssuerAndSerialNumber,
260 * digestAlgorithm DigestAlgorithmIdentifier,
261 * authenticatedAttributes
262 * [0] IMPLICIT Attributes OPTIONAL,
263 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
264 * encryptedDigest EncryptedDigest,
265 * unauthenticatedAttributes
266 * [1] IMPLICIT Attributes OPTIONAL,
Daniel Axtens35384792020-09-02 14:48:45 +1000267 * Returns 0 if the signerInfo is valid.
268 * Return negative error code for failure.
Nick Childbb82ab72022-10-28 12:28:54 -0500269 * Structure must not contain vales for authenticatedAttributes
270 * and unauthenticatedAttributes.
Daniel Axtens35384792020-09-02 14:48:45 +1000271 **/
272static int pkcs7_get_signer_info( unsigned char **p, unsigned char *end,
273 mbedtls_pkcs7_signer_info *signer )
274{
275 unsigned char *end_signer;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500276 int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000277 size_t len = 0;
278
Nick Child9f4fb3e2022-09-12 16:21:02 -0500279 asn1_ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
Daniel Axtens35384792020-09-02 14:48:45 +1000280 | MBEDTLS_ASN1_SEQUENCE );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500281 if( asn1_ret != 0 )
282 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000283
284 end_signer = *p + len;
285
286 ret = pkcs7_get_version( p, end_signer, &signer->version );
287 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500288 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000289
Nick Child9f4fb3e2022-09-12 16:21:02 -0500290 asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
291 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
292 if( asn1_ret != 0 )
293 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000294
295 /* Parsing IssuerAndSerialNumber */
296 signer->issuer_raw.p = *p;
297
Nick Child9f4fb3e2022-09-12 16:21:02 -0500298 asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
299 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
300 if( asn1_ret != 0 )
301 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000302
303 ret = mbedtls_x509_get_name( p, *p + len, &signer->issuer );
304 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500305 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000306
307 signer->issuer_raw.len = *p - signer->issuer_raw.p;
308
309 ret = mbedtls_x509_get_serial( p, end_signer, &signer->serial );
310 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500311 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000312
313 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->alg_identifier );
314 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500315 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000316
Nick Childbb82ab72022-10-28 12:28:54 -0500317 /* Asssume authenticatedAttributes is nonexistent */
318
Daniel Axtens35384792020-09-02 14:48:45 +1000319 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->sig_alg_identifier );
320 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500321 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000322
323 ret = pkcs7_get_signature( p, end_signer, &signer->sig );
324 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500325 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000326
327 /* Do not permit any unauthenticated attributes */
328 if( *p != end_signer )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500329 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
Daniel Axtens35384792020-09-02 14:48:45 +1000330
Nick Child9f4fb3e2022-09-12 16:21:02 -0500331out:
332 if( asn1_ret != 0 )
333 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
334 asn1_ret );
335 else if( ret != 0 )
336 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
337
338 return( ret );
Daniel Axtens35384792020-09-02 14:48:45 +1000339}
340
341static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer )
342{
343 mbedtls_x509_name *name_cur;
344 mbedtls_x509_name *name_prv;
345
346 if( signer == NULL )
347 return;
348
349 name_cur = signer->issuer.next;
350 while( name_cur != NULL )
351 {
352 name_prv = name_cur;
353 name_cur = name_cur->next;
354 mbedtls_free( name_prv );
355 }
Gilles Peskinee7f8c612022-11-27 21:51:19 +0100356 signer->issuer.next = NULL;
Daniel Axtens35384792020-09-02 14:48:45 +1000357}
358
359/**
360 * SignerInfos ::= SET of SignerInfo
Nayna Jainc9deb182020-11-16 19:03:12 +0000361 * Return number of signers added to the signed data,
362 * 0 or higher is valid.
363 * Return negative error code for failure.
364 **/
365static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end,
366 mbedtls_pkcs7_signer_info *signers_set )
367{
Daniel Axtens35384792020-09-02 14:48:45 +1000368 unsigned char *end_set;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500369 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000370 int count = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000371 size_t len = 0;
372
373 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
374 | MBEDTLS_ASN1_SET );
375 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500376 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100377 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret ) );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500378 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000379
Daniel Axtens35384792020-09-02 14:48:45 +1000380 /* Detect zero signers */
381 if( len == 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500382 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100383 return( 0 );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500384 }
Daniel Axtens35384792020-09-02 14:48:45 +1000385
Nayna Jainc9deb182020-11-16 19:03:12 +0000386 end_set = *p + len;
387
Daniel Axtens35384792020-09-02 14:48:45 +1000388 ret = pkcs7_get_signer_info( p, end_set, signers_set );
Nayna Jainc9deb182020-11-16 19:03:12 +0000389 if( ret != 0 )
Gilles Peskine47a73262022-11-27 21:46:56 +0100390 return( ret );
Daniel Axtens35384792020-09-02 14:48:45 +1000391 count++;
Nayna Jainc9deb182020-11-16 19:03:12 +0000392
Gilles Peskine47a73262022-11-27 21:46:56 +0100393 mbedtls_pkcs7_signer_info *prev = signers_set;
Daniel Axtens35384792020-09-02 14:48:45 +1000394 while( *p != end_set )
395 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100396 mbedtls_pkcs7_signer_info *signer =
397 mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) );
Daniel Axtens35384792020-09-02 14:48:45 +1000398 if( !signer )
399 {
400 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
401 goto cleanup;
402 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000403
Daniel Axtens35384792020-09-02 14:48:45 +1000404 ret = pkcs7_get_signer_info( p, end_set, signer );
405 if( ret != 0 ) {
406 mbedtls_free( signer );
407 goto cleanup;
408 }
409 prev->next = signer;
410 prev = signer;
411 count++;
412 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000413
Gilles Peskine47a73262022-11-27 21:46:56 +0100414 return( count );
Nayna Jainc9deb182020-11-16 19:03:12 +0000415
Daniel Axtens35384792020-09-02 14:48:45 +1000416cleanup:
Daniel Axtens35384792020-09-02 14:48:45 +1000417 pkcs7_free_signer_info( signers_set );
Gilles Peskine47a73262022-11-27 21:46:56 +0100418 mbedtls_pkcs7_signer_info *signer = signers_set->next;
Gilles Peskine290f01b2022-11-27 21:28:31 +0100419 while( signer != NULL )
Daniel Axtens35384792020-09-02 14:48:45 +1000420 {
421 prev = signer;
422 signer = signer->next;
423 pkcs7_free_signer_info( prev );
424 mbedtls_free( prev );
425 }
Gilles Peskine290f01b2022-11-27 21:28:31 +0100426 signers_set->next = NULL;
Daniel Axtens35384792020-09-02 14:48:45 +1000427 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000428}
429
430/**
431 * SignedData ::= SEQUENCE {
432 * version Version,
433 * digestAlgorithms DigestAlgorithmIdentifiers,
434 * contentInfo ContentInfo,
435 * certificates
436 * [0] IMPLICIT ExtendedCertificatesAndCertificates
437 * OPTIONAL,
438 * crls
439 * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
440 * signerInfos SignerInfos }
441 */
442static int pkcs7_get_signed_data( unsigned char *buf, size_t buflen,
443 mbedtls_pkcs7_signed_data *signed_data )
444{
445 unsigned char *p = buf;
446 unsigned char *end = buf + buflen;
447 unsigned char *end_set;
448 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500449 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000450 mbedtls_md_type_t md_alg;
451
452 ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
453 | MBEDTLS_ASN1_SEQUENCE );
454 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500455 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100456 return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret ) );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500457 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000458
459 end_set = p + len;
460
461 /* Get version of signed data */
462 ret = pkcs7_get_version( &p, end_set, &signed_data->version );
463 if( ret != 0 )
Gilles Peskine47a73262022-11-27 21:46:56 +0100464 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000465
466 /* Get digest algorithm */
467 ret = pkcs7_get_digest_algorithm_set( &p, end_set,
468 &signed_data->digest_alg_identifiers );
469 if( ret != 0 )
Gilles Peskine47a73262022-11-27 21:46:56 +0100470 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000471
472 ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
473 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500474 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100475 return( MBEDTLS_ERR_PKCS7_INVALID_ALG );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500476 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000477
478 /* Do not expect any content */
479 ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
480 if( ret != 0 )
Gilles Peskine47a73262022-11-27 21:46:56 +0100481 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000482
483 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
484 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100485 return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO );
Nayna Jainc9deb182020-11-16 19:03:12 +0000486 }
487
Nayna Jainc9deb182020-11-16 19:03:12 +0000488 /* Look for certificates, there may or may not be any */
489 mbedtls_x509_crt_init( &signed_data->certs );
490 ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs );
491 if( ret < 0 )
Gilles Peskine47a73262022-11-27 21:46:56 +0100492 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000493
494 signed_data->no_of_certs = ret;
495
496 /*
497 * Currently CRLs are not supported. If CRL exist, the parsing will fail
498 * at next step of getting signers info and return error as invalid
499 * signer info.
500 */
501
502 signed_data->no_of_crls = 0;
503
504 /* Get signers info */
505 ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers );
506 if( ret < 0 )
Gilles Peskine47a73262022-11-27 21:46:56 +0100507 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000508
509 signed_data->no_of_signers = ret;
510
Daniel Axtens35384792020-09-02 14:48:45 +1000511 /* Don't permit trailing data */
Nayna Jainc9deb182020-11-16 19:03:12 +0000512 if ( p != end )
Gilles Peskine47a73262022-11-27 21:46:56 +0100513 return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT );
Nayna Jainc9deb182020-11-16 19:03:12 +0000514
Gilles Peskine47a73262022-11-27 21:46:56 +0100515 return( 0 );
Nayna Jainc9deb182020-11-16 19:03:12 +0000516}
517
518int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
519 const size_t buflen )
520{
Nick Childbb82ab72022-10-28 12:28:54 -0500521 unsigned char *p;
Nayna Jainc9deb182020-11-16 19:03:12 +0000522 unsigned char *end;
523 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500524 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jain673a2262020-12-14 22:44:49 +0000525 int isoidset = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000526
Gilles Peskine47a73262022-11-27 21:46:56 +0100527 if( pkcs7 == NULL )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500528 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100529 return( MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500530 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000531
532 /* make an internal copy of the buffer for parsing */
Nick Childbb82ab72022-10-28 12:28:54 -0500533 pkcs7->raw.p = p = mbedtls_calloc( 1, buflen );
Nayna Jainc9deb182020-11-16 19:03:12 +0000534 if( pkcs7->raw.p == NULL )
535 {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500536 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
537 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000538 }
Nick Childbb82ab72022-10-28 12:28:54 -0500539 memcpy( p, buf, buflen );
Nayna Jainc9deb182020-11-16 19:03:12 +0000540 pkcs7->raw.len = buflen;
Nick Childbb82ab72022-10-28 12:28:54 -0500541 end = p + buflen;
Nayna Jainc9deb182020-11-16 19:03:12 +0000542
Nick Childbb82ab72022-10-28 12:28:54 -0500543 ret = pkcs7_get_content_info_type( &p, end, &pkcs7->content_type_oid );
Nayna Jainc9deb182020-11-16 19:03:12 +0000544 if( ret != 0 )
Nayna Jain673a2262020-12-14 22:44:49 +0000545 {
546 len = buflen;
547 goto try_data;
548 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000549
550 if( ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid )
551 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid )
552 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid )
553 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid )
554 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid )
555 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) )
556 {
557 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
558 goto out;
559 }
560
561 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid ) )
562 {
563 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
564 goto out;
565 }
566
Nayna Jain673a2262020-12-14 22:44:49 +0000567 isoidset = 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000568
Nick Childbb82ab72022-10-28 12:28:54 -0500569 ret = pkcs7_get_next_content_len( &p, end, &len );
Nayna Jainc9deb182020-11-16 19:03:12 +0000570 if( ret != 0 )
571 goto out;
572
Nayna Jain673a2262020-12-14 22:44:49 +0000573try_data:
Nick Childbb82ab72022-10-28 12:28:54 -0500574 ret = pkcs7_get_signed_data( p, len, &pkcs7->signed_data );
Nayna Jain673a2262020-12-14 22:44:49 +0000575 if ( ret != 0 )
576 goto out;
577
578 if ( !isoidset )
579 {
580 pkcs7->content_type_oid.tag = MBEDTLS_ASN1_OID;
581 pkcs7->content_type_oid.len = MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS7_SIGNED_DATA );
582 pkcs7->content_type_oid.p = (unsigned char *)MBEDTLS_OID_PKCS7_SIGNED_DATA;
583 }
584
585 ret = MBEDTLS_PKCS7_SIGNED_DATA;
Nayna Jainc9deb182020-11-16 19:03:12 +0000586
587out:
Nayna Jain673a2262020-12-14 22:44:49 +0000588 if ( ret < 0 )
Nayna Jainc9deb182020-11-16 19:03:12 +0000589 mbedtls_pkcs7_free( pkcs7 );
Nayna Jain673a2262020-12-14 22:44:49 +0000590
Nayna Jainc9deb182020-11-16 19:03:12 +0000591 return( ret );
592}
593
Nick Child73621ef2022-10-28 11:23:15 -0500594static int mbedtls_pkcs7_data_or_hash_verify( mbedtls_pkcs7 *pkcs7,
595 const mbedtls_x509_crt *cert,
596 const unsigned char *data,
597 size_t datalen,
598 const int is_data_hash )
Nayna Jainc9deb182020-11-16 19:03:12 +0000599{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500600 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000601 unsigned char *hash;
602 mbedtls_pk_context pk_cxt = cert->pk;
603 const mbedtls_md_info_t *md_info;
604 mbedtls_md_type_t md_alg;
Daniel Axtens35384792020-09-02 14:48:45 +1000605 mbedtls_pkcs7_signer_info *signer;
Nayna Jainc9deb182020-11-16 19:03:12 +0000606
Daniel Axtens35384792020-09-02 14:48:45 +1000607 if( pkcs7->signed_data.no_of_signers == 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500608 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100609 return( MBEDTLS_ERR_PKCS7_INVALID_CERT );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500610 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000611
Nick Child73621ef2022-10-28 11:23:15 -0500612 if( mbedtls_x509_time_is_past( &cert->valid_to ) ||
613 mbedtls_x509_time_is_future( &cert->valid_from ))
614 {
Gilles Peskine47a73262022-11-27 21:46:56 +0100615 return( MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID );
Nick Child73621ef2022-10-28 11:23:15 -0500616 }
617
Daniel Axtens35384792020-09-02 14:48:45 +1000618 /*
619 * Potential TODOs
620 * Currently we iterate over all signers and return success if any of them
621 * verify.
622 *
623 * However, we could make this better by checking against the certificate's
624 * identification and SignerIdentifier fields first. That would also allow
625 * us to distinguish between 'no signature for key' and 'signature for key
626 * failed to validate'.
627 *
628 * We could also cache hashes by md, so if there are several sigs all using
629 * the same algo we don't recalculate the hash each time.
630 */
Nick Child7089ce82022-09-14 14:10:00 -0500631 for( signer = &pkcs7->signed_data.signers; signer; signer = signer->next )
Nick Child66718412022-02-22 17:19:59 -0600632 {
Daniel Axtens35384792020-09-02 14:48:45 +1000633 ret = mbedtls_oid_get_md_alg( &signer->alg_identifier, &md_alg );
634 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500635 {
636 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Nick Child7089ce82022-09-14 14:10:00 -0500637 continue;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500638 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000639
Daniel Axtens35384792020-09-02 14:48:45 +1000640 md_info = mbedtls_md_info_from_type( md_alg );
Nick Child7089ce82022-09-14 14:10:00 -0500641 if( md_info == NULL )
642 {
643 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
644 continue;
645 }
Daniel Axtens35384792020-09-02 14:48:45 +1000646
647 hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
648 if( hash == NULL ) {
Gilles Peskine47a73262022-11-27 21:46:56 +0100649 return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
Daniel Axtens35384792020-09-02 14:48:45 +1000650 }
Gilles Peskine47a73262022-11-27 21:46:56 +0100651 /* BEGIN must free hash before jumping out */
Nick Child73621ef2022-10-28 11:23:15 -0500652 if( is_data_hash )
653 {
654 if( datalen != mbedtls_md_get_size( md_info ))
655 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
656 else
657 memcpy(hash, data, datalen);
658 }
659 else
660 {
661 ret = mbedtls_md( md_info, data, datalen, hash );
662 }
Daniel Axtens35384792020-09-02 14:48:45 +1000663 if( ret != 0 )
664 {
Nick Child7089ce82022-09-14 14:10:00 -0500665 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Daniel Axtens35384792020-09-02 14:48:45 +1000666 mbedtls_free( hash );
Nick Child7089ce82022-09-14 14:10:00 -0500667 continue;
Daniel Axtens35384792020-09-02 14:48:45 +1000668 }
669
670 ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash,
671 mbedtls_md_get_size( md_info ),
672 signer->sig.p, signer->sig.len );
Daniel Axtens35384792020-09-02 14:48:45 +1000673 mbedtls_free( hash );
Gilles Peskine47a73262022-11-27 21:46:56 +0100674 /* END must free hash before jumping out */
Daniel Axtens35384792020-09-02 14:48:45 +1000675
676 if( ret == 0 )
677 break;
Daniel Axtens35384792020-09-02 14:48:45 +1000678 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000679
680 return( ret );
681}
Nick Child73621ef2022-10-28 11:23:15 -0500682int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
683 const mbedtls_x509_crt *cert,
684 const unsigned char *data,
685 size_t datalen )
686{
687 return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, data, datalen, 0 ) );
688}
Nayna Jainc9deb182020-11-16 19:03:12 +0000689
690int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
691 const mbedtls_x509_crt *cert,
Nick Child5f9456f2022-09-19 10:01:25 -0500692 const unsigned char *hash,
Nick Child8ce1b1a2022-09-14 14:51:23 -0500693 size_t hashlen )
Nayna Jainc9deb182020-11-16 19:03:12 +0000694{
Nick Child73621ef2022-10-28 11:23:15 -0500695 return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, hash, hashlen, 1 ) );
Nayna Jainc9deb182020-11-16 19:03:12 +0000696}
697
698/*
699 * Unallocate all pkcs7 data
700 */
701void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 )
702{
Daniel Axtens35384792020-09-02 14:48:45 +1000703 mbedtls_pkcs7_signer_info *signer_cur;
704 mbedtls_pkcs7_signer_info *signer_prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000705
706 if( pkcs7 == NULL || pkcs7->raw.p == NULL )
707 return;
708
709 mbedtls_free( pkcs7->raw.p );
710
711 mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
712 mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
713
Daniel Axtens35384792020-09-02 14:48:45 +1000714 signer_cur = pkcs7->signed_data.signers.next;
715 pkcs7_free_signer_info( &pkcs7->signed_data.signers );
716 while( signer_cur != NULL )
Nayna Jainc9deb182020-11-16 19:03:12 +0000717 {
Daniel Axtens35384792020-09-02 14:48:45 +1000718 signer_prev = signer_cur;
719 signer_cur = signer_prev->next;
720 pkcs7_free_signer_info( signer_prev );
721 mbedtls_free( signer_prev );
Nayna Jainc9deb182020-11-16 19:03:12 +0000722 }
723
724 pkcs7->raw.p = NULL;
725}
726
727#endif