blob: 9dcbab26c404606b840a796c01a80eda917ff44f [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{
61 memset( pkcs7, 0, sizeof( mbedtls_pkcs7 ) );
62 pkcs7->raw.p = NULL;
63}
64
65static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end,
66 size_t *len )
67{
Nick Child9f4fb3e2022-09-12 16:21:02 -050068 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +000069
Nick Child9f4fb3e2022-09-12 16:21:02 -050070 ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED
71 | MBEDTLS_ASN1_CONTEXT_SPECIFIC );
72 if( ret != 0 )
Nayna Jainc9deb182020-11-16 19:03:12 +000073 {
Nick Child9f4fb3e2022-09-12 16:21:02 -050074 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000075 }
76
Nick Child9f4fb3e2022-09-12 16:21:02 -050077 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000078}
79
80/**
81 * version Version
82 * Version ::= INTEGER
83 **/
84static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver )
85{
Nick Child9f4fb3e2022-09-12 16:21:02 -050086 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +000087
Nick Child9f4fb3e2022-09-12 16:21:02 -050088 ret = mbedtls_asn1_get_int( p, end, ver );
89 if( ret != 0 )
90 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000091
92 /* If version != 1, return invalid version */
93 if( *ver != MBEDTLS_PKCS7_SUPPORTED_VERSION )
Nick Child9f4fb3e2022-09-12 16:21:02 -050094 ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
Nayna Jainc9deb182020-11-16 19:03:12 +000095
Nick Child9f4fb3e2022-09-12 16:21:02 -050096 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +000097}
98
99/**
100 * ContentInfo ::= SEQUENCE {
101 * contentType ContentType,
102 * content
103 * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
104 **/
105static int pkcs7_get_content_info_type( unsigned char **p, unsigned char *end,
106 mbedtls_pkcs7_buf *pkcs7 )
107{
108 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500109 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jain673a2262020-12-14 22:44:49 +0000110 unsigned char *start = *p;
Nayna Jainc9deb182020-11-16 19:03:12 +0000111
112 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
113 | MBEDTLS_ASN1_SEQUENCE );
Nick Childc448c942021-07-01 15:29:50 -0400114 if( ret != 0 ) {
115 *p = start;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500116 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
117 goto out;
Nick Childc448c942021-07-01 15:29:50 -0400118 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000119
120 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
Nayna Jain673a2262020-12-14 22:44:49 +0000121 if( ret != 0 ) {
122 *p = start;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500123 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret );
124 goto out;
Nayna Jain673a2262020-12-14 22:44:49 +0000125 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000126
127 pkcs7->tag = MBEDTLS_ASN1_OID;
128 pkcs7->len = len;
129 pkcs7->p = *p;
130
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;
201 unsigned char *end_set, *end_cert;
202 unsigned char *start = *p;
203
204 if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
205 | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
206 {
207 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500208 ret = 0;
209 else
210 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
211 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000212 }
213 start = *p;
214 end_set = *p + len1;
215
216 ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
217 | MBEDTLS_ASN1_SEQUENCE );
218 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500219 {
220 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_CERT, ret );
221 goto out;
222 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000223
224 end_cert = *p + len2;
225
226 /*
227 * This is to verify that there is only one signer certificate. It seems it is
228 * not easy to differentiate between the chain vs different signer's certificate.
229 * So, we support only the root certificate and the single signer.
230 * The behaviour would be improved with addition of multiple signer support.
231 */
232 if (end_cert != end_set)
Nick Child9f4fb3e2022-09-12 16:21:02 -0500233 {
Nick Child34d5e932022-09-14 14:44:03 -0500234 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500235 goto out;
236 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000237
238 *p = start;
239 if( ( ret = mbedtls_x509_crt_parse( certs, *p, len1 ) ) < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500240 {
241 ret = MBEDTLS_ERR_PKCS7_INVALID_CERT;
242 goto out;
243 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000244
245 *p = *p + len1;
246
Nick Child9f4fb3e2022-09-12 16:21:02 -0500247 /*
248 * Since in this version we strictly support single certificate, and reaching
249 * here implies we have parsed successfully, we return 1.
250 */
251 ret = 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000252
Nick Child9f4fb3e2022-09-12 16:21:02 -0500253out:
254 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000255}
256
257/**
258 * EncryptedDigest ::= OCTET STRING
259 **/
260static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
261 mbedtls_pkcs7_buf *signature )
262{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500263 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000264 size_t len = 0;
265
266 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING );
267 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500268 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000269
270 signature->tag = MBEDTLS_ASN1_OCTET_STRING;
271 signature->len = len;
272 signature->p = *p;
273
274 *p = *p + len;
275
Nick Child9f4fb3e2022-09-12 16:21:02 -0500276out:
277 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000278}
279
280/**
Nayna Jainc9deb182020-11-16 19:03:12 +0000281 * SignerInfo ::= SEQUENCE {
282 * version Version;
283 * issuerAndSerialNumber IssuerAndSerialNumber,
284 * digestAlgorithm DigestAlgorithmIdentifier,
285 * authenticatedAttributes
286 * [0] IMPLICIT Attributes OPTIONAL,
287 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
288 * encryptedDigest EncryptedDigest,
289 * unauthenticatedAttributes
290 * [1] IMPLICIT Attributes OPTIONAL,
Daniel Axtens35384792020-09-02 14:48:45 +1000291 * Returns 0 if the signerInfo is valid.
292 * Return negative error code for failure.
293 **/
294static int pkcs7_get_signer_info( unsigned char **p, unsigned char *end,
295 mbedtls_pkcs7_signer_info *signer )
296{
297 unsigned char *end_signer;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500298 int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000299 size_t len = 0;
300
Nick Child9f4fb3e2022-09-12 16:21:02 -0500301 asn1_ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
Daniel Axtens35384792020-09-02 14:48:45 +1000302 | MBEDTLS_ASN1_SEQUENCE );
Nick Child9f4fb3e2022-09-12 16:21:02 -0500303 if( asn1_ret != 0 )
304 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000305
306 end_signer = *p + len;
307
308 ret = pkcs7_get_version( p, end_signer, &signer->version );
309 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500310 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000311
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 /* Parsing IssuerAndSerialNumber */
318 signer->issuer_raw.p = *p;
319
Nick Child9f4fb3e2022-09-12 16:21:02 -0500320 asn1_ret = mbedtls_asn1_get_tag( p, end_signer, &len,
321 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE );
322 if( asn1_ret != 0 )
323 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000324
325 ret = mbedtls_x509_get_name( p, *p + len, &signer->issuer );
326 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500327 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000328
329 signer->issuer_raw.len = *p - signer->issuer_raw.p;
330
331 ret = mbedtls_x509_get_serial( p, end_signer, &signer->serial );
332 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500333 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000334
335 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->alg_identifier );
336 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500337 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000338
339 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->sig_alg_identifier );
340 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500341 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000342
343 ret = pkcs7_get_signature( p, end_signer, &signer->sig );
344 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500345 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000346
347 /* Do not permit any unauthenticated attributes */
348 if( *p != end_signer )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500349 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
Daniel Axtens35384792020-09-02 14:48:45 +1000350
Nick Child9f4fb3e2022-09-12 16:21:02 -0500351out:
352 if( asn1_ret != 0 )
353 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
354 asn1_ret );
355 else if( ret != 0 )
356 ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
357
358 return( ret );
Daniel Axtens35384792020-09-02 14:48:45 +1000359}
360
361static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer )
362{
363 mbedtls_x509_name *name_cur;
364 mbedtls_x509_name *name_prv;
365
366 if( signer == NULL )
367 return;
368
369 name_cur = signer->issuer.next;
370 while( name_cur != NULL )
371 {
372 name_prv = name_cur;
373 name_cur = name_cur->next;
374 mbedtls_free( name_prv );
375 }
376}
377
378/**
379 * SignerInfos ::= SET of SignerInfo
Nayna Jainc9deb182020-11-16 19:03:12 +0000380 * Return number of signers added to the signed data,
381 * 0 or higher is valid.
382 * Return negative error code for failure.
383 **/
384static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end,
385 mbedtls_pkcs7_signer_info *signers_set )
386{
Daniel Axtens35384792020-09-02 14:48:45 +1000387 unsigned char *end_set;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500388 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Daniel Axtens35384792020-09-02 14:48:45 +1000389 int count = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000390 size_t len = 0;
Daniel Axtens35384792020-09-02 14:48:45 +1000391 mbedtls_pkcs7_signer_info *signer, *prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000392
393 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
394 | MBEDTLS_ASN1_SET );
395 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500396 {
397 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret );
398 goto out;
399 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000400
Daniel Axtens35384792020-09-02 14:48:45 +1000401 /* Detect zero signers */
402 if( len == 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500403 {
404 ret = 0;
405 goto out;
406 }
Daniel Axtens35384792020-09-02 14:48:45 +1000407
Nayna Jainc9deb182020-11-16 19:03:12 +0000408 end_set = *p + len;
409
Daniel Axtens35384792020-09-02 14:48:45 +1000410 ret = pkcs7_get_signer_info( p, end_set, signers_set );
Nayna Jainc9deb182020-11-16 19:03:12 +0000411 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500412 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000413 count++;
Nayna Jainc9deb182020-11-16 19:03:12 +0000414
Daniel Axtens35384792020-09-02 14:48:45 +1000415 prev = signers_set;
416 while( *p != end_set )
417 {
418 signer = mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) );
419 if( !signer )
420 {
421 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
422 goto cleanup;
423 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000424
Daniel Axtens35384792020-09-02 14:48:45 +1000425 ret = pkcs7_get_signer_info( p, end_set, signer );
426 if( ret != 0 ) {
427 mbedtls_free( signer );
428 goto cleanup;
429 }
430 prev->next = signer;
431 prev = signer;
432 count++;
433 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000434
Nick Child9f4fb3e2022-09-12 16:21:02 -0500435 ret = count;
436 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000437
Daniel Axtens35384792020-09-02 14:48:45 +1000438cleanup:
439 signer = signers_set->next;
440 pkcs7_free_signer_info( signers_set );
441 while( signer )
442 {
443 prev = signer;
444 signer = signer->next;
445 pkcs7_free_signer_info( prev );
446 mbedtls_free( prev );
447 }
Nick Child9f4fb3e2022-09-12 16:21:02 -0500448
449out:
Daniel Axtens35384792020-09-02 14:48:45 +1000450 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000451}
452
453/**
454 * SignedData ::= SEQUENCE {
455 * version Version,
456 * digestAlgorithms DigestAlgorithmIdentifiers,
457 * contentInfo ContentInfo,
458 * certificates
459 * [0] IMPLICIT ExtendedCertificatesAndCertificates
460 * OPTIONAL,
461 * crls
462 * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
463 * signerInfos SignerInfos }
464 */
465static int pkcs7_get_signed_data( unsigned char *buf, size_t buflen,
466 mbedtls_pkcs7_signed_data *signed_data )
467{
468 unsigned char *p = buf;
469 unsigned char *end = buf + buflen;
470 unsigned char *end_set;
471 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500472 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jainc9deb182020-11-16 19:03:12 +0000473 mbedtls_md_type_t md_alg;
474
475 ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
476 | MBEDTLS_ASN1_SEQUENCE );
477 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500478 {
479 ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret );
480 goto out;
481 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000482
483 end_set = p + len;
484
485 /* Get version of signed data */
486 ret = pkcs7_get_version( &p, end_set, &signed_data->version );
487 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500488 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000489
490 /* Get digest algorithm */
491 ret = pkcs7_get_digest_algorithm_set( &p, end_set,
492 &signed_data->digest_alg_identifiers );
493 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500494 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000495
496 ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
497 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500498 {
499 ret = MBEDTLS_ERR_PKCS7_INVALID_ALG;
500 goto out;
501 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000502
503 /* Do not expect any content */
504 ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
505 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500506 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000507
508 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
509 {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500510 ret = MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
511 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000512 }
513
514 p = p + signed_data->content.oid.len;
515
516 /* Look for certificates, there may or may not be any */
517 mbedtls_x509_crt_init( &signed_data->certs );
518 ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs );
519 if( ret < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500520 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000521
522 signed_data->no_of_certs = ret;
523
524 /*
525 * Currently CRLs are not supported. If CRL exist, the parsing will fail
526 * at next step of getting signers info and return error as invalid
527 * signer info.
528 */
529
530 signed_data->no_of_crls = 0;
531
532 /* Get signers info */
533 ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers );
534 if( ret < 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500535 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000536
537 signed_data->no_of_signers = ret;
538
Daniel Axtens35384792020-09-02 14:48:45 +1000539 /* Don't permit trailing data */
Nayna Jainc9deb182020-11-16 19:03:12 +0000540 if ( p != end )
541 ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500542 else
543 ret = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000544
Nick Child9f4fb3e2022-09-12 16:21:02 -0500545out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000546 return( ret );
547}
548
549int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
550 const size_t buflen )
551{
552 unsigned char *start;
553 unsigned char *end;
554 size_t len = 0;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500555 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nayna Jain673a2262020-12-14 22:44:49 +0000556 int isoidset = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000557
558 if( !pkcs7 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500559 {
560 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
561 goto out;
562 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000563
564 /* make an internal copy of the buffer for parsing */
565 pkcs7->raw.p = start = mbedtls_calloc( 1, buflen );
566 if( pkcs7->raw.p == NULL )
567 {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500568 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
569 goto out;
Nayna Jainc9deb182020-11-16 19:03:12 +0000570 }
571 memcpy( start, buf, buflen );
572 pkcs7->raw.len = buflen;
573 end = start + buflen;
574
575 ret = pkcs7_get_content_info_type( &start, end, &pkcs7->content_type_oid );
576 if( ret != 0 )
Nayna Jain673a2262020-12-14 22:44:49 +0000577 {
578 len = buflen;
579 goto try_data;
580 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000581
582 if( ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid )
583 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid )
584 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid )
585 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid )
586 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid )
587 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) )
588 {
589 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
590 goto out;
591 }
592
593 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid ) )
594 {
595 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
596 goto out;
597 }
598
Nayna Jain673a2262020-12-14 22:44:49 +0000599 isoidset = 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000600 start = start + pkcs7->content_type_oid.len;
601
602 ret = pkcs7_get_next_content_len( &start, end, &len );
603 if( ret != 0 )
604 goto out;
605
Nayna Jain673a2262020-12-14 22:44:49 +0000606try_data:
Nayna Jainc9deb182020-11-16 19:03:12 +0000607 ret = pkcs7_get_signed_data( start, 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
627int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
628 const mbedtls_x509_crt *cert,
629 const unsigned char *data,
630 size_t datalen )
631{
632
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
Daniel Axtens35384792020-09-02 14:48:45 +1000646 /*
647 * Potential TODOs
648 * Currently we iterate over all signers and return success if any of them
649 * verify.
650 *
651 * However, we could make this better by checking against the certificate's
652 * identification and SignerIdentifier fields first. That would also allow
653 * us to distinguish between 'no signature for key' and 'signature for key
654 * failed to validate'.
655 *
656 * We could also cache hashes by md, so if there are several sigs all using
657 * the same algo we don't recalculate the hash each time.
658 */
Nick Child7089ce82022-09-14 14:10:00 -0500659 for( signer = &pkcs7->signed_data.signers; signer; signer = signer->next )
Nick Child66718412022-02-22 17:19:59 -0600660 {
Daniel Axtens35384792020-09-02 14:48:45 +1000661 ret = mbedtls_oid_get_md_alg( &signer->alg_identifier, &md_alg );
662 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500663 {
664 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Nick Child7089ce82022-09-14 14:10:00 -0500665 continue;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500666 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000667
Daniel Axtens35384792020-09-02 14:48:45 +1000668 md_info = mbedtls_md_info_from_type( md_alg );
Nick Child7089ce82022-09-14 14:10:00 -0500669 if( md_info == NULL )
670 {
671 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
672 continue;
673 }
Daniel Axtens35384792020-09-02 14:48:45 +1000674
675 hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
676 if( hash == NULL ) {
Nick Child9f4fb3e2022-09-12 16:21:02 -0500677 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
678 goto out;
Daniel Axtens35384792020-09-02 14:48:45 +1000679 }
680
681 ret = mbedtls_md( md_info, data, datalen, hash );
682 if( ret != 0 )
683 {
Nick Child7089ce82022-09-14 14:10:00 -0500684 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Daniel Axtens35384792020-09-02 14:48:45 +1000685 mbedtls_free( hash );
Nick Child7089ce82022-09-14 14:10:00 -0500686 continue;
Daniel Axtens35384792020-09-02 14:48:45 +1000687 }
688
689 ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash,
690 mbedtls_md_get_size( md_info ),
691 signer->sig.p, signer->sig.len );
692
693 mbedtls_free( hash );
694
695 if( ret == 0 )
696 break;
Daniel Axtens35384792020-09-02 14:48:45 +1000697 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000698
Nick Child9f4fb3e2022-09-12 16:21:02 -0500699out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000700 return( ret );
701}
702
703int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
704 const mbedtls_x509_crt *cert,
705 const unsigned char *hash, size_t hashlen)
706{
Nick Child9f4fb3e2022-09-12 16:21:02 -0500707 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Nick Child62b2d7e2022-07-14 16:24:59 -0500708 const mbedtls_md_info_t *md_info;
Nayna Jainc9deb182020-11-16 19:03:12 +0000709 mbedtls_md_type_t md_alg;
710 mbedtls_pk_context pk_cxt;
Nick Child62b2d7e2022-07-14 16:24:59 -0500711 mbedtls_pkcs7_signer_info *signer;
Nayna Jainc9deb182020-11-16 19:03:12 +0000712
713 pk_cxt = cert->pk;
Nick Child62b2d7e2022-07-14 16:24:59 -0500714
715 if( pkcs7->signed_data.no_of_signers == 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500716 {
717 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
718 goto out;
719 }
Nick Child62b2d7e2022-07-14 16:24:59 -0500720
721 signer = &pkcs7->signed_data.signers;
Nick Child7089ce82022-09-14 14:10:00 -0500722 for( signer = &pkcs7->signed_data.signers; signer; signer = signer->next )
Nick Child62b2d7e2022-07-14 16:24:59 -0500723 {
724 ret = mbedtls_oid_get_md_alg( &signer->alg_identifier, &md_alg );
725 if( ret != 0 )
Nick Child9f4fb3e2022-09-12 16:21:02 -0500726 {
727 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Nick Child7089ce82022-09-14 14:10:00 -0500728 continue;
Nick Child9f4fb3e2022-09-12 16:21:02 -0500729 }
Nick Child62b2d7e2022-07-14 16:24:59 -0500730
731 md_info = mbedtls_md_info_from_type( md_alg );
Nick Child7089ce82022-09-14 14:10:00 -0500732 if( md_info == NULL )
733 {
734 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
735 continue;
736 }
Nick Child62b2d7e2022-07-14 16:24:59 -0500737
738 if( hashlen != mbedtls_md_get_size( md_info ) )
739 {
740 ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
741 signer = signer->next;
742 continue;
743 }
744
745 ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash, hashlen,
746 pkcs7->signed_data.signers.sig.p,
747 pkcs7->signed_data.signers.sig.len );
748 if( ret == 0 )
749 break;
Nick Child62b2d7e2022-07-14 16:24:59 -0500750 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000751
Nick Child9f4fb3e2022-09-12 16:21:02 -0500752out:
Nayna Jainc9deb182020-11-16 19:03:12 +0000753 return ( ret );
754}
755
756/*
757 * Unallocate all pkcs7 data
758 */
759void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 )
760{
Daniel Axtens35384792020-09-02 14:48:45 +1000761 mbedtls_pkcs7_signer_info *signer_cur;
762 mbedtls_pkcs7_signer_info *signer_prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000763
764 if( pkcs7 == NULL || pkcs7->raw.p == NULL )
765 return;
766
767 mbedtls_free( pkcs7->raw.p );
768
769 mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
770 mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
771
Daniel Axtens35384792020-09-02 14:48:45 +1000772 signer_cur = pkcs7->signed_data.signers.next;
773 pkcs7_free_signer_info( &pkcs7->signed_data.signers );
774 while( signer_cur != NULL )
Nayna Jainc9deb182020-11-16 19:03:12 +0000775 {
Daniel Axtens35384792020-09-02 14:48:45 +1000776 signer_prev = signer_cur;
777 signer_cur = signer_prev->next;
778 pkcs7_free_signer_info( signer_prev );
779 mbedtls_free( signer_prev );
Nayna Jainc9deb182020-11-16 19:03:12 +0000780 }
781
782 pkcs7->raw.p = NULL;
783}
784
785#endif