diff --git a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h index 1dd964b6..1056d691 100644 --- a/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h +++ b/libwvdrmengine/oemcrypto/include/OEMCryptoCENC.h @@ -1557,6 +1557,7 @@ OEMCryptoResult OEMCrypto_LoadTestRSAKey(); * Returns: * OEMCrypto_SUCCESS success * OEMCrypto_ERROR_INVALID_SESSION + * OEMCrypto_ERROR_INVALID_CONTEXT * OEMCrypto_ERROR_SHORT_BUFFER if the signature buffer is too small. * OEMCrypto_ERROR_INVALID_RSA_KEY * OEMCrypto_ERROR_INSUFFICIENT_RESOURCES diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp index 5f07553f..b0c03ca8 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp @@ -408,27 +408,25 @@ size_t SessionContext::RSASignatureSize() { return static_cast(RSA_size(rsa_key_)); } -bool SessionContext::GenerateRSASignature(const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length, - RSA_Padding_Scheme padding_scheme) { +OEMCryptoResult SessionContext::GenerateRSASignature( + const uint8_t* message, size_t message_length, uint8_t* signature, + size_t* signature_length, RSA_Padding_Scheme padding_scheme) { if (message == NULL || message_length == 0 || signature == NULL || signature_length == 0) { LOGE("[GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); - return false; + return OEMCrypto_ERROR_INVALID_CONTEXT; } if (!rsa_key_) { LOGE("[GenerateRSASignature(): no RSA key set]"); - return false; + return OEMCrypto_ERROR_INVALID_RSA_KEY; } if (*signature_length < static_cast(RSA_size(rsa_key_))) { *signature_length = RSA_size(rsa_key_); - return false; + return OEMCrypto_ERROR_SHORT_BUFFER; } if ((padding_scheme & allowed_schemes_) != padding_scheme) { LOGE("[GenerateRSASignature(): padding_scheme not allowed]"); - return false; + return OEMCrypto_ERROR_INVALID_RSA_KEY; } // This is the standard padding scheme used for license requests. @@ -438,7 +436,7 @@ bool SessionContext::GenerateRSASignature(const uint8_t* message, if (!SHA1(message, message_length, hash)) { LOGE("[GeneratRSASignature(): error creating signature hash.]"); dump_openssl_error(); - return false; + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } // Add PSS padding. @@ -449,7 +447,7 @@ bool SessionContext::GenerateRSASignature(const uint8_t* message, if (status == -1) { LOGE("[GeneratRSASignature(): error padding hash.]"); dump_openssl_error(); - return false; + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } // Encrypt PSS padded digest. @@ -458,13 +456,13 @@ bool SessionContext::GenerateRSASignature(const uint8_t* message, if (status == -1) { LOGE("[GeneratRSASignature(): error in private encrypt.]"); dump_openssl_error(); - return false; + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } // This is the alternate padding scheme used by cast receivers only. } else if (padding_scheme == kSign_PKCS1_Block1) { if (message_length > 83) { LOGE("[GeneratRSASignature(): RSA digest too large.]"); - return false; + return OEMCrypto_ERROR_SIGNATURE_FAILURE; } // Pad the message with PKCS1 padding, and then encrypt. size_t status = RSA_private_encrypt(message_length, message, signature, @@ -472,12 +470,12 @@ bool SessionContext::GenerateRSASignature(const uint8_t* message, if (status != *signature_length) { LOGE("[GeneratRSASignature(): error in RSA private encrypt. status=%d]", status); dump_openssl_error(); - return false; + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } } else { // Bad RSA_Padding_Scheme - return false; + return OEMCrypto_ERROR_INVALID_RSA_KEY; } - return true; + return OEMCrypto_SUCCESS; } // Validate message signature @@ -696,24 +694,25 @@ bool SessionContext::InstallKey(const KeyId& key_id, return true; } -bool SessionContext::RefreshKey(const KeyId& key_id, - const std::vector& key_control, - const std::vector& key_control_iv) { +OEMCryptoResult SessionContext::RefreshKey( + const KeyId& key_id, + const std::vector& key_control, + const std::vector& key_control_iv) { if (key_id.empty()) { // Key control is not encrypted if key id is NULL KeyControlBlock key_control_block(key_control); if (!key_control_block.valid()) { LOGE("Parse key control error."); - return false; + return OEMCrypto_ERROR_INVALID_CONTEXT; } if ((key_control_block.control_bits() & kControlNonceEnabled) && (!CheckNonce(key_control_block.nonce()))) { LOGE("KCB: BAD Nonce"); - return false; + return OEMCrypto_ERROR_INVALID_NONCE; } // Apply duration to all keys in this session session_keys_.UpdateDuration(key_control_block); - return true; + return OEMCrypto_SUCCESS; } Key* content_key = session_keys_.Find(key_id); @@ -722,14 +721,14 @@ bool SessionContext::RefreshKey(const KeyId& key_id, if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) { LOGD("Error: no matching content key."); } - return false; + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } if (key_control.empty()) { if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) { LOGD("Error: no key_control."); } - return false; + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } const std::vector content_key_value = content_key->value(); @@ -750,7 +749,7 @@ bool SessionContext::RefreshKey(const KeyId& key_id, if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) { LOGD("Error decrypting key control block."); } - return false; + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } } @@ -759,15 +758,15 @@ bool SessionContext::RefreshKey(const KeyId& key_id, if (LogCategoryEnabled(kLoggingDumpKeyControlBlocks)) { LOGD("Parse key control error."); } - return false; + return OEMCrypto_ERROR_INVALID_CONTEXT; } if ((key_control_block.control_bits() & kControlNonceEnabled) && (!CheckNonce(key_control_block.nonce()))) { LOGE("KCB: BAD Nonce"); - return false; + return OEMCrypto_ERROR_INVALID_NONCE; } content_key->UpdateDuration(key_control_block); - return true; + return OEMCrypto_SUCCESS; } bool SessionContext::DecryptRSAKey(const uint8_t* enc_rsa_key, diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h index 560d131c..63f831de 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h @@ -15,7 +15,7 @@ #include "lock.h" #include "oemcrypto_key_mock.h" #include "oemcrypto_keybox_mock.h" -#include "OEMCryptoCENC.h" // Needed for enum OEMCrypto_Algorithm. +#include "OEMCryptoCENC.h" // Needed for enums only. #include "wv_cdm_types.h" namespace wvoec_mock { @@ -99,11 +99,11 @@ class SessionContext { uint8_t* signature, size_t* signature_length); size_t RSASignatureSize(); - bool GenerateRSASignature(const uint8_t* message, - size_t message_length, - uint8_t* signature, - size_t* signature_length, - RSA_Padding_Scheme padding_scheme); + OEMCryptoResult GenerateRSASignature(const uint8_t* message, + size_t message_length, + uint8_t* signature, + size_t* signature_length, + RSA_Padding_Scheme padding_scheme); bool ValidateMessage(const uint8_t* message, size_t message_length, const uint8_t* signature, @@ -157,9 +157,9 @@ class SessionContext { size_t message_length, const uint8_t* signature, size_t signature_length); - bool RefreshKey(const KeyId& key_id, - const std::vector& key_control, - const std::vector& key_control_iv); + OEMCryptoResult RefreshKey(const KeyId& key_id, + const std::vector& key_control, + const std::vector& key_control_iv); bool UpdateMacKeys(const std::vector& mac_keys, const std::vector& iv); bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data); diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp index 39105df2..096efd81 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp @@ -444,7 +444,7 @@ OEMCryptoResult OEMCrypto_RefreshKeys( } // Decrypt and refresh keys in key refresh object - bool status = true; + OEMCryptoResult status = OEMCrypto_SUCCESS; std::vector key_id; std::vector key_control; std::vector key_control_iv; @@ -469,15 +469,17 @@ OEMCryptoResult OEMCrypto_RefreshKeys( key_array[i].key_control + wvcdm::KEY_CONTROL_SIZE); } - if (!session_ctx->RefreshKey(key_id, key_control, key_control_iv)) { - LOGE("[OEMCrypto_RefreshKeys(): error in key %i]", i); - status = false; + status = session_ctx->RefreshKey(key_id, key_control, key_control_iv); + if (status != OEMCrypto_SUCCESS) { + LOGE("[OEMCrypto_RefreshKeys(): error %u in key %i]", status, i); break; } } session_ctx->FlushNonces(); - if (!status) return OEMCrypto_ERROR_UNKNOWN_FAILURE; + if (status != OEMCrypto_SUCCESS) { + return status; + } session_ctx->StartTimer(); return OEMCrypto_SUCCESS; @@ -1101,10 +1103,6 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature( LOGE("OEMCrypto_GenerateRSASignature: OEMCrypto Not Initialized."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_GenerateRSASignature(): ERROR_KEYBOX_INVALID]"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } if (signature_length == 0) { LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); @@ -1129,19 +1127,19 @@ OEMCryptoResult OEMCrypto_GenerateRSASignature( return OEMCrypto_ERROR_INVALID_CONTEXT; } - if (session_ctx->GenerateRSASignature(message, - message_length, - signature, - signature_length, - padding_scheme)) { + OEMCryptoResult sts = session_ctx->GenerateRSASignature(message, + message_length, + signature, + signature_length, + padding_scheme); + if (sts == OEMCrypto_SUCCESS) { if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) { if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) { dump_hex("signature", signature, *signature_length); } } - return OEMCrypto_SUCCESS; } - return OEMCrypto_ERROR_UNKNOWN_FAILURE;; + return sts; } extern "C" @@ -1625,6 +1623,7 @@ OEMCryptoResult OEMCrypto_DeleteUsageTable() { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } crypto_engine->usage_table()->Clear(); + crypto_engine->usage_table()->UpdateTable(); return OEMCrypto_SUCCESS; } diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.cpp index e77107dd..d1b2ed40 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.cpp @@ -241,7 +241,7 @@ UsageTable::UsageTable(CryptoEngine *ce) { // At this point, the stored table looks valid. We can load in all the // entries. - for (size_t i = 0; i < stored_table->count; i++) { + for (uint64_t i = 0; i < stored_table->count; i++) { UsageTableEntry *entry = new UsageTableEntry(&stored_table->entries[i].entry); table_[entry->pst_hash()] = entry; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.h index 09dca5f4..093c6e61 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_usage_table_mock.h @@ -39,7 +39,7 @@ struct StoredUsageTable { uint8_t signature[SHA256_DIGEST_LENGTH]; uint8_t iv[wvcdm::KEY_IV_SIZE]; int64_t generation; - size_t count; + uint64_t count; AlignedStoredUsageEntry entries[]; }; diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 2c649c50..6f53fdc8 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -678,7 +678,7 @@ class Session { } void RefreshTestKeys(const size_t key_count, uint32_t control_bits, - uint32_t nonce, bool expect_good) { + uint32_t nonce, OEMCryptoResult expected_result) { // Note: we store the message in encrypted_license_, but the refresh key // message is not actually encrypted. It is, however, signed. FillRefreshMessage(key_count, control_bits, nonce); @@ -688,17 +688,13 @@ class Session { OEMCryptoResult sts = OEMCrypto_RefreshKeys( session_id(), message_ptr(), sizeof(MessageData), &signature_[0], signature_.size(), key_count, key_array); - if (expect_good) { - ASSERT_EQ(OEMCrypto_SUCCESS, sts); - } else { - ASSERT_NE(OEMCrypto_SUCCESS, sts); - } + ASSERT_EQ(expected_result, sts); TestDecryptCTR(); sleep(kShortSleep); // Should still be valid key. TestDecryptCTR(false); sleep(kShortSleep + kLongSleep); // Should be after first expiration. - if (expect_good) { + if (expected_result == OEMCrypto_SUCCESS) { TestDecryptCTR(false, OEMCrypto_SUCCESS); } else { TestDecryptCTR(false, OEMCrypto_ERROR_UNKNOWN_FAILURE); @@ -2157,7 +2153,8 @@ TEST_P(SessionTestRefreshKeyTest, RefreshWithNonce) { s.LoadTestKeys("", new_mac_keys_); uint32_t nonce; s.GenerateNonce(&nonce); - s.RefreshTestKeys(num_keys_, wvoec_mock::kControlNonceEnabled, nonce, true); + s.RefreshTestKeys(num_keys_, wvoec_mock::kControlNonceEnabled, nonce, + OEMCrypto_SUCCESS); } TEST_P(SessionTestRefreshKeyTest, RefreshNoNonce) { @@ -2169,7 +2166,7 @@ TEST_P(SessionTestRefreshKeyTest, RefreshNoNonce) { s.LoadTestKeys("", new_mac_keys_); uint32_t nonce; s.GenerateNonce(&nonce); - s.RefreshTestKeys(num_keys_, 0, 0, true); + s.RefreshTestKeys(num_keys_, 0, 0, OEMCrypto_SUCCESS); } TEST_P(SessionTestRefreshKeyTest, RefreshOldNonce) { @@ -2181,7 +2178,8 @@ TEST_P(SessionTestRefreshKeyTest, RefreshOldNonce) { s.EncryptAndSign(); s.LoadTestKeys("", new_mac_keys_); uint32_t nonce = s.get_nonce(); - s.RefreshTestKeys(num_keys_, wvoec_mock::kControlNonceEnabled, nonce, false); + s.RefreshTestKeys(num_keys_, wvoec_mock::kControlNonceEnabled, nonce, + OEMCrypto_ERROR_INVALID_NONCE); } TEST_P(SessionTestRefreshKeyTest, RefreshBadNonce) { @@ -2195,7 +2193,8 @@ TEST_P(SessionTestRefreshKeyTest, RefreshBadNonce) { uint32_t nonce; s.GenerateNonce(&nonce); nonce ^= 42; - s.RefreshTestKeys(num_keys_, wvoec_mock::kControlNonceEnabled, nonce, false); + s.RefreshTestKeys(num_keys_, wvoec_mock::kControlNonceEnabled, nonce, + OEMCrypto_ERROR_INVALID_NONCE); } // Of only one key control block in the refesh, we update all the keys. @@ -5286,9 +5285,7 @@ TEST_P(UsageTableTestWithMAC, OfflineBadNonce) { Session s; s.open(); s.GenerateTestSessionKeys(); - s.FillSimpleMessage( - 0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceOrEntry, - 42, pst); + s.FillSimpleMessage(0, wvoec_mock::kControlNonceOrEntry, 42, pst); s.EncryptAndSign(); uint8_t* pst_ptr = s.encrypted_license().pst; OEMCryptoResult sts = OEMCrypto_LoadKeys( @@ -5306,9 +5303,7 @@ TEST_P(UsageTableTestWithMAC, OfflineEmptyPST) { Session s; s.open(); s.GenerateTestSessionKeys(); - s.FillSimpleMessage( - 0, wvoec_mock::kControlNonceEnabled | wvoec_mock::kControlNonceOrEntry, - s.get_nonce()); + s.FillSimpleMessage(0, wvoec_mock::kControlNonceOrEntry, s.get_nonce()); s.EncryptAndSign(); OEMCryptoResult sts = OEMCrypto_LoadKeys( s.session_id(), s.message_ptr(), sizeof(MessageData), &s.signature()[0], @@ -5368,8 +5363,7 @@ TEST_P(UsageTableTestWithMAC, BadRange) { Session s; s.open(); s.GenerateTestSessionKeys(); - s.FillSimpleMessage(0, wvoec_mock::kControlNonceOrEntry, - s.get_nonce(), pst); + s.FillSimpleMessage(0, wvoec_mock::kControlNonceOrEntry,s.get_nonce(), pst); s.EncryptAndSign(); uint8_t* pst_ptr = s.license().pst; // Bad: not in encrypted_license. ASSERT_NE(