blob: ab7bebdf2f7ec5f2a361e709c6d2ce8b77c23bf6 [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
37#if defined(MBEDTLS_PLATFORM_C)
38#include "mbedtls/platform.h"
39#include "mbedtls/platform_util.h"
40#else
41#include <stdio.h>
42#include <stdlib.h>
43#define mbedtls_free free
44#define mbedtls_calloc calloc
45#define mbedtls_printf printf
46#define mbedtls_snprintf snprintf
47#endif
48
49#if defined(MBEDTLS_HAVE_TIME)
50#include "mbedtls/platform_time.h"
51#endif
52#if defined(MBEDTLS_HAVE_TIME_DATE)
53#include <time.h>
54#endif
55
56/**
57 * Initializes the pkcs7 structure.
58 */
59void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 )
60{
Nick Child8ce1b1a2022-09-14 14:51:23 -050061 memset( pkcs7, 0, sizeof( *pkcs7 ) );
Nayna Jainc9deb182020-11-16 19:03:12 +000062}
63
64static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end,
65 size_t *len )
66{
Nick Child9f4fb3e2022-09-12 16:21:02 -050067 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +000068
Nick Child9f4fb3e2022-09-12 16:21:02 -050069 ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED
70 | MBEDTLS_ASN1_CONTEXT_SPECIFIC );
71 if( ret != 0 )
Nayna Jainc9deb182020-11-16 19:03:12 +000072 {
Nick Child9f4fb3e2022-09-12 16:21:02 -050073 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000074 }
75
Nick Child9f4fb3e2022-09-12 16:21:02 -050076 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000077}
78
79/**
80 * version Version
81 * Version ::= INTEGER
82 **/
83static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver )
84{
Nick Child9f4fb3e2022-09-12 16:21:02 -050085 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +000086
Nick Child9f4fb3e2022-09-12 16:21:02 -050087 ret = mbedtls_asn1_get_int( p, end, ver );
88 if( ret != 0 )
89 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000090
91 /* If version != 1, return invalid version */
92 if( *ver != MBEDTLS_PKCS7_SUPPORTED_VERSION )
Nick Child9f4fb3e2022-09-12 16:21:02 -050093 ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
Nayna Jainc9deb182020-11-16 19:03:12 +000094
Nick Child9f4fb3e2022-09-12 16:21:02 -050095 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000096}
97
98/**
99 * ContentInfo ::= SEQUENCE {
100 * contentType ContentType,
101 * content
102 * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
103 **/
104static int pkcs7_get_content_info_type( unsigned char **p, unsigned char *end,
105 mbedtls_pkcs7_buf *pkcs7 )
106{
107 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500108 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jain673a2262020-12-14 22:44:49 +0000109 unsigned char *start = *p;
Nayna Jainc9deb182020-11-16 19:03:12 +0000110
111 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
112 | MBEDTLS_ASN1_SEQUENCE );
Nick Childc448c942021-07-01 15:29:50 -0400113 if( ret != 0 ) {
114 *p = start;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500115 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
116 goto out;
Nick Childc448c942021-07-01 15:29:50 -0400117 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000118
119 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
Nayna Jain673a2262020-12-14 22:44:49 +0000120 if( ret != 0 ) {
121 *p = start;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500122 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
123 goto out;
Nayna Jain673a2262020-12-14 22:44:49 +0000124 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000125
126 pkcs7->tag = MBEDTLS_ASN1_OID;
127 pkcs7->len = len;
128 pkcs7->p = *p;
Nick Childbb82ab72022-10-28 12:28:54 -0500129 *p += len;
Nayna Jainc9deb182020-11-16 19:03:12 +0000130
Nick Child9f4fb3e2022-09-12 16:21:02 -0500131out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000132 return( ret );
133}
134
135/**
136 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
137 *
138 * This is from x509.h
139 **/
140static int pkcs7_get_digest_algorithm( unsigned char **p, unsigned char *end,
141 mbedtls_x509_buf *alg )
142{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500143 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000144
145 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500146 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000147
Nick Child9f4fb3e2022-09-12 16:21:02 -0500148 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000149}
150
151/**
152 * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
153 **/
154static int pkcs7_get_digest_algorithm_set( unsigned char **p,
155 unsigned char *end,
156 mbedtls_x509_buf *alg )
157{
158 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500159 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000160
161 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
162 | MBEDTLS_ASN1_SET );
163 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500164 {
165 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
166 goto out;
167 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000168
169 end = *p + len;
170
Nayna Jainc9deb182020-11-16 19:03:12 +0000171 ret = mbedtls_asn1_get_alg_null( p, end, alg );
172 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500173 {
174 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
175 goto out;
176 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000177
Nick Child34d5e932022-09-14 14:44:03 -0500178 /** For now, it assumes there is only one digest algorithm specified **/
Nayna Jainc9deb182020-11-16 19:03:12 +0000179 if ( *p != end )
Nick Child34d5e932022-09-14 14:44:03 -0500180 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
Nayna Jainc9deb182020-11-16 19:03:12 +0000181
Nick Child9f4fb3e2022-09-12 16:21:02 -0500182out:
183 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000184}
185
186/**
187 * certificates :: SET OF ExtendedCertificateOrCertificate,
188 * ExtendedCertificateOrCertificate ::= CHOICE {
189 * certificate Certificate -- x509,
190 * extendedCertificate[0] IMPLICIT ExtendedCertificate }
191 * Return number of certificates added to the signed data,
192 * 0 or higher is valid.
193 * Return negative error code for failure.
194 **/
195static int pkcs7_get_certificates( unsigned char **p, unsigned char *end,
196 mbedtls_x509_crt *certs )
197{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500198 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000199 size_t len1 = 0;
200 size_t len2 = 0;
Nick Childbb82ab72022-10-28 12:28:54 -0500201 unsigned char *end_set, *end_cert, *start;
Nayna Jainc9deb182020-11-16 19:03:12 +0000202
203 if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
204 | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
205 {
206 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500207 ret = 0;
208 else
209 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
210 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000211 }
212 start = *p;
213 end_set = *p + len1;
214
215 ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
216 | MBEDTLS_ASN1_SEQUENCE );
217 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500218 {
219 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CERT, ret );
220 goto out;
221 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000222
223 end_cert = *p + len2;
224
225 /*
226 * This is to verify that there is only one signer certificate. It seems it is
227 * not easy to differentiate between the chain vs different signer's certificate.
228 * So, we support only the root certificate and the single signer.
229 * The behaviour would be improved with addition of multiple signer support.
230 */
Nick Child8ce1b1a2022-09-14 14:51:23 -0500231 if ( end_cert != end_set )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500232 {
Nick Child34d5e932022-09-14 14:44:03 -0500233 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500234 goto out;
235 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000236
237 *p = start;
Nick Childbb82ab72022-10-28 12:28:54 -0500238 if( ( ret = mbedtls_x509_crt_parse_der( certs, *p, len1 ) ) < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500239 {
240 ret = MBEDTLS_ERR_PKCS7_INVALID_CERT;
241 goto out;
242 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000243
244 *p = *p + len1;
245
Nick Child5f9456f2022-09-19 10:01:25 -0500246 /*
Nick Child9f4fb3e2022-09-12 16:21:02 -0500247 * Since in this version we strictly support single certificate, and reaching
Nick Child5f9456f2022-09-19 10:01:25 -0500248 * here implies we have parsed successfully, we return 1.
Nick Child9f4fb3e2022-09-12 16:21:02 -0500249 */
250 ret = 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000251
Nick Child9f4fb3e2022-09-12 16:21:02 -0500252out:
253 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000254}
255
256/**
257 * EncryptedDigest ::= OCTET STRING
258 **/
259static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
260 mbedtls_pkcs7_buf *signature )
261{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500262 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000263 size_t len = 0;
264
265 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING );
266 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500267 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000268
269 signature->tag = MBEDTLS_ASN1_OCTET_STRING;
270 signature->len = len;
271 signature->p = *p;
272
273 *p = *p + len;
274
Nick Child9f4fb3e2022-09-12 16:21:02 -0500275out:
276 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000277}
278
279/**
Nayna Jainc9deb182020-11-16 19:03:12 +0000280 * SignerInfo ::= SEQUENCE {
281 * version Version;
282 * issuerAndSerialNumber IssuerAndSerialNumber,
283 * digestAlgorithm DigestAlgorithmIdentifier,
284 * authenticatedAttributes
285 * [0] IMPLICIT Attributes OPTIONAL,
286 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
287 * encryptedDigest EncryptedDigest,
288 * unauthenticatedAttributes
289 * [1] IMPLICIT Attributes OPTIONAL,
Daniel Axtens35384792020-09-02 14:48:45 +1000290 * Returns 0 if the signerInfo is valid.
291 * Return negative error code for failure.
Nick Childbb82ab72022-10-28 12:28:54 -0500292 * Structure must not contain vales for authenticatedAttributes
293 * and unauthenticatedAttributes.
Daniel Axtens35384792020-09-02 14:48:45 +1000294 **/
295static int pkcs7_get_signer_info( unsigned char **p, unsigned char *end,
296 mbedtls_pkcs7_signer_info *signer )
297{
298 unsigned char *end_signer;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500299 int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000300 size_t len = 0;
301
Nick Child9f4fb3e2022-09-12 16:21:02 -0500302 asn1_ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
Daniel Axtens35384792020-09-02 14:48:45 +1000303 | MBEDTLS_ASN1_SEQUENCE );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500304 if( asn1_ret != 0 )
305 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000306
307 end_signer = *p + len;
308
309 ret = pkcs7_get_version( p, end_signer, &signer->version );
310 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500311 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000312
Nick Child9f4fb3e2022-09-12 16:21:02 -0500313 asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
314 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
315 if( asn1_ret != 0 )
316 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000317
318 /* Parsing IssuerAndSerialNumber */
319 signer->issuer_raw.p = *p;
320
Nick Child9f4fb3e2022-09-12 16:21:02 -0500321 asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
322 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
323 if( asn1_ret != 0 )
324 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000325
326 ret = mbedtls_x509_get_name( p, *p + len, &signer->issuer );
327 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500328 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000329
330 signer->issuer_raw.len = *p - signer->issuer_raw.p;
331
332 ret = mbedtls_x509_get_serial( p, end_signer, &signer->serial );
333 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500334 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000335
336 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->alg_identifier );
337 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500338 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000339
Nick Childbb82ab72022-10-28 12:28:54 -0500340 /* Asssume authenticatedAttributes is nonexistent */
341
Daniel Axtens35384792020-09-02 14:48:45 +1000342 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->sig_alg_identifier );
343 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500344 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000345
346 ret = pkcs7_get_signature( p, end_signer, &signer->sig );
347 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500348 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000349
350 /* Do not permit any unauthenticated attributes */
351 if( *p != end_signer )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500352 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
Daniel Axtens35384792020-09-02 14:48:45 +1000353
Nick Child9f4fb3e2022-09-12 16:21:02 -0500354out:
355 if( asn1_ret != 0 )
356 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
357 asn1_ret );
358 else if( ret != 0 )
359 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
360
361 return( ret );
Daniel Axtens35384792020-09-02 14:48:45 +1000362}
363
364static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer )
365{
366 mbedtls_x509_name *name_cur;
367 mbedtls_x509_name *name_prv;
368
369 if( signer == NULL )
370 return;
371
372 name_cur = signer->issuer.next;
373 while( name_cur != NULL )
374 {
375 name_prv = name_cur;
376 name_cur = name_cur->next;
377 mbedtls_free( name_prv );
378 }
379}
380
381/**
382 * SignerInfos ::= SET of SignerInfo
Nayna Jainc9deb182020-11-16 19:03:12 +0000383 * Return number of signers added to the signed data,
384 * 0 or higher is valid.
385 * Return negative error code for failure.
386 **/
387static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end,
388 mbedtls_pkcs7_signer_info *signers_set )
389{
Daniel Axtens35384792020-09-02 14:48:45 +1000390 unsigned char *end_set;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500391 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000392 int count = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000393 size_t len = 0;
Daniel Axtens35384792020-09-02 14:48:45 +1000394 mbedtls_pkcs7_signer_info *signer, *prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000395
396 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
397 | MBEDTLS_ASN1_SET );
398 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500399 {
400 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret );
401 goto out;
402 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000403
Daniel Axtens35384792020-09-02 14:48:45 +1000404 /* Detect zero signers */
405 if( len == 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500406 {
407 ret = 0;
408 goto out;
409 }
Daniel Axtens35384792020-09-02 14:48:45 +1000410
Nayna Jainc9deb182020-11-16 19:03:12 +0000411 end_set = *p + len;
412
Daniel Axtens35384792020-09-02 14:48:45 +1000413 ret = pkcs7_get_signer_info( p, end_set, signers_set );
Nayna Jainc9deb182020-11-16 19:03:12 +0000414 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500415 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000416 count++;
Nayna Jainc9deb182020-11-16 19:03:12 +0000417
Daniel Axtens35384792020-09-02 14:48:45 +1000418 prev = signers_set;
419 while( *p != end_set )
420 {
421 signer = mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) );
422 if( !signer )
423 {
424 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
425 goto cleanup;
426 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000427
Daniel Axtens35384792020-09-02 14:48:45 +1000428 ret = pkcs7_get_signer_info( p, end_set, signer );
429 if( ret != 0 ) {
430 mbedtls_free( signer );
431 goto cleanup;
432 }
433 prev->next = signer;
434 prev = signer;
435 count++;
436 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000437
Nick Child9f4fb3e2022-09-12 16:21:02 -0500438 ret = count;
439 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000440
Daniel Axtens35384792020-09-02 14:48:45 +1000441cleanup:
442 signer = signers_set->next;
443 pkcs7_free_signer_info( signers_set );
444 while( signer )
445 {
446 prev = signer;
447 signer = signer->next;
448 pkcs7_free_signer_info( prev );
449 mbedtls_free( prev );
450 }
Nick Child9f4fb3e2022-09-12 16:21:02 -0500451
452out:
Daniel Axtens35384792020-09-02 14:48:45 +1000453 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000454}
455
456/**
457 * SignedData ::= SEQUENCE {
458 * version Version,
459 * digestAlgorithms DigestAlgorithmIdentifiers,
460 * contentInfo ContentInfo,
461 * certificates
462 * [0] IMPLICIT ExtendedCertificatesAndCertificates
463 * OPTIONAL,
464 * crls
465 * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
466 * signerInfos SignerInfos }
467 */
468static int pkcs7_get_signed_data( unsigned char *buf, size_t buflen,
469 mbedtls_pkcs7_signed_data *signed_data )
470{
471 unsigned char *p = buf;
472 unsigned char *end = buf + buflen;
473 unsigned char *end_set;
474 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500475 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000476 mbedtls_md_type_t md_alg;
477
478 ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
479 | MBEDTLS_ASN1_SEQUENCE );
480 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500481 {
482 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
483 goto out;
484 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000485
486 end_set = p + len;
487
488 /* Get version of signed data */
489 ret = pkcs7_get_version( &p, end_set, &signed_data->version );
490 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500491 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000492
493 /* Get digest algorithm */
494 ret = pkcs7_get_digest_algorithm_set( &p, end_set,
495 &signed_data->digest_alg_identifiers );
496 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500497 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000498
499 ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
500 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500501 {
502 ret = MBEDTLS_ERR_PKCS7_INVALID_ALG;
503 goto out;
504 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000505
506 /* Do not expect any content */
507 ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
508 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500509 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000510
511 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
512 {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500513 ret = MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
514 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000515 }
516
Nayna Jainc9deb182020-11-16 19:03:12 +0000517 /* Look for certificates, there may or may not be any */
518 mbedtls_x509_crt_init( &signed_data->certs );
519 ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs );
520 if( ret < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500521 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000522
523 signed_data->no_of_certs = ret;
524
525 /*
526 * Currently CRLs are not supported. If CRL exist, the parsing will fail
527 * at next step of getting signers info and return error as invalid
528 * signer info.
529 */
530
531 signed_data->no_of_crls = 0;
532
533 /* Get signers info */
534 ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers );
535 if( ret < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500536 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000537
538 signed_data->no_of_signers = ret;
539
Daniel Axtens35384792020-09-02 14:48:45 +1000540 /* Don't permit trailing data */
Nayna Jainc9deb182020-11-16 19:03:12 +0000541 if ( p != end )
542 ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500543 else
544 ret = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000545
Nick Child9f4fb3e2022-09-12 16:21:02 -0500546out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000547 return( ret );
548}
549
550int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
551 const size_t buflen )
552{
Nick Childbb82ab72022-10-28 12:28:54 -0500553 unsigned char *p;
Nayna Jainc9deb182020-11-16 19:03:12 +0000554 unsigned char *end;
555 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500556 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jain673a2262020-12-14 22:44:49 +0000557 int isoidset = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000558
559 if( !pkcs7 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500560 {
561 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
562 goto out;
563 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000564
565 /* make an internal copy of the buffer for parsing */
Nick Childbb82ab72022-10-28 12:28:54 -0500566 pkcs7->raw.p = p = mbedtls_calloc( 1, buflen );
Nayna Jainc9deb182020-11-16 19:03:12 +0000567 if( pkcs7->raw.p == NULL )
568 {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500569 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
570 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000571 }
Nick Childbb82ab72022-10-28 12:28:54 -0500572 memcpy( p, buf, buflen );
Nayna Jainc9deb182020-11-16 19:03:12 +0000573 pkcs7->raw.len = buflen;
Nick Childbb82ab72022-10-28 12:28:54 -0500574 end = p + buflen;
Nayna Jainc9deb182020-11-16 19:03:12 +0000575
Nick Childbb82ab72022-10-28 12:28:54 -0500576 ret = pkcs7_get_content_info_type( &p, end, &pkcs7->content_type_oid );
Nayna Jainc9deb182020-11-16 19:03:12 +0000577 if( ret != 0 )
Nayna Jain673a2262020-12-14 22:44:49 +0000578 {
579 len = buflen;
580 goto try_data;
581 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000582
583 if( ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid )
584 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid )
585 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid )
586 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid )
587 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid )
588 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) )
589 {
590 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
591 goto out;
592 }
593
594 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid ) )
595 {
596 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
597 goto out;
598 }
599
Nayna Jain673a2262020-12-14 22:44:49 +0000600 isoidset = 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000601
Nick Childbb82ab72022-10-28 12:28:54 -0500602 ret = pkcs7_get_next_content_len( &p, end, &len );
Nayna Jainc9deb182020-11-16 19:03:12 +0000603 if( ret != 0 )
604 goto out;
605
Nayna Jain673a2262020-12-14 22:44:49 +0000606try_data:
Nick Childbb82ab72022-10-28 12:28:54 -0500607 ret = pkcs7_get_signed_data( p, len, &pkcs7->signed_data );
Nayna Jain673a2262020-12-14 22:44:49 +0000608 if ( ret != 0 )
609 goto out;
610
611 if ( !isoidset )
612 {
613 pkcs7->content_type_oid.tag = MBEDTLS_ASN1_OID;
614 pkcs7->content_type_oid.len = MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS7_SIGNED_DATA );
615 pkcs7->content_type_oid.p = (unsigned char *)MBEDTLS_OID_PKCS7_SIGNED_DATA;
616 }
617
618 ret = MBEDTLS_PKCS7_SIGNED_DATA;
Nayna Jainc9deb182020-11-16 19:03:12 +0000619
620out:
Nayna Jain673a2262020-12-14 22:44:49 +0000621 if ( ret < 0 )
Nayna Jainc9deb182020-11-16 19:03:12 +0000622 mbedtls_pkcs7_free( pkcs7 );
Nayna Jain673a2262020-12-14 22:44:49 +0000623
Nayna Jainc9deb182020-11-16 19:03:12 +0000624 return( ret );
625}
626
Nick Child73621ef2022-10-28 11:23:15 -0500627static int mbedtls_pkcs7_data_or_hash_verify( mbedtls_pkcs7 *pkcs7,
628 const mbedtls_x509_crt *cert,
629 const unsigned char *data,
630 size_t datalen,
631 const int is_data_hash )
Nayna Jainc9deb182020-11-16 19:03:12 +0000632{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500633 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000634 unsigned char *hash;
635 mbedtls_pk_context pk_cxt = cert->pk;
636 const mbedtls_md_info_t *md_info;
637 mbedtls_md_type_t md_alg;
Daniel Axtens35384792020-09-02 14:48:45 +1000638 mbedtls_pkcs7_signer_info *signer;
Nayna Jainc9deb182020-11-16 19:03:12 +0000639
Daniel Axtens35384792020-09-02 14:48:45 +1000640 if( pkcs7->signed_data.no_of_signers == 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500641 {
642 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
643 goto out;
644 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000645
Nick Child73621ef2022-10-28 11:23:15 -0500646 if( mbedtls_x509_time_is_past( &cert->valid_to ) ||
647 mbedtls_x509_time_is_future( &cert->valid_from ))
648 {
649 printf("EXPRED\n");
650 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
651 goto out;
652 }
653
Daniel Axtens35384792020-09-02 14:48:45 +1000654 /*
655 * Potential TODOs
656 * Currently we iterate over all signers and return success if any of them
657 * verify.
658 *
659 * However, we could make this better by checking against the certificate's
660 * identification and SignerIdentifier fields first. That would also allow
661 * us to distinguish between 'no signature for key' and 'signature for key
662 * failed to validate'.
663 *
664 * We could also cache hashes by md, so if there are several sigs all using
665 * the same algo we don't recalculate the hash each time.
666 */
Nick Child7089ce82022-09-14 14:10:00 -0500667 for( signer = &pkcs7->signed_data.signers; signer; signer = signer->next )
Nick Child66718412022-02-22 17:19:59 -0600668 {
Daniel Axtens35384792020-09-02 14:48:45 +1000669 ret = mbedtls_oid_get_md_alg( &signer->alg_identifier, &md_alg );
670 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500671 {
672 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Nick Child7089ce82022-09-14 14:10:00 -0500673 continue;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500674 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000675
Daniel Axtens35384792020-09-02 14:48:45 +1000676 md_info = mbedtls_md_info_from_type( md_alg );
Nick Child7089ce82022-09-14 14:10:00 -0500677 if( md_info == NULL )
678 {
679 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
680 continue;
681 }
Daniel Axtens35384792020-09-02 14:48:45 +1000682
683 hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
684 if( hash == NULL ) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500685 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
686 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000687 }
Nick Child73621ef2022-10-28 11:23:15 -0500688 if( is_data_hash )
689 {
690 if( datalen != mbedtls_md_get_size( md_info ))
691 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
692 else
693 memcpy(hash, data, datalen);
694 }
695 else
696 {
697 ret = mbedtls_md( md_info, data, datalen, hash );
698 }
Daniel Axtens35384792020-09-02 14:48:45 +1000699 if( ret != 0 )
700 {
Nick Child7089ce82022-09-14 14:10:00 -0500701 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Daniel Axtens35384792020-09-02 14:48:45 +1000702 mbedtls_free( hash );
Nick Child7089ce82022-09-14 14:10:00 -0500703 continue;
Daniel Axtens35384792020-09-02 14:48:45 +1000704 }
705
706 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 mbedtls_free( hash );
710
711 if( ret == 0 )
712 break;
Daniel Axtens35384792020-09-02 14:48:45 +1000713 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000714
Nick Child9f4fb3e2022-09-12 16:21:02 -0500715out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000716 return( ret );
717}
Nick Child73621ef2022-10-28 11:23:15 -0500718int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
719 const mbedtls_x509_crt *cert,
720 const unsigned char *data,
721 size_t datalen )
722{
723 return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, data, datalen, 0 ) );
724}
Nayna Jainc9deb182020-11-16 19:03:12 +0000725
726int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
727 const mbedtls_x509_crt *cert,
Nick Child5f9456f2022-09-19 10:01:25 -0500728 const unsigned char *hash,
Nick Child8ce1b1a2022-09-14 14:51:23 -0500729 size_t hashlen )
Nayna Jainc9deb182020-11-16 19:03:12 +0000730{
Nick Child73621ef2022-10-28 11:23:15 -0500731 return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, hash, hashlen, 1 ) );
Nayna Jainc9deb182020-11-16 19:03:12 +0000732}
733
734/*
735 * Unallocate all pkcs7 data
736 */
737void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 )
738{
Daniel Axtens35384792020-09-02 14:48:45 +1000739 mbedtls_pkcs7_signer_info *signer_cur;
740 mbedtls_pkcs7_signer_info *signer_prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000741
742 if( pkcs7 == NULL || pkcs7->raw.p == NULL )
743 return;
744
745 mbedtls_free( pkcs7->raw.p );
746
747 mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
748 mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
749
Daniel Axtens35384792020-09-02 14:48:45 +1000750 signer_cur = pkcs7->signed_data.signers.next;
751 pkcs7_free_signer_info( &pkcs7->signed_data.signers );
752 while( signer_cur != NULL )
Nayna Jainc9deb182020-11-16 19:03:12 +0000753 {
Daniel Axtens35384792020-09-02 14:48:45 +1000754 signer_prev = signer_cur;
755 signer_cur = signer_prev->next;
756 pkcs7_free_signer_info( signer_prev );
757 mbedtls_free( signer_prev );
Nayna Jainc9deb182020-11-16 19:03:12 +0000758 }
759
760 pkcs7->raw.p = NULL;
761}
762
763#endif