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:
John W. Bruce
2020-03-26 13:20:15 -07:00
parent c0d7f16b78
commit d21d70f533
5 changed files with 53 additions and 61 deletions

View File

@@ -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;
}