// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine Master // License Agreement. // // Reference implementation of OEMCrypto APIs // #include "oemcrypto_rsa_key_shared.h" #include #include #include #include #include #include #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(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