diff options
author | Adam Langley <agl@chromium.org> | 2014-08-21 21:54:06 +0400 |
---|---|---|
committer | Adam Langley <agl@google.com> | 2014-08-26 01:38:08 +0400 |
commit | 9c01e00c2e5bb8087c27203c0adccd9738beb64d (patch) | |
tree | 8fb4501a8b05d649506580db138a302713955aa2 /crypto/x509 | |
parent | cc8fcf45bbf37cbee85d4b8dac9d9814f6831961 (diff) |
Rework support for ASN.1 BER.
Previously, the ASN.1 functions in bytestring were capable of processing
indefinite length elements when the _ber functions were used. That works
well enough for PKCS#3, but NSS goes a bit crazy with BER encoding and
PKCS#12. Rather than complicate the core bytestring functions further,
the BER support is removed from them and moved to a separate function
that converts from BER to DER (if needed).
Change-Id: I2212b28e99bab9fab8c61f80d2012d3e5a3cc2f0
Reviewed-on: https://boringssl-review.googlesource.com/1591
Reviewed-by: Adam Langley <agl@google.com>
Diffstat (limited to 'crypto/x509')
-rw-r--r-- | crypto/x509/pkcs7.c | 71 |
1 files changed, 45 insertions, 26 deletions
diff --git a/crypto/x509/pkcs7.c b/crypto/x509/pkcs7.c index 7744fcce..75c101bd 100644 --- a/crypto/x509/pkcs7.c +++ b/crypto/x509/pkcs7.c @@ -19,48 +19,61 @@ #include <openssl/obj.h> #include <openssl/stack.h> +#include "../bytestring/internal.h" + int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) { - CBS content_info, content_type, wrapped_signed_data, signed_data, - version_bytes, certificates; - int nid; + uint8_t *der_bytes = NULL; + size_t der_len; + CBS in, content_info, content_type, wrapped_signed_data, signed_data, + certificates; const size_t initial_certs_len = sk_X509_num(out_certs); + uint64_t version; + int ret = 0; + + /* The input may be in BER format. */ + if (!CBS_asn1_ber_to_der(cbs, &der_bytes, &der_len)) { + return 0; + } + if (der_bytes != NULL) { + CBS_init(&in, der_bytes, der_len); + } else { + CBS_init(&in, CBS_data(cbs), CBS_len(cbs)); + } /* See https://tools.ietf.org/html/rfc2315#section-7 */ - if (!CBS_get_asn1_ber(cbs, &content_info, CBS_ASN1_SEQUENCE) || + if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE) || !CBS_get_asn1(&content_info, &content_type, CBS_ASN1_OBJECT)) { - return 0; + goto err; } - nid = OBJ_cbs2nid(&content_type); - if (nid != NID_pkcs7_signed) { + if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) { OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates, X509_R_NOT_PKCS7_SIGNED_DATA); - return 0; + goto err; } /* See https://tools.ietf.org/html/rfc2315#section-9.1 */ - if (!CBS_get_asn1_ber(&content_info, &wrapped_signed_data, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || - !CBS_get_asn1_ber(&wrapped_signed_data, &signed_data, - CBS_ASN1_SEQUENCE) || - !CBS_get_asn1_ber(&signed_data, &version_bytes, CBS_ASN1_INTEGER) || - !CBS_get_asn1_ber(&signed_data, NULL /* digests */, CBS_ASN1_SET) || - !CBS_get_asn1_ber(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) { - return 0; + if (!CBS_get_asn1(&content_info, &wrapped_signed_data, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || + !CBS_get_asn1(&wrapped_signed_data, &signed_data, CBS_ASN1_SEQUENCE) || + !CBS_get_asn1_uint64(&signed_data, &version) || + !CBS_get_asn1(&signed_data, NULL /* digests */, CBS_ASN1_SET) || + !CBS_get_asn1(&signed_data, NULL /* content */, CBS_ASN1_SEQUENCE)) { + goto err; } - if (CBS_len(&version_bytes) < 1 || CBS_data(&version_bytes)[0] == 0) { + if (version < 1) { OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates, X509_R_BAD_PKCS7_VERSION); - return 0; + goto err; } - if (!CBS_get_asn1_ber(&signed_data, &certificates, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { + if (!CBS_get_asn1(&signed_data, &certificates, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) { OPENSSL_PUT_ERROR(X509, PKCS7_get_certificates, X509_R_NO_CERTIFICATES_INCLUDED); - return 0; + goto err; } while (CBS_len(&certificates) > 0) { @@ -86,15 +99,21 @@ int PKCS7_get_certificates(STACK_OF(X509) *out_certs, CBS *cbs) { sk_X509_push(out_certs, x509); } - return 1; + ret = 1; err: - while (sk_X509_num(out_certs) != initial_certs_len) { - X509 *x509 = sk_X509_pop(out_certs); - X509_free(x509); + if (der_bytes) { + OPENSSL_free(der_bytes); + } + + if (!ret) { + while (sk_X509_num(out_certs) != initial_certs_len) { + X509 *x509 = sk_X509_pop(out_certs); + X509_free(x509); + } } - return 0; + return ret; } int PKCS7_bundle_certificates(CBB *out, const STACK_OF(X509) *certs) { |