Restore OpenSSL Compatibility
(This is a merge of http://go/wvgerrit/96226.) This patch does a number of different things in order to re-enable the CDM to use OpenSSL 1.1.0+ out of the box, instead of just BoringSSL: * To support https://cryptography.io/, BoringSSL has reimplemented just enough of the OpenSSL PKCS7 API that we can fulfill our purposes with code that works on either library. This patch replaces code in privacy_crypto_boringssl.cpp and oec_session_util.cpp that was only compatible with BoringSSL with code that also works in OpenSSL. * Replaces code in oec_session_util.cpp that used the deprecated OpenSSL 1.0.0 API with OpenSSL 1.1.0-compatible code. This code previously worked on BoringSSL because they have not yet removed the OpenSSL 1.0.0 functions, even though they also implemented the 1.1.0 API. * Replaces openssl/mem.h (which does not work in OpenSSL 1.1.0 and higher) with openssl/crypto.h. (which works in all OpenSSL and BoringSSL releases) This does not require any function code changes. * The OID-comparison code in privacy_crypto_boringssl.cpp was using BoringSSL-exclusive functions to convert OBJ-format OIDs to text. Conversion functions that work on either library exist. However, the new code uses a different technique instead, pre-converting the passed-in OID to OBJ format. This allows it to be compared to the certificate directly, avoiding converting every certificate extension OID to text. * Allows the selection of "openssl" as the privacy_crypto_impl and adds a variable to configure OpenSSL. More will follow in future patches as more configurations of OpenSSL are supported. Bug: 140053043 Test: CE CDM Unit Tests Test: CE CDM Unit Tests w/ the x86-64 Platform Reconfigured to OpenSSL Test: Android Unit Tests Change-Id: I57cebbbfb59e0bcab85b589b98fb9ffd18885415
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/pkcs7.h>
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/x509v3.h>
|
||||
@@ -69,22 +70,6 @@ class boringssl_ptr {
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(boringssl_ptr);
|
||||
};
|
||||
|
||||
void DeleteX509Stack(STACK_OF(X509) * stack) {
|
||||
sk_X509_pop_free(stack, X509_free);
|
||||
}
|
||||
|
||||
std::string GetExtensionOid(X509_EXTENSION* extension) {
|
||||
ASN1_OBJECT* const extension_object = X509_EXTENSION_get_object(extension);
|
||||
if (!extension_object) {
|
||||
return "";
|
||||
}
|
||||
|
||||
const int size = OBJ_obj2txt(nullptr, 0, extension_object, 1);
|
||||
std::string ret(size, '\0');
|
||||
OBJ_obj2txt(&ret[0], ret.size() + 1, extension_object, 1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace wvcdm {
|
||||
@@ -324,27 +309,34 @@ bool RsaPublicKey::VerifySignature(const std::string& message,
|
||||
}
|
||||
|
||||
bool ExtractExtensionValueFromCertificate(const std::string& cert,
|
||||
const std::string& extension_oid,
|
||||
const std::string& expected_oid,
|
||||
size_t cert_index, uint32_t* value) {
|
||||
// Load the certificate chain into a BoringSSL X509 Stack
|
||||
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
||||
sk_X509_new_null());
|
||||
if (!x509_stack) {
|
||||
LOGE("Unable to allocate X509 stack");
|
||||
// Convert the OID to OBJ form
|
||||
boringssl_ptr<ASN1_OBJECT, ASN1_OBJECT_free> expected_obj(
|
||||
OBJ_txt2obj(expected_oid.c_str(), true));
|
||||
|
||||
// The cert is a PKCS7 signed data type. First, parse it into an OpenSSL
|
||||
// structure and find the certificate list.
|
||||
//
|
||||
// We must make defensive copies of cert's properties because of how
|
||||
// d2i_PKCS7() works.
|
||||
const unsigned char* cert_data =
|
||||
reinterpret_cast<const unsigned char*>(cert.data());
|
||||
long cert_size = static_cast<long>(cert.size());
|
||||
boringssl_ptr<PKCS7, PKCS7_free> pkcs7(
|
||||
d2i_PKCS7(NULL, &cert_data, cert_size));
|
||||
if (!pkcs7) {
|
||||
LOGE("Error parsing PKCS7 message");
|
||||
return false;
|
||||
} else if (!PKCS7_type_is_signed(pkcs7.get())) {
|
||||
LOGE("Unexpected PKCS7 message type");
|
||||
return false;
|
||||
}
|
||||
|
||||
CBS pkcs7;
|
||||
CBS_init(&pkcs7, reinterpret_cast<const uint8_t*>(cert.data()), cert.size());
|
||||
if (!PKCS7_get_certificates(x509_stack.get(), &pkcs7)) {
|
||||
LOGE("Error getting certificate chain");
|
||||
return false;
|
||||
}
|
||||
|
||||
STACK_OF(X509)* certs = x509_stack.get();
|
||||
STACK_OF(X509)* certs = pkcs7->d.sign->cert;
|
||||
|
||||
// Find the desired certificate from the stack.
|
||||
if (sk_X509_num(certs) <= cert_index) {
|
||||
if (cert_index >= static_cast<size_t>(sk_X509_num(certs))) {
|
||||
LOGE(
|
||||
"Unexpected number of certificates in chain: "
|
||||
"count = %zu, minimum = %zu",
|
||||
@@ -367,7 +359,13 @@ bool ExtractExtensionValueFromCertificate(const std::string& cert,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (GetExtensionOid(extension) != extension_oid) {
|
||||
ASN1_OBJECT* const extension_obj = X509_EXTENSION_get_object(extension);
|
||||
if (extension_obj == nullptr) {
|
||||
LOGE("Unable to get cert extension OID: cert_index = %d", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (OBJ_cmp(extension_obj, expected_obj.get()) != 0) {
|
||||
// This extension is not the Widevine System ID, so we should move on to
|
||||
// the next one.
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user