diff options
author | Adam Vartanian <flooey@google.com> | 2018-08-10 14:55:24 +0100 |
---|---|---|
committer | Adam Vartanian <flooey@google.com> | 2018-08-10 15:32:39 +0100 |
commit | bfcf3a72c0bcb62cfde80e932db0668a7f96c0f8 (patch) | |
tree | 3ab110046e45c25f8f69df137f8a9d4a52bf60b5 /src/crypto/pkcs7/pkcs7_x509.c | |
parent | 6120b2b9dfbe5b19fe2d0f69a4b8418ad5f7fe08 (diff) | |
download | boringssl-bfcf3a72c0bcb62cfde80e932db0668a7f96c0f8.tar.gz |
external/boringssl: Sync to 8625ec4b436ccb4098ed4aac10891eff8372be41.
This includes the following changes:
https://boringssl.googlesource.com/boringssl/+log/c596415ec62b501523d80f9afa26b135406da6bf..8625ec4b436ccb4098ed4aac10891eff8372be41
Test: cts -m CtsLibcoreTestCases
Change-Id: I47a45e6b6f46b19fcbcb6c917895867d56dcd2ca
Diffstat (limited to 'src/crypto/pkcs7/pkcs7_x509.c')
-rw-r--r-- | src/crypto/pkcs7/pkcs7_x509.c | 194 |
1 files changed, 178 insertions, 16 deletions
diff --git a/src/crypto/pkcs7/pkcs7_x509.c b/src/crypto/pkcs7/pkcs7_x509.c index 7bc39d27..a2a6b46a 100644 --- a/src/crypto/pkcs7/pkcs7_x509.c +++ b/src/crypto/pkcs7/pkcs7_x509.c @@ -26,6 +26,7 @@ #include <openssl/x509.h> #include "internal.h" +#include "../internal.h" int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) { @@ -64,28 +65,24 @@ err: int PKCS7_get_CRLs(STACK_OF(X509_CRL) *out_crls, CBS *cbs) { CBS signed_data, crls; uint8_t *der_bytes = NULL; - int ret = 0; + int ret = 0, has_crls; const size_t initial_crls_len = sk_X509_CRL_num(out_crls); - if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs)) { - return 0; - } - // See https://tools.ietf.org/html/rfc2315#section-9.1 - - // Even if only CRLs are included, there may be an empty certificates block. - // OpenSSL does this, for example. - if (CBS_peek_asn1_tag(&signed_data, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) && - !CBS_get_asn1(&signed_data, NULL /* certificates */, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + if (!pkcs7_parse_header(&der_bytes, &signed_data, cbs) || + // Even if only CRLs are included, there may be an empty certificates + // block. OpenSSL does this, for example. + !CBS_get_optional_asn1( + &signed_data, NULL, NULL, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || + !CBS_get_optional_asn1( + &signed_data, &crls, &has_crls, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) { goto err; } - if (!CBS_get_asn1(&signed_data, &crls, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 1)) { - OPENSSL_PUT_ERROR(PKCS7, PKCS7_R_NO_CRLS_INCLUDED); - goto err; + if (!has_crls) { + CBS_init(&crls, NULL, 0); } while (CBS_len(&crls) > 0) { @@ -231,3 +228,168 @@ static int pkcs7_bundle_crls_cb(CBB *out, const void *arg) { int PKCS7_bundle_CRLs(CBB *out, const STACK_OF(X509_CRL) *crls) { return pkcs7_bundle(out, pkcs7_bundle_crls_cb, crls); } + +static PKCS7 *pkcs7_new(CBS *cbs) { + PKCS7 *ret = OPENSSL_malloc(sizeof(PKCS7)); + if (ret == NULL) { + return NULL; + } + OPENSSL_memset(ret, 0, sizeof(PKCS7)); + ret->type = (ASN1_OBJECT *)OBJ_nid2obj(NID_pkcs7_signed); + ret->d.sign = OPENSSL_malloc(sizeof(PKCS7_SIGNED)); + if (ret->d.sign == NULL) { + goto err; + } + ret->d.sign->cert = sk_X509_new_null(); + ret->d.sign->crl = sk_X509_CRL_new_null(); + CBS copy = *cbs, copy2 = *cbs; + if (ret->d.sign->cert == NULL || ret->d.sign->crl == NULL || + !PKCS7_get_certificates(ret->d.sign->cert, ©) || + !PKCS7_get_CRLs(ret->d.sign->crl, cbs)) { + goto err; + } + + if (sk_X509_num(ret->d.sign->cert) == 0) { + sk_X509_free(ret->d.sign->cert); + ret->d.sign->cert = NULL; + } + + if (sk_X509_CRL_num(ret->d.sign->crl) == 0) { + sk_X509_CRL_free(ret->d.sign->crl); + ret->d.sign->crl = NULL; + } + + ret->ber_len = CBS_len(©2) - CBS_len(cbs); + ret->ber_bytes = BUF_memdup(CBS_data(©2), ret->ber_len); + if (ret->ber_bytes == NULL) { + goto err; + } + + return ret; + +err: + PKCS7_free(ret); + return NULL; +} + +PKCS7 *d2i_PKCS7(PKCS7 **out, const uint8_t **inp, + size_t len) { + CBS cbs; + CBS_init(&cbs, *inp, len); + PKCS7 *ret = pkcs7_new(&cbs); + if (ret == NULL) { + return NULL; + } + *inp = CBS_data(&cbs); + if (out != NULL) { + PKCS7_free(*out); + *out = ret; + } + return ret; +} + +PKCS7 *d2i_PKCS7_bio(BIO *bio, PKCS7 **out) { + // Use a generous bound, to allow for PKCS#7 files containing large root sets. + static const size_t kMaxSize = 4 * 1024 * 1024; + uint8_t *data; + size_t len; + if (!BIO_read_asn1(bio, &data, &len, kMaxSize)) { + return NULL; + } + + CBS cbs; + CBS_init(&cbs, data, len); + PKCS7 *ret = pkcs7_new(&cbs); + OPENSSL_free(data); + if (out != NULL && ret != NULL) { + PKCS7_free(*out); + *out = ret; + } + return ret; +} + +int i2d_PKCS7(const PKCS7 *p7, uint8_t **out) { + if (p7->ber_len > INT_MAX) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW); + return -1; + } + + if (out == NULL) { + return (int)p7->ber_len; + } + + if (*out == NULL) { + *out = OPENSSL_malloc(p7->ber_len); + if (*out == NULL) { + OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE); + return -1; + } + OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len); + } else { + OPENSSL_memcpy(*out, p7->ber_bytes, p7->ber_len); + *out += p7->ber_len; + } + return (int)p7->ber_len; +} + +int i2d_PKCS7_bio(BIO *bio, const PKCS7 *p7) { + size_t written = 0; + while (written < p7->ber_len) { + size_t todo = p7->ber_len - written; + int len = todo > INT_MAX ? INT_MAX : (int)todo; + int ret = BIO_write(bio, p7->ber_bytes + written, len); + if (ret <= 0) { + return 0; + } + written += (size_t)ret; + } + return 1; +} + +void PKCS7_free(PKCS7 *p7) { + if (p7 == NULL) { + return; + } + + OPENSSL_free(p7->ber_bytes); + ASN1_OBJECT_free(p7->type); + // We only supported signed data. + if (p7->d.sign != NULL) { + sk_X509_pop_free(p7->d.sign->cert, X509_free); + sk_X509_CRL_pop_free(p7->d.sign->crl, X509_CRL_free); + OPENSSL_free(p7->d.sign); + } + OPENSSL_free(p7); +} + +// We only support signed data, so these getters are no-ops. +int PKCS7_type_is_data(const PKCS7 *p7) { return 0; } +int PKCS7_type_is_digest(const PKCS7 *p7) { return 0; } +int PKCS7_type_is_encrypted(const PKCS7 *p7) { return 0; } +int PKCS7_type_is_enveloped(const PKCS7 *p7) { return 0; } +int PKCS7_type_is_signed(const PKCS7 *p7) { return 1; } +int PKCS7_type_is_signedAndEnveloped(const PKCS7 *p7) { return 0; } + +PKCS7 *PKCS7_sign(X509 *sign_cert, EVP_PKEY *pkey, STACK_OF(X509) *certs, + BIO *data, int flags) { + if (sign_cert != NULL || pkey != NULL || flags != PKCS7_DETACHED) { + OPENSSL_PUT_ERROR(PKCS7, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED); + return NULL; + } + + uint8_t *der; + size_t len; + CBB cbb; + if (!CBB_init(&cbb, 2048) || + !PKCS7_bundle_certificates(&cbb, certs) || + !CBB_finish(&cbb, &der, &len)) { + CBB_cleanup(&cbb); + return NULL; + } + + CBS cbs; + CBS_init(&cbs, der, len); + PKCS7 *ret = pkcs7_new(&cbs); + OPENSSL_free(der); + return ret; +} |