@@ -722,6 +722,55 @@ int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
722722 return ret ;
723723}
724724
725+ static int mbedtls_pkcs7_hash_authenticated_attributes (const mbedtls_md_info_t * md_info ,
726+ const mbedtls_x509_buf * buf ,
727+ unsigned char * output )
728+ {
729+ int ret ;
730+ mbedtls_md_context_t md_ctx ;
731+
732+ unsigned char asn1_tag_buf [1 ];
733+ unsigned char asn1_length_buf [1 + sizeof (size_t )];
734+ unsigned char * p = asn1_length_buf + sizeof (asn1_length_buf );
735+ int asn1_length_buf_len ;
736+
737+ mbedtls_md_init (& md_ctx );
738+
739+ if ((ret = mbedtls_md_setup (& md_ctx , md_info , 0 )) != 0 ) {
740+ goto exit ;
741+ }
742+ if ((ret = mbedtls_md_starts (& md_ctx )) != 0 ) {
743+ goto exit ;
744+ }
745+
746+ /*
747+ * Per RFC 2315 9.3, the message digest is computed on the complete DER encoding
748+ * of the Attributes value. We therefore need to hash the tag and the ASN.1 length
749+ * on top of the actual buffer contents.
750+ */
751+ asn1_tag_buf [0 ] = buf -> tag ;
752+ if ((ret = mbedtls_md_update (& md_ctx , asn1_tag_buf , sizeof (asn1_tag_buf ))) != 0 ) {
753+ goto exit ;
754+ }
755+ if ((ret = asn1_length_buf_len = mbedtls_asn1_write_len (& p , asn1_length_buf , buf -> len )) < 0 ) {
756+ goto exit ;
757+ }
758+ if ((ret = mbedtls_md_update (& md_ctx , p , asn1_length_buf_len )) != 0 ) {
759+ goto exit ;
760+ }
761+ if ((ret = mbedtls_md_update (& md_ctx , buf -> p , buf -> len )) != 0 ) {
762+ goto exit ;
763+ }
764+
765+ if ((ret = mbedtls_md_finish (& md_ctx , output )) != 0 ) {
766+ goto exit ;
767+ }
768+
769+ exit :
770+ mbedtls_md_free (& md_ctx );
771+ return ret ;
772+ }
773+
725774static int mbedtls_pkcs7_data_or_hash_verify (mbedtls_pkcs7 * pkcs7 ,
726775 const mbedtls_x509_crt * cert ,
727776 const unsigned char * data ,
@@ -788,9 +837,42 @@ static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
788837 * failed to validate'.
789838 */
790839 for (signer = & pkcs7 -> signed_data .signers ; signer ; signer = signer -> next ) {
791- ret = mbedtls_pk_verify (& pk_cxt , md_alg , hash ,
792- mbedtls_md_get_size (md_info ),
793- signer -> sig .p , signer -> sig .len );
840+ if (signer -> auth_attributes_raw .p != NULL ) {
841+ unsigned char * signer_hash ;
842+
843+ if (signer -> auth_attributes .message_digest_raw .len != mbedtls_md_get_size (md_info ) ||
844+ memcmp (hash , signer -> auth_attributes .message_digest_raw .p , mbedtls_md_get_size (md_info ))) {
845+ mbedtls_free (hash );
846+ return MBEDTLS_ERR_PKCS7_VERIFY_FAIL ;
847+ }
848+
849+ signer_hash = mbedtls_calloc (mbedtls_md_get_size (md_info ), 1 );
850+ if (signer_hash == NULL ) {
851+ mbedtls_free (hash );
852+ return MBEDTLS_ERR_PKCS7_ALLOC_FAILED ;
853+ }
854+
855+ /* BEGIN must free signer_hash before jumping out */
856+ ret = mbedtls_pkcs7_hash_authenticated_attributes (md_info ,
857+ & signer -> auth_attributes_raw ,
858+ signer_hash );
859+ if (ret != 0 ) {
860+ mbedtls_free (signer_hash );
861+ mbedtls_free (hash );
862+ return MBEDTLS_ERR_PKCS7_VERIFY_FAIL ;
863+ }
864+
865+ ret = mbedtls_pk_verify (& pk_cxt , md_alg , signer_hash ,
866+ mbedtls_md_get_size (md_info ),
867+ signer -> sig .p , signer -> sig .len );
868+
869+ mbedtls_free (signer_hash );
870+ /* END must free signer_hash before jumping out */
871+ } else {
872+ ret = mbedtls_pk_verify (& pk_cxt , md_alg , hash ,
873+ mbedtls_md_get_size (md_info ),
874+ signer -> sig .p , signer -> sig .len );
875+ }
794876
795877 if (ret == 0 ) {
796878 break ;
0 commit comments