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:
@@ -49,12 +49,7 @@ void PrintTo(const vector<uint8_t>& value, ostream* os) {
|
||||
} // namespace std
|
||||
|
||||
namespace {
|
||||
void DeleteX509Stack(STACK_OF(X509)* stack) {
|
||||
sk_X509_pop_free(stack, X509_free);
|
||||
}
|
||||
|
||||
constexpr size_t kTestSubsampleSectionSize = 256;
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace wvoec {
|
||||
@@ -1161,22 +1156,25 @@ void Session::LoadOEMCert(bool verify_cert) {
|
||||
public_cert.data(), &public_cert_length));
|
||||
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_LoadOEMPrivateKey(session_id()));
|
||||
|
||||
// Load the certificate chain into a BoringSSL X509 Stack
|
||||
const boringssl_ptr<STACK_OF(X509), DeleteX509Stack> x509_stack(
|
||||
sk_X509_new_null());
|
||||
ASSERT_TRUE(x509_stack.NotNull()) << "Unable to allocate X509 stack.";
|
||||
// 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 public_cert's properties because of how
|
||||
// d2i_PKCS7() works.
|
||||
const unsigned char* cert_data =
|
||||
reinterpret_cast<const unsigned char*>(public_cert.data());
|
||||
long cert_size = static_cast<long>(public_cert.size());
|
||||
boringssl_ptr<PKCS7, PKCS7_free> pkcs7(
|
||||
d2i_PKCS7(NULL, &cert_data, cert_size));
|
||||
ASSERT_TRUE(pkcs7.NotNull()) << "Error parsing PKCS7 message";
|
||||
ASSERT_TRUE(PKCS7_type_is_signed(pkcs7.get()))
|
||||
<< "Unexpected PKCS7 message type";
|
||||
|
||||
CBS pkcs7;
|
||||
CBS_init(&pkcs7, public_cert.data(), public_cert.size());
|
||||
if (!PKCS7_get_certificates(x509_stack.get(), &pkcs7)) {
|
||||
dump_boringssl_error();
|
||||
FAIL() << "Unable to deserialize certificate chain.";
|
||||
}
|
||||
|
||||
STACK_OF(X509)* certs = x509_stack.get();
|
||||
STACK_OF(X509)* certs = pkcs7->d.sign->cert;
|
||||
|
||||
// Load the public cert's key into public_rsa_ and verify, if requested
|
||||
for (size_t i = 0; certs && i < sk_X509_num(certs); i++) {
|
||||
for (size_t i = 0; certs && i < static_cast<size_t>(sk_X509_num(certs));
|
||||
++i) {
|
||||
X509* x509_cert = sk_X509_value(certs, i);
|
||||
boringssl_ptr<EVP_PKEY, EVP_PKEY_free> pubkey(X509_get_pubkey(x509_cert));
|
||||
ASSERT_TRUE(pubkey.NotNull());
|
||||
@@ -1253,12 +1251,10 @@ bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
size_t signature_length) {
|
||||
EVP_MD_CTX md_ctx_struct;
|
||||
EVP_MD_CTX* md_ctx = &md_ctx_struct;
|
||||
EVP_MD_CTX_init(md_ctx);
|
||||
boringssl_ptr<EVP_MD_CTX, EVP_MD_CTX_free> md_ctx(EVP_MD_CTX_new());
|
||||
EVP_PKEY_CTX* pkey_ctx = nullptr;
|
||||
|
||||
if (EVP_DigestVerifyInit(md_ctx, &pkey_ctx, EVP_sha1(),
|
||||
if (EVP_DigestVerifyInit(md_ctx.get(), &pkey_ctx, EVP_sha1(),
|
||||
nullptr /* no ENGINE */, pkey) != 1) {
|
||||
LOGE("EVP_DigestVerifyInit failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
@@ -1280,12 +1276,12 @@ bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyUpdate(md_ctx, message, message_length) != 1) {
|
||||
if (EVP_DigestVerifyUpdate(md_ctx.get(), message, message_length) != 1) {
|
||||
LOGE("EVP_DigestVerifyUpdate failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyFinal(md_ctx, const_cast<uint8_t*>(signature),
|
||||
if (EVP_DigestVerifyFinal(md_ctx.get(), const_cast<uint8_t*>(signature),
|
||||
signature_length) != 1) {
|
||||
LOGE(
|
||||
"EVP_DigestVerifyFinal failed in VerifyPSSSignature. (Probably a bad "
|
||||
@@ -1293,12 +1289,10 @@ bool Session::VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
goto err;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_cleanup(md_ctx);
|
||||
return true;
|
||||
|
||||
err:
|
||||
dump_boringssl_error();
|
||||
EVP_MD_CTX_cleanup(md_ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user