Skip to content

Commit ff3e4d8

Browse files
committed
Add support for internal certificates
Author: Joakim Sindholt via mbed-tls <[email protected]> Signed-off-by: Dave Rodgman <[email protected]>
1 parent 3ef804d commit ff3e4d8

File tree

2 files changed

+90
-42
lines changed

2 files changed

+90
-42
lines changed

include/mbedtls/pkcs7.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,9 @@ int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
209209
* PKCS7 structure itself.
210210
*
211211
* \param pkcs7 PKCS7 structure containing signature.
212-
* \param cert Certificate containing key to verify signature.
212+
* \param cert Trusted certificates either containing keys to verify the
213+
* signature or to verify an embedded certificate containing
214+
* the key.
213215
* \param data Plain data on which signature has to be verified.
214216
* \param datalen Length of the data.
215217
*
@@ -219,7 +221,7 @@ int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
219221
* \return 0 if the signature verifies, or a negative error code on failure.
220222
*/
221223
int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
222-
const mbedtls_x509_crt *cert,
224+
mbedtls_x509_crt *cert,
223225
const unsigned char *data,
224226
size_t datalen);
225227

@@ -238,7 +240,9 @@ int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
238240
* PKCS7 structure itself.
239241
*
240242
* \param pkcs7 PKCS7 structure containing signature.
241-
* \param cert Certificate containing key to verify signature.
243+
* \param cert Trusted certificates either containing keys to verify the
244+
* signature or to verify an embedded certificate containing
245+
* the key.
242246
* \param hash Hash of the plain data on which signature has to be verified.
243247
* \param hashlen Length of the hash.
244248
*
@@ -248,7 +252,7 @@ int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
248252
* \return 0 if the signature verifies, or a negative error code on failure.
249253
*/
250254
int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,
251-
const mbedtls_x509_crt *cert,
255+
mbedtls_x509_crt *cert,
252256
const unsigned char *hash, size_t hashlen);
253257

254258
/**

library/pkcs7.c

Lines changed: 82 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
270270
size_t len1 = 0;
271271
size_t len2 = 0;
272272
unsigned char *end_set, *end_cert, *start;
273+
int n = 0;
273274

274275
if ((ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
275276
| MBEDTLS_ASN1_CONTEXT_SPECIFIC)) != 0) {
@@ -279,39 +280,30 @@ static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
279280
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
280281
}
281282
}
282-
start = *p;
283283
end_set = *p + len1;
284284

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+
}
290292

291-
end_cert = *p + len2;
293+
end_cert = *p + len2;
292294

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++;
306302
}
307303

308-
*p = *p + len1;
304+
*p = end_set;
309305

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;
315307
}
316308

317309
/**
@@ -719,29 +711,40 @@ static int pkcs7_signed_attrs_match(mbedtls_asn1_named_data *attrs,
719711
return 0;
720712
}
721713

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+
722728
static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
723-
const mbedtls_x509_crt *cert,
729+
mbedtls_x509_crt *cert,
724730
const unsigned char *data,
725731
size_t datalen,
726732
const int is_data_hash)
727733
{
728734
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
729735
unsigned char *hash;
730-
mbedtls_pk_context pk_cxt = cert->pk;
736+
mbedtls_pk_context pk_ctx;
737+
mbedtls_x509_crt *pk_cert;
731738
const mbedtls_md_info_t *md_info;
732739
mbedtls_md_type_t md_alg;
733740
mbedtls_md_context_t md_ctx;
734741
mbedtls_pkcs7_signer_info *signer;
742+
uint32_t flags;
735743

736744
if (pkcs7->signed_data.no_of_signers == 0) {
737745
return MBEDTLS_ERR_PKCS7_INVALID_CERT;
738746
}
739747

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-
745748
/*
746749
* Potential TODOs
747750
* 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,
812815
mbedtls_md_free(&md_ctx);
813816
}
814817

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+
818862
mbedtls_free(hash);
819863
/* END must free hash before jumping out */
820864

@@ -826,15 +870,15 @@ static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
826870
return ret;
827871
}
828872
int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
829-
const mbedtls_x509_crt *cert,
873+
mbedtls_x509_crt *cert,
830874
const unsigned char *data,
831875
size_t datalen)
832876
{
833877
return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);
834878
}
835879

836880
int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,
837-
const mbedtls_x509_crt *cert,
881+
mbedtls_x509_crt *cert,
838882
const unsigned char *hash,
839883
size_t hashlen)
840884
{

0 commit comments

Comments
 (0)