blob: ca0170a6dcc7fc328227f862559a588c86294980 [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;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500106 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
107 goto out;
Nick Childc448c942021-07-01 15:29:50 -0400108 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000109
110 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
Nayna Jain673a2262020-12-14 22:44:49 +0000111 if( ret != 0 ) {
112 *p = start;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500113 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
114 goto out;
Nayna Jain673a2262020-12-14 22:44:49 +0000115 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000116
117 pkcs7->tag = MBEDTLS_ASN1_OID;
118 pkcs7->len = len;
119 pkcs7->p = *p;
Nick Childbb82ab72022-10-28 12:28:54 -0500120 *p += len;
Nayna Jainc9deb182020-11-16 19:03:12 +0000121
Nick Child9f4fb3e2022-09-12 16:21:02 -0500122out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000123 return( ret );
124}
125
126/**
127 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
128 *
129 * This is from x509.h
130 **/
131static int pkcs7_get_digest_algorithm( unsigned char **p, unsigned char *end,
132 mbedtls_x509_buf *alg )
133{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500134 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000135
136 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500137 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000138
Nick Child9f4fb3e2022-09-12 16:21:02 -0500139 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000140}
141
142/**
143 * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
144 **/
145static int pkcs7_get_digest_algorithm_set( unsigned char **p,
146 unsigned char *end,
147 mbedtls_x509_buf *alg )
148{
149 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500150 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000151
152 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
153 | MBEDTLS_ASN1_SET );
154 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500155 {
156 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_ALG, ret );
157 goto out;
158 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000159
160 end = *p + len;
161
Nayna Jainc9deb182020-11-16 19:03:12 +0000162 ret = mbedtls_asn1_get_alg_null( p, end, alg );
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
Nick Child34d5e932022-09-14 14:44:03 -0500169 /** For now, it assumes there is only one digest algorithm specified **/
Nayna Jainc9deb182020-11-16 19:03:12 +0000170 if ( *p != end )
Nick Child34d5e932022-09-14 14:44:03 -0500171 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
Nayna Jainc9deb182020-11-16 19:03:12 +0000172
Nick Child9f4fb3e2022-09-12 16:21:02 -0500173out:
174 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000175}
176
177/**
178 * certificates :: SET OF ExtendedCertificateOrCertificate,
179 * ExtendedCertificateOrCertificate ::= CHOICE {
180 * certificate Certificate -- x509,
181 * extendedCertificate[0] IMPLICIT ExtendedCertificate }
182 * Return number of certificates added to the signed data,
183 * 0 or higher is valid.
184 * Return negative error code for failure.
185 **/
186static int pkcs7_get_certificates( unsigned char **p, unsigned char *end,
187 mbedtls_x509_crt *certs )
188{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500189 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000190 size_t len1 = 0;
191 size_t len2 = 0;
Nick Childbb82ab72022-10-28 12:28:54 -0500192 unsigned char *end_set, *end_cert, *start;
Nayna Jainc9deb182020-11-16 19:03:12 +0000193
194 if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
195 | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
196 {
197 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500198 ret = 0;
199 else
200 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
201 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000202 }
203 start = *p;
204 end_set = *p + len1;
205
206 ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
207 | MBEDTLS_ASN1_SEQUENCE );
208 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500209 {
210 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CERT, ret );
211 goto out;
212 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000213
214 end_cert = *p + len2;
215
216 /*
217 * This is to verify that there is only one signer certificate. It seems it is
218 * not easy to differentiate between the chain vs different signer's certificate.
219 * So, we support only the root certificate and the single signer.
220 * The behaviour would be improved with addition of multiple signer support.
221 */
Nick Child8ce1b1a2022-09-14 14:51:23 -0500222 if ( end_cert != end_set )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500223 {
Nick Child34d5e932022-09-14 14:44:03 -0500224 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500225 goto out;
226 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000227
228 *p = start;
Nick Childbb82ab72022-10-28 12:28:54 -0500229 if( ( ret = mbedtls_x509_crt_parse_der( certs, *p, len1 ) ) < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500230 {
231 ret = MBEDTLS_ERR_PKCS7_INVALID_CERT;
232 goto out;
233 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000234
235 *p = *p + len1;
236
Nick Child5f9456f2022-09-19 10:01:25 -0500237 /*
Nick Child9f4fb3e2022-09-12 16:21:02 -0500238 * Since in this version we strictly support single certificate, and reaching
Nick Child5f9456f2022-09-19 10:01:25 -0500239 * here implies we have parsed successfully, we return 1.
Nick Child9f4fb3e2022-09-12 16:21:02 -0500240 */
241 ret = 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000242
Nick Child9f4fb3e2022-09-12 16:21:02 -0500243out:
244 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000245}
246
247/**
248 * EncryptedDigest ::= OCTET STRING
249 **/
250static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
251 mbedtls_pkcs7_buf *signature )
252{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500253 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000254 size_t len = 0;
255
256 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING );
257 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500258 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000259
260 signature->tag = MBEDTLS_ASN1_OCTET_STRING;
261 signature->len = len;
262 signature->p = *p;
263
264 *p = *p + len;
265
Nick Child9f4fb3e2022-09-12 16:21:02 -0500266out:
267 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000268}
269
270/**
Nayna Jainc9deb182020-11-16 19:03:12 +0000271 * SignerInfo ::= SEQUENCE {
272 * version Version;
273 * issuerAndSerialNumber IssuerAndSerialNumber,
274 * digestAlgorithm DigestAlgorithmIdentifier,
275 * authenticatedAttributes
276 * [0] IMPLICIT Attributes OPTIONAL,
277 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
278 * encryptedDigest EncryptedDigest,
279 * unauthenticatedAttributes
280 * [1] IMPLICIT Attributes OPTIONAL,
Daniel Axtens35384792020-09-02 14:48:45 +1000281 * Returns 0 if the signerInfo is valid.
282 * Return negative error code for failure.
Nick Childbb82ab72022-10-28 12:28:54 -0500283 * Structure must not contain vales for authenticatedAttributes
284 * and unauthenticatedAttributes.
Daniel Axtens35384792020-09-02 14:48:45 +1000285 **/
286static int pkcs7_get_signer_info( unsigned char **p, unsigned char *end,
287 mbedtls_pkcs7_signer_info *signer )
288{
289 unsigned char *end_signer;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500290 int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000291 size_t len = 0;
292
Nick Child9f4fb3e2022-09-12 16:21:02 -0500293 asn1_ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
Daniel Axtens35384792020-09-02 14:48:45 +1000294 | MBEDTLS_ASN1_SEQUENCE );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500295 if( asn1_ret != 0 )
296 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000297
298 end_signer = *p + len;
299
300 ret = pkcs7_get_version( p, end_signer, &signer->version );
301 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500302 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000303
Nick Child9f4fb3e2022-09-12 16:21:02 -0500304 asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
305 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
306 if( asn1_ret != 0 )
307 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000308
309 /* Parsing IssuerAndSerialNumber */
310 signer->issuer_raw.p = *p;
311
Nick Child9f4fb3e2022-09-12 16:21:02 -0500312 asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
313 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
314 if( asn1_ret != 0 )
315 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000316
317 ret = mbedtls_x509_get_name( p, *p + len, &signer->issuer );
318 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500319 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000320
321 signer->issuer_raw.len = *p - signer->issuer_raw.p;
322
323 ret = mbedtls_x509_get_serial( p, end_signer, &signer->serial );
324 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500325 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000326
327 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->alg_identifier );
328 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500329 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000330
Nick Childbb82ab72022-10-28 12:28:54 -0500331 /* Asssume authenticatedAttributes is nonexistent */
332
Daniel Axtens35384792020-09-02 14:48:45 +1000333 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->sig_alg_identifier );
334 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500335 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000336
337 ret = pkcs7_get_signature( p, end_signer, &signer->sig );
338 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500339 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000340
341 /* Do not permit any unauthenticated attributes */
342 if( *p != end_signer )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500343 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
Daniel Axtens35384792020-09-02 14:48:45 +1000344
Nick Child9f4fb3e2022-09-12 16:21:02 -0500345out:
346 if( asn1_ret != 0 )
347 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
348 asn1_ret );
349 else if( ret != 0 )
350 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
351
352 return( ret );
Daniel Axtens35384792020-09-02 14:48:45 +1000353}
354
355static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer )
356{
357 mbedtls_x509_name *name_cur;
358 mbedtls_x509_name *name_prv;
359
360 if( signer == NULL )
361 return;
362
363 name_cur = signer->issuer.next;
364 while( name_cur != NULL )
365 {
366 name_prv = name_cur;
367 name_cur = name_cur->next;
368 mbedtls_free( name_prv );
369 }
370}
371
372/**
373 * SignerInfos ::= SET of SignerInfo
Nayna Jainc9deb182020-11-16 19:03:12 +0000374 * Return number of signers added to the signed data,
375 * 0 or higher is valid.
376 * Return negative error code for failure.
377 **/
378static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end,
379 mbedtls_pkcs7_signer_info *signers_set )
380{
Daniel Axtens35384792020-09-02 14:48:45 +1000381 unsigned char *end_set;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500382 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000383 int count = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000384 size_t len = 0;
Daniel Axtens35384792020-09-02 14:48:45 +1000385 mbedtls_pkcs7_signer_info *signer, *prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000386
387 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
388 | MBEDTLS_ASN1_SET );
389 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500390 {
391 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret );
392 goto out;
393 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000394
Daniel Axtens35384792020-09-02 14:48:45 +1000395 /* Detect zero signers */
396 if( len == 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500397 {
398 ret = 0;
399 goto out;
400 }
Daniel Axtens35384792020-09-02 14:48:45 +1000401
Nayna Jainc9deb182020-11-16 19:03:12 +0000402 end_set = *p + len;
403
Daniel Axtens35384792020-09-02 14:48:45 +1000404 ret = pkcs7_get_signer_info( p, end_set, signers_set );
Nayna Jainc9deb182020-11-16 19:03:12 +0000405 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500406 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000407 count++;
Nayna Jainc9deb182020-11-16 19:03:12 +0000408
Daniel Axtens35384792020-09-02 14:48:45 +1000409 prev = signers_set;
410 while( *p != end_set )
411 {
412 signer = mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) );
413 if( !signer )
414 {
415 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
416 goto cleanup;
417 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000418
Daniel Axtens35384792020-09-02 14:48:45 +1000419 ret = pkcs7_get_signer_info( p, end_set, signer );
420 if( ret != 0 ) {
421 mbedtls_free( signer );
422 goto cleanup;
423 }
424 prev->next = signer;
425 prev = signer;
426 count++;
427 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000428
Nick Child9f4fb3e2022-09-12 16:21:02 -0500429 ret = count;
430 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000431
Daniel Axtens35384792020-09-02 14:48:45 +1000432cleanup:
433 signer = signers_set->next;
434 pkcs7_free_signer_info( signers_set );
435 while( signer )
436 {
437 prev = signer;
438 signer = signer->next;
439 pkcs7_free_signer_info( prev );
440 mbedtls_free( prev );
441 }
Nick Child9f4fb3e2022-09-12 16:21:02 -0500442
443out:
Daniel Axtens35384792020-09-02 14:48:45 +1000444 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000445}
446
447/**
448 * SignedData ::= SEQUENCE {
449 * version Version,
450 * digestAlgorithms DigestAlgorithmIdentifiers,
451 * contentInfo ContentInfo,
452 * certificates
453 * [0] IMPLICIT ExtendedCertificatesAndCertificates
454 * OPTIONAL,
455 * crls
456 * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
457 * signerInfos SignerInfos }
458 */
459static int pkcs7_get_signed_data( unsigned char *buf, size_t buflen,
460 mbedtls_pkcs7_signed_data *signed_data )
461{
462 unsigned char *p = buf;
463 unsigned char *end = buf + buflen;
464 unsigned char *end_set;
465 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500466 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000467 mbedtls_md_type_t md_alg;
468
469 ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
470 | MBEDTLS_ASN1_SEQUENCE );
471 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500472 {
473 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
474 goto out;
475 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000476
477 end_set = p + len;
478
479 /* Get version of signed data */
480 ret = pkcs7_get_version( &p, end_set, &signed_data->version );
481 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500482 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000483
484 /* Get digest algorithm */
485 ret = pkcs7_get_digest_algorithm_set( &p, end_set,
486 &signed_data->digest_alg_identifiers );
487 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500488 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000489
490 ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
491 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500492 {
493 ret = MBEDTLS_ERR_PKCS7_INVALID_ALG;
494 goto out;
495 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000496
497 /* Do not expect any content */
498 ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
499 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500500 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000501
502 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
503 {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500504 ret = MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
505 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000506 }
507
Nayna Jainc9deb182020-11-16 19:03:12 +0000508 /* Look for certificates, there may or may not be any */
509 mbedtls_x509_crt_init( &signed_data->certs );
510 ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs );
511 if( ret < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500512 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000513
514 signed_data->no_of_certs = ret;
515
516 /*
517 * Currently CRLs are not supported. If CRL exist, the parsing will fail
518 * at next step of getting signers info and return error as invalid
519 * signer info.
520 */
521
522 signed_data->no_of_crls = 0;
523
524 /* Get signers info */
525 ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers );
526 if( ret < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500527 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000528
529 signed_data->no_of_signers = ret;
530
Daniel Axtens35384792020-09-02 14:48:45 +1000531 /* Don't permit trailing data */
Nayna Jainc9deb182020-11-16 19:03:12 +0000532 if ( p != end )
533 ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500534 else
535 ret = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000536
Nick Child9f4fb3e2022-09-12 16:21:02 -0500537out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000538 return( ret );
539}
540
541int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
542 const size_t buflen )
543{
Nick Childbb82ab72022-10-28 12:28:54 -0500544 unsigned char *p;
Nayna Jainc9deb182020-11-16 19:03:12 +0000545 unsigned char *end;
546 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500547 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jain673a2262020-12-14 22:44:49 +0000548 int isoidset = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000549
550 if( !pkcs7 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500551 {
552 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
553 goto out;
554 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000555
556 /* make an internal copy of the buffer for parsing */
Nick Childbb82ab72022-10-28 12:28:54 -0500557 pkcs7->raw.p = p = mbedtls_calloc( 1, buflen );
Nayna Jainc9deb182020-11-16 19:03:12 +0000558 if( pkcs7->raw.p == NULL )
559 {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500560 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
561 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000562 }
Nick Childbb82ab72022-10-28 12:28:54 -0500563 memcpy( p, buf, buflen );
Nayna Jainc9deb182020-11-16 19:03:12 +0000564 pkcs7->raw.len = buflen;
Nick Childbb82ab72022-10-28 12:28:54 -0500565 end = p + buflen;
Nayna Jainc9deb182020-11-16 19:03:12 +0000566
Nick Childbb82ab72022-10-28 12:28:54 -0500567 ret = pkcs7_get_content_info_type( &p, end, &pkcs7->content_type_oid );
Nayna Jainc9deb182020-11-16 19:03:12 +0000568 if( ret != 0 )
Nayna Jain673a2262020-12-14 22:44:49 +0000569 {
570 len = buflen;
571 goto try_data;
572 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000573
574 if( ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid )
575 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid )
576 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid )
577 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid )
578 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid )
579 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) )
580 {
581 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
582 goto out;
583 }
584
585 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid ) )
586 {
587 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
588 goto out;
589 }
590
Nayna Jain673a2262020-12-14 22:44:49 +0000591 isoidset = 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000592
Nick Childbb82ab72022-10-28 12:28:54 -0500593 ret = pkcs7_get_next_content_len( &p, end, &len );
Nayna Jainc9deb182020-11-16 19:03:12 +0000594 if( ret != 0 )
595 goto out;
596
Nayna Jain673a2262020-12-14 22:44:49 +0000597try_data:
Nick Childbb82ab72022-10-28 12:28:54 -0500598 ret = pkcs7_get_signed_data( p, len, &pkcs7->signed_data );
Nayna Jain673a2262020-12-14 22:44:49 +0000599 if ( ret != 0 )
600 goto out;
601
602 if ( !isoidset )
603 {
604 pkcs7->content_type_oid.tag = MBEDTLS_ASN1_OID;
605 pkcs7->content_type_oid.len = MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS7_SIGNED_DATA );
606 pkcs7->content_type_oid.p = (unsigned char *)MBEDTLS_OID_PKCS7_SIGNED_DATA;
607 }
608
609 ret = MBEDTLS_PKCS7_SIGNED_DATA;
Nayna Jainc9deb182020-11-16 19:03:12 +0000610
611out:
Nayna Jain673a2262020-12-14 22:44:49 +0000612 if ( ret < 0 )
Nayna Jainc9deb182020-11-16 19:03:12 +0000613 mbedtls_pkcs7_free( pkcs7 );
Nayna Jain673a2262020-12-14 22:44:49 +0000614
Nayna Jainc9deb182020-11-16 19:03:12 +0000615 return( ret );
616}
617
Nick Child73621ef2022-10-28 11:23:15 -0500618static int mbedtls_pkcs7_data_or_hash_verify( mbedtls_pkcs7 *pkcs7,
619 const mbedtls_x509_crt *cert,
620 const unsigned char *data,
621 size_t datalen,
622 const int is_data_hash )
Nayna Jainc9deb182020-11-16 19:03:12 +0000623{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500624 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000625 unsigned char *hash;
626 mbedtls_pk_context pk_cxt = cert->pk;
627 const mbedtls_md_info_t *md_info;
628 mbedtls_md_type_t md_alg;
Daniel Axtens35384792020-09-02 14:48:45 +1000629 mbedtls_pkcs7_signer_info *signer;
Nayna Jainc9deb182020-11-16 19:03:12 +0000630
Daniel Axtens35384792020-09-02 14:48:45 +1000631 if( pkcs7->signed_data.no_of_signers == 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500632 {
Nick Child3951a4f2022-10-31 09:17:15 -0500633 ret = MBEDTLS_ERR_PKCS7_INVALID_CERT;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500634 goto out;
635 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000636
Nick Child73621ef2022-10-28 11:23:15 -0500637 if( mbedtls_x509_time_is_past( &cert->valid_to ) ||
638 mbedtls_x509_time_is_future( &cert->valid_from ))
639 {
Nick Child3951a4f2022-10-31 09:17:15 -0500640 ret = MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
Nick Child73621ef2022-10-28 11:23:15 -0500641 goto out;
642 }
643
Daniel Axtens35384792020-09-02 14:48:45 +1000644 /*
645 * Potential TODOs
646 * Currently we iterate over all signers and return success if any of them
647 * verify.
648 *
649 * However, we could make this better by checking against the certificate's
650 * identification and SignerIdentifier fields first. That would also allow
651 * us to distinguish between 'no signature for key' and 'signature for key
652 * failed to validate'.
653 *
654 * We could also cache hashes by md, so if there are several sigs all using
655 * the same algo we don't recalculate the hash each time.
656 */
Nick Child7089ce82022-09-14 14:10:00 -0500657 for( signer = &pkcs7->signed_data.signers; signer; signer = signer->next )
Nick Child66718412022-02-22 17:19:59 -0600658 {
Daniel Axtens35384792020-09-02 14:48:45 +1000659 ret = mbedtls_oid_get_md_alg( &signer->alg_identifier, &md_alg );
660 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500661 {
662 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Nick Child7089ce82022-09-14 14:10:00 -0500663 continue;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500664 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000665
Daniel Axtens35384792020-09-02 14:48:45 +1000666 md_info = mbedtls_md_info_from_type( md_alg );
Nick Child7089ce82022-09-14 14:10:00 -0500667 if( md_info == NULL )
668 {
669 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
670 continue;
671 }
Daniel Axtens35384792020-09-02 14:48:45 +1000672
673 hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
674 if( hash == NULL ) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500675 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
676 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000677 }
Nick Child73621ef2022-10-28 11:23:15 -0500678 if( is_data_hash )
679 {
680 if( datalen != mbedtls_md_get_size( md_info ))
681 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
682 else
683 memcpy(hash, data, datalen);
684 }
685 else
686 {
687 ret = mbedtls_md( md_info, data, datalen, hash );
688 }
Daniel Axtens35384792020-09-02 14:48:45 +1000689 if( ret != 0 )
690 {
Nick Child7089ce82022-09-14 14:10:00 -0500691 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Daniel Axtens35384792020-09-02 14:48:45 +1000692 mbedtls_free( hash );
Nick Child7089ce82022-09-14 14:10:00 -0500693 continue;
Daniel Axtens35384792020-09-02 14:48:45 +1000694 }
695
696 ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash,
697 mbedtls_md_get_size( md_info ),
698 signer->sig.p, signer->sig.len );
Daniel Axtens35384792020-09-02 14:48:45 +1000699 mbedtls_free( hash );
700
701 if( ret == 0 )
702 break;
Daniel Axtens35384792020-09-02 14:48:45 +1000703 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000704
Nick Child9f4fb3e2022-09-12 16:21:02 -0500705out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000706 return( ret );
707}
Nick Child73621ef2022-10-28 11:23:15 -0500708int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
709 const mbedtls_x509_crt *cert,
710 const unsigned char *data,
711 size_t datalen )
712{
713 return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, data, datalen, 0 ) );
714}
Nayna Jainc9deb182020-11-16 19:03:12 +0000715
716int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
717 const mbedtls_x509_crt *cert,
Nick Child5f9456f2022-09-19 10:01:25 -0500718 const unsigned char *hash,
Nick Child8ce1b1a2022-09-14 14:51:23 -0500719 size_t hashlen )
Nayna Jainc9deb182020-11-16 19:03:12 +0000720{
Nick Child73621ef2022-10-28 11:23:15 -0500721 return( mbedtls_pkcs7_data_or_hash_verify( pkcs7, cert, hash, hashlen, 1 ) );
Nayna Jainc9deb182020-11-16 19:03:12 +0000722}
723
724/*
725 * Unallocate all pkcs7 data
726 */
727void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 )
728{
Daniel Axtens35384792020-09-02 14:48:45 +1000729 mbedtls_pkcs7_signer_info *signer_cur;
730 mbedtls_pkcs7_signer_info *signer_prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000731
732 if( pkcs7 == NULL || pkcs7->raw.p == NULL )
733 return;
734
735 mbedtls_free( pkcs7->raw.p );
736
737 mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
738 mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
739
Daniel Axtens35384792020-09-02 14:48:45 +1000740 signer_cur = pkcs7->signed_data.signers.next;
741 pkcs7_free_signer_info( &pkcs7->signed_data.signers );
742 while( signer_cur != NULL )
Nayna Jainc9deb182020-11-16 19:03:12 +0000743 {
Daniel Axtens35384792020-09-02 14:48:45 +1000744 signer_prev = signer_cur;
745 signer_cur = signer_prev->next;
746 pkcs7_free_signer_info( signer_prev );
747 mbedtls_free( signer_prev );
Nayna Jainc9deb182020-11-16 19:03:12 +0000748 }
749
750 pkcs7->raw.p = NULL;
751}
752
753#endif