Files
android/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.cpp
Fred Gylys-Colwell 830a7acc48 Sync oemcrypto reference code
This is a merge from the Widevine repo of
http://go/wvgerrit/117311
Update backwards compatibility builds

http://go/wvgerrit/117423
Restrict maximum size of key id
To protect from out-of-memory found by fuzz testing.

http://go/wvgerrit/117683
Generation number should wrap

The master generation number should wrap around on overflow. This
means that we cannot use less than to check for a skew of 1.

http://go/wvgerrit/119232
Replace 0 with nullptr

Bug: 176234903
Bug: 184866351
Bug: 161243686
Test: ran unit tests (CL affects test code only)
Merged-In: Ie787bcf9c66a7605700c3dc29a8aa16406926ce3
Change-Id: I2b02a36a70a0920f31ffc00de102a23516d4b20e
2021-06-24 03:38:55 +00:00

102 lines
2.6 KiB
C++

// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
//
// Reference implementation of OEMCrypto APIs
//
#include "oemcrypto_rsa_key_shared.h"
#include <assert.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/x509.h>
#include "log.h"
namespace wvoec_ref {
void dump_boringssl_error() {
int count = 0;
while (unsigned long err = ERR_get_error()) {
count++;
char buffer[120];
ERR_error_string_n(err, buffer, sizeof(buffer));
LOGE("BoringSSL Error %d -- %lu -- %s", count, err, buffer);
}
LOGE("Reported %d BoringSSL Errors", count);
}
void RSA_shared_ptr::reset() {
if (rsa_key_ && key_owned_) {
RSA_free(rsa_key_);
}
key_owned_ = false;
rsa_key_ = nullptr;
}
bool RSA_shared_ptr::LoadPkcs8RsaKey(const uint8_t* buffer, size_t length) {
assert(buffer != nullptr);
reset();
uint8_t* pkcs8_rsa_key = const_cast<uint8_t*>(buffer);
BIO* bio = BIO_new_mem_buf(pkcs8_rsa_key, length);
if (bio == nullptr) {
LOGE("[LoadPkcs8RsaKey(): Could not allocate bio buffer]");
return false;
}
bool success = true;
PKCS8_PRIV_KEY_INFO* pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, nullptr);
if (pkcs8_pki == nullptr) {
BIO_reset(bio);
pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, nullptr);
if (pkcs8_pki == nullptr) {
LOGE("[LoadPkcs8RsaKey(): d2i_PKCS8_PRIV_KEY_INFO_bio returned nullptr]");
dump_boringssl_error();
success = false;
}
}
EVP_PKEY* evp = nullptr;
if (success) {
evp = EVP_PKCS82PKEY(pkcs8_pki);
if (evp == nullptr) {
LOGE("[LoadPkcs8RsaKey(): EVP_PKCS82PKEY returned nullptr]");
dump_boringssl_error();
success = false;
}
}
if (success) {
rsa_key_ = EVP_PKEY_get1_RSA(evp);
if (rsa_key_ == nullptr) {
LOGE("[LoadPkcs8RsaKey(): PrivateKeyInfo did not contain an RSA key]");
success = false;
}
key_owned_ = true;
}
if (evp != nullptr) {
EVP_PKEY_free(evp);
}
if (pkcs8_pki != nullptr) {
PKCS8_PRIV_KEY_INFO_free(pkcs8_pki);
}
BIO_free(bio);
if (!success) {
return false;
}
switch (RSA_check_key(rsa_key_)) {
case 1: // valid.
return true;
case 0: // not valid.
LOGE("[LoadPkcs8RsaKey(): rsa key not valid]");
dump_boringssl_error();
return false;
default: // -1 == check failed.
LOGE("[LoadPkcs8RsaKey(): error checking rsa key]");
dump_boringssl_error();
return false;
}
}
} // namespace wvoec_ref