@@ -270,6 +270,7 @@ static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
270
270
size_t len1 = 0 ;
271
271
size_t len2 = 0 ;
272
272
unsigned char * end_set , * end_cert , * start ;
273
+ int n = 0 ;
273
274
274
275
if ((ret = mbedtls_asn1_get_tag (p , end , & len1 , MBEDTLS_ASN1_CONSTRUCTED
275
276
| MBEDTLS_ASN1_CONTEXT_SPECIFIC )) != 0 ) {
@@ -279,39 +280,30 @@ static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
279
280
return MBEDTLS_ERROR_ADD (MBEDTLS_ERR_PKCS7_INVALID_FORMAT , ret );
280
281
}
281
282
}
282
- start = * p ;
283
283
end_set = * p + len1 ;
284
284
285
- ret = mbedtls_asn1_get_tag (p , end_set , & len2 , MBEDTLS_ASN1_CONSTRUCTED
286
- | MBEDTLS_ASN1_SEQUENCE );
287
- if (ret != 0 ) {
288
- return MBEDTLS_ERROR_ADD (MBEDTLS_ERR_PKCS7_INVALID_CERT , ret );
289
- }
285
+ while (* p != end_set ) {
286
+ start = * p ;
287
+ ret = mbedtls_asn1_get_tag (p , end_set , & len2 , MBEDTLS_ASN1_CONSTRUCTED
288
+ | MBEDTLS_ASN1_SEQUENCE );
289
+ if (ret != 0 ) {
290
+ return MBEDTLS_ERROR_ADD (MBEDTLS_ERR_PKCS7_INVALID_CERT , ret );
291
+ }
290
292
291
- end_cert = * p + len2 ;
293
+ end_cert = * p + len2 ;
292
294
293
- /*
294
- * This is to verify that there is only one signer certificate. It seems it is
295
- * not easy to differentiate between the chain vs different signer's certificate.
296
- * So, we support only the root certificate and the single signer.
297
- * The behaviour would be improved with addition of multiple signer support.
298
- */
299
- if (end_cert != end_set ) {
300
- return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE ;
301
- }
302
-
303
- * p = start ;
304
- if ((ret = mbedtls_x509_crt_parse_der (certs , * p , len1 )) < 0 ) {
305
- return MBEDTLS_ERR_PKCS7_INVALID_CERT ;
295
+ * p = start ;
296
+ if ((ret = mbedtls_x509_crt_parse_der (certs , * p ,
297
+ (size_t )(end_cert - * p ))) < 0 ) {
298
+ return MBEDTLS_ERR_PKCS7_INVALID_CERT ;
299
+ }
300
+ * p = end_cert ;
301
+ n ++ ;
306
302
}
307
303
308
- * p = * p + len1 ;
304
+ * p = end_set ;
309
305
310
- /*
311
- * Since in this version we strictly support single certificate, and reaching
312
- * here implies we have parsed successfully, we return 1.
313
- */
314
- return 1 ;
306
+ return n ;
315
307
}
316
308
317
309
/**
@@ -719,29 +711,40 @@ static int pkcs7_signed_attrs_match(mbedtls_asn1_named_data *attrs,
719
711
return 0 ;
720
712
}
721
713
714
+ static mbedtls_x509_crt * pkcs7_find_cert (mbedtls_x509_buf * serial ,
715
+ mbedtls_x509_crt * cert )
716
+ {
717
+ for (; cert != NULL ; cert = cert -> next )
718
+ {
719
+ if (serial -> len == cert -> serial .len &&
720
+ memcmp (serial -> p , cert -> serial .p , serial -> len ) == 0 ) {
721
+ return cert ;
722
+ }
723
+ }
724
+
725
+ return NULL ;
726
+ }
727
+
722
728
static int mbedtls_pkcs7_data_or_hash_verify (mbedtls_pkcs7 * pkcs7 ,
723
- const mbedtls_x509_crt * cert ,
729
+ mbedtls_x509_crt * cert ,
724
730
const unsigned char * data ,
725
731
size_t datalen ,
726
732
const int is_data_hash )
727
733
{
728
734
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED ;
729
735
unsigned char * hash ;
730
- mbedtls_pk_context pk_cxt = cert -> pk ;
736
+ mbedtls_pk_context pk_ctx ;
737
+ mbedtls_x509_crt * pk_cert ;
731
738
const mbedtls_md_info_t * md_info ;
732
739
mbedtls_md_type_t md_alg ;
733
740
mbedtls_md_context_t md_ctx ;
734
741
mbedtls_pkcs7_signer_info * signer ;
742
+ uint32_t flags ;
735
743
736
744
if (pkcs7 -> signed_data .no_of_signers == 0 ) {
737
745
return MBEDTLS_ERR_PKCS7_INVALID_CERT ;
738
746
}
739
747
740
- if (mbedtls_x509_time_is_past (& cert -> valid_to ) ||
741
- mbedtls_x509_time_is_future (& cert -> valid_from )) {
742
- return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID ;
743
- }
744
-
745
748
/*
746
749
* Potential TODOs
747
750
* Currently we iterate over all signers and return success if any of them
@@ -812,9 +815,50 @@ static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
812
815
mbedtls_md_free (& md_ctx );
813
816
}
814
817
815
- ret = mbedtls_pk_verify (& pk_cxt , md_alg , hash ,
816
- mbedtls_md_get_size (md_info ),
817
- signer -> sig .p , signer -> sig .len );
818
+ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL ;
819
+
820
+ /* try trusted certificates */
821
+ for (pk_cert = pkcs7_find_cert (& signer -> serial , cert );
822
+ pk_cert != NULL ;
823
+ pk_cert = pkcs7_find_cert (& signer -> serial , pk_cert -> next )) {
824
+ if (mbedtls_x509_time_is_past (& pk_cert -> valid_to ) ||
825
+ mbedtls_x509_time_is_future (& pk_cert -> valid_from )) {
826
+ ret = MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID ;
827
+ continue ;
828
+ }
829
+ pk_ctx = pk_cert -> pk ;
830
+ ret = mbedtls_pk_verify (& pk_ctx , md_alg , hash ,
831
+ mbedtls_md_get_size (md_info ),
832
+ signer -> sig .p , signer -> sig .len );
833
+ if (ret == 0 ) {
834
+ break ;
835
+ }
836
+ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL ;
837
+ }
838
+
839
+ /* try embedded certs with a chain of trust back to a trusted cert */
840
+ if (ret != 0 ) {
841
+ for (pk_cert = pkcs7_find_cert (& signer -> serial ,
842
+ & pkcs7 -> signed_data .certs );
843
+ pk_cert != NULL ;
844
+ pk_cert = pkcs7_find_cert (& signer -> serial , pk_cert -> next )) {
845
+ if (mbedtls_x509_crt_verify (pk_cert , cert ,
846
+ & pkcs7 -> signed_data .crl , NULL ,
847
+ & flags , NULL , NULL ) != 0 ) {
848
+ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL ;
849
+ continue ;
850
+ }
851
+ pk_ctx = pk_cert -> pk ;
852
+ ret = mbedtls_pk_verify (& pk_ctx , md_alg , hash ,
853
+ mbedtls_md_get_size (md_info ),
854
+ signer -> sig .p , signer -> sig .len );
855
+ if (ret == 0 ) {
856
+ break ;
857
+ }
858
+ ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL ;
859
+ }
860
+ }
861
+
818
862
mbedtls_free (hash );
819
863
/* END must free hash before jumping out */
820
864
@@ -826,15 +870,15 @@ static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
826
870
return ret ;
827
871
}
828
872
int mbedtls_pkcs7_signed_data_verify (mbedtls_pkcs7 * pkcs7 ,
829
- const mbedtls_x509_crt * cert ,
873
+ mbedtls_x509_crt * cert ,
830
874
const unsigned char * data ,
831
875
size_t datalen )
832
876
{
833
877
return mbedtls_pkcs7_data_or_hash_verify (pkcs7 , cert , data , datalen , 0 );
834
878
}
835
879
836
880
int mbedtls_pkcs7_signed_hash_verify (mbedtls_pkcs7 * pkcs7 ,
837
- const mbedtls_x509_crt * cert ,
881
+ mbedtls_x509_crt * cert ,
838
882
const unsigned char * hash ,
839
883
size_t hashlen )
840
884
{
0 commit comments