diff --git a/libwvdrmengine/cdm/core/test/fake_provisioning_server.cpp b/libwvdrmengine/cdm/core/test/fake_provisioning_server.cpp index 2c6b813b..4b550450 100644 --- a/libwvdrmengine/cdm/core/test/fake_provisioning_server.cpp +++ b/libwvdrmengine/cdm/core/test/fake_provisioning_server.cpp @@ -284,7 +284,8 @@ bool FakeProvisioningServer::MakeResponse( wvoec::KeyDeriver key_deriver; // Not only is this Prov 2.0 specific, it assumes the device is using the // standard test keybox. - key_deriver.DeriveKeys(wvoec::kTestKeybox.device_key_, mac_context_v, + key_deriver.DeriveKeys(wvoec::kTestKeybox.device_key_, + sizeof(wvoec::kTestKeybox.device_key_), mac_context_v, enc_context_v); // Create a structure to hold the RSA private key. This is used by the key diff --git a/libwvdrmengine/oemcrypto/test/oec_key_deriver.cpp b/libwvdrmengine/oemcrypto/test/oec_key_deriver.cpp index dc1d2371..21d50781 100644 --- a/libwvdrmengine/oemcrypto/test/oec_key_deriver.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_key_deriver.cpp @@ -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& context, - int counter, vector* out) { +void KeyDeriver::DeriveKey(const uint8_t* key, size_t master_key_size, + const vector& context, int counter, + vector* 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 message; message.push_back(static_cast(counter)); @@ -114,24 +118,24 @@ void KeyDeriver::DeriveKey(const uint8_t* key, const vector& 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& mac_key_context, const vector& enc_key_context) { // Generate derived key for mac key std::vector 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 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); } diff --git a/libwvdrmengine/oemcrypto/test/oec_key_deriver.h b/libwvdrmengine/oemcrypto/test/oec_key_deriver.h index 65b4ad71..4741da49 100644 --- a/libwvdrmengine/oemcrypto/test/oec_key_deriver.h +++ b/libwvdrmengine/oemcrypto/test/oec_key_deriver.h @@ -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& mac_key_context, const std::vector& 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& context, - int counter, std::vector* 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& context, int counter, + std::vector* out); std::vector mac_key_server_; std::vector mac_key_client_; diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index f6af9e83..36839b70 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -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 mac_context; vector 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& message, ASSERT_EQ(result, OEMCrypto_SUCCESS) << "ECC signature check failed"; } +void Session::VerifySignature(const vector& 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* session_key, vector* enc_session_key) { if (!public_rsa_) { @@ -1800,6 +1814,17 @@ bool Session::GenerateEccSessionKey(vector* session_key, return true; } +bool Session::GenerateSessionKey(vector* session_key, + vector* 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& wrapped_drm_key) { ASSERT_EQ(OEMCrypto_SUCCESS, diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index 7bbe2541..cca1698c 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -606,6 +606,12 @@ class Session { // |public_ecc_| using Widevine ECDSA. void VerifyEccSignature(const vector& 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& 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* session_key, vector* ecdh_public_key_data); + // Based on the key type installed, call GenerateRsaSessionKey or + // GenerateEccSessionKey. + bool GenerateSessionKey(vector* session_key, + vector* key_material); // Calls OEMCrypto_RewrapDeviceRSAKey30 with the given provisioning response // message. If force is true, we assert that the key loads successfully. diff --git a/libwvdrmengine/oemcrypto/test/ota_keybox_test.cpp b/libwvdrmengine/oemcrypto/test/ota_keybox_test.cpp index ec8377e8..359da3a8 100644 --- a/libwvdrmengine/oemcrypto/test/ota_keybox_test.cpp +++ b/libwvdrmengine/oemcrypto/test/ota_keybox_test.cpp @@ -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 message( request.data(), request.data() + request.size() - HMAC_SHA256_SIGNATURE_SIZE);