summaryrefslogtreecommitdiff
path: root/src/crypto/pkcs7/pkcs7_x509.c
diff options
context:
space:
mode:
authorAdam Vartanian <flooey@google.com>2018-08-10 14:55:24 +0100
committerAdam Vartanian <flooey@google.com>2018-08-10 15:32:39 +0100
commitbfcf3a72c0bcb62cfde80e932db0668a7f96c0f8 (patch)
tree3ab110046e45c25f8f69df137f8a9d4a52bf60b5 /src/crypto/pkcs7/pkcs7_x509.c
parent6120b2b9dfbe5b19fe2d0f69a4b8418ad5f7fe08 (diff)
downloadboringssl-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.c194
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, &copy) ||
+ !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(&copy2) - CBS_len(cbs);
+ ret->ber_bytes = BUF_memdup(CBS_data(&copy2), 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;
+}