Sync oemcrypto files from cdm udc-dev to Android

Changes included in this CL:

166806: Update OEMCrypto_GetDeviceInformation() | https://widevine-internal-review.googlesource.com/c/cdm/+/166806
166808: Update Android L3 after OEMCrypto_GetDeviceInformation() signature changes | https://widevine-internal-review.googlesource.com/c/cdm/+/166808
166809: Decode device info and write it to CSR payload | https://widevine-internal-review.googlesource.com/c/cdm/+/166809
167158: Fix Android include path and copy_files | https://widevine-internal-review.googlesource.com/c/cdm/+/167158
167159: Fix common typos and use inclusive language suggested by Android linter | https://widevine-internal-review.googlesource.com/c/cdm/+/167159

165618: Explicitly state python3 where needed. | https://widevine-internal-review.googlesource.com/c/cdm/+/165618

166757: Update Android.bp for Android | https://widevine-internal-review.googlesource.com/c/cdm/+/166757
164993: Refactor basic oemcrypto unit tests | https://widevine-internal-review.googlesource.com/c/cdm/+/164993
164978: Update OEMCrypto Unit Test Docs | https://widevine-internal-review.googlesource.com/c/cdm/+/164978
166941: Update make files for OEMCrypto | https://widevine-internal-review.googlesource.com/c/cdm/+/166941

165279: Refactor license unit tests | https://widevine-internal-review.googlesource.com/c/cdm/+/165279
165318: Refactor provisioning unit tests | https://widevine-internal-review.googlesource.com/c/cdm/+/165318
164800: Add extra check for renew on license load unit test | https://widevine-internal-review.googlesource.com/c/cdm/+/164800
165860: Remove duplicate definition of MaybeHex() | https://widevine-internal-review.googlesource.com/c/cdm/+/165860

164889: Updated CoreCommonRequestFromMessage and fix test | https://widevine-internal-review.googlesource.com/c/cdm/+/164889
164967: Add OPK pre-hook and post-hook error codes | https://widevine-internal-review.googlesource.com/c/cdm/+/164967
165140: Add hidden device_id_length to v18 provisioning message | https://widevine-internal-review.googlesource.com/c/cdm/+/165140
165204: Fix memory leak in oemcrypto test | https://widevine-internal-review.googlesource.com/c/cdm/+/165204

165958: Fix oemcrypto_generic_verify_fuzz mutator signature offset | https://widevine-internal-review.googlesource.com/c/cdm/+/165958

166037: Support SHA-256 in OEMCrypto Session Util | https://widevine-internal-review.googlesource.com/c/cdm/+/166037

Test: Run GtsMediaTests on Pixel 7
Bug: 270612144

Change-Id: Iff0820a2de7d043a820470a130af65b0dcadb759
This commit is contained in:
Cong Lin
2023-02-27 18:25:02 -08:00
parent 3f7ecbc43e
commit e8add8eed8
44 changed files with 302003 additions and 298675 deletions

View File

@@ -0,0 +1,627 @@
// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine
// License Agreement.
//
#include "oemcrypto_provisioning_test.h"
#include "log.h"
#include "oemcrypto_basic_test.h"
#include "oemcrypto_resource_test.h"
#include "oemcrypto_session_tests_helper.h"
#include "platform.h"
namespace wvoec {
/// @addtogroup provision
/// @{
// This test is used to print the device ID to stdout.
TEST_F(OEMCryptoKeyboxTest, NormalGetDeviceId) {
OEMCryptoResult sts;
uint8_t dev_id[128] = {0};
size_t dev_id_len = 128;
sts = OEMCrypto_GetDeviceID(dev_id, &dev_id_len);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
cout << " NormalGetDeviceId: dev_id = "
<< MaybeHex(dev_id, dev_id_len) << " len = " << dev_id_len << endl;
}
TEST_F(OEMCryptoKeyboxTest, GetDeviceIdShortBuffer) {
OEMCryptoResult sts;
uint8_t dev_id[128];
for (int i = 0; i < 128; ++i) {
dev_id[i] = 0x55;
}
dev_id[127] = '\0';
size_t dev_id_len = 0;
sts = OEMCrypto_GetDeviceID(dev_id, &dev_id_len);
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
// On short buffer error, function should return minimum buffer length
ASSERT_GT(dev_id_len, 0u);
// Should also return short buffer if passed a zero length and a null buffer.
dev_id_len = 0;
sts = OEMCrypto_GetDeviceID(nullptr, &dev_id_len);
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER, sts);
// On short buffer error, function should return minimum buffer length
ASSERT_GT(dev_id_len, 0u);
}
TEST_F(OEMCryptoKeyboxTest, NormalGetKeyData) {
OEMCryptoResult sts;
uint8_t key_data[256];
size_t key_data_len = sizeof(key_data);
sts = OEMCrypto_GetKeyData(key_data, &key_data_len);
uint32_t* data = reinterpret_cast<uint32_t*>(key_data);
printf(" NormalGetKeyData: system_id = %u = 0x%04X, version=%u\n",
htonl(data[1]), htonl(data[1]), htonl(data[0]));
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
}
TEST_F(OEMCryptoKeyboxTest, GetKeyDataNullPointer) {
OEMCryptoResult sts;
uint8_t key_data[256];
sts = OEMCrypto_GetKeyData(key_data, nullptr);
ASSERT_NE(OEMCrypto_SUCCESS, sts);
}
// This test makes sure the installed keybox is valid. It doesn't really check
// that it is a production keybox. That must be done by an integration test.
TEST_F(OEMCryptoKeyboxTest, ProductionKeyboxValid) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxValid());
}
// This tests GenerateDerivedKeys with an 8k context.
TEST_F(OEMCryptoKeyboxTest, GenerateDerivedKeysFromKeyboxLargeBuffer) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
const size_t max_size = GetResourceValue(kLargeMessageSize);
vector<uint8_t> mac_context(max_size);
vector<uint8_t> enc_context(max_size);
// Stripe the data so the two vectors are not identical, and not all zeroes.
for (size_t i = 0; i < max_size; i++) {
mac_context[i] = i % 0x100;
enc_context[i] = (3 * i) % 0x100;
}
ASSERT_EQ(OEMCrypto_SUCCESS,
OEMCrypto_GenerateDerivedKeys(
s.session_id(), mac_context.data(), mac_context.size(),
enc_context.data(), enc_context.size()));
}
// This verifies that the device really does claim to have a certificate.
// It should be filtered out for devices that have a keybox.
TEST_F(OEMCryptoProv30Test, DeviceClaimsOEMCertificate) {
ASSERT_EQ(OEMCrypto_OEMCertificate, OEMCrypto_GetProvisioningMethod());
}
TEST_F(OEMCryptoProv30Test, GetDeviceId) {
OEMCryptoResult sts;
std::vector<uint8_t> dev_id(128, 0);
size_t dev_id_len = dev_id.size();
sts = OEMCrypto_GetDeviceID(dev_id.data(), &dev_id_len);
if (sts == OEMCrypto_ERROR_SHORT_BUFFER) {
ASSERT_GT(dev_id_len, 0u);
dev_id.resize(dev_id_len);
sts = OEMCrypto_GetDeviceID(dev_id.data(), &dev_id_len);
}
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
dev_id.resize(dev_id_len);
cout << " NormalGetDeviceId: dev_id = " << MaybeHex(dev_id)
<< " len = " << dev_id_len << endl;
}
// The OEM certificate must be valid.
TEST_F(OEMCryptoProv30Test, CertValidAPI15) {
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_IsKeyboxOrOEMCertValid());
}
TEST_F(OEMCryptoProv30Test, OEMCertValid) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
bool kVerify = true;
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert(kVerify)); // Load and verify.
}
// This verifies that the OEM Certificate cannot be used for other RSA padding
// schemes. Those schemes should only be used by cast receiver certificates.
TEST_F(OEMCryptoProv30Test, OEMCertForbiddenPaddingScheme) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(s.LoadOEMCert());
OEMCryptoResult sts;
// Sign a Message
vector<uint8_t> data(500);
GetRandBytes(data.data(), data.size());
size_t signature_length = 0;
// We need a size one vector to pass as a pointer.
vector<uint8_t> signature(1, 0);
vector<uint8_t> zero(1, 0);
sts = OEMCrypto_GenerateRSASignature(s.session_id(), data.data(), data.size(),
signature.data(), &signature_length,
kSign_PKCS1_Block1);
if (OEMCrypto_ERROR_SHORT_BUFFER == sts) {
// The OEMCrypto could complain about buffer length first, so let's
// resize and check if it's writing to the signature again.
signature.resize(signature_length, 0);
zero.resize(signature_length, 0);
sts = OEMCrypto_GenerateRSASignature(s.session_id(), data.data(),
data.size(), signature.data(),
&signature_length, kSign_PKCS1_Block1);
}
EXPECT_NE(OEMCrypto_SUCCESS, sts)
<< "OEM Cert Signed with forbidden kSign_PKCS1_Block1.";
ASSERT_EQ(zero, signature); // signature should not be computed.
}
// Calling OEMCrypto_GetOEMPublicCertificate should not change the session's
// private key.
TEST_F(OEMCryptoProv30Test, GetCertOnlyAPI16) {
if (wrapped_drm_key_.size() == 0) {
// If we don't have a wrapped key yet, create one.
// This wrapped key will be shared by all sessions in the test.
ASSERT_NO_FATAL_FAILURE(CreateWrappedDRMKey());
}
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
// Install the DRM Cert's RSA key.
ASSERT_NO_FATAL_FAILURE(s.LoadWrappedRsaDrmKey(wrapped_drm_key_));
ASSERT_NO_FATAL_FAILURE(s.SetTestRsaPublicKey());
// Request the OEM Cert. -- This should NOT load the OEM Private key.
vector<uint8_t> public_cert;
size_t public_cert_length = 0;
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
OEMCrypto_GetOEMPublicCertificate(nullptr, &public_cert_length));
ASSERT_LT(0u, public_cert_length);
public_cert.resize(public_cert_length);
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_GetOEMPublicCertificate(
public_cert.data(), &public_cert_length));
// Derive keys from the session key -- this should use the DRM Cert's key.
// It should NOT use the OEM Private key because that key should not have
// been loaded.
ASSERT_NO_FATAL_FAILURE(s.GenerateDerivedKeysFromSessionKey());
// Now fill a message and try to load it.
LicenseRoundTrip license_messages(&s);
license_messages.set_control(0);
ASSERT_NO_FATAL_FAILURE(license_messages.SignAndVerifyRequest());
ASSERT_NO_FATAL_FAILURE(license_messages.CreateDefaultResponse());
ASSERT_NO_FATAL_FAILURE(license_messages.EncryptAndSignResponse());
ASSERT_EQ(OEMCrypto_SUCCESS, license_messages.LoadResponse());
}
// This verifies that the device really does claim to have BCC.
// It should be filtered out for devices that have a keybox or factory OEM
// cert.
TEST_F(OEMCryptoProv40Test, DeviceClaimsBootCertificateChain) {
ASSERT_EQ(OEMCrypto_GetProvisioningMethod(), OEMCrypto_BootCertificateChain);
}
// Verifies that short buffer error returns when the buffer is short.
TEST_F(OEMCryptoProv40Test, GetBootCertificateChainShortBuffer) {
std::vector<uint8_t> bcc;
size_t bcc_size = 0;
std::vector<uint8_t> additional_signature;
size_t additional_signature_size = 0;
ASSERT_EQ(OEMCrypto_GetBootCertificateChain(bcc.data(), &bcc_size,
additional_signature.data(),
&additional_signature_size),
OEMCrypto_ERROR_SHORT_BUFFER);
ASSERT_NE(bcc_size, 0uL);
}
// Verifies BCC can be successfully returned.
TEST_F(OEMCryptoProv40Test, GetBootCertificateChainSuccess) {
std::vector<uint8_t> bcc;
size_t bcc_size = 0;
std::vector<uint8_t> additional_signature;
size_t additional_signature_size = 0;
ASSERT_EQ(OEMCrypto_GetBootCertificateChain(bcc.data(), &bcc_size,
additional_signature.data(),
&additional_signature_size),
OEMCrypto_ERROR_SHORT_BUFFER);
bcc.resize(bcc_size);
additional_signature.resize(additional_signature_size);
ASSERT_EQ(OEMCrypto_GetBootCertificateChain(bcc.data(), &bcc_size,
additional_signature.data(),
&additional_signature_size),
OEMCrypto_SUCCESS);
}
// Verifies that short buffer error returns when the buffer is short.
TEST_F(OEMCryptoProv40Test, GenerateCertificateKeyPairShortBuffer) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
std::vector<uint8_t> public_key;
size_t public_key_size = 0;
std::vector<uint8_t> public_key_signature;
size_t public_key_signature_size = 0;
std::vector<uint8_t> wrapped_private_key;
size_t wrapped_private_key_size = 0;
OEMCrypto_PrivateKeyType key_type;
ASSERT_EQ(
OEMCrypto_GenerateCertificateKeyPair(
s.session_id(), public_key.data(), &public_key_size,
public_key_signature.data(), &public_key_signature_size,
wrapped_private_key.data(), &wrapped_private_key_size, &key_type),
OEMCrypto_ERROR_SHORT_BUFFER);
ASSERT_NE(public_key_size, 0uL);
ASSERT_NE(public_key_signature_size, 0uL);
ASSERT_NE(wrapped_private_key_size, 0uL);
}
// Verifies a pair of key can be successfully returned.
TEST_F(OEMCryptoProv40Test, GenerateCertificateKeyPairSuccess) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
std::vector<uint8_t> public_key;
size_t public_key_size = 0;
std::vector<uint8_t> public_key_signature;
size_t public_key_signature_size = 0;
std::vector<uint8_t> wrapped_private_key;
size_t wrapped_private_key_size = 0;
OEMCrypto_PrivateKeyType key_type;
ASSERT_EQ(
OEMCrypto_GenerateCertificateKeyPair(
s.session_id(), public_key.data(), &public_key_size,
public_key_signature.data(), &public_key_signature_size,
wrapped_private_key.data(), &wrapped_private_key_size, &key_type),
OEMCrypto_ERROR_SHORT_BUFFER);
public_key.resize(public_key_size);
public_key_signature.resize(public_key_signature_size);
wrapped_private_key.resize(wrapped_private_key_size);
ASSERT_EQ(
OEMCrypto_GenerateCertificateKeyPair(
s.session_id(), public_key.data(), &public_key_size,
public_key_signature.data(), &public_key_signature_size,
wrapped_private_key.data(), &wrapped_private_key_size, &key_type),
OEMCrypto_SUCCESS);
public_key.resize(public_key_size);
public_key_signature.resize(public_key_signature_size);
wrapped_private_key.resize(wrapped_private_key_size);
// Parse the public key generated to make sure it is correctly formatted.
ASSERT_NO_FATAL_FAILURE(s.SetPublicKeyFromSubjectPublicKey(
key_type, public_key.data(), public_key_size));
}
// Verifies the generated key pairs are different on each call.
TEST_F(OEMCryptoProv40Test, GenerateCertificateKeyPairsAreDifferent) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
// Large buffer to make sure it is large enough.
size_t public_key_size1 = 10000;
std::vector<uint8_t> public_key1(public_key_size1);
size_t public_key_signature_size1 = 10000;
std::vector<uint8_t> public_key_signature1(public_key_signature_size1);
size_t wrapped_private_key_size1 = 10000;
std::vector<uint8_t> wrapped_private_key1(wrapped_private_key_size1);
OEMCrypto_PrivateKeyType key_type1;
ASSERT_EQ(
OEMCrypto_GenerateCertificateKeyPair(
s.session_id(), public_key1.data(), &public_key_size1,
public_key_signature1.data(), &public_key_signature_size1,
wrapped_private_key1.data(), &wrapped_private_key_size1, &key_type1),
OEMCrypto_SUCCESS);
EXPECT_NE(public_key_size1, 0UL);
EXPECT_NE(public_key_signature_size1, 0UL);
EXPECT_NE(wrapped_private_key_size1, 0UL);
public_key1.resize(public_key_size1);
public_key_signature1.resize(public_key_signature_size1);
wrapped_private_key1.resize(wrapped_private_key_size1);
size_t public_key_size2 = 10000;
std::vector<uint8_t> public_key2(public_key_size2);
size_t public_key_signature_size2 = 10000;
std::vector<uint8_t> public_key_signature2(public_key_signature_size2);
size_t wrapped_private_key_size2 = 10000;
std::vector<uint8_t> wrapped_private_key2(wrapped_private_key_size2);
OEMCrypto_PrivateKeyType key_type2;
ASSERT_EQ(
OEMCrypto_GenerateCertificateKeyPair(
s.session_id(), public_key2.data(), &public_key_size2,
public_key_signature2.data(), &public_key_signature_size2,
wrapped_private_key2.data(), &wrapped_private_key_size2, &key_type2),
OEMCrypto_SUCCESS);
EXPECT_NE(public_key_size2, 0UL);
EXPECT_NE(public_key_signature_size2, 0UL);
EXPECT_NE(wrapped_private_key_size2, 0UL);
public_key2.resize(public_key_size2);
public_key_signature2.resize(public_key_signature_size2);
wrapped_private_key2.resize(wrapped_private_key_size2);
EXPECT_NE(public_key1, public_key2);
EXPECT_NE(public_key_signature1, public_key_signature2);
EXPECT_NE(wrapped_private_key1, wrapped_private_key2);
}
TEST_F(OEMCryptoProv40Test, GetDeviceInformationAPI18) {
std::vector<uint8_t> device_info;
size_t device_info_length = 0;
OEMCryptoResult sts =
OEMCrypto_GetDeviceInformation(device_info.data(), &device_info_length);
ASSERT_EQ(sts, OEMCrypto_ERROR_SHORT_BUFFER);
ASSERT_NE(device_info_length, 0uL);
device_info.resize(device_info_length);
ASSERT_EQ(
OEMCrypto_GetDeviceInformation(device_info.data(), &device_info_length),
OEMCrypto_SUCCESS);
EXPECT_NE(device_info_length, 0uL);
}
TEST_F(OEMCryptoProv40Test, GetDeviceSignedCsrPayloadAPI18) {
std::vector<uint8_t> challenge(64, 0xaa);
// TODO: add cppbor support for oemcrypto tests for all targets. Before that,
// use hex values which are equivalent of the commented cppbor statement.
// std::vector<uint8_t> device_info = cppbor::Map()
// .add("manufacturer", "google")
// .add("fused", 0)
// .add("other", "ignored")
// .canonicalize()
// .encode();
//
std::vector<uint8_t> device_info = {
0xa3, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x0, 0x65, 0x6f, 0x74,
0x68, 0x65, 0x72, 0x67, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64,
0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72,
0x65, 0x72, 0x66, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65};
std::vector<uint8_t> signed_csr_payload;
size_t signed_csr_payload_length = 0;
OEMCryptoResult sts = OEMCrypto_GetDeviceSignedCsrPayload(
challenge.data(), challenge.size(), device_info.data(),
device_info.size(), signed_csr_payload.data(),
&signed_csr_payload_length);
ASSERT_EQ(sts, OEMCrypto_ERROR_SHORT_BUFFER);
ASSERT_NE(signed_csr_payload_length, 0uL);
signed_csr_payload.resize(signed_csr_payload_length);
ASSERT_EQ(OEMCrypto_GetDeviceSignedCsrPayload(
challenge.data(), challenge.size(), device_info.data(),
device_info.size(), signed_csr_payload.data(),
&signed_csr_payload_length),
OEMCrypto_SUCCESS);
EXPECT_NE(signed_csr_payload_length, 0uL);
}
TEST_F(OEMCryptoProv40Test, GetDeviceSignedCsrPayloadInvalid) {
std::vector<uint8_t> signed_csr_payload;
size_t signed_csr_payload_length = 0;
std::vector<uint8_t> challenge(64, 0xaa);
std::vector<uint8_t> device_info = {
0xa3, 0x65, 0x66, 0x75, 0x73, 0x65, 0x64, 0x0, 0x65, 0x6f, 0x74,
0x68, 0x65, 0x72, 0x67, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64,
0x6c, 0x6d, 0x61, 0x6e, 0x75, 0x66, 0x61, 0x63, 0x74, 0x75, 0x72,
0x65, 0x72, 0x66, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65};
std::vector<uint8_t> challenge_empty;
OEMCryptoResult sts = OEMCrypto_GetDeviceSignedCsrPayload(
challenge_empty.data(), challenge_empty.size(), device_info.data(),
device_info.size(), signed_csr_payload.data(),
&signed_csr_payload_length);
if (sts == OEMCrypto_ERROR_NOT_IMPLEMENTED) return;
ASSERT_EQ(sts, OEMCrypto_ERROR_INVALID_CONTEXT);
// Oversized challenge
std::vector<uint8_t> challenge_long(65, 0xaa);
sts = OEMCrypto_GetDeviceSignedCsrPayload(
challenge_long.data(), challenge_long.size(), device_info.data(),
device_info.size(), signed_csr_payload.data(),
&signed_csr_payload_length);
ASSERT_EQ(sts, OEMCrypto_ERROR_INVALID_CONTEXT);
std::vector<uint8_t> device_empty;
sts = OEMCrypto_GetDeviceSignedCsrPayload(
challenge.data(), challenge.size(), device_empty.data(),
device_empty.size(), signed_csr_payload.data(),
&signed_csr_payload_length);
ASSERT_EQ(sts, OEMCrypto_ERROR_INVALID_CONTEXT);
}
// Verifies that an OEM private key can be installed.
TEST_F(OEMCryptoProv40Test, InstallOemPrivateKeySuccess) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
// First generate a key pair.
// Large buffer to make sure it is large enough.
size_t public_key_size = 10000;
std::vector<uint8_t> public_key(public_key_size);
size_t public_key_signature_size = 10000;
std::vector<uint8_t> public_key_signature(public_key_signature_size);
size_t wrapped_private_key_size = 10000;
std::vector<uint8_t> wrapped_private_key(wrapped_private_key_size);
OEMCrypto_PrivateKeyType key_type;
ASSERT_EQ(
OEMCrypto_GenerateCertificateKeyPair(
s.session_id(), public_key.data(), &public_key_size,
public_key_signature.data(), &public_key_signature_size,
wrapped_private_key.data(), &wrapped_private_key_size, &key_type),
OEMCrypto_SUCCESS);
public_key.resize(public_key_size);
public_key_signature.resize(public_key_signature_size);
wrapped_private_key.resize(wrapped_private_key_size);
// Install the generated private key.
ASSERT_EQ(OEMCrypto_InstallOemPrivateKey(s.session_id(), key_type,
wrapped_private_key.data(),
wrapped_private_key_size),
OEMCrypto_SUCCESS);
}
// If data is empty or random, the API should return non-success status.
TEST_F(OEMCryptoProv40Test, InstallOemPrivateKeyInvalidDataFail) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
// Empty key fails.
std::vector<uint8_t> wrapped_private_key;
OEMCrypto_PrivateKeyType key_type = OEMCrypto_RSA_Private_Key;
ASSERT_NE(OEMCrypto_InstallOemPrivateKey(s.session_id(), key_type,
wrapped_private_key.data(),
wrapped_private_key.size()),
OEMCrypto_SUCCESS);
// Random key data fails.
wrapped_private_key = {1, 2, 3};
ASSERT_NE(OEMCrypto_InstallOemPrivateKey(s.session_id(), key_type,
wrapped_private_key.data(),
wrapped_private_key.size()),
OEMCrypto_SUCCESS);
}
// Verifies that an OEM private key can be installed, and used by
// GenerateCertificateKeyPair call.
TEST_F(OEMCryptoProv40Test, InstallOemPrivateKeyCanBeUsed) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
// First generate a key pair.
size_t public_key_size1 = 10000;
std::vector<uint8_t> public_key1(public_key_size1);
size_t public_key_signature_size1 = 10000;
std::vector<uint8_t> public_key_signature1(public_key_signature_size1);
size_t wrapped_private_key_size1 = 10000;
std::vector<uint8_t> wrapped_private_key1(wrapped_private_key_size1);
OEMCrypto_PrivateKeyType key_type1;
ASSERT_EQ(
OEMCrypto_GenerateCertificateKeyPair(
s.session_id(), public_key1.data(), &public_key_size1,
public_key_signature1.data(), &public_key_signature_size1,
wrapped_private_key1.data(), &wrapped_private_key_size1, &key_type1),
OEMCrypto_SUCCESS);
EXPECT_NE(public_key_size1, 0UL);
EXPECT_NE(public_key_signature_size1, 0UL);
EXPECT_NE(wrapped_private_key_size1, 0UL);
public_key1.resize(public_key_size1);
public_key_signature1.resize(public_key_signature_size1);
wrapped_private_key1.resize(wrapped_private_key_size1);
// Install the generated private key.
ASSERT_EQ(OEMCrypto_InstallOemPrivateKey(s.session_id(), key_type1,
wrapped_private_key1.data(),
wrapped_private_key_size1),
OEMCrypto_SUCCESS);
// Now calling GenerateCertificateKeyPair should use wrapped_private_key to
// sign the newly generated public key.
size_t public_key_size2 = 10000;
std::vector<uint8_t> public_key2(public_key_size2);
size_t public_key_signature_size2 = 10000;
std::vector<uint8_t> public_key_signature2(public_key_signature_size2);
size_t wrapped_private_key_size2 = 10000;
std::vector<uint8_t> wrapped_private_key2(wrapped_private_key_size2);
OEMCrypto_PrivateKeyType key_type2;
ASSERT_EQ(
OEMCrypto_GenerateCertificateKeyPair(
s.session_id(), public_key2.data(), &public_key_size2,
public_key_signature2.data(), &public_key_signature_size2,
wrapped_private_key2.data(), &wrapped_private_key_size2, &key_type2),
OEMCrypto_SUCCESS);
EXPECT_NE(public_key_size2, 0UL);
EXPECT_NE(public_key_signature_size2, 0UL);
EXPECT_NE(wrapped_private_key_size2, 0UL);
public_key2.resize(public_key_size2);
public_key_signature2.resize(public_key_signature_size2);
wrapped_private_key2.resize(wrapped_private_key_size2);
// Verify public_key_signature2 with public_key1.
if (key_type2 == OEMCrypto_PrivateKeyType::OEMCrypto_RSA_Private_Key) {
ASSERT_NO_FATAL_FAILURE(s.SetRsaPublicKeyFromSubjectPublicKey(
public_key1.data(), public_key1.size()));
ASSERT_NO_FATAL_FAILURE(
s.VerifyRsaSignature(public_key2, public_key_signature2.data(),
public_key_signature2.size(), kSign_RSASSA_PSS));
} else if (key_type2 == OEMCrypto_PrivateKeyType::OEMCrypto_ECC_Private_Key) {
ASSERT_NO_FATAL_FAILURE(s.SetEccPublicKeyFromSubjectPublicKey(
public_key1.data(), public_key1.size()));
ASSERT_NO_FATAL_FAILURE(s.VerifyEccSignature(public_key2,
public_key_signature2.data(),
public_key_signature2.size()));
}
}
/** Verify that the private key from an OEM Cert cannot be loaded as a DRM
* cert.
*/
TEST_F(OEMCryptoProv40Test, OEMPrivateKeyCannotBeDRMKey) {
// Create an OEM Cert and save it for alter.
Session s1;
ASSERT_NO_FATAL_FAILURE(s1.open());
ASSERT_NO_FATAL_FAILURE(CreateProv4OEMKey(&s1));
ASSERT_EQ(s1.IsPublicKeySet(), true);
s1.close();
const std::vector<uint8_t> wrapped_oem_key1 = wrapped_oem_key_;
// Now create a new OEM cert, load the second key, and try to load key1
// as the DRM key.
Session s2;
ASSERT_NO_FATAL_FAILURE(s2.open());
ASSERT_NO_FATAL_FAILURE(CreateProv4OEMKey(&s2));
s2.close();
// Load the current key as the OEM key in session 3.
Session s3;
ASSERT_NO_FATAL_FAILURE(s3.open());
// Now try to load key 1 as a DRM key. That should fail.
ASSERT_EQ(OEMCrypto_ERROR_INVALID_KEY,
OEMCrypto_LoadDRMPrivateKey(s3.session_id(), oem_key_type_,
wrapped_oem_key1.data(),
wrapped_oem_key1.size()));
}
/** The private key for a DRM Cert cannot be loaded as an OEM Certificate. */
TEST_F(OEMCryptoProv40Test, DRMPrivateKeyCannotBeOEMKey) {
// Create a DRM cert and save it for later.
Session s1;
// Make sure the drm private key exists.
ASSERT_NO_FATAL_FAILURE(s1.open());
ASSERT_NO_FATAL_FAILURE(InstallTestDrmKey(&s1));
ASSERT_NE(wrapped_drm_key_.size(), 0u);
// Now try to load the drm private key as an OEM key.
Session s2;
ASSERT_NO_FATAL_FAILURE(s2.open());
ASSERT_EQ(OEMCrypto_ERROR_INVALID_KEY,
OEMCrypto_InstallOemPrivateKey(
s2.session_id(), drm_key_type_,
reinterpret_cast<const uint8_t*>(wrapped_drm_key_.data()),
wrapped_drm_key_.size()));
}
TEST_F(OEMCryptoProv40Test, GetDeviceId) {
OEMCryptoResult sts;
std::vector<uint8_t> dev_id;
size_t dev_id_len = dev_id.size();
sts = OEMCrypto_GetDeviceID(dev_id.data(), &dev_id_len);
if (sts == OEMCrypto_ERROR_SHORT_BUFFER) {
ASSERT_GT(dev_id_len, 0u);
dev_id.resize(dev_id_len);
sts = OEMCrypto_GetDeviceID(dev_id.data(), &dev_id_len);
}
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
dev_id.resize(dev_id_len);
cout << " NormalGetDeviceId: dev_id = " << MaybeHex(dev_id)
<< " len = " << dev_id_len << endl;
// Device id should be stable. Query again.
std::vector<uint8_t> dev_id2(dev_id_len);
sts = OEMCrypto_GetDeviceID(dev_id2.data(), &dev_id_len);
ASSERT_EQ(OEMCrypto_SUCCESS, sts);
ASSERT_EQ(dev_id2, dev_id);
}
// Verifies provisioning stage 1 OEM cert provisioning round trip works
TEST_F(OEMCryptoProv40Test, ProvisionOemCert) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(CreateProv4OEMKey(&s));
ASSERT_EQ(s.IsPublicKeySet(), true);
}
// Verifies both provisioning stages OEM and DRM cert provisioning round trip
// works
TEST_F(OEMCryptoProv40Test, ProvisionDrmCert) {
Session s;
ASSERT_NO_FATAL_FAILURE(s.open());
ASSERT_NO_FATAL_FAILURE(InstallTestDrmKey(&s));
ASSERT_EQ(s.IsPublicKeySet(), true);
}
/// @}
} // namespace wvoec