From 830a7acc48285c9adfcbd23616d6dbb78def8f9f Mon Sep 17 00:00:00 2001 From: Fred Gylys-Colwell Date: Mon, 21 Jun 2021 23:10:45 +0000 Subject: [PATCH] Sync oemcrypto reference code This is a merge from the Widevine repo of http://go/wvgerrit/117311 Update backwards compatibility builds http://go/wvgerrit/117423 Restrict maximum size of key id To protect from out-of-memory found by fuzz testing. http://go/wvgerrit/117683 Generation number should wrap The master generation number should wrap around on overflow. This means that we cannot use less than to check for a skew of 1. http://go/wvgerrit/119232 Replace 0 with nullptr Bug: 176234903 Bug: 184866351 Bug: 161243686 Test: ran unit tests (CL affects test code only) Merged-In: Ie787bcf9c66a7605700c3dc29a8aa16406926ce3 Change-Id: I2b02a36a70a0920f31ffc00de102a23516d4b20e --- .../oemcrypto/ref/src/oemcrypto_engine_ref.h | 2 +- .../oemcrypto/ref/src/oemcrypto_ref.cpp | 19 +++-- .../ref/src/oemcrypto_rsa_key_shared.cpp | 2 +- .../ref/src/oemcrypto_rsa_key_shared.h | 2 +- .../oemcrypto/ref/src/oemcrypto_session.cpp | 6 +- .../ref/src/oemcrypto_usage_table_ref.cpp | 16 ++-- .../ref/src/oemcrypto_usage_table_ref.h | 2 +- libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp | 2 +- .../ref/test/oemcrypto_wvcrc32_unittest.cpp | 74 ------------------- 9 files changed, 30 insertions(+), 95 deletions(-) delete mode 100644 libwvdrmengine/oemcrypto/ref/test/oemcrypto_wvcrc32_unittest.cpp diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h index 3150f21b..aadb5128 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h @@ -50,7 +50,7 @@ typedef enum SessionType { class CryptoEngine { public: static const uint32_t kApiVersion = 16; - static const uint32_t kMinorApiVersion = 3; + static const uint32_t kMinorApiVersion = 4; static const int64_t kTimeInfoUpdateWindowInSeconds = 300; // This is like a factory method, except we choose which version to use at diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp index a05bb7f5..d2d99c41 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp @@ -554,9 +554,12 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_QueryKeyControl( return OEMCrypto_ERROR_UNKNOWN_FAILURE; } uint32_t* block = reinterpret_cast(key_control_block); - if ((key_control_block_length == nullptr) || - (*key_control_block_length < wvoec::KEY_CONTROL_SIZE)) { + if (key_control_block_length == nullptr) { + return OEMCrypto_ERROR_INVALID_CONTEXT; + } + if (*key_control_block_length < wvoec::KEY_CONTROL_SIZE) { LOGE("[OEMCrypto_QueryKeyControl(): OEMCrypto_ERROR_SHORT_BUFFER]"); + *key_control_block_length = wvoec::KEY_CONTROL_SIZE; return OEMCrypto_ERROR_SHORT_BUFFER; } *key_control_block_length = wvoec::KEY_CONTROL_SIZE; @@ -572,6 +575,9 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_QueryKeyControl( LOGE("[OEMCrypto_QueryKeyControl(): ERROR_INVALID_SESSION]"); return OEMCrypto_ERROR_INVALID_SESSION; } + if (key_id_length > wvoec::KEY_ID_SIZE || key_id_length == 0) { + return OEMCrypto_ERROR_INVALID_CONTEXT; + } const std::vector key_id_str = std::vector(key_id, key_id + key_id_length); if (!session_ctx->QueryKeyControlBlock(key_id_str, block)) { @@ -596,7 +602,9 @@ OEMCrypto_SelectKey(const OEMCrypto_SESSION session, const uint8_t* key_id, LOGE("[OEMCrypto_SelectKey(): ERROR_INVALID_SESSION]"); return OEMCrypto_ERROR_INVALID_SESSION; } - + if (key_id_length > wvoec::KEY_ID_SIZE || key_id_length == 0) { + return OEMCrypto_ERROR_INVALID_CONTEXT; + } const std::vector key_id_str = std::vector(key_id, key_id + key_id_length); return session_ctx->SelectContentKey(key_id_str, cipher_mode); @@ -1272,7 +1280,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateRSASignature( return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - if (signature_length == 0) { + if (signature_length == nullptr) { LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } @@ -1289,8 +1297,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateRSASignature( return OEMCrypto_ERROR_SHORT_BUFFER; } - if (message == nullptr || message_length == 0 || signature == nullptr || - signature_length == 0) { + if (message == nullptr || message_length == 0 || signature == nullptr) { LOGE("[OEMCrypto_GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.cpp index 6c73ad81..83cd52fc 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.cpp @@ -1,5 +1,5 @@ // Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine Master +// source code may only be used and distributed under the Widevine // License Agreement. // // Reference implementation of OEMCrypto APIs diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.h index 98ea154e..5f832cd5 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_rsa_key_shared.h @@ -1,5 +1,5 @@ // Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine Master +// source code may only be used and distributed under the Widevine // License Agreement. // // Reference implementation of OEMCrypto APIs diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp index 9a1ab8e5..880eabd7 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp @@ -227,7 +227,7 @@ bool SessionContext::DeriveKey(const std::vector& key, return false; } - if (!CMAC_Init(cmac_ctx, &key[0], key.size(), cipher, 0)) { + if (!CMAC_Init(cmac_ctx, &key[0], key.size(), cipher, nullptr)) { LOGE("[DeriveKey(): OEMCrypto_ERROR_CMAC_FAILURE]"); CMAC_CTX_free(cmac_ctx); return false; @@ -521,7 +521,7 @@ OEMCryptoResult SessionContext::GenerateCertSignature( size_t* signature_length) { // TODO(b/67735947): Add ECC cert support. if (message == nullptr || message_length == 0 || signature == nullptr || - signature_length == 0) { + signature_length == nullptr) { LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); return OEMCrypto_ERROR_INVALID_CONTEXT; } @@ -571,7 +571,7 @@ 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 == nullptr || message_length == 0 || signature == nullptr || - signature_length == 0) { + signature_length == nullptr) { LOGE("OEMCrypto_ERROR_INVALID_CONTEXT"); return OEMCrypto_ERROR_INVALID_CONTEXT; } diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp index b3750c1f..f0183661 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.cpp @@ -407,11 +407,12 @@ OEMCryptoResult UsageTable::LoadUsageEntry( if (new_entry->generation_number() != generation_numbers_[index]) { LOGE("Generation SKEW: %ld -> %ld", new_entry->generation_number(), generation_numbers_[index]); - if ((new_entry->generation_number() + 1 < generation_numbers_[index]) || - (new_entry->generation_number() - 1 > generation_numbers_[index])) { + if ((new_entry->generation_number() + 1 == generation_numbers_[index]) || + (new_entry->generation_number() - 1 == generation_numbers_[index])) { + status = OEMCrypto_WARNING_GENERATION_SKEW; + } else { return OEMCrypto_ERROR_GENERATION_SKEW; } - status = OEMCrypto_WARNING_GENERATION_SKEW; } sessions_[index] = session; *entry = std::move(new_entry); @@ -583,11 +584,12 @@ OEMCryptoResult UsageTable::LoadUsageTableHeader( if (clear->master_generation != master_generation_number_) { LOGE("Generation SKEW: %ld -> %ld", clear->master_generation, master_generation_number_); - if ((clear->master_generation + 1 < master_generation_number_) || - (clear->master_generation - 1 > master_generation_number_)) { + if ((clear->master_generation + 1 == master_generation_number_) || + (clear->master_generation - 1 == master_generation_number_)) { + status = OEMCrypto_WARNING_GENERATION_SKEW; + } else { return OEMCrypto_ERROR_GENERATION_SKEW; } - status = OEMCrypto_WARNING_GENERATION_SKEW; } int64_t* stored_generations = reinterpret_cast(&clear_buffer[0] + sizeof(SignedHeaderBlock)); @@ -615,7 +617,7 @@ OEMCryptoResult UsageTable::MoveEntry(UsageTableEntry* entry, return OEMCrypto_ERROR_UNKNOWN_FAILURE; } sessions_[new_index] = sessions_[entry->index()]; - sessions_[entry->index()] = 0; + sessions_[entry->index()] = nullptr; entry->set_index(new_index); generation_numbers_[new_index] = master_generation_number_; diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h index 7fdd1785..18c0cfcd 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_usage_table_ref.h @@ -107,7 +107,7 @@ class UsageTable { OEMCryptoResult ShrinkUsageTableHeader(uint32_t new_table_size, uint8_t* header_buffer, size_t* header_buffer_length); - void ReleaseEntry(uint32_t index) { sessions_[index] = 0; } + void ReleaseEntry(uint32_t index) { sessions_[index] = nullptr; } void IncrementGeneration(); static size_t SignedHeaderSize(size_t count); diff --git a/libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp b/libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp index 000ac260..604b5e29 100644 --- a/libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/wvcrc.cpp @@ -2,7 +2,7 @@ // source code may only be used and distributed under the Widevine // License Agreement. // -// Compute CRC32/MPEG2 Checksum. Needed for verification of WV Keybox. +// Compute CRC32 Checksum. Needed for verification of WV Keybox. // #include "platform.h" #include "wvcrc32.h" diff --git a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_wvcrc32_unittest.cpp b/libwvdrmengine/oemcrypto/ref/test/oemcrypto_wvcrc32_unittest.cpp deleted file mode 100644 index baabaa14..00000000 --- a/libwvdrmengine/oemcrypto/ref/test/oemcrypto_wvcrc32_unittest.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary -// source code may only be used and distributed under the Widevine License -// Agreement. -// -// Reference implementation of OEMCrypto APIs -// -#include - -#include "wvcrc32.h" - -namespace wvoec_ref { - -uint32_t ComputeCrc32(const std::string& s) { - return wvcrc32(reinterpret_cast(s.data()), s.size()); -} - -uint32_t ComputeCrc32Cont(const std::string& s, uint32_t prev_crc) { - return wvcrc32Cont(reinterpret_cast(s.data()), s.size(), - prev_crc); -} - -TEST(OEMCryptoWvCrc32Test, BasicTest) { - EXPECT_EQ(0xF88AC628, ComputeCrc32("abcdefg")); - EXPECT_EQ(0xDF520F72, ComputeCrc32("Widevine")); - EXPECT_EQ(0x0376E6E7, ComputeCrc32("123456789")); - EXPECT_EQ(0xBA62119E, - ComputeCrc32("The quick brown fox jumps over the lazy dog")); -} - -TEST(OEMCryptoWvCrc32Test, StreamTest) { - const std::vector parts = {"The ", "quick", " brown ", - "fox", " jumps ", "over", - " the ", "lazy", " dog"}; - uint32_t crc = wvcrc32Init(); - for (const auto& part : parts) { - crc = ComputeCrc32Cont(part, crc); - } - EXPECT_EQ(0xBA62119E, crc); -} - -TEST(OEMCryptoWvCrc32Test, Keybox) { - // clang-format off - const uint8_t kKeyboxData[128] = { - // deviceID = WidevineCRCTestKeyBox - 0x57, 0x69, 0x64, 0x65, 0x76, 0x69, 0x6e, 0x65, - 0x43, 0x52, 0x43, 0x54, 0x65, 0x73, 0x74, 0x4b, - 0x65, 0x79, 0x62, 0x6f, 0x78, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // key = random - 0x8a, 0x7c, 0xda, 0x3e, 0x09, 0xd9, 0x8e, 0xd5, - 0x47, 0x47, 0x00, 0x84, 0x5a, 0x1f, 0x52, 0xd4, - // data = random - 0x98, 0xa5, 0x00, 0x19, 0x8b, 0xfe, 0x54, 0xfd, - 0xca, 0x4d, 0x26, 0xa3, 0xfa, 0xaa, 0x3b, 0x6c, - 0x35, 0xfe, 0x03, 0x7c, 0xbf, 0x35, 0xba, 0xce, - 0x31, 0xb5, 0x1e, 0x3c, 0x49, 0xd6, 0x3f, 0x9c, - 0x3a, 0xde, 0x9b, 0x58, 0xcc, 0x54, 0x8d, 0xc0, - 0x4b, 0x04, 0xcc, 0xee, 0xae, 0x4d, 0x9f, 0x90, - 0xd3, 0xf3, 0xfe, 0x23, 0x26, 0x13, 0x56, 0x80, - 0xe4, 0x3b, 0x79, 0x22, 0x69, 0x5d, 0xd6, 0xb7, - 0xa0, 0x0e, 0x7e, 0x07, 0xcd, 0x1a, 0x15, 0xca, - // magic - 'k', 'b', 'o', 'x', - // crc - 0x09, 0x7b, 0x7e, 0xcc - }; - // clang-format on - const uint32_t crc_computed = wvcrc32n(kKeyboxData, 124); - uint32_t crc_current; - memcpy(&crc_current, &kKeyboxData[124], 4); - EXPECT_EQ(crc_computed, crc_current); -} - -} // namespace wvoec_ref