widevine: update to work with BoringSSL.
This change: 1) Switches the Makefiles over to using LOCAL_STATIC_LIBRARIES, which I understand is the new hotness, rather than setting a -I flag directly. 2) Switches to the non-deprecated _ex versions for EVP_EncryptFinal. 3) Uses the EVP_PKEY interface for checking PSS signatures. This is the only supported interface in OpenSSL: the PSS padding check functions are only exported in upstream OpenSSL because it's a library from the 90s and they don't have a concept of "unexported". Also, by using the EVP functions, OpenSSL/BoringSSL can do a better job of being constant-time. Since there aren't any obvious tests for checking that the signtaure verification still works, I tested with the code in the referenced paste, which includes both the old and new verification functions and checks that they both work on a sample signature. (And I also checked that they both fail when a bit in the signature is changed.) https://paste.googleplex.com/5747976139964416 Change-Id: Iae7409c53eeea9c3892a32c180d7181d72467dcb
This commit is contained in:
@@ -888,7 +888,8 @@ static const uint8_t kTestRSAPublicKey3_2048[] = {
|
||||
static void dump_openssl_error() {
|
||||
while (unsigned long err = ERR_get_error()) {
|
||||
char buffer[120];
|
||||
cout << "openssl error -- " << ERR_error_string(err, buffer) << "\n";
|
||||
ERR_error_string_n(err, buffer, sizeof(buffer));
|
||||
cout << "openssl error -- " << buffer << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1390,6 +1391,57 @@ class Session {
|
||||
}
|
||||
}
|
||||
|
||||
static bool VerifyPSSSignature(EVP_PKEY* pkey, const uint8_t* message,
|
||||
size_t message_length,
|
||||
const uint8_t* signature,
|
||||
size_t signature_length) {
|
||||
EVP_MD_CTX ctx;
|
||||
EVP_MD_CTX_init(&ctx);
|
||||
EVP_PKEY_CTX* pctx = NULL;
|
||||
|
||||
if (EVP_DigestVerifyInit(&ctx, &pctx, EVP_sha1(), NULL /* no ENGINE */,
|
||||
pkey) != 1) {
|
||||
LOGE("EVP_DigestVerifyInit failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_signature_md(pctx, EVP_sha1()) != 1) {
|
||||
LOGE("EVP_PKEY_CTX_set_signature_md failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) != 1) {
|
||||
LOGE("EVP_PKEY_CTX_set_rsa_padding failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, SHA_DIGEST_LENGTH) != 1) {
|
||||
LOGE("EVP_PKEY_CTX_set_rsa_pss_saltlen failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyUpdate(&ctx, message, message_length) != 1) {
|
||||
LOGE("EVP_DigestVerifyUpdate failed in VerifyPSSSignature");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (EVP_DigestVerifyFinal(&ctx, const_cast<uint8_t*>(signature),
|
||||
signature_length) != 1) {
|
||||
LOGE(
|
||||
"EVP_DigestVerifyFinal failed in VerifyPSSSignature. (Probably a bad "
|
||||
"signature.)");
|
||||
goto err;
|
||||
}
|
||||
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return true;
|
||||
|
||||
err:
|
||||
dump_openssl_error();
|
||||
EVP_MD_CTX_cleanup(&ctx);
|
||||
return false;
|
||||
}
|
||||
|
||||
void VerifyRSASignature(const uint8_t* message, size_t message_length,
|
||||
const uint8_t* signature, size_t signature_length,
|
||||
RSA_Padding_Scheme padding_scheme) {
|
||||
@@ -1400,28 +1452,13 @@ class Session {
|
||||
<< RSA_size(public_rsa_) << "\n";
|
||||
|
||||
if (padding_scheme == kSign_RSASSA_PSS) {
|
||||
// Hash the message using SHA1.
|
||||
uint8_t hash[SHA_DIGEST_LENGTH];
|
||||
if (!SHA1(message, message_length, hash)) {
|
||||
dump_openssl_error();
|
||||
EXPECT_TRUE(false) << "Error computing SHA1. ";
|
||||
}
|
||||
EVP_PKEY *pkey = EVP_PKEY_new();
|
||||
ASSERT_TRUE(EVP_PKEY_set1_RSA(pkey, public_rsa_) == 1);
|
||||
|
||||
// Decrypt signature to padded digest.
|
||||
uint8_t padded_digest[signature_length];
|
||||
int status;
|
||||
status = RSA_public_decrypt(signature_length, signature, padded_digest,
|
||||
public_rsa_, RSA_NO_PADDING);
|
||||
if (status == -1) {
|
||||
dump_openssl_error();
|
||||
EXPECT_TRUE(false) << "VerifyRSASignature. in RSA_Public_digest ";
|
||||
}
|
||||
status = RSA_verify_PKCS1_PSS(public_rsa_, hash, EVP_sha1(),
|
||||
padded_digest, SHA_DIGEST_LENGTH);
|
||||
if (status != 1) {
|
||||
dump_openssl_error();
|
||||
EXPECT_TRUE(false) << "VerifyRSASignature. in RSA_verify_PKCS1_PSS ";
|
||||
}
|
||||
const bool ok = VerifyPSSSignature(pkey, message, message_length,
|
||||
signature, signature_length);
|
||||
EVP_PKEY_free(pkey);
|
||||
EXPECT_TRUE(ok) << "PSS signature check failed";
|
||||
} else if (padding_scheme == kSign_PKCS1_Block1) {
|
||||
uint8_t padded_digest[signature_length];
|
||||
int status;
|
||||
|
||||
Reference in New Issue
Block a user