blob: 0f4e1ec2b49755d960563af04a7c77c9f2665fc4 [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"
27
28#include <stdlib.h>
29#include <stdio.h>
30#include <string.h>
31#if defined(MBEDTLS_FS_IO)
32#include <sys/types.h>
33#include <sys/stat.h>
34#endif
35
36#if defined(MBEDTLS_PLATFORM_C)
37#include "mbedtls/platform.h"
38#include "mbedtls/platform_util.h"
39#else
40#include <stdio.h>
41#include <stdlib.h>
42#define mbedtls_free free
43#define mbedtls_calloc calloc
44#define mbedtls_printf printf
45#define mbedtls_snprintf snprintf
46#endif
47
48#if defined(MBEDTLS_HAVE_TIME)
49#include "mbedtls/platform_time.h"
50#endif
51#if defined(MBEDTLS_HAVE_TIME_DATE)
52#include <time.h>
53#endif
54
55/**
56 * Initializes the pkcs7 structure.
57 */
58void mbedtls_pkcs7_init( mbedtls_pkcs7 *pkcs7 )
59{
60 memset( pkcs7, 0, sizeof( mbedtls_pkcs7 ) );
61 pkcs7->raw.p = NULL;
62}
63
64static int pkcs7_get_next_content_len( unsigned char **p, unsigned char *end,
65 size_t *len )
66{
67 int ret;
68
69 if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_CONSTRUCTED
70 | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
71 {
72 return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
73 }
74
75 return( 0 );
76}
77
78/**
79 * version Version
80 * Version ::= INTEGER
81 **/
82static int pkcs7_get_version( unsigned char **p, unsigned char *end, int *ver )
83{
84 int ret;
85
86 if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 )
87 return( MBEDTLS_ERR_PKCS7_INVALID_VERSION + ret );
88
89 /* If version != 1, return invalid version */
90 if( *ver != MBEDTLS_PKCS7_SUPPORTED_VERSION )
91 return( MBEDTLS_ERR_PKCS7_INVALID_VERSION );
92
93 return( 0 );
94}
95
96/**
97 * ContentInfo ::= SEQUENCE {
98 * contentType ContentType,
99 * content
100 * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
101 **/
102static int pkcs7_get_content_info_type( unsigned char **p, unsigned char *end,
103 mbedtls_pkcs7_buf *pkcs7 )
104{
105 size_t len = 0;
106 int ret;
Nayna Jain673a2262020-12-14 22:44:49 +0000107 unsigned char *start = *p;
Nayna Jainc9deb182020-11-16 19:03:12 +0000108
109 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
110 | MBEDTLS_ASN1_SEQUENCE );
Nick Childc448c942021-07-01 15:29:50 -0400111 if( ret != 0 ) {
112 *p = start;
Nayna Jainc9deb182020-11-16 19:03:12 +0000113 return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
Nick Childc448c942021-07-01 15:29:50 -0400114 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000115
116 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OID );
Nayna Jain673a2262020-12-14 22:44:49 +0000117 if( ret != 0 ) {
118 *p = start;
Nayna Jainc9deb182020-11-16 19:03:12 +0000119 return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO + ret );
Nayna Jain673a2262020-12-14 22:44:49 +0000120 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000121
122 pkcs7->tag = MBEDTLS_ASN1_OID;
123 pkcs7->len = len;
124 pkcs7->p = *p;
125
126 return( ret );
127}
128
129/**
130 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
131 *
132 * This is from x509.h
133 **/
134static int pkcs7_get_digest_algorithm( unsigned char **p, unsigned char *end,
135 mbedtls_x509_buf *alg )
136{
137 int ret;
138
139 if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 )
140 return( MBEDTLS_ERR_PKCS7_INVALID_ALG );
141
142 return( 0 );
143}
144
145/**
146 * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
147 **/
148static int pkcs7_get_digest_algorithm_set( unsigned char **p,
149 unsigned char *end,
150 mbedtls_x509_buf *alg )
151{
152 size_t len = 0;
153 int ret;
154
155 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
156 | MBEDTLS_ASN1_SET );
157 if( ret != 0 )
158 return( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
159
160 end = *p + len;
161
162 /** For now, it assumes there is only one digest algorithm specified **/
163 ret = mbedtls_asn1_get_alg_null( p, end, alg );
164 if( ret != 0 )
165 return( MBEDTLS_ERR_PKCS7_INVALID_ALG + ret );
166
167 if ( *p != end )
168 return ( MBEDTLS_ERR_PKCS7_INVALID_FORMAT );
169
170 return( 0 );
171}
172
173/**
174 * certificates :: SET OF ExtendedCertificateOrCertificate,
175 * ExtendedCertificateOrCertificate ::= CHOICE {
176 * certificate Certificate -- x509,
177 * extendedCertificate[0] IMPLICIT ExtendedCertificate }
178 * Return number of certificates added to the signed data,
179 * 0 or higher is valid.
180 * Return negative error code for failure.
181 **/
182static int pkcs7_get_certificates( unsigned char **p, unsigned char *end,
183 mbedtls_x509_crt *certs )
184{
185 int ret;
186 size_t len1 = 0;
187 size_t len2 = 0;
188 unsigned char *end_set, *end_cert;
189 unsigned char *start = *p;
190
191 if( ( ret = mbedtls_asn1_get_tag( p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
192 | MBEDTLS_ASN1_CONTEXT_SPECIFIC ) ) != 0 )
193 {
194 if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG )
195 return( 0 );
196
197 return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
198 }
199 start = *p;
200 end_set = *p + len1;
201
202 ret = mbedtls_asn1_get_tag( p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
203 | MBEDTLS_ASN1_SEQUENCE );
204 if( ret != 0 )
205 return( MBEDTLS_ERR_PKCS7_INVALID_CERT + ret );
206
207 end_cert = *p + len2;
208
209 /*
210 * This is to verify that there is only one signer certificate. It seems it is
211 * not easy to differentiate between the chain vs different signer's certificate.
212 * So, we support only the root certificate and the single signer.
213 * The behaviour would be improved with addition of multiple signer support.
214 */
215 if (end_cert != end_set)
216 return ( MBEDTLS_ERR_PKCS7_INVALID_CERT );
217
218 *p = start;
219 if( ( ret = mbedtls_x509_crt_parse( certs, *p, len1 ) ) < 0 )
220 return( MBEDTLS_ERR_PKCS7_INVALID_CERT );
221
222 *p = *p + len1;
223
224 /* Since in this version we strictly support single certificate, and reaching
225 * here implies we have parsed successfully, we return 1. */
226
227 return( 1 );
228}
229
230/**
231 * EncryptedDigest ::= OCTET STRING
232 **/
233static int pkcs7_get_signature( unsigned char **p, unsigned char *end,
234 mbedtls_pkcs7_buf *signature )
235{
236 int ret;
237 size_t len = 0;
238
239 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_OCTET_STRING );
240 if( ret != 0 )
241 return( ret );
242
243 signature->tag = MBEDTLS_ASN1_OCTET_STRING;
244 signature->len = len;
245 signature->p = *p;
246
247 *p = *p + len;
248
249 return( 0 );
250}
251
252/**
Nayna Jainc9deb182020-11-16 19:03:12 +0000253 * SignerInfo ::= SEQUENCE {
254 * version Version;
255 * issuerAndSerialNumber IssuerAndSerialNumber,
256 * digestAlgorithm DigestAlgorithmIdentifier,
257 * authenticatedAttributes
258 * [0] IMPLICIT Attributes OPTIONAL,
259 * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
260 * encryptedDigest EncryptedDigest,
261 * unauthenticatedAttributes
262 * [1] IMPLICIT Attributes OPTIONAL,
Daniel Axtens35384792020-09-02 14:48:45 +1000263 * Returns 0 if the signerInfo is valid.
264 * Return negative error code for failure.
265 **/
266static int pkcs7_get_signer_info( unsigned char **p, unsigned char *end,
267 mbedtls_pkcs7_signer_info *signer )
268{
269 unsigned char *end_signer;
270 int ret;
271 size_t len = 0;
272
273 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
274 | MBEDTLS_ASN1_SEQUENCE );
275 if( ret != 0 )
276 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
277
278 end_signer = *p + len;
279
280 ret = pkcs7_get_version( p, end_signer, &signer->version );
281 if( ret != 0 )
282 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
283
284 ret = mbedtls_asn1_get_tag( p, end_signer, &len, MBEDTLS_ASN1_CONSTRUCTED
285 | MBEDTLS_ASN1_SEQUENCE );
286 if( ret != 0 )
287 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
288
289 /* Parsing IssuerAndSerialNumber */
290 signer->issuer_raw.p = *p;
291
292 ret = mbedtls_asn1_get_tag( p, end_signer, &len, MBEDTLS_ASN1_CONSTRUCTED
293 | MBEDTLS_ASN1_SEQUENCE );
294 if( ret != 0 )
295 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
296
297 ret = mbedtls_x509_get_name( p, *p + len, &signer->issuer );
298 if( ret != 0 )
299 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
300
301 signer->issuer_raw.len = *p - signer->issuer_raw.p;
302
303 ret = mbedtls_x509_get_serial( p, end_signer, &signer->serial );
304 if( ret != 0 )
305 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
306
307 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->alg_identifier );
308 if( ret != 0 )
309 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
310
311 ret = pkcs7_get_digest_algorithm( p, end_signer, &signer->sig_alg_identifier );
312 if( ret != 0 )
313 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
314
315 ret = pkcs7_get_signature( p, end_signer, &signer->sig );
316 if( ret != 0 )
317 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
318
319 /* Do not permit any unauthenticated attributes */
320 if( *p != end_signer )
321 return ( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO );
322
323 return( 0 );
324}
325
326static void pkcs7_free_signer_info( mbedtls_pkcs7_signer_info *signer )
327{
328 mbedtls_x509_name *name_cur;
329 mbedtls_x509_name *name_prv;
330
331 if( signer == NULL )
332 return;
333
334 name_cur = signer->issuer.next;
335 while( name_cur != NULL )
336 {
337 name_prv = name_cur;
338 name_cur = name_cur->next;
339 mbedtls_free( name_prv );
340 }
341}
342
343/**
344 * SignerInfos ::= SET of SignerInfo
Nayna Jainc9deb182020-11-16 19:03:12 +0000345 * Return number of signers added to the signed data,
346 * 0 or higher is valid.
347 * Return negative error code for failure.
348 **/
349static int pkcs7_get_signers_info_set( unsigned char **p, unsigned char *end,
350 mbedtls_pkcs7_signer_info *signers_set )
351{
Daniel Axtens35384792020-09-02 14:48:45 +1000352 unsigned char *end_set;
Nayna Jainc9deb182020-11-16 19:03:12 +0000353 int ret;
Daniel Axtens35384792020-09-02 14:48:45 +1000354 int count = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000355 size_t len = 0;
Daniel Axtens35384792020-09-02 14:48:45 +1000356 mbedtls_pkcs7_signer_info *signer, *prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000357
358 ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
359 | MBEDTLS_ASN1_SET );
360 if( ret != 0 )
361 return( MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO + ret );
362
Daniel Axtens35384792020-09-02 14:48:45 +1000363 /* Detect zero signers */
364 if( len == 0 )
365 return( 0 );
366
Nayna Jainc9deb182020-11-16 19:03:12 +0000367 end_set = *p + len;
368
Daniel Axtens35384792020-09-02 14:48:45 +1000369 ret = pkcs7_get_signer_info( p, end_set, signers_set );
Nayna Jainc9deb182020-11-16 19:03:12 +0000370 if( ret != 0 )
Daniel Axtens35384792020-09-02 14:48:45 +1000371 return( ret );
372 count++;
Nayna Jainc9deb182020-11-16 19:03:12 +0000373
Daniel Axtens35384792020-09-02 14:48:45 +1000374 prev = signers_set;
375 while( *p != end_set )
376 {
377 signer = mbedtls_calloc( 1, sizeof( mbedtls_pkcs7_signer_info ) );
378 if( !signer )
379 {
380 ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
381 goto cleanup;
382 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000383
Daniel Axtens35384792020-09-02 14:48:45 +1000384 ret = pkcs7_get_signer_info( p, end_set, signer );
385 if( ret != 0 ) {
386 mbedtls_free( signer );
387 goto cleanup;
388 }
389 prev->next = signer;
390 prev = signer;
391 count++;
392 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000393
Daniel Axtens35384792020-09-02 14:48:45 +1000394 return( count );
Nayna Jainc9deb182020-11-16 19:03:12 +0000395
Daniel Axtens35384792020-09-02 14:48:45 +1000396cleanup:
397 signer = signers_set->next;
398 pkcs7_free_signer_info( signers_set );
399 while( signer )
400 {
401 prev = signer;
402 signer = signer->next;
403 pkcs7_free_signer_info( prev );
404 mbedtls_free( prev );
405 }
406 return( ret );
Nayna Jainc9deb182020-11-16 19:03:12 +0000407}
408
409/**
410 * SignedData ::= SEQUENCE {
411 * version Version,
412 * digestAlgorithms DigestAlgorithmIdentifiers,
413 * contentInfo ContentInfo,
414 * certificates
415 * [0] IMPLICIT ExtendedCertificatesAndCertificates
416 * OPTIONAL,
417 * crls
418 * [0] IMPLICIT CertificateRevocationLists OPTIONAL,
419 * signerInfos SignerInfos }
420 */
421static int pkcs7_get_signed_data( unsigned char *buf, size_t buflen,
422 mbedtls_pkcs7_signed_data *signed_data )
423{
424 unsigned char *p = buf;
425 unsigned char *end = buf + buflen;
426 unsigned char *end_set;
427 size_t len = 0;
428 int ret;
429 mbedtls_md_type_t md_alg;
430
431 ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
432 | MBEDTLS_ASN1_SEQUENCE );
433 if( ret != 0 )
434 return( MBEDTLS_ERR_PKCS7_INVALID_FORMAT + ret );
435
436 end_set = p + len;
437
438 /* Get version of signed data */
439 ret = pkcs7_get_version( &p, end_set, &signed_data->version );
440 if( ret != 0 )
441 return( ret );
442
443 /* Get digest algorithm */
444 ret = pkcs7_get_digest_algorithm_set( &p, end_set,
445 &signed_data->digest_alg_identifiers );
446 if( ret != 0 )
447 return( ret );
448
449 ret = mbedtls_oid_get_md_alg( &signed_data->digest_alg_identifiers, &md_alg );
450 if( ret != 0 )
451 return( MBEDTLS_ERR_PKCS7_INVALID_ALG );
452
453 /* Do not expect any content */
454 ret = pkcs7_get_content_info_type( &p, end_set, &signed_data->content.oid );
455 if( ret != 0 )
456 return( ret );
457
458 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &signed_data->content.oid ) )
459 {
460 return( MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO ) ;
461 }
462
463 p = p + signed_data->content.oid.len;
464
465 /* Look for certificates, there may or may not be any */
466 mbedtls_x509_crt_init( &signed_data->certs );
467 ret = pkcs7_get_certificates( &p, end_set, &signed_data->certs );
468 if( ret < 0 )
469 return( ret ) ;
470
471 signed_data->no_of_certs = ret;
472
473 /*
474 * Currently CRLs are not supported. If CRL exist, the parsing will fail
475 * at next step of getting signers info and return error as invalid
476 * signer info.
477 */
478
479 signed_data->no_of_crls = 0;
480
481 /* Get signers info */
482 ret = pkcs7_get_signers_info_set( &p, end_set, &signed_data->signers );
483 if( ret < 0 )
484 return( ret );
485
486 signed_data->no_of_signers = ret;
487
Daniel Axtens35384792020-09-02 14:48:45 +1000488 /* Don't permit trailing data */
Nayna Jainc9deb182020-11-16 19:03:12 +0000489 if ( p != end )
490 ret = MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
491
492 ret = 0;
493 return( ret );
494}
495
496int mbedtls_pkcs7_parse_der( mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
497 const size_t buflen )
498{
499 unsigned char *start;
500 unsigned char *end;
501 size_t len = 0;
502 int ret;
Nayna Jain673a2262020-12-14 22:44:49 +0000503 int isoidset = 0;
Nayna Jainc9deb182020-11-16 19:03:12 +0000504
505 if( !pkcs7 )
506 return( MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA );
507
508 /* make an internal copy of the buffer for parsing */
509 pkcs7->raw.p = start = mbedtls_calloc( 1, buflen );
510 if( pkcs7->raw.p == NULL )
511 {
512 return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
513 }
514 memcpy( start, buf, buflen );
515 pkcs7->raw.len = buflen;
516 end = start + buflen;
517
518 ret = pkcs7_get_content_info_type( &start, end, &pkcs7->content_type_oid );
519 if( ret != 0 )
Nayna Jain673a2262020-12-14 22:44:49 +0000520 {
521 len = buflen;
522 goto try_data;
523 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000524
525 if( ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DATA, &pkcs7->content_type_oid )
526 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid )
527 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENVELOPED_DATA, &pkcs7->content_type_oid )
528 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, &pkcs7->content_type_oid )
529 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_DIGESTED_DATA, &pkcs7->content_type_oid )
530 || ! MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, &pkcs7->content_type_oid ) )
531 {
532 ret = MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
533 goto out;
534 }
535
536 if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS7_SIGNED_DATA, &pkcs7->content_type_oid ) )
537 {
538 ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
539 goto out;
540 }
541
Nayna Jain673a2262020-12-14 22:44:49 +0000542 isoidset = 1;
Nayna Jainc9deb182020-11-16 19:03:12 +0000543 start = start + pkcs7->content_type_oid.len;
544
545 ret = pkcs7_get_next_content_len( &start, end, &len );
546 if( ret != 0 )
547 goto out;
548
Nayna Jain673a2262020-12-14 22:44:49 +0000549try_data:
Nayna Jainc9deb182020-11-16 19:03:12 +0000550 ret = pkcs7_get_signed_data( start, len, &pkcs7->signed_data );
Nayna Jain673a2262020-12-14 22:44:49 +0000551 if ( ret != 0 )
552 goto out;
553
554 if ( !isoidset )
555 {
556 pkcs7->content_type_oid.tag = MBEDTLS_ASN1_OID;
557 pkcs7->content_type_oid.len = MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS7_SIGNED_DATA );
558 pkcs7->content_type_oid.p = (unsigned char *)MBEDTLS_OID_PKCS7_SIGNED_DATA;
559 }
560
561 ret = MBEDTLS_PKCS7_SIGNED_DATA;
Nayna Jainc9deb182020-11-16 19:03:12 +0000562
563out:
Nayna Jain673a2262020-12-14 22:44:49 +0000564 if ( ret < 0 )
Nayna Jainc9deb182020-11-16 19:03:12 +0000565 mbedtls_pkcs7_free( pkcs7 );
Nayna Jain673a2262020-12-14 22:44:49 +0000566
Nayna Jainc9deb182020-11-16 19:03:12 +0000567 return( ret );
568}
569
570int mbedtls_pkcs7_signed_data_verify( mbedtls_pkcs7 *pkcs7,
571 const mbedtls_x509_crt *cert,
572 const unsigned char *data,
573 size_t datalen )
574{
575
Daniel Axtens35384792020-09-02 14:48:45 +1000576 int ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
Nayna Jainc9deb182020-11-16 19:03:12 +0000577 unsigned char *hash;
578 mbedtls_pk_context pk_cxt = cert->pk;
579 const mbedtls_md_info_t *md_info;
580 mbedtls_md_type_t md_alg;
Daniel Axtens35384792020-09-02 14:48:45 +1000581 mbedtls_pkcs7_signer_info *signer;
Nayna Jainc9deb182020-11-16 19:03:12 +0000582
Daniel Axtens35384792020-09-02 14:48:45 +1000583 if( pkcs7->signed_data.no_of_signers == 0 )
Nayna Jainc9deb182020-11-16 19:03:12 +0000584 return( MBEDTLS_ERR_PKCS7_VERIFY_FAIL );
585
Nayna Jainc9deb182020-11-16 19:03:12 +0000586
Daniel Axtens35384792020-09-02 14:48:45 +1000587 /*
588 * Potential TODOs
589 * Currently we iterate over all signers and return success if any of them
590 * verify.
591 *
592 * However, we could make this better by checking against the certificate's
593 * identification and SignerIdentifier fields first. That would also allow
594 * us to distinguish between 'no signature for key' and 'signature for key
595 * failed to validate'.
596 *
597 * We could also cache hashes by md, so if there are several sigs all using
598 * the same algo we don't recalculate the hash each time.
599 */
600 signer = &pkcs7->signed_data.signers;
601 while( signer )
Nick Child66718412022-02-22 17:19:59 -0600602 {
Daniel Axtens35384792020-09-02 14:48:45 +1000603 ret = mbedtls_oid_get_md_alg( &signer->alg_identifier, &md_alg );
604 if( ret != 0 )
605 return( MBEDTLS_ERR_PKCS7_VERIFY_FAIL );
Nayna Jainc9deb182020-11-16 19:03:12 +0000606
Daniel Axtens35384792020-09-02 14:48:45 +1000607 md_info = mbedtls_md_info_from_type( md_alg );
608
609 hash = mbedtls_calloc( mbedtls_md_get_size( md_info ), 1 );
610 if( hash == NULL ) {
611 return( MBEDTLS_ERR_PKCS7_ALLOC_FAILED );
612 }
613
614 ret = mbedtls_md( md_info, data, datalen, hash );
615 if( ret != 0 )
616 {
617 mbedtls_free( hash );
618 return( ret );
619 }
620
621 ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash,
622 mbedtls_md_get_size( md_info ),
623 signer->sig.p, signer->sig.len );
624
625 mbedtls_free( hash );
626
627 if( ret == 0 )
628 break;
629
630 signer = signer->next;
631 }
Nayna Jainc9deb182020-11-16 19:03:12 +0000632
633 return( ret );
634}
635
636int mbedtls_pkcs7_signed_hash_verify( mbedtls_pkcs7 *pkcs7,
637 const mbedtls_x509_crt *cert,
638 const unsigned char *hash, size_t hashlen)
639{
640 int ret;
641 mbedtls_md_type_t md_alg;
642 mbedtls_pk_context pk_cxt;
643
644 ret = mbedtls_oid_get_md_alg( &pkcs7->signed_data.digest_alg_identifiers, &md_alg );
645 if( ret != 0 )
646 return( MBEDTLS_ERR_PKCS7_VERIFY_FAIL );
647
648 pk_cxt = cert->pk;
649 ret = mbedtls_pk_verify( &pk_cxt, md_alg, hash, hashlen,
650 pkcs7->signed_data.signers.sig.p,
651 pkcs7->signed_data.signers.sig.len );
652
653 return ( ret );
654}
655
656/*
657 * Unallocate all pkcs7 data
658 */
659void mbedtls_pkcs7_free( mbedtls_pkcs7 *pkcs7 )
660{
Daniel Axtens35384792020-09-02 14:48:45 +1000661 mbedtls_pkcs7_signer_info *signer_cur;
662 mbedtls_pkcs7_signer_info *signer_prev;
Nayna Jainc9deb182020-11-16 19:03:12 +0000663
664 if( pkcs7 == NULL || pkcs7->raw.p == NULL )
665 return;
666
667 mbedtls_free( pkcs7->raw.p );
668
669 mbedtls_x509_crt_free( &pkcs7->signed_data.certs );
670 mbedtls_x509_crl_free( &pkcs7->signed_data.crl );
671
Daniel Axtens35384792020-09-02 14:48:45 +1000672 signer_cur = pkcs7->signed_data.signers.next;
673 pkcs7_free_signer_info( &pkcs7->signed_data.signers );
674 while( signer_cur != NULL )
Nayna Jainc9deb182020-11-16 19:03:12 +0000675 {
Daniel Axtens35384792020-09-02 14:48:45 +1000676 signer_prev = signer_cur;
677 signer_cur = signer_prev->next;
678 pkcs7_free_signer_info( signer_prev );
679 mbedtls_free( signer_prev );
Nayna Jainc9deb182020-11-16 19:03:12 +0000680 }
681
682 pkcs7->raw.p = NULL;
683}
684
685#endif