Skip to content

Commit 9f7895a

Browse files
pkcs7: verify authenticated attributes if present
Signed-off-by: Jean-Baptiste Boric <[email protected]>
1 parent 8a104a9 commit 9f7895a

File tree

1 file changed

+85
-3
lines changed

1 file changed

+85
-3
lines changed

library/pkcs7.c

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
725774
static 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

Comments
 (0)