Support 32 bytes session key

[ Merge of http://go/wvgerrit/149849 ]

With ECC based DRM cert, the session key is expected to be 32, as
compared to 16 bytes in RSA case. This CL adds supports for 32 bytes
session key.

Bug: 236317198
Test: oemcrypto_test
Change-Id: I657fdd92d17736a23375ddcd457f83efa6ca6d1f
This commit is contained in:
Alex Dale
2022-06-21 16:01:20 -07:00
parent 02c7062349
commit d874fffaec
6 changed files with 63 additions and 21 deletions

View File

@@ -83,19 +83,23 @@ void Encryptor::PadAndEncryptProvisioningMessage(
// This generates the data for deriving one key. If there are failures in
// this function, then there is something wrong with the test program and its
// dependency on BoringSSL.
void KeyDeriver::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
int counter, vector<uint8_t>* out) {
void KeyDeriver::DeriveKey(const uint8_t* key, size_t master_key_size,
const vector<uint8_t>& context, int counter,
vector<uint8_t>* out) {
ASSERT_NE(key, nullptr);
ASSERT_FALSE(context.empty());
ASSERT_GE(4, counter);
ASSERT_LE(1, counter);
ASSERT_NE(out, nullptr);
// For RSA, the master key is expected to be 16 bytes; for EC key, 32 bytes.
ASSERT_TRUE(master_key_size == KEY_SIZE || master_key_size == 2 * KEY_SIZE);
const EVP_CIPHER* cipher = EVP_aes_128_cbc();
const EVP_CIPHER* cipher =
master_key_size == KEY_SIZE ? EVP_aes_128_cbc() : EVP_aes_256_cbc();
CMAC_CTX* cmac_ctx = CMAC_CTX_new();
ASSERT_NE(nullptr, cmac_ctx);
ASSERT_TRUE(CMAC_Init(cmac_ctx, key, KEY_SIZE, cipher, nullptr));
ASSERT_TRUE(CMAC_Init(cmac_ctx, key, master_key_size, cipher, nullptr));
std::vector<uint8_t> message;
message.push_back(static_cast<uint8_t>(counter));
@@ -114,24 +118,24 @@ void KeyDeriver::DeriveKey(const uint8_t* key, const vector<uint8_t>& context,
// This generates the data for deriving a set of keys. If there are failures in
// this function, then there is something wrong with the test program and its
// dependency on BoringSSL.
void KeyDeriver::DeriveKeys(const uint8_t* master_key,
void KeyDeriver::DeriveKeys(const uint8_t* master_key, size_t master_key_size,
const vector<uint8_t>& mac_key_context,
const vector<uint8_t>& enc_key_context) {
// Generate derived key for mac key
std::vector<uint8_t> mac_key_part2;
DeriveKey(master_key, mac_key_context, 1, &mac_key_server_);
DeriveKey(master_key, mac_key_context, 2, &mac_key_part2);
DeriveKey(master_key, master_key_size, mac_key_context, 1, &mac_key_server_);
DeriveKey(master_key, master_key_size, mac_key_context, 2, &mac_key_part2);
mac_key_server_.insert(mac_key_server_.end(), mac_key_part2.begin(),
mac_key_part2.end());
DeriveKey(master_key, mac_key_context, 3, &mac_key_client_);
DeriveKey(master_key, mac_key_context, 4, &mac_key_part2);
DeriveKey(master_key, master_key_size, mac_key_context, 3, &mac_key_client_);
DeriveKey(master_key, master_key_size, mac_key_context, 4, &mac_key_part2);
mac_key_client_.insert(mac_key_client_.end(), mac_key_part2.begin(),
mac_key_part2.end());
// Generate derived key for encryption key
std::vector<uint8_t> enc_key;
DeriveKey(master_key, enc_key_context, 1, &enc_key);
DeriveKey(master_key, master_key_size, enc_key_context, 1, &enc_key);
set_enc_key(enc_key);
}

View File

@@ -62,7 +62,7 @@ class KeyDeriver : public Encryptor {
KeyDeriver& operator=(const KeyDeriver&) = default;
// Generate mac and enc keys give the master key.
void DeriveKeys(const uint8_t* master_key,
void DeriveKeys(const uint8_t* master_key, size_t master_key_size,
const std::vector<uint8_t>& mac_key_context,
const std::vector<uint8_t>& enc_key_context);
// Sign the buffer with server's mac key.
@@ -80,9 +80,11 @@ class KeyDeriver : public Encryptor {
void set_mac_keys(const uint8_t* mac_keys);
private:
// Internal utility function to derive key using CMAC-128
void DeriveKey(const uint8_t* key, const std::vector<uint8_t>& context,
int counter, std::vector<uint8_t>* out);
// Internal utility function to derive key using CMAC-128 or CMAC-256 based on
// master_key_size.
void DeriveKey(const uint8_t* key, size_t master_key_size,
const std::vector<uint8_t>& context, int counter,
std::vector<uint8_t>* out);
std::vector<uint8_t> mac_key_server_;
std::vector<uint8_t> mac_key_client_;

View File

@@ -568,8 +568,8 @@ void LicenseRoundTrip::VerifyRequestSignature(
generated_signature.size(), kSign_RSASSA_PSS);
SHA256(data.data(), core_message_length, request_hash_);
} else {
session()->VerifyRsaSignature(data, generated_signature.data(),
generated_signature.size(), kSign_RSASSA_PSS);
session()->VerifySignature(data, generated_signature.data(),
generated_signature.size(), kSign_RSASSA_PSS);
SHA256(data.data(), core_message_length, request_hash_);
}
}
@@ -1498,7 +1498,8 @@ void Session::GenerateDerivedKeysFromKeybox(
OEMCrypto_GenerateDerivedKeys(
session_id(), mac_context.data(), mac_context.size(),
enc_context.data(), enc_context.size()));
key_deriver_.DeriveKeys(keybox.device_key_, mac_context, enc_context);
key_deriver_.DeriveKeys(keybox.device_key_, sizeof(keybox.device_key_),
mac_context, enc_context);
}
void Session::GenerateDerivedKeysFromSessionKey() {
@@ -1509,7 +1510,7 @@ void Session::GenerateDerivedKeysFromSessionKey() {
<< "No public RSA/ECC key loaded in test code";
// A failure here probably indicates that there is something wrong with the
// test program and its dependency on BoringSSL.
ASSERT_TRUE(GenerateRsaSessionKey(&session_key, &enc_session_key));
ASSERT_TRUE(GenerateSessionKey(&session_key, &enc_session_key));
vector<uint8_t> mac_context;
vector<uint8_t> enc_context;
FillDefaultContext(&mac_context, &enc_context);
@@ -1520,7 +1521,8 @@ void Session::GenerateDerivedKeysFromSessionKey() {
mac_context.data(), mac_context.size(), enc_context.data(),
enc_context.size()));
key_deriver_.DeriveKeys(session_key.data(), mac_context, enc_context);
key_deriver_.DeriveKeys(session_key.data(), session_key.size(), mac_context,
enc_context);
}
void Session::TestDecryptCTR(bool select_key_first,
@@ -1764,6 +1766,18 @@ void Session::VerifyEccSignature(const vector<uint8_t>& message,
ASSERT_EQ(result, OEMCrypto_SUCCESS) << "ECC signature check failed";
}
void Session::VerifySignature(const vector<uint8_t>& message,
const uint8_t* signature, size_t signature_length,
RSA_Padding_Scheme padding_scheme) {
if (public_rsa_ != nullptr) {
return VerifyRsaSignature(message, signature, signature_length,
padding_scheme);
} else if (public_ec_ != nullptr) {
return VerifyEccSignature(message, signature, signature_length);
}
FAIL() << "No public RSA or ECC key loaded in test code";
}
bool Session::GenerateRsaSessionKey(vector<uint8_t>* session_key,
vector<uint8_t>* enc_session_key) {
if (!public_rsa_) {
@@ -1800,6 +1814,17 @@ bool Session::GenerateEccSessionKey(vector<uint8_t>* session_key,
return true;
}
bool Session::GenerateSessionKey(vector<uint8_t>* session_key,
vector<uint8_t>* key_material) {
if (public_rsa_ != nullptr) {
return GenerateRsaSessionKey(session_key, key_material);
} else if (public_ec_ != nullptr) {
return GenerateEccSessionKey(session_key, key_material);
}
cerr << "No public RSA or ECC key loaded in test code\n";
return false;
}
void Session::LoadWrappedDrmKey(OEMCrypto_PrivateKeyType key_type,
const vector<uint8_t>& wrapped_drm_key) {
ASSERT_EQ(OEMCrypto_SUCCESS,

View File

@@ -606,6 +606,12 @@ class Session {
// |public_ecc_| using Widevine ECDSA.
void VerifyEccSignature(const vector<uint8_t>& message,
const uint8_t* signature, size_t signature_length);
// Verify RSA or ECC signature based on the key type installed. The
// padding_scheme will be ignored in case of ECC key.
void VerifySignature(const vector<uint8_t>& message, const uint8_t* signature,
size_t signature_length,
RSA_Padding_Scheme padding_scheme);
// Encrypts a known session key with public_rsa_ for use in future calls to
// OEMCrypto_DeriveKeysFromSessionKey or OEMCrypto_RewrapDeviceRSAKey30.
// The unencrypted session key is stored in session_key.
@@ -616,6 +622,10 @@ class Session {
// The unencrypted session key is stored in session_key.
bool GenerateEccSessionKey(vector<uint8_t>* session_key,
vector<uint8_t>* ecdh_public_key_data);
// Based on the key type installed, call GenerateRsaSessionKey or
// GenerateEccSessionKey.
bool GenerateSessionKey(vector<uint8_t>* session_key,
vector<uint8_t>* key_material);
// Calls OEMCrypto_RewrapDeviceRSAKey30 with the given provisioning response
// message. If force is true, we assert that the key loads successfully.

View File

@@ -268,7 +268,7 @@ TEST_F(OTAKeyboxProvisioningTest, BasicTest) {
std::copy(bit_size_string.begin(), bit_size_string.end(),
std::back_inserter(enc_context));
KeyDeriver keys;
keys.DeriveKeys(model_key.data(), mac_context, enc_context);
keys.DeriveKeys(model_key.data(), model_key.size(), mac_context, enc_context);
const std::vector<uint8_t> message(
request.data(),
request.data() + request.size() - HMAC_SHA256_SIGNATURE_SIZE);