diff --git a/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC.pdf b/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC.pdf index c024d6aa..8491ab86 100644 Binary files a/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC.pdf and b/libwvdrmengine/docs/WidevineModularDRMSecurityIntegrationGuideforCENC.pdf differ diff --git a/libwvdrmengine/docs/Widevine_Modular_DRM_Version_11_Delta.pdf b/libwvdrmengine/docs/Widevine_Modular_DRM_Version_11_Delta.pdf index 0827756f..fbed7b02 100644 Binary files a/libwvdrmengine/docs/Widevine_Modular_DRM_Version_11_Delta.pdf and b/libwvdrmengine/docs/Widevine_Modular_DRM_Version_11_Delta.pdf differ diff --git a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp index 63e1126b..be6a7c4f 100644 --- a/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp +++ b/libwvdrmengine/oemcrypto/test/oemcrypto_test.cpp @@ -47,11 +47,10 @@ void PrintTo(const vector& value, std::ostream* os) { } struct PatternTestVariant { - PatternTestVariant(size_t encrypt, size_t skip, size_t offset, - OEMCryptoCipherMode mode) { + PatternTestVariant(size_t encrypt, size_t skip, OEMCryptoCipherMode mode) { this->pattern.encrypt = encrypt; this->pattern.skip = skip; - this->pattern.offset = offset; + this->pattern.offset = 0; this->mode = mode; } OEMCrypto_CENCEncryptPatternDesc pattern; @@ -61,7 +60,7 @@ struct PatternTestVariant { void PrintTo(const PatternTestVariant& param, ::std::ostream* os) { *os << ((param.mode == OEMCrypto_CipherMode_CTR) ? "CTR mode" : "CBC mode") << ", encrypt=" << param.pattern.encrypt - << ", skip=" << param.pattern.skip << ", offset=" << param.pattern.offset; + << ", skip=" << param.pattern.skip; } } // namespace std @@ -2426,7 +2425,6 @@ struct SampleSize { struct SampleInitData { uint8_t iv[AES_BLOCK_SIZE]; - size_t pattern_offset; size_t block_offset; }; @@ -2460,8 +2458,6 @@ class OEMCryptoSessionTestsDecryptTests memcpy(iv, &starting_iv[0], AES_BLOCK_SIZE); - size_t pattern_offset = - pattern_.offset; // block index into encrypted/skip block pattern. size_t buffer_index = 0; // byte index into in and out. size_t block_offset = 0; // byte index into current block. for (size_t i = 0; i < subsample_size_.size(); i++) { @@ -2474,7 +2470,9 @@ class OEMCryptoSessionTestsDecryptTests // Save the current iv and offsets for call to DecryptCENC. sample_init_data_.push_back(SampleInitData()); memcpy(sample_init_data_[i].iv, iv, AES_BLOCK_SIZE); - sample_init_data_[i].pattern_offset = pattern_offset; + // Note: final CENC spec specifies the pattern_offset = 0 at the + // start of each subsample. + size_t pattern_offset = 0; sample_init_data_[i].block_offset = block_offset; size_t subsample_end = buffer_index + subsample_size_[i].encrypted_size; @@ -2543,7 +2541,7 @@ class OEMCryptoSessionTestsDecryptTests size_t buffer_offset = 0; for (size_t i = 0; i < subsample_size_.size(); i++) { OEMCrypto_CENCEncryptPatternDesc pattern = pattern_; - pattern.offset = sample_init_data_[i].pattern_offset; + pattern.offset = 0; // Final CENC spec says pattern offset always 0. bool is_encrypted = false; OEMCrypto_DestBufferDesc destBuffer; size_t block_offset = 0; @@ -2605,6 +2603,11 @@ class OEMCryptoSessionTestsDecryptTests vector sample_init_data_; }; +// Tests that generate partial ending blocks. These tests should not be used +// with CTR mode and pattern encrypt. +class OEMCryptoSessionTestsPartialBlockTests : + public OEMCryptoSessionTestsDecryptTests {}; + TEST_P(OEMCryptoSessionTestsDecryptTests, SingleLargeSubsample) { // This subsample size should be larger a few encrypt/skip patterns. Most // test cases use a pattern length of 160, so we'll run through at least two @@ -2686,7 +2689,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, NoOffset) { // the decrypt step. // If this test fails for CTR mode, then it is probably handleing the // block_offset incorrectly. -TEST_P(OEMCryptoSessionTestsDecryptTests, EvenOffset) { +TEST_P(OEMCryptoSessionTestsPartialBlockTests, EvenOffset) { subsample_size_.push_back(SampleSize(25, 8)); subsample_size_.push_back(SampleSize(25, 32)); subsample_size_.push_back(SampleSize(25, 50)); @@ -2714,7 +2717,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, EvenOffset) { // 0, so an error is expected in the decrypt step. // Another way to view the block offset is with the formula: // block_boundary + block_offset = beginning of subsample. -TEST_P(OEMCryptoSessionTestsDecryptTests, OddOffset) { +TEST_P(OEMCryptoSessionTestsPartialBlockTests, OddOffset) { subsample_size_.push_back(SampleSize(10, 50)); subsample_size_.push_back(SampleSize(10, 75)); subsample_size_.push_back(SampleSize(10, 25)); @@ -2759,7 +2762,7 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptWithNearWrap) { // This tests the case where an encrypted sample is not an even number of // blocks. For CTR mode, the partial block is encrypted. For CBC mode the // partial block should be a copy of the clear data. -TEST_P(OEMCryptoSessionTestsDecryptTests, PartialBlock) { +TEST_P(OEMCryptoSessionTestsPartialBlockTests, PartialBlock) { // Note: for more complete test coverage, we want a sample size that is in // the encrypted range for some tests, e.g. (3,7), and in the skip range for // other tests, e.g. (7, 3). 3*16 < 50 and 7*16 > 50. @@ -2900,25 +2903,37 @@ TEST_P(OEMCryptoSessionTestsDecryptTests, DecryptCENCPerformance) { } INSTANTIATE_TEST_CASE_P( - PatternTests, OEMCryptoSessionTestsDecryptTests, - Values(PatternTestVariant(0, 0, 0, OEMCrypto_CipherMode_CTR), - PatternTestVariant(3, 7, 0, OEMCrypto_CipherMode_CTR), - PatternTestVariant(3, 7, 2, OEMCrypto_CipherMode_CTR), - PatternTestVariant(7, 3, 2, OEMCrypto_CipherMode_CTR), - PatternTestVariant(0, 0, 0, OEMCrypto_CipherMode_CBC), - PatternTestVariant(3, 7, 0, OEMCrypto_CipherMode_CBC), - PatternTestVariant(3, 7, 2, OEMCrypto_CipherMode_CBC), - PatternTestVariant(7, 3, 2, OEMCrypto_CipherMode_CBC), + CTRTests, OEMCryptoSessionTestsPartialBlockTests, + Values(PatternTestVariant(0, 0, OEMCrypto_CipherMode_CTR) + )); +INSTANTIATE_TEST_CASE_P( + CBCTests, OEMCryptoSessionTestsPartialBlockTests, + Values(PatternTestVariant(0, 0, OEMCrypto_CipherMode_CBC), + PatternTestVariant(3, 7, OEMCrypto_CipherMode_CBC), // HLS Edge case. We should follow the CENC spec, not HLS spec. - PatternTestVariant(9, 1, 0, OEMCrypto_CipherMode_CBC), - PatternTestVariant(1, 9, 0, OEMCrypto_CipherMode_CBC), + PatternTestVariant(9, 1, OEMCrypto_CipherMode_CBC), + PatternTestVariant(1, 9, OEMCrypto_CipherMode_CBC), + PatternTestVariant(1, 3, OEMCrypto_CipherMode_CBC), + PatternTestVariant(2, 1, OEMCrypto_CipherMode_CBC) + )); +INSTANTIATE_TEST_CASE_P( + CTRTests, OEMCryptoSessionTestsDecryptTests, + Values(PatternTestVariant(0, 0, OEMCrypto_CipherMode_CTR), + PatternTestVariant(3, 7, OEMCrypto_CipherMode_CTR), // Pattern length should be 10, but that is not guaranteed. - PatternTestVariant(5, 3, 2, OEMCrypto_CipherMode_CTR), - PatternTestVariant(1, 3, 0, OEMCrypto_CipherMode_CTR), - PatternTestVariant(2, 1, 0, OEMCrypto_CipherMode_CTR), - PatternTestVariant(5, 3, 2, OEMCrypto_CipherMode_CBC), - PatternTestVariant(1, 3, 0, OEMCrypto_CipherMode_CBC), - PatternTestVariant(2, 1, 0, OEMCrypto_CipherMode_CBC) + PatternTestVariant(1, 3, OEMCrypto_CipherMode_CTR), + PatternTestVariant(2, 1, OEMCrypto_CipherMode_CTR) + )); +INSTANTIATE_TEST_CASE_P( + CBCTests, OEMCryptoSessionTestsDecryptTests, + Values(PatternTestVariant(0, 0, OEMCrypto_CipherMode_CBC), + PatternTestVariant(3, 7, OEMCrypto_CipherMode_CBC), + // HLS Edge case. We should follow the CENC spec, not HLS spec. + PatternTestVariant(9, 1, OEMCrypto_CipherMode_CBC), + PatternTestVariant(1, 9, OEMCrypto_CipherMode_CBC), + // Pattern length should be 10, but that is not guaranteed. + PatternTestVariant(1, 3, OEMCrypto_CipherMode_CBC), + PatternTestVariant(2, 1, OEMCrypto_CipherMode_CBC) )); TEST_F(OEMCryptoSessionTests, DecryptSecureToClear) {