mbedtls/external: support decoding multiple signer's cert
Support decoding multiple signer's cert in the signed data within
a PKCS7 message.
The PR for this patch is at:
https://github.com/Mbed-TLS/mbedtls/pull/9001
For enabling EFI loader PKCS7 features with MbedTLS build,
we need this patch on top of MbedTLS v3.6.0 before it is merged into
the next MbedTLS LTS release.
Signed-off-by: Raymond Mao <raymond.mao@linaro.org>
diff --git a/lib/mbedtls/external/mbedtls/library/pkcs7.c b/lib/mbedtls/external/mbedtls/library/pkcs7.c
index da73fb3..0110522 100644
--- a/lib/mbedtls/external/mbedtls/library/pkcs7.c
+++ b/lib/mbedtls/external/mbedtls/library/pkcs7.c
@@ -62,6 +62,36 @@
}
/**
+ * Get and decode one cert from a sequence.
+ * Return 0 for success,
+ * Return negative error code for failure.
+ **/
+static int pkcs7_get_one_cert(unsigned char **p, unsigned char *end,
+ mbedtls_x509_crt *certs)
+{
+ int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+ size_t len = 0;
+ unsigned char *start = *p;
+ unsigned char *end_cert;
+
+ ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
+ | MBEDTLS_ASN1_SEQUENCE);
+ if (ret != 0) {
+ return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);
+ }
+
+ end_cert = *p + len;
+
+ if ((ret = mbedtls_x509_crt_parse_der(certs, start, end_cert - start)) < 0) {
+ return MBEDTLS_ERR_PKCS7_INVALID_CERT;
+ }
+
+ *p = end_cert;
+
+ return 0;
+}
+
+/**
* version Version
* Version ::= INTEGER
**/
@@ -178,11 +208,12 @@
mbedtls_x509_crt *certs)
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
- size_t len1 = 0;
- size_t len2 = 0;
- unsigned char *end_set, *end_cert, *start;
+ size_t len = 0;
+ unsigned char *end_set;
+ int num_of_certs = 0;
- ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
+ /* Get the set of certs */
+ ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_CONTEXT_SPECIFIC);
if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return 0;
@@ -190,38 +221,26 @@
if (ret != 0) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
}
- start = *p;
- end_set = *p + len1;
+ end_set = *p + len;
- ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
- | MBEDTLS_ASN1_SEQUENCE);
+ ret = pkcs7_get_one_cert(p, end_set, certs);
if (ret != 0) {
- return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);
+ return ret;
}
- end_cert = *p + len2;
+ num_of_certs++;
- /*
- * This is to verify that there is only one signer certificate. It seems it is
- * not easy to differentiate between the chain vs different signer's certificate.
- * So, we support only the root certificate and the single signer.
- * The behaviour would be improved with addition of multiple signer support.
- */
- if (end_cert != end_set) {
- return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
+ while (*p != end_set) {
+ ret = pkcs7_get_one_cert(p, end_set, certs);
+ if (ret != 0) {
+ return ret;
+ }
+ num_of_certs++;
}
- if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) {
- return MBEDTLS_ERR_PKCS7_INVALID_CERT;
- }
+ *p = end_set;
- *p = end_cert;
-
- /*
- * Since in this version we strictly support single certificate, and reaching
- * here implies we have parsed successfully, we return 1.
- */
- return 1;
+ return num_of_certs;
}
/**