OEMCrypto v16.1
Merge of http://go/wvgerrit/93404 This CL updates the Widevine CDM to support OEMCrypto v16.1 Test: Tested in 16.2 CL Bug: 141247171 Change-Id: I69bd993500f6fb63bf6010c8b0250dc7acc3d71b
This commit is contained in:
@@ -177,6 +177,7 @@ class WvCdmEngineTest : public WvCdmEnginePreProvTest {
|
||||
CdmKeySetId key_set_id;
|
||||
|
||||
InitializationData init_data(init_data_type_string, key_id);
|
||||
if (g_cutoff >= LOG_DEBUG) init_data.DumpToLogs();
|
||||
|
||||
CdmKeyRequest key_request;
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ class MockCryptoSession : public TestCryptoSession {
|
||||
MOCK_METHOD0(GetSecurityLevel, CdmSecurityLevel());
|
||||
MOCK_METHOD0(Open, CdmResponseType());
|
||||
MOCK_METHOD1(Open, CdmResponseType(SecurityLevel));
|
||||
MOCK_METHOD1(LoadCertificatePrivateKey, CdmResponseType(std::string&));
|
||||
MOCK_METHOD1(LoadCertificatePrivateKey, CdmResponseType(const std::string&));
|
||||
MOCK_METHOD0(DeleteAllUsageReports, CdmResponseType());
|
||||
MOCK_METHOD1(GetUsageSupportType, CdmResponseType(CdmUsageSupportType* type));
|
||||
MOCK_METHOD0(GetUsageTableHeader, UsageTableHeader*());
|
||||
|
||||
362
libwvdrmengine/cdm/core/test/fake_provisioning_server.cpp
Normal file
362
libwvdrmengine/cdm/core/test/fake_provisioning_server.cpp
Normal file
@@ -0,0 +1,362 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#include "fake_provisioning_server.h"
|
||||
|
||||
#include "core_message_deserialize.h"
|
||||
#include "core_message_serialize.h"
|
||||
#include "core_message_serialize_proto.h"
|
||||
#include "crypto_session.h"
|
||||
#include "license_protocol.pb.h"
|
||||
#include "log.h"
|
||||
#include "oec_session_util.h"
|
||||
#include "oec_test_data.h"
|
||||
#include "privacy_crypto.h"
|
||||
#include "service_certificate.h"
|
||||
#include "string_conversions.h"
|
||||
|
||||
// TODO: refactor oec_session so that these are not needed.
|
||||
#include <gtest/gtest.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/cmac.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/x509_vfy.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace wvcdm {
|
||||
namespace {
|
||||
// This is a sample RSA private key, it pairs with the public fake service
|
||||
// certificate below.
|
||||
// From file test_rsa_key_2_carmichael.pk8 in team shared drive. Size is 1216.
|
||||
const std::string kPrivateKeyFakeServiceCert = a2bs_hex(
|
||||
"308204bc020100300d06092a864886f70d0101010500048204a6308204a2020100028201"
|
||||
"0100a700366065dcbd545a2a40b4e1159458114f9458dddea71f3c2ce08809296157675e"
|
||||
"567eee278f59349a2aaa9db44efaa76ad4c97a53c14e9fe334f73db7c910474f28da3fce"
|
||||
"317bfd0610ebf7be92f9affb3e68daee1a644cf329f2739e39d8f66fd8b28082718eb5a4"
|
||||
"f2c23ecd0acab604cd9a138b54735425548cbe987a67addab34eb3fa82a84a6798565754"
|
||||
"71cd127feda301c06a8b24039688be97662abc53c98306515a88651318e43aed6bf1615b"
|
||||
"4cc81ef4c2ae085e2d5ff8127fa2fcbb211830dafe40fb01ca2e370ecedd768782460b3a"
|
||||
"778fc072072c7f9d1e865bed2729df039762ef44d35b3ddb9c5e1b7b39b40b6d046bbbbb"
|
||||
"2c5fcfb37a050203010001028201000af94a1972881b4ed82fef999332da51212e1406f4"
|
||||
"e9651cf9d4cf1a5153cd48338c30eddd536f2982f9e074deb11301888fce14c13b90b7cc"
|
||||
"6cdf35a1f21a3dbe19d70ae46775bbfa87f403b57f69e40b6adc928254641a942de46340"
|
||||
"b2b4856bc834baa21430471aeb906230434402c70c30c07fa947aede682792aa1195f56f"
|
||||
"fc198b49a0779dc6135d73ff45a24c3bf3e12dd7c470e26c37994c7aa927f83ad6fdc5d8"
|
||||
"fa2d0e714b857ececb1c7971bdff63036b5868e014ca5e85fdd0b7e06814ff2c8222268a"
|
||||
"3fbfb02a90ffc772fc66513e519f82680ef3657488abb7e5975f0f3ee53abca4a150dd5c"
|
||||
"944b0c7071484ed0ec468fdfa29afed8351a2f02818100cf738cbe6d452d0c0b5d5c6c75"
|
||||
"78cc3548b698f1b964608c43eb85ab04b67d1b717506e2da84682e7f4ce373b4de514bb6"
|
||||
"51867bd0e64df3d1cf1afe7f3a83bab3e1ff541393d79c2780b71e649ef7322b4629f7f8"
|
||||
"186cf74abe4bee96908fa216226acc48067463437f2722443c2d3b62f11cb42733852660"
|
||||
"4816cbeff8cd3702818100ce15436e4b0ff93f87c3414597b149c2192387e4241c64e528"
|
||||
"cb431014140e19cbbbdbfd119d1768786d6170633aa1b3f3a75b0effb76111549199e591"
|
||||
"322deb3fd83ef7d4cbd2a341c1eec69213eb7f4258f4d0b2741d8e8746cd14b816adb5bd"
|
||||
"0d6c955a16bfe953dafbed835167a955ab54029520a6681753a8ea43e5b0a3028180679c"
|
||||
"32833957ff73b089648bd6f00a2de2af301c2a97f3909aab9b0b1b4379a0a73de7be8d9c"
|
||||
"ebdbad40dda90080b8e1b3a16c2592e433b2beeb4d74265f37439c6c17760a812082a148"
|
||||
"2c2d45dc0f624332bbeb5941f9ca58ce4a665354c828101e087116d802714158d456ccf5"
|
||||
"b131a3ed008509bf3595412940198335246902818055100bcc3ba9753d16e1ae50766394"
|
||||
"494cad10cb47687cf0e5dcb86aab8ef79f082c1b8aa2b98fceec5e61a8cd1c87604ac31a"
|
||||
"5fdf8726c6cb7c69e48b01065922fa344b81873c036d020a77e615d8cfa768266cfa2bd9"
|
||||
"835a2d0c3b701cd448bea70ad9bedcc30c2133b366ff1c1bc89676e86f4474bc9b1c7dc8"
|
||||
"ac21a86e370281802c7cad1e75f6691de7a6ca747d67c8652866c443a6bd4057aeb7652c"
|
||||
"52f9e4c7817b56a3d20de83370cf0684b34e4450756196864bb62badf0ad57d0370d1d35"
|
||||
"50cb69223929b93ad329230260f7ab3040da8e4d457026f4a20dd0645d473c18f4d45295"
|
||||
"00ae846b47b23c82d37253de722cf7c12236d91856fe392833e0db03");
|
||||
|
||||
// This is a fake service certificate.
|
||||
// From the team shared drive file
|
||||
// oem-7913-leaf-and-intermediate-certs-test-key-2-carmichael.p7b, size 2353.
|
||||
const std::string kPublicFakeServiceCert = a2bs_hex(
|
||||
"3082092d06092a864886f70d010702a082091e3082091a0201013100300f06092a864886"
|
||||
"f70d010701a0020400a08208fe3082037130820259a003020102021100c28d2022828b9e"
|
||||
"639d15892ca98fd95d300d06092a864886f70d01010b0500306b310b3009060355040613"
|
||||
"025553310b300906035504080c0257413111300f06035504070c084b69726b6c616e6431"
|
||||
"0f300d060355040a0c06476f6f676c653111300f060355040b0c085769646576696e6531"
|
||||
"18301606035504030c0f73797374656d2069643a2037393133301e170d31383031313131"
|
||||
"33323632325a170d3338303130363133323632325a30653112301006035504030c093739"
|
||||
"31332d6c656166310b3009060355040613025553310b300906035504080c025741311130"
|
||||
"0f06035504070c084b69726b6c616e64310f300d060355040a0c06476f6f676c65311130"
|
||||
"0f060355040b0c085769646576696e6530820122300d06092a864886f70d010101050003"
|
||||
"82010f003082010a0282010100a700366065dcbd545a2a40b4e1159458114f9458dddea7"
|
||||
"1f3c2ce08809296157675e567eee278f59349a2aaa9db44efaa76ad4c97a53c14e9fe334"
|
||||
"f73db7c910474f28da3fce317bfd0610ebf7be92f9affb3e68daee1a644cf329f2739e39"
|
||||
"d8f66fd8b28082718eb5a4f2c23ecd0acab604cd9a138b54735425548cbe987a67addab3"
|
||||
"4eb3fa82a84a679856575471cd127feda301c06a8b24039688be97662abc53c98306515a"
|
||||
"88651318e43aed6bf1615b4cc81ef4c2ae085e2d5ff8127fa2fcbb211830dafe40fb01ca"
|
||||
"2e370ecedd768782460b3a778fc072072c7f9d1e865bed2729df039762ef44d35b3ddb9c"
|
||||
"5e1b7b39b40b6d046bbbbb2c5fcfb37a050203010001a31630143012060a2b06010401d6"
|
||||
"79040101040402021ee9300d06092a864886f70d01010b050003820101008895eccd8ba7"
|
||||
"51da7481a539621a0e2ede3c37eaad7cee9b268ee2d634cdb770babfa0a3feb34bbcf41c"
|
||||
"726681d50933780c6121a8f1e2c9e283c21902f2e8ab17363a0b20af0fae2e7368ac15ee"
|
||||
"9cc092037e9563aaad159643203be59b1fca02baf0077680d7a31aebc8db037b4356e596"
|
||||
"6b86fe08588a84bde94718eeb2a8057bf0fdaab985cd7a0e6b6c9fc675d22afe5bf3b731"
|
||||
"6cace3009fe7dde381c136c31c5fdff2c35efa5532d85ca8e5ccb64ae9e2cc3844074659"
|
||||
"348479f9ee3c4b4890ab73b0a192c3d6838781ca1281d65df76f7a355e4f02668a478882"
|
||||
"abf0121db9753b7ba83615efa8120e53b4837853c052aea60aa053dc1c1522dd17983082"
|
||||
"05853082036da003020102021003b1f758df1de325000b103dd5e6e464300d06092a8648"
|
||||
"86f70d01010b0500307e310b30090603550406130255533113301106035504080c0a5761"
|
||||
"7368696e67746f6e3111300f06035504070c084b69726b6c616e64310f300d060355040a"
|
||||
"0c06476f6f676c653111300f060355040b0c085769646576696e65312330210603550403"
|
||||
"0c1a7769646576696e652e636f6d2f6f656d2d726f6f742d70726f64301e170d31373131"
|
||||
"31383031313333355a170d3237313131383031313331335a306b310b3009060355040613"
|
||||
"025553310b300906035504080c0257413111300f06035504070c084b69726b6c616e6431"
|
||||
"0f300d060355040a0c06476f6f676c653111300f060355040b0c085769646576696e6531"
|
||||
"18301606035504030c0f73797374656d2069643a203739313330820122300d06092a8648"
|
||||
"86f70d01010105000382010f003082010a0282010100aec871ae080c06062d817ca98bb3"
|
||||
"d666e4f6085e5a75e874617a88ca85140d58a409196c60c9ad911cbf04b34710637f0258"
|
||||
"c21ebdcc0777aa7e14a8c201cde84660536f2fda172d4d9d0e5db55095aeab6e43e3b000"
|
||||
"12b405824a2b14630d1f0612aae19de7badae3fc7c6c73ae56f8abf7519331ef8fe4b601"
|
||||
"2ceb7be4d8b3ea70378905a9515772989ea846dbeb7a382b2fc027b7c2e19a17dff5d69c"
|
||||
"d58cb86642d5041e7c364c1e3e45514d417222533df4577c6c33342445df84874aa6cb7c"
|
||||
"03a3aa8e2d8201278774821abc0f7669abe04e70be37fcc82c91174fd5263b7b90b52d64"
|
||||
"baf7d28ab48f389d8ebae75c52f10ab8c01bb6b1707e475994590203010001a382011030"
|
||||
"82010c30120603551d130101ff040830060101ff020100300e0603551d0f0101ff040403"
|
||||
"020204301d0603551d0e041604144bcbdfaa02de8dc3e7e585db2e8abe756b8a67583081"
|
||||
"b20603551d230481aa3081a78014049466aaf96189b6dbb5f713383d6284b8180a8fa181"
|
||||
"83a48180307e310b30090603550406130255533113301106035504080c0a57617368696e"
|
||||
"67746f6e3111300f06035504070c084b69726b6c616e64310f300d060355040a0c06476f"
|
||||
"6f676c653111300f060355040b0c085769646576696e653123302106035504030c1a7769"
|
||||
"646576696e652e636f6d2f6f656d2d726f6f742d70726f64820900df86053101be9a9a30"
|
||||
"12060a2b06010401d679040101040402021ee9300d06092a864886f70d01010b05000382"
|
||||
"020100613f2f43e4be6634ef9206e988ba6a1d4f545a97b175d793f845c6839236fd55a9"
|
||||
"210bdcf6ae11dc622144bd041d582c03f8e4e21ebae6dd19dd56fdce06735f941eb603db"
|
||||
"3d7babab72647bde7d4dcf7ef09129c17713c26f80ab7aa8ceb01c2ac59cfb0be59f9c1b"
|
||||
"c94b58df9618f7676789a4e91448acfa9d862aeb752c2bbf637dc74e7ead392db47c07a5"
|
||||
"5ae83ad4f50c4ff3a29c3c32ed9d4b4905bc1fa013e6dd827906313bc697ec8daa4fef14"
|
||||
"3c21f672b20942c774feef70bde98541300bb36b590c0f1175d4bbb1dfb1dfb3fab33a43"
|
||||
"177d8a82aea207f88351fb16fb64b646dabe322bc0ee782a84a9540af92d6165dea59766"
|
||||
"7902f89717e2d49f9eacccae999a0304bb45feb2f580babfdd24e5e61e5d36a5870cdf60"
|
||||
"816fb75fb91fca753c1a63b0ebe695860daea6c92a94f1d0be75c8f807d788ffecf9cd49"
|
||||
"c6fe4d7f441ed8afa9722798e25a08ea55d3b3eadc7669511001467d33949c94effe761c"
|
||||
"c6d715533e8d3d299a586af1759eea1b4cf04776acc6a2324440dffeff9df4e2c2faa15f"
|
||||
"2e66e997cb27266e53e4e8862cead3696c614ffec1c98b05926f4796cef033fa7c78249b"
|
||||
"d78d36563786bc725af9b9b093f0817810f2b0c279915ecfbc8cf2320ff72d30d813774f"
|
||||
"789e408de63a98b2aa134d2549346c809e1903dbcdf5b154741b673c46ac3e5da2d91383"
|
||||
"30eb823b06ab3c397dd0683100");
|
||||
|
||||
// This is a private RSA key that is paired with the DRM certificate below.
|
||||
const std::string kPrivateKeySampleDRMCert = a2bs_hex(
|
||||
"308204BC020100300D06092A864886F70D0101010500048204A6308204A202010002820101"
|
||||
"00E68EAD7C67ED983A72C89BC55054D26821C3399702E7906B77C7E09AE607D40B0013484B"
|
||||
"0C557A810E19A814B4F14D55E60456EE21BC19F29EFFDA416BC9CBF0CE2C684E5A44F77008"
|
||||
"038E0666EE7995166381E00F7EB2C38845F5CD2B790D35570D07D7EE225ED94A5D9421EE60"
|
||||
"BCD075ADFBA71F4E7363DB5E0B1E05352F6945A3A1F0E41899A3BF1DE322FEECCCD577225B"
|
||||
"CB79550D0014343EA64312EB32919B6E8D6EC1E349FA54074D829E80C8CE7E1E713AB50917"
|
||||
"A4AC98C898A85F7C267417D35180CF1BF3E6CABE04C8AC6422F36137FAD800A83EABB8C970"
|
||||
"C4248435F1B4C9C659865864BC714AF4D9A425F28626BEF9DB3A42510135FF2B69213F0203"
|
||||
"010001028201000C5D9CAA6E7C8CCC9DB96AB9637C9928629F30E88B8C55EF9DA607C2E711"
|
||||
"866AEC9F1C22824FD75932A367A36CAD0083D9E963AC33FCFDBB4891DA67E5DB15E81D76BE"
|
||||
"456D8C03656BD89CF674F0D76E8A9BDDAC61C85ED823E7F4AE0365E3B277AFC83AE997C854"
|
||||
"892B89B5642EA611DC2DEFB05FFA7A2FE1E5225D82D3FE6DE1F1B3DE0A5386E1F75FE21E20"
|
||||
"E38A517FDFF1598BF9C2210EDDED222D9C6045494015E7FDC76084E57D2A58184E8F84153D"
|
||||
"BD1CC5E0C2FB84085EEAA42A046205AA1B0BDC30DCF077941AC001C03BEE1E6F3F8E0D6A95"
|
||||
"1C9672B54C11F3BBAB5F9F18816F32A7E3A1F1755CDEA30C2805D21C90891B6B1CC9601B0B"
|
||||
"DE8601A902818100F41622BA193DF0D70D76FB47D38BFA711D52530DDC438B7F4A88685B60"
|
||||
"B5D4A1937E8B63EC6FF4EA650BF129A7649A2A5376622AE2D5B4AD2064FC9E0A05C28D0510"
|
||||
"412DDF5660BB008C4340965B80CC0A9CCA559B783179B6ECA6952999A86B8CECCE1582C3E0"
|
||||
"E603E357D2FF59181EA3E3A25361C4E287DEB192132A4C2E2D02818100F1CF7ECBB795E456"
|
||||
"D5C976E512EE63C25C79A3FAE9CF4B8C838950B69E97373819E838266678CD11DF45E9E9B0"
|
||||
"A53183D79C6E1713A9F47A51E39DFC730EA76B3B0460E1A8E1BC932A84875610F79267C81F"
|
||||
"F794E1FC80A8687AFE3120CC6A3EBAC1735FDFF20FE7809879F205F7C933845FC6B8D18DD7"
|
||||
"88031B3E8B19155C9B028180510FCCE6AB1D640FB79C0D25B47EE7648B8D5CA1DCC5DDDD1F"
|
||||
"5E9FF1C0F382334AED9AD34BA17EE01D40D30DB756F4D01BB9D42E53F90F30F3F235E73282"
|
||||
"E932B63CC8B8B8545279A85BECB5D5797C13C76E7CCFE37B0E4B52D1D31CF49CE04F1F9541"
|
||||
"77E95EAE2115A779F24BF545CA5F39691E71F8D616B3819B769BF482DD028180491A86E5C5"
|
||||
"B1BE1F76707ACE5443D7CAF9B4189C11B586CC8B33A7401E7FEEC4BA2857595C9F66B7E17D"
|
||||
"3C7356E10A3026ADF72668DE77B7C72BFE26450E8814C5F9D3E444EF41D868013AFD0D121B"
|
||||
"A3DE7FB394C221593010AE264CE9F282A8464397C2C36C65DC822716AED19910ADCF763918"
|
||||
"C4D991F05FA80BE77784DAC30281800C5FDD98BB2EF766B9D43784CC2FC22FC27D6F41BDCA"
|
||||
"9A4EFB0197FFD599C3528B31E42B12BBA3788019C9B546F66B22C8AE91BAB5B4D86FF46C2F"
|
||||
"6AF3D579C834A301AE61E0C01CA914D8C4DAA3AE0DA92ABEC1122A78055E8B257D0658E080"
|
||||
"BC7C1184BDDA1133EB9951A1E80F2A4F2DC01A01A6035337DADE95E7B77394CB");
|
||||
|
||||
// This is a DRM certificate that was intercepted from a provisioning response
|
||||
// from the production server to a device with the test keybox.
|
||||
const std::string kPublicSampleDRMCert = a2bs_hex(
|
||||
"0ABC02080212107CB49F987A635E1E0A52184694582D6E18A2C99EEC05228E023082010A02"
|
||||
"82010100E68EAD7C67ED983A72C89BC55054D26821C3399702E7906B77C7E09AE607D40B00"
|
||||
"13484B0C557A810E19A814B4F14D55E60456EE21BC19F29EFFDA416BC9CBF0CE2C684E5A44"
|
||||
"F77008038E0666EE7995166381E00F7EB2C38845F5CD2B790D35570D07D7EE225ED94A5D94"
|
||||
"21EE60BCD075ADFBA71F4E7363DB5E0B1E05352F6945A3A1F0E41899A3BF1DE322FEECCCD5"
|
||||
"77225BCB79550D0014343EA64312EB32919B6E8D6EC1E349FA54074D829E80C8CE7E1E713A"
|
||||
"B50917A4AC98C898A85F7C267417D35180CF1BF3E6CABE04C8AC6422F36137FAD800A83EAB"
|
||||
"B8C970C4248435F1B4C9C659865864BC714AF4D9A425F28626BEF9DB3A42510135FF2B6921"
|
||||
"3F020301000128E83D3A0C7769646576696E652E636F6D1280028F1B043BBFFF8B126F970C"
|
||||
"9F0722C19DCDDD9A02146A8527249DC7CB78FEC38AF92935B37003B3B47D492A94E8787D40"
|
||||
"86C6E754D4EB77A8C92F721A6516D7F91A308E8CE2EC4712C4FAA3ADB3482A63D816B10902"
|
||||
"245D96B38D61F5D0053FC0302B338763F9CB1F3E843BDDE2B520770872F844E8C6BD8C611A"
|
||||
"FA81EA5542BF0312335FC13ACC0679747BBC2F44459CDAA7241B119BE0158A0A90A2567C8B"
|
||||
"096D733727E22B0CA24E248A94649F1F4D80CF588115E6675DF01C0192A4D0C5E6FCE326E4"
|
||||
"2368DE6BF572D97D1AF140AC7DECDF8DC41A0276437D52AFDA2F7A6E76DA2B4466EBC63AA9"
|
||||
"EA827DAC355B815D306A431CEEDF1D9C62E478E33B4CC41AB4050AAE020801121065802C9B"
|
||||
"625E5A319C33DC1CB7C3C6D418E3A5BDD005228E023082010A0282010100B80502043C2A8A"
|
||||
"0FD8D25C613E1E3E3B5E349F332F04516A7510D38021A5629B9AA027AEAD3C759B7AFE70BE"
|
||||
"D65F3DF6860FF5EB60B983A3FFA33FDE06F3B73014DFC845AB371C6600562E9D904F842B8B"
|
||||
"A4A5D9200FFA3ED45D705520A5C372A889F9E314386234C6897AE655851FCD9ADB4EF9126C"
|
||||
"78386EA93BCB25BA3EC475C55C608E771C763AB02506F9B07252D6ABF7EA64B1EBDE7B95C6"
|
||||
"407690533BD6890B9274C16066F74FC401EA355F0A02106814D49BF0C89E6E1F8DB2A47841"
|
||||
"CD0DAD793296A107C36223404F2BF1FCA16FD0A4B982634DB62407F8F14ACAE3B05A038BD3"
|
||||
"E4BBBAE4391BBFA7A47FB9D01DE857EA88E5E36EE36E245859FC0F020301000128E83D1280"
|
||||
"037E06581A019184AB572AFDCADDD03F161CE68200F8E6F8AD161947360BC8D49C0D68009B"
|
||||
"1C4644F9B3F3FB6DDFD92EF92DE62D41D459D29D81BFAEF3970A3A39D25B2662ECB03B2DA7"
|
||||
"B68302FAA6DD98D95A143CC8C1CB6ADDA76D2EE9C3723FAF95A29CDC3E968B6821A91C051C"
|
||||
"A280A86669710A1AD7A44BF9218027460DF694E2E9270396DF221963F21EE6AA220A5EE4A4"
|
||||
"D0FEB3D53EB5732F8F91E9A96B3B8BE284C51339EA284D4D0EDD55B6AD56F7416420E05E05"
|
||||
"9F9734A96BE25AA44560DBA8C38755A42A82BD7F88EDD19DF346A667B33B8114C76A8838C4"
|
||||
"23D824A50B23251A088136D6E8F475299D2AFD46CEA51B5CBDF789A572125CD24FBB813B38"
|
||||
"7A10CD2A30E3447634AB3408F96B9CF3D98896D405F3F540D9C57962760FCD177CDD101EB8"
|
||||
"A4148B9C29CED5EAD645A95B698F1CDC6E1DB6678B85074186080D68D13CD37E07B16DE370"
|
||||
"CD9AFB9B25564A73A30E2AF8085EA37D310C474F0E67AC00CA992A5296FAEDAD7AA06ECD79"
|
||||
"0F1E3D426558FA98383E3CD2ED4830");
|
||||
} // namespace
|
||||
|
||||
FakeProvisioningServer::FakeProvisioningServer() {
|
||||
// Generate a service certificate that can convince the CDM we are a real
|
||||
// provisioning server. it only works if the CDM is compiled with the symbol
|
||||
// ACCEPT_TEST_CERT defined.
|
||||
video_widevine::DrmDeviceCertificate cert;
|
||||
cert.set_type(video_widevine::DrmDeviceCertificate_CertificateType_SERVICE);
|
||||
|
||||
cert.set_public_key(kPublicFakeServiceCert);
|
||||
cert.set_serial_number("Serial Number 007");
|
||||
cert.set_provider_id("Unit Test Provider");
|
||||
|
||||
std::string serialized_cert;
|
||||
cert.SerializeToString(&serialized_cert);
|
||||
|
||||
video_widevine::SignedDrmDeviceCertificate signed_cert;
|
||||
signed_cert.set_drm_certificate(serialized_cert);
|
||||
signed_cert.SerializeToString(&service_certificate_);
|
||||
}
|
||||
|
||||
bool FakeProvisioningServer::MakeResponse(
|
||||
const std::string& serialized_signed_request, std::string* json_response) {
|
||||
if (json_response == nullptr) {
|
||||
LOGE("json_response is jullptr.");
|
||||
return false;
|
||||
}
|
||||
json_response->clear();
|
||||
|
||||
// First, parse the signed request and the request.
|
||||
video_widevine::SignedProvisioningMessage signed_request;
|
||||
if (!signed_request.ParseFromString(serialized_signed_request)) {
|
||||
LOGE("Failed to parse signed provisioning request");
|
||||
return false;
|
||||
}
|
||||
std::string serialized_message = signed_request.message();
|
||||
video_widevine::ProvisioningRequest provisioning_request;
|
||||
if (!provisioning_request.ParseFromString(serialized_message)) {
|
||||
LOGE("Failed to parse provisioning request");
|
||||
return false;
|
||||
}
|
||||
std::string request_signature = signed_request.signature();
|
||||
LOGD("Requested certificate type %s",
|
||||
provisioning_request.options().certificate_type() ==
|
||||
video_widevine::ProvisioningOptions::WIDEVINE_DRM
|
||||
? "WIDEVINE_DRM"
|
||||
: "X509");
|
||||
|
||||
video_widevine::SignedProvisioningMessage::ProtocolVersion version =
|
||||
signed_request.protocol_version();
|
||||
LOGD("Request uses protocol version: %d", version);
|
||||
if (version != video_widevine::SignedProvisioningMessage::PROVISIONING_20) {
|
||||
LOGE("Fake provisioning server only handles Keyboxes");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Next, we derive the keys from the keybox device key. This is Provisioning
|
||||
// 2.0 specific.
|
||||
// TODO(b/141438127): Add support for provisioing 3.0.
|
||||
std::string mac_context;
|
||||
GenerateMacContext(serialized_message, &mac_context);
|
||||
std::vector<uint8_t> mac_context_v(mac_context.begin(), mac_context.end());
|
||||
std::string enc_context;
|
||||
GenerateEncryptContext(serialized_message, &enc_context);
|
||||
std::vector<uint8_t> enc_context_v(enc_context.begin(), enc_context.end());
|
||||
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,
|
||||
enc_context_v);
|
||||
|
||||
// Create a structure to hold the RSA private key. This is used by the key
|
||||
// deriver to encrypt the key.
|
||||
wvoec::RSAPrivateKeyMessage clear_rsa_key;
|
||||
if (sizeof(clear_rsa_key.rsa_key) < kPrivateKeySampleDRMCert.size()) {
|
||||
LOGE("Private key too big");
|
||||
return false;
|
||||
}
|
||||
memcpy(clear_rsa_key.rsa_key, kPrivateKeySampleDRMCert.data(),
|
||||
kPrivateKeySampleDRMCert.size());
|
||||
clear_rsa_key.rsa_key_length = kPrivateKeySampleDRMCert.size();
|
||||
wvoec::RSAPrivateKeyMessage encrypted_rsa_key;
|
||||
key_deriver.PadAndEncryptProvisioningMessage(&clear_rsa_key,
|
||||
&encrypted_rsa_key);
|
||||
|
||||
// Fill out the provisioning response with the public DRM cert, and the
|
||||
// encrypted private RSA key.
|
||||
video_widevine::ProvisioningResponse provisioning_response;
|
||||
provisioning_response.set_device_certificate(kPublicSampleDRMCert);
|
||||
provisioning_response.set_device_rsa_key(std::string(
|
||||
encrypted_rsa_key.rsa_key,
|
||||
encrypted_rsa_key.rsa_key + encrypted_rsa_key.rsa_key_length));
|
||||
provisioning_response.set_device_rsa_key_iv(std::string(
|
||||
encrypted_rsa_key.rsa_key_iv,
|
||||
encrypted_rsa_key.rsa_key_iv + sizeof(encrypted_rsa_key.rsa_key_iv)));
|
||||
provisioning_response.set_nonce(provisioning_request.nonce());
|
||||
|
||||
// Sign the response.
|
||||
video_widevine::SignedProvisioningMessage signed_response;
|
||||
signed_response.set_protocol_version(signed_request.protocol_version());
|
||||
std::string message;
|
||||
provisioning_response.SerializeToString(&message);
|
||||
signed_response.set_message(message);
|
||||
|
||||
if (signed_request.has_oemcrypto_core_message()) {
|
||||
// If the request has a core message, then the response should also have a
|
||||
// core message.
|
||||
std::string core_request = signed_request.oemcrypto_core_message();
|
||||
oemcrypto_core_message::ODK_ProvisioningRequest core_request_data;
|
||||
if (!oemcrypto_core_message::deserialize::
|
||||
CoreProvisioningRequestFromMessage(core_request,
|
||||
&core_request_data)) {
|
||||
LOGE("Core request did not parse.");
|
||||
return false;
|
||||
}
|
||||
std::string core_response;
|
||||
oemcrypto_core_message::serialize::CreateCoreProvisioningResponseFromProto(
|
||||
message, core_request_data, &core_response);
|
||||
signed_response.set_oemcrypto_core_message(core_response);
|
||||
// Also, the signature should be over the concatenation of the core message
|
||||
// and the message body. This is done to ensure that neither the message
|
||||
// body, nor the oemcrypto core message are tampered with. See "Widevine
|
||||
// Core Message Serialization" for details.
|
||||
message = core_response + message;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> signature_v;
|
||||
key_deriver.ServerSignBuffer(reinterpret_cast<const uint8_t*>(message.data()),
|
||||
message.size(), &signature_v);
|
||||
std::string signature(signature_v.begin(), signature_v.end());
|
||||
signed_response.set_signature(signature);
|
||||
|
||||
// Finally, base 64 encode and surround with just enough fake json to fool the
|
||||
// CDM.
|
||||
std::string response_data;
|
||||
signed_response.SerializeToString(&response_data);
|
||||
std::vector<uint8_t> response_data_v(response_data.begin(),
|
||||
response_data.end());
|
||||
static const std::string json_start = "{ \"signedResponse\": \"";
|
||||
static const std::string json_end = "\" }";
|
||||
*json_response = json_start + Base64SafeEncode(response_data_v) + json_end;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
32
libwvdrmengine/cdm/core/test/fake_provisioning_server.h
Normal file
32
libwvdrmengine/cdm/core/test/fake_provisioning_server.h
Normal file
@@ -0,0 +1,32 @@
|
||||
// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
|
||||
#ifndef WVCDM_CORE_FAKE_PROVISIONING_SERVER_H_
|
||||
#define WVCDM_CORE_FAKE_PROVISIONING_SERVER_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "config_test_env.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
// A fake provisioning server. This can be used to generate custom made
|
||||
// provisioning responses.
|
||||
class FakeProvisioningServer {
|
||||
public:
|
||||
FakeProvisioningServer();
|
||||
|
||||
// Get the service certificate for this server.
|
||||
const std::string& service_certificate() { return service_certificate_; }
|
||||
// Make a response for this request. Returns true on success.
|
||||
bool MakeResponse(const std::string& serialized_signed_request,
|
||||
std::string* json_response);
|
||||
|
||||
private:
|
||||
std::string service_certificate_;
|
||||
};
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // WVCDM_CORE_FAKE_PROVISIONING_SERVER_H_
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "crypto_session.h"
|
||||
#include "initialization_data.h"
|
||||
#include "license.h"
|
||||
#include "mock_clock.h"
|
||||
#include "policy_engine.h"
|
||||
#include "properties.h"
|
||||
#include "service_certificate.h"
|
||||
@@ -112,6 +113,7 @@ const std::string kLicenseRequestSignature = a2bs_hex(
|
||||
"8D24103EB15C63C227A0D57A9D90F5A409D2D55147EE10A35AE291D2D725C7F161FF827221"
|
||||
"9AE18B91516E0CDD0B581590DDDEA2A2527E2C9ABA273629B586A9D22D451A827E332CFC3E"
|
||||
"9BEDB6CF3D8713F9E11675DF1F5DB9038DBBECAB9D1683F8722CAF6E18EC8C04AEE5");
|
||||
const std::string kFakeCoreMessage = a2bs_hex("DEADBEEF");
|
||||
|
||||
const CryptoSession::SupportedCertificateTypes kDefaultSupportedCertTypes = {
|
||||
true, true, true};
|
||||
@@ -142,8 +144,8 @@ class MockCryptoSession : public TestCryptoSession {
|
||||
MOCK_METHOD1(GetSupportedCertificateTypes, bool(SupportedCertificateTypes*));
|
||||
MOCK_METHOD1(GetApiVersion, bool(uint32_t*));
|
||||
MOCK_METHOD1(GenerateNonce, CdmResponseType(uint32_t*));
|
||||
MOCK_METHOD3(PrepareRequest,
|
||||
CdmResponseType(const std::string&, bool, std::string*));
|
||||
MOCK_METHOD3(PrepareAndSignLicenseRequest,
|
||||
CdmResponseType(const std::string&, std::string*, std::string*));
|
||||
MOCK_METHOD1(LoadEntitledContentKeys,
|
||||
CdmResponseType(const std::vector<CryptoKey>& key_array));
|
||||
MOCK_METHOD1(GetResourceRatingTier, bool(uint32_t*));
|
||||
@@ -158,11 +160,6 @@ class MockPolicyEngine : public PolicyEngine {
|
||||
void(const std::vector<video_widevine::WidevinePsshData_EntitledKey>&));
|
||||
};
|
||||
|
||||
class MockClock : public Clock {
|
||||
public:
|
||||
MOCK_METHOD0(GetCurrentTime, int64_t());
|
||||
};
|
||||
|
||||
class MockInitializationData : public InitializationData {
|
||||
public:
|
||||
MockInitializationData(const std::string& type, const CdmInitData& data)
|
||||
@@ -326,9 +323,11 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
EXPECT_CALL(*clock_, GetCurrentTime()).WillOnce(Return(kLicenseStartTime));
|
||||
EXPECT_CALL(*crypto_session_, GenerateNonce(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kNonce), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*crypto_session_, PrepareRequest(_, Eq(false), NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<2>(kLicenseRequestSignature), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
PrepareAndSignLicenseRequest(_, NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kFakeCoreMessage),
|
||||
SetArgPointee<2>(kLicenseRequestSignature),
|
||||
Return(NO_ERROR)));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, kEmptyString,
|
||||
@@ -353,6 +352,8 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidation) {
|
||||
EXPECT_TRUE(std::equal(signed_message.signature().begin(),
|
||||
signed_message.signature().end(),
|
||||
kLicenseRequestSignature.begin()));
|
||||
EXPECT_TRUE(signed_message.has_oemcrypto_core_message());
|
||||
EXPECT_EQ(kFakeCoreMessage, signed_message.oemcrypto_core_message());
|
||||
EXPECT_TRUE(!signed_message.msg().empty());
|
||||
|
||||
// Verify license request
|
||||
@@ -447,9 +448,11 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
||||
EXPECT_CALL(*clock_, GetCurrentTime()).WillOnce(Return(kLicenseStartTime));
|
||||
EXPECT_CALL(*crypto_session_, GenerateNonce(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kNonce), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*crypto_session_, PrepareRequest(_, Eq(false), NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<2>(kLicenseRequestSignature), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
PrepareAndSignLicenseRequest(_, NotNull(), NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kFakeCoreMessage),
|
||||
SetArgPointee<2>(kLicenseRequestSignature),
|
||||
Return(NO_ERROR)));
|
||||
|
||||
CreateCdmLicense();
|
||||
EXPECT_TRUE(cdm_license_->Init(kToken, kClientTokenDrmCert, kEmptyString,
|
||||
@@ -474,6 +477,8 @@ TEST_F(CdmLicenseTest, PrepareKeyRequestValidationV15) {
|
||||
EXPECT_TRUE(std::equal(signed_message.signature().begin(),
|
||||
signed_message.signature().end(),
|
||||
kLicenseRequestSignature.begin()));
|
||||
EXPECT_TRUE(signed_message.has_oemcrypto_core_message());
|
||||
EXPECT_EQ(kFakeCoreMessage, signed_message.oemcrypto_core_message());
|
||||
EXPECT_TRUE(!signed_message.msg().empty());
|
||||
|
||||
// Verify license request
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine Master
|
||||
// License Agreement.
|
||||
// This file adds some print methods so that when unit tests fail, the
|
||||
// will print the name of an enumeration instead of the numeric value.
|
||||
|
||||
#include "test_base.h"
|
||||
|
||||
@@ -17,7 +15,9 @@
|
||||
#include <vector>
|
||||
|
||||
#include "cdm_engine.h"
|
||||
#include "clock.h"
|
||||
#include "crypto_session.h"
|
||||
#include "fake_provisioning_server.h"
|
||||
#include "file_store.h"
|
||||
#include "license.h"
|
||||
#include "log.h"
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "platform.h"
|
||||
#include "properties.h"
|
||||
#include "test_printers.h"
|
||||
#include "test_sleep.h"
|
||||
#include "url_request.h"
|
||||
|
||||
using wvcdm::metrics::EngineMetrics;
|
||||
@@ -98,6 +99,11 @@ void show_menu(const char* prog_name, const std::string& extra_help_text) {
|
||||
<< " in the url" << std::endl
|
||||
<< std::endl;
|
||||
|
||||
std::cout << " --fake_sleep" << std::endl;
|
||||
std::cout << " Use a fake clock to sleep for duration tests. This cannot"
|
||||
<< " be used with a real OEMCrypto." << std::endl
|
||||
<< std::endl;
|
||||
|
||||
std::cout << extra_help_text << std::endl;
|
||||
}
|
||||
|
||||
@@ -201,7 +207,7 @@ CdmResponseType TestCryptoSession::GenerateNonce(uint32_t* nonce) {
|
||||
for (int i = 0; status != NO_ERROR; i++) {
|
||||
LOGV("Recovering from nonce flood.");
|
||||
if (i > 2) return status;
|
||||
sleep(1);
|
||||
TestSleep::Sleep(1);
|
||||
status = CryptoSession::GenerateNonce(nonce);
|
||||
}
|
||||
return NO_ERROR;
|
||||
@@ -273,104 +279,127 @@ void WvCdmTestBase::Provision() {
|
||||
CdmSessionId session_id;
|
||||
FileSystem file_system;
|
||||
|
||||
// TODO(fredgc): provision for different SPOIDs.
|
||||
CdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
if (config_.provisioning_server() == "fake") {
|
||||
LOGD("Using fake provisioning server.");
|
||||
|
||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||
cert_type, cert_authority, config_.provisioning_service_certificate(),
|
||||
&prov_request, &provisioning_server_url);
|
||||
ASSERT_EQ(NO_ERROR, result);
|
||||
|
||||
if (binary_provisioning_) {
|
||||
binary_prov_request = prov_request;
|
||||
prov_request = std::string(Base64SafeEncodeNoPad(std::vector<uint8_t>(
|
||||
binary_prov_request.begin(), binary_prov_request.end())));
|
||||
}
|
||||
|
||||
LOGV("Provisioning request: req = %s", prov_request.c_str());
|
||||
|
||||
// Ignore URL provided by CdmEngine. Use ours, as configured
|
||||
// for test vs. production server.
|
||||
provisioning_server_url.assign(config_.provisioning_server());
|
||||
|
||||
// TODO(b/139361531): Remove loop once provisioning service is stable.
|
||||
std::string http_message;
|
||||
size_t attempt_num = 0;
|
||||
bool provision_success = false;
|
||||
do {
|
||||
if (attempt_num > 0) {
|
||||
// Sleep between attempts.
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
CdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
FakeProvisioningServer server;
|
||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||
cert_type, cert_authority, server.service_certificate(), &prov_request,
|
||||
&provisioning_server_url);
|
||||
ASSERT_EQ(NO_ERROR, result);
|
||||
if (!binary_provisioning_) {
|
||||
std::vector<uint8_t> prov_request_v = Base64SafeDecode(prov_request);
|
||||
prov_request = std::string(prov_request_v.begin(), prov_request_v.end());
|
||||
}
|
||||
++attempt_num;
|
||||
std::string response;
|
||||
ASSERT_TRUE(server.MakeResponse(prov_request, &response))
|
||||
<< "Fake provisioning server could not provision";
|
||||
result =
|
||||
cdm_engine.HandleProvisioningResponse(response, &cert, &wrapped_key);
|
||||
EXPECT_EQ(NO_ERROR, result);
|
||||
} else {
|
||||
// TODO(fredgc): provision for different SPOIDs.
|
||||
CdmEngine cdm_engine(&file_system,
|
||||
std::shared_ptr<EngineMetrics>(new EngineMetrics));
|
||||
|
||||
// Make request.
|
||||
UrlRequest url_request(provisioning_server_url);
|
||||
if (!url_request.is_connected()) {
|
||||
LOGE("Failed to connect to provisioning server: url = %s",
|
||||
provisioning_server_url.c_str());
|
||||
continue;
|
||||
}
|
||||
url_request.PostCertRequestInQueryString(prov_request);
|
||||
|
||||
// Receive and parse response.
|
||||
if (!url_request.GetResponse(&http_message)) {
|
||||
LOGE("Failed to get provisioning response");
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGV("http_message: \n%s\n", http_message.c_str());
|
||||
CdmResponseType result = cdm_engine.GetProvisioningRequest(
|
||||
cert_type, cert_authority, config_.provisioning_service_certificate(),
|
||||
&prov_request, &provisioning_server_url);
|
||||
ASSERT_EQ(NO_ERROR, result);
|
||||
|
||||
if (binary_provisioning_) {
|
||||
// extract provisioning response from received message
|
||||
// Extracts signed response from JSON string, result is serialized
|
||||
// protobuf.
|
||||
static const std::string kMessageStart = "\"signedResponse\": \"";
|
||||
static const std::string kMessageEnd = "\"";
|
||||
std::string protobuf_response;
|
||||
if (!ExtractSignedMessage(http_message, kMessageStart, kMessageEnd,
|
||||
&protobuf_response)) {
|
||||
LOGE("Failed to extract signed serialized response from JSON response");
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGV("Extracted response message: \n%s\n", protobuf_response.c_str());
|
||||
|
||||
// base64 decode response to yield binary protobuf
|
||||
std::vector<uint8_t> response_vec(Base64SafeDecode(protobuf_response));
|
||||
if (response_vec.empty() && !protobuf_response.empty()) {
|
||||
LOGE("Failed to decode base64 of response: response = %s",
|
||||
protobuf_response.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string binary_protobuf_response(response_vec.begin(),
|
||||
response_vec.end());
|
||||
|
||||
if (cdm_engine.HandleProvisioningResponse(binary_protobuf_response, &cert,
|
||||
&wrapped_key) != NO_ERROR) {
|
||||
LOGE("Failed to handle provisioning response");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (cdm_engine.HandleProvisioningResponse(http_message, &cert,
|
||||
&wrapped_key) != NO_ERROR) {
|
||||
LOGE("Failed to handle binary provisioning response");
|
||||
continue;
|
||||
}
|
||||
binary_prov_request = prov_request;
|
||||
prov_request = std::string(Base64SafeEncodeNoPad(std::vector<uint8_t>(
|
||||
binary_prov_request.begin(), binary_prov_request.end())));
|
||||
}
|
||||
provision_success = true;
|
||||
} while (attempt_num <= kDefaultMaxProvisioningAttempts &&
|
||||
!provision_success);
|
||||
|
||||
if (attempt_num > 1) {
|
||||
LOGW("Provisioning request failed at least once: attempts = %zu",
|
||||
attempt_num);
|
||||
LOGV("Provisioning request: req = %s", prov_request.c_str());
|
||||
|
||||
// Ignore URL provided by CdmEngine. Use ours, as configured
|
||||
// for test vs. production server.
|
||||
provisioning_server_url.assign(config_.provisioning_server());
|
||||
|
||||
// TODO(b/139361531): Remove loop once provisioning service is stable.
|
||||
std::string http_message;
|
||||
size_t attempt_num = 0;
|
||||
bool provision_success = false;
|
||||
do {
|
||||
if (attempt_num > 0) {
|
||||
// Sleep between attempts.
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
}
|
||||
++attempt_num;
|
||||
|
||||
// Make request.
|
||||
UrlRequest url_request(provisioning_server_url);
|
||||
if (!url_request.is_connected()) {
|
||||
LOGE("Failed to connect to provisioning server: url = %s",
|
||||
provisioning_server_url.c_str());
|
||||
continue;
|
||||
}
|
||||
url_request.PostCertRequestInQueryString(prov_request);
|
||||
|
||||
// Receive and parse response.
|
||||
if (!url_request.GetResponse(&http_message)) {
|
||||
LOGE("Failed to get provisioning response");
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGV("http_message: \n%s\n", http_message.c_str());
|
||||
|
||||
if (binary_provisioning_) {
|
||||
// extract provisioning response from received message
|
||||
// Extracts signed response from JSON string, result is serialized
|
||||
// protobuf.
|
||||
static const std::string kMessageStart = "\"signedResponse\": \"";
|
||||
static const std::string kMessageEnd = "\"";
|
||||
std::string protobuf_response;
|
||||
if (!ExtractSignedMessage(http_message, kMessageStart, kMessageEnd,
|
||||
&protobuf_response)) {
|
||||
LOGE(
|
||||
"Failed to extract signed serialized response from JSON "
|
||||
"response");
|
||||
continue;
|
||||
}
|
||||
|
||||
LOGV("Extracted response message: \n%s\n", protobuf_response.c_str());
|
||||
|
||||
// base64 decode response to yield binary protobuf
|
||||
std::vector<uint8_t> response_vec(Base64SafeDecode(protobuf_response));
|
||||
if (response_vec.empty() && !protobuf_response.empty()) {
|
||||
LOGE("Failed to decode base64 of response: response = %s",
|
||||
protobuf_response.c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string binary_protobuf_response(response_vec.begin(),
|
||||
response_vec.end());
|
||||
|
||||
if (cdm_engine.HandleProvisioningResponse(
|
||||
binary_protobuf_response, &cert, &wrapped_key) != NO_ERROR) {
|
||||
LOGE("Failed to handle provisioning response");
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (cdm_engine.HandleProvisioningResponse(http_message, &cert,
|
||||
&wrapped_key) != NO_ERROR) {
|
||||
LOGE("Failed to handle binary provisioning response");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
provision_success = true;
|
||||
} while (attempt_num <= kDefaultMaxProvisioningAttempts &&
|
||||
!provision_success);
|
||||
|
||||
if (attempt_num > 1) {
|
||||
LOGW("Provisioning request failed at least once: attempts = %zu",
|
||||
attempt_num);
|
||||
}
|
||||
ASSERT_TRUE(provision_success)
|
||||
<< "Failed to provision: message = " << http_message;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(provision_success)
|
||||
<< "Failed to provision: message = " << http_message;
|
||||
}
|
||||
|
||||
// TODO(fredgc): Replace this with a pre-defined DRM certificate. We could do
|
||||
@@ -399,7 +428,6 @@ bool WvCdmTestBase::Initialize(int argc, const char* const argv[],
|
||||
const std::string& extra_help_text) {
|
||||
Properties::Init();
|
||||
bool is_cast_receiver = false;
|
||||
bool force_load_test_keybox = false; // TODO(fredgc): obsolete. remove.
|
||||
bool filter_tests = true;
|
||||
bool show_usage = false;
|
||||
int verbosity = 0;
|
||||
@@ -413,6 +441,11 @@ bool WvCdmTestBase::Initialize(int argc, const char* const argv[],
|
||||
filter_tests = false;
|
||||
} else if (arg == "--cast") {
|
||||
is_cast_receiver = true;
|
||||
} else if (arg == "--fake_sleep") {
|
||||
wvcdm::TestSleep::set_real_sleep(false);
|
||||
} else if (arg.find("--gtest") == 0) {
|
||||
// gtest arguments will be passed to gtest by the main program.
|
||||
continue;
|
||||
} else {
|
||||
const auto index = arg.find('=');
|
||||
if (index == std::string::npos) {
|
||||
@@ -465,14 +498,17 @@ bool WvCdmTestBase::Initialize(int argc, const char* const argv[],
|
||||
|
||||
// Displays server url, port and key Id being used
|
||||
std::cout << std::endl;
|
||||
std::cout << "Default Server: " << default_config_.license_server()
|
||||
std::cout << "Default Provisioning Server: "
|
||||
<< default_config_.provisioning_server() << std::endl;
|
||||
std::cout << "Default License Server: " << default_config_.license_server()
|
||||
<< std::endl;
|
||||
std::cout << "Default KeyID: " << default_config_.key_id() << std::endl
|
||||
<< std::endl;
|
||||
|
||||
// Figure out which tests are appropriate for OEMCrypto, based on features
|
||||
// supported.
|
||||
wvoec::global_features.Initialize(is_cast_receiver, force_load_test_keybox);
|
||||
wvoec::global_features.Initialize();
|
||||
wvoec::global_features.set_cast_receiver(is_cast_receiver);
|
||||
// If the user requests --no_filter, we don't change the filter, otherwise, we
|
||||
// filter out features that are not supported.
|
||||
if (filter_tests) {
|
||||
@@ -715,4 +751,26 @@ bool TestLicenseHolder::DeriveKey(const std::vector<uint8_t>& key,
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MakePSSH(const video_widevine::WidevinePsshData& header) {
|
||||
std::string data;
|
||||
header.SerializeToString(&data);
|
||||
return MakePSSH(data);
|
||||
}
|
||||
|
||||
std::string MakePSSH(const std::string& serialized_header) {
|
||||
const uint32_t version = 0;
|
||||
const std::string system_id = InitializationData::WidevineSystemID();
|
||||
size_t system_id_size = system_id.size();
|
||||
size_t data_size = serialized_header.size();
|
||||
size_t atom_size = data_size + system_id_size + 4 * 4;
|
||||
|
||||
std::string pssh = EncodeUint32(atom_size);
|
||||
pssh.append("pssh");
|
||||
pssh.append(EncodeUint32(version));
|
||||
pssh.append(system_id);
|
||||
pssh.append(EncodeUint32(data_size));
|
||||
pssh.append(serialized_header);
|
||||
return pssh;
|
||||
}
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
@@ -147,6 +147,12 @@ class TestLicenseHolder {
|
||||
std::vector<uint8_t> session_key_;
|
||||
};
|
||||
|
||||
// Given a PSSH data structure, this makes a PSSH string for use in
|
||||
// generating a license request.
|
||||
std::string MakePSSH(const video_widevine::WidevinePsshData& header);
|
||||
// Given a serialized PSSH data, this generates a full PSSH string.
|
||||
std::string MakePSSH(const std::string& serialized_header);
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
#endif // WVCDM_CORE_TEST_BASE_H_
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include "test_base.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
if (!wvcdm::WvCdmTestBase::Initialize(argc, argv)) return 0;
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
@@ -56,12 +56,6 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case CERT_PROVISIONING_RESPONSE_ERROR_4:
|
||||
*os << "CERT_PROVISIONING_RESPONSE_ERROR_4";
|
||||
break;
|
||||
case CERT_PROVISIONING_RESPONSE_ERROR_5:
|
||||
*os << "CERT_PROVISIONING_RESPONSE_ERROR_5";
|
||||
break;
|
||||
case CERT_PROVISIONING_RESPONSE_ERROR_6:
|
||||
*os << "CERT_PROVISIONING_RESPONSE_ERROR_6";
|
||||
break;
|
||||
case CERT_PROVISIONING_RESPONSE_ERROR_7:
|
||||
*os << "CERT_PROVISIONING_RESPONSE_ERROR_7";
|
||||
break;
|
||||
@@ -89,6 +83,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case COPY_OLD_USAGE_ENTRY_UNKNOWN_ERROR:
|
||||
*os << "COPY_OLD_USAGE_ENTRY_UNKNOWN_ERROR";
|
||||
break;
|
||||
case CORE_MESSAGE_NOT_FOUND:
|
||||
*os << "CORE_MESSAGE_NOT_FOUND";
|
||||
break;
|
||||
case CREATE_USAGE_ENTRY_UNKNOWN_ERROR:
|
||||
*os << "CREATE_USAGE_ENTRY_UNKNOWN_ERROR";
|
||||
break;
|
||||
@@ -395,6 +392,9 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case INVALID_SESSION_1:
|
||||
*os << "INVALID_SESSION_1";
|
||||
break;
|
||||
case INVALID_SESSION_2:
|
||||
*os << "INVALID_SESSION_2";
|
||||
break;
|
||||
case INVALID_SESSION_ID:
|
||||
*os << "INVALID_SESSION_ID";
|
||||
break;
|
||||
@@ -533,6 +533,15 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case LOAD_KEY_ERROR:
|
||||
*os << "LOAD_KEY_ERROR";
|
||||
break;
|
||||
case LOAD_LICENSE_ERROR:
|
||||
*os << "LOAD_LICENSE_ERROR";
|
||||
break;
|
||||
case LOAD_PROVISIONING_ERROR:
|
||||
*os << "LOAD_PROVISIONING_ERROR";
|
||||
break;
|
||||
case LOAD_RENEWAL_ERROR:
|
||||
*os << "LOAD_RENEWAL_ERROR";
|
||||
break;
|
||||
case LOAD_SRM_ERROR:
|
||||
*os << "LOAD_SRM_ERROR";
|
||||
break;
|
||||
@@ -710,9 +719,6 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case RESTORE_OFFLINE_LICENSE_ERROR_2:
|
||||
*os << "RESTORE_OFFLINE_LICENSE_ERROR_2";
|
||||
break;
|
||||
case REWRAP_DEVICE_RSA_KEY_30_ERROR:
|
||||
*os << "REWRAP_DEVICE_RSA_KEY_30_ERROR";
|
||||
break;
|
||||
case REWRAP_DEVICE_RSA_KEY_ERROR:
|
||||
*os << "REWRAP_DEVICE_RSA_KEY_ERROR";
|
||||
break;
|
||||
@@ -779,9 +785,6 @@ void PrintTo(const enum CdmResponseType& value, ::std::ostream* os) {
|
||||
case SESSION_NOT_FOUND_16:
|
||||
*os << "SESSION_NOT_FOUND_16";
|
||||
break;
|
||||
case SESSION_NOT_FOUND_17:
|
||||
*os << "SESSION_NOT_FOUND_17";
|
||||
break;
|
||||
case SESSION_NOT_FOUND_18:
|
||||
*os << "SESSION_NOT_FOUND_18";
|
||||
break;
|
||||
@@ -1141,6 +1144,34 @@ void PrintTo(const enum OEMCryptoResult& value, ::std::ostream* os) {
|
||||
case OEMCrypto_ERROR_SYSTEM_INVALIDATED:
|
||||
*os << "SYSTEM_INVALIDATED";
|
||||
break;
|
||||
case OEMCrypto_ERROR_LICENSE_RELOAD:
|
||||
*os << "LICENSE_RELOAD";
|
||||
break;
|
||||
case OEMCrypto_ERROR_MULTIPLE_USAGE_ENTRIES:
|
||||
*os << "MULTIPLE_USAGE_ENTRIES";
|
||||
break;
|
||||
case OEMCrypto_WARNING_MIXED_OUTPUT_PROTECTION:
|
||||
*os << "MIXED_OUTPUT_PROTECTION";
|
||||
break;
|
||||
// ODK Values.
|
||||
case ODK_ERROR_CORE_MESSAGE:
|
||||
*os << "CORE_MESSAGE";
|
||||
break;
|
||||
case ODK_SET_TIMER:
|
||||
*os << "SET_TIMER";
|
||||
break;
|
||||
case ODK_DISABLE_TIMER:
|
||||
*os << "DISABLE_TIMER";
|
||||
break;
|
||||
case ODK_TIMER_EXPIRED:
|
||||
*os << "TIMER_EXPIRED";
|
||||
break;
|
||||
case ODK_UNSUPPORTED_API:
|
||||
*os << "UNSUPPORTED_API";
|
||||
break;
|
||||
case ODK_STALE_RENEWAL:
|
||||
*os << "STALE_RENEWAL";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,28 +144,28 @@ const size_t kUsageInfoFileArraySize = ArraySize(kUsageInfoFileArray);
|
||||
std::vector<std::string> kUsageInfoFileList;
|
||||
|
||||
const DeviceFiles::CdmUsageData kCdmUsageData1 = {
|
||||
/* provider_session_token = */ "provider_session_token_1",
|
||||
/* license_request = */ "license_request_1",
|
||||
/* license = */ "license_1",
|
||||
/* key_set_id = */ "key_set_id_1",
|
||||
/* usage_entry = */ "usage_entry_1",
|
||||
/* usage_entry_number = */ 0,
|
||||
/* provider_session_token = */ "provider_session_token_1",
|
||||
/* license_request = */ "license_request_1",
|
||||
/* license = */ "license_1",
|
||||
/* key_set_id = */ "key_set_id_1",
|
||||
/* usage_entry = */ "usage_entry_1",
|
||||
/* usage_entry_number = */ 0,
|
||||
};
|
||||
const DeviceFiles::CdmUsageData kCdmUsageData2 = {
|
||||
/* provider_session_token = */ "provider_session_token_2",
|
||||
/* license_request = */ "license_request_2",
|
||||
/* license = */ "license_2",
|
||||
/* key_set_id = */ "key_set_id_2",
|
||||
/* usage_entry = */ "usage_entry_2",
|
||||
/* usage_entry_number = */ 0,
|
||||
/* provider_session_token = */ "provider_session_token_2",
|
||||
/* license_request = */ "license_request_2",
|
||||
/* license = */ "license_2",
|
||||
/* key_set_id = */ "key_set_id_2",
|
||||
/* usage_entry = */ "usage_entry_2",
|
||||
/* usage_entry_number = */ 0,
|
||||
};
|
||||
const DeviceFiles::CdmUsageData kCdmUsageData3 = {
|
||||
/* provider_session_token = */ "provider_session_token_3",
|
||||
/* license_request = */ "license_request_3",
|
||||
/* license = */ "license_3",
|
||||
/* key_set_id = */ "key_set_id_3",
|
||||
/* usage_entry = */ "usage_entry_3",
|
||||
/* usage_entry_number = */ 0,
|
||||
/* provider_session_token = */ "provider_session_token_3",
|
||||
/* license_request = */ "license_request_3",
|
||||
/* license = */ "license_3",
|
||||
/* key_set_id = */ "key_set_id_3",
|
||||
/* usage_entry = */ "usage_entry_3",
|
||||
/* usage_entry_number = */ 0,
|
||||
};
|
||||
const std::vector<DeviceFiles::CdmUsageData> kEmptyUsageInfoUsageDataList;
|
||||
|
||||
@@ -340,8 +340,8 @@ void InitVectorConstants() {
|
||||
}
|
||||
}
|
||||
|
||||
void ToVector(std::vector<CdmUsageEntryInfo>& vec, const CdmUsageEntryInfo* arr,
|
||||
size_t total_size) {
|
||||
void ToVector(std::vector<CdmUsageEntryInfo>& vec,
|
||||
const CdmUsageEntryInfo* arr, size_t total_size) {
|
||||
size_t max = total_size / sizeof(CdmUsageEntryInfo);
|
||||
vec.clear();
|
||||
for (size_t i = 0; i < max; i++) {
|
||||
@@ -410,7 +410,8 @@ class MockDeviceFiles : public DeviceFiles {
|
||||
const std::string&, const CdmUsageEntry&, uint32_t));
|
||||
MOCK_METHOD2(RetrieveUsageInfo,
|
||||
bool(const std::string&, std::vector<CdmUsageData>*));
|
||||
MOCK_METHOD1(ListLicenses, bool(std::vector<std::string>* key_set_ids));
|
||||
MOCK_METHOD1(ListLicenses,
|
||||
bool(std::vector<std::string>* key_set_ids));
|
||||
MOCK_METHOD1(ListUsageInfoFiles,
|
||||
bool(std::vector<std::string>* usage_info_files));
|
||||
|
||||
@@ -438,10 +439,10 @@ class MockCryptoSession : public TestCryptoSession {
|
||||
// Partial mock of the UsageTableHeader. This is to test when dependency
|
||||
// exist on internal methods which would require complex expectations
|
||||
class MockUsageTableHeader : public UsageTableHeader {
|
||||
public:
|
||||
MockUsageTableHeader() : UsageTableHeader() {}
|
||||
MOCK_METHOD3(DeleteEntry, CdmResponseType(uint32_t, DeviceFiles*,
|
||||
metrics::CryptoMetrics*));
|
||||
public:
|
||||
MockUsageTableHeader() : UsageTableHeader() {}
|
||||
MOCK_METHOD3(DeleteEntry, CdmResponseType(uint32_t, DeviceFiles*,
|
||||
metrics::CryptoMetrics*));
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -468,7 +469,9 @@ using ::testing::UnorderedElementsAreArray;
|
||||
|
||||
class UsageTableHeaderTest : public WvCdmTestBase {
|
||||
public:
|
||||
static void SetUpTestCase() { InitVectorConstants(); }
|
||||
static void SetUpTestCase() {
|
||||
InitVectorConstants();
|
||||
}
|
||||
|
||||
// Useful when UsageTableHeader is mocked
|
||||
void DeleteEntry(uint32_t usage_entry_number, DeviceFiles*,
|
||||
@@ -563,7 +566,10 @@ class UsageTableHeaderInitializationTest
|
||||
: public UsageTableHeaderTest,
|
||||
public ::testing::WithParamInterface<CdmSecurityLevel> {
|
||||
public:
|
||||
static void SetUpTestCase() { InitVectorConstants(); }
|
||||
static void SetUpTestCase() {
|
||||
InitVectorConstants();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
TEST_P(UsageTableHeaderInitializationTest, CreateUsageTableHeader) {
|
||||
@@ -572,18 +578,12 @@ TEST_P(UsageTableHeaderInitializationTest, CreateUsageTableHeader) {
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
|
||||
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
|
||||
SetArgPointee<2>(false), Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyLicenseList), Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageInfoFilesList), Return(false)));
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
|
||||
kEmptyUsageEntryInfoVector))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
}
|
||||
@@ -594,27 +594,15 @@ TEST_P(UsageTableHeaderInitializationTest, Upgrade_UnableToRetrieveLicenses) {
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
|
||||
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
|
||||
SetArgPointee<2>(false), Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kLicenseList), Return(true)));
|
||||
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageInfoFilesList), Return(false)));
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
|
||||
// TODO: Why not being called?
|
||||
// EXPECT_CALL(*device_files_, DeleteAllLicenses()).WillOnce(Return(true));
|
||||
//EXPECT_CALL(*device_files_, DeleteAllLicenses()).WillOnce(Return(true));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
|
||||
kEmptyUsageEntryInfoVector))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
.WillOnce(Return(true));
|
||||
|
||||
for (size_t i = 0; i < kLicenseList.size(); ++i) {
|
||||
device_files_->DeleteLicense(kLicenseList[i]);
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveLicense(kLicenseList[i], NotNull(), NotNull()))
|
||||
.WillOnce(Return(false));
|
||||
}
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
}
|
||||
|
||||
@@ -624,24 +612,12 @@ TEST_P(UsageTableHeaderInitializationTest, Upgrade_UnableToRetrieveUsageInfo) {
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyUsageTableHeader),
|
||||
SetArgPointee<1>(kEmptyUsageEntryInfoVector),
|
||||
SetArgPointee<2>(false), Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListLicenses(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kEmptyLicenseList), Return(false)));
|
||||
EXPECT_CALL(*device_files_, ListUsageInfoFiles(NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(kUsageInfoFileList), Return(true)));
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(kEmptyUsageTableHeader), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kEmptyUsageTableHeader,
|
||||
kEmptyUsageEntryInfoVector))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(true));
|
||||
for (size_t i = 0; i < kUsageInfoFileList.size(); ++i) {
|
||||
EXPECT_CALL(*device_files_,
|
||||
RetrieveUsageInfo(kUsageInfoFileList[i], NotNull()))
|
||||
.WillOnce(DoAll(SetArgPointee<1>(kEmptyUsageInfoUsageDataList),
|
||||
Return(false)));
|
||||
}
|
||||
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
}
|
||||
|
||||
@@ -681,8 +657,8 @@ TEST_P(UsageTableHeaderInitializationTest,
|
||||
|
||||
SecurityLevel security_level =
|
||||
(GetParam() == kSecurityLevelL3) ? kLevel3 : kLevelDefault;
|
||||
EXPECT_CALL(*crypto_session_, Open(security_level))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
Open(security_level)).WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*crypto_session_, LoadUsageTableHeader(kUsageTableHeader))
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageTableHeader(NotNull()))
|
||||
@@ -729,20 +705,22 @@ TEST_P(UsageTableHeaderInitializationTest,
|
||||
// Expectations for AddEntry
|
||||
uint32_t expect_usage_entry_number = k201UsageEntryInfoVector.size();
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(expect_usage_entry_number), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_,
|
||||
StoreUsageTableInfo(kUsageTableHeader, usage_entries_202))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(expect_usage_entry_number),
|
||||
Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kUsageTableHeader,
|
||||
usage_entries_202))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
// Expectations for DeleteEntry
|
||||
SecurityLevel security_level =
|
||||
(GetParam() == kSecurityLevelL3) ? kLevel3 : kLevelDefault;
|
||||
EXPECT_CALL(*crypto_session_, Open(security_level))
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
Open(security_level))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(NO_ERROR));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
ShrinkUsageTableHeader(usage_entries_202.size() - 1, NotNull()))
|
||||
EXPECT_CALL(
|
||||
*crypto_session_,
|
||||
ShrinkUsageTableHeader(usage_entries_202.size() - 1, NotNull()))
|
||||
.WillOnce(Return(SHRINK_USAGE_TABLER_HEADER_UNKNOWN_ERROR));
|
||||
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
@@ -764,26 +742,29 @@ TEST_P(UsageTableHeaderInitializationTest,
|
||||
// Expectations for AddEntry
|
||||
uint32_t expect_usage_entry_number = k201UsageEntryInfoVector.size();
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(expect_usage_entry_number), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_,
|
||||
StoreUsageTableInfo(kUsageTableHeader, usage_entries_202))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(expect_usage_entry_number),
|
||||
Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kUsageTableHeader,
|
||||
usage_entries_202))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
// Expectations for DeleteEntry
|
||||
SecurityLevel security_level =
|
||||
(GetParam() == kSecurityLevelL3) ? kLevel3 : kLevelDefault;
|
||||
|
||||
EXPECT_CALL(*crypto_session_, Open(security_level))
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
Open(security_level))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(NO_ERROR));
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
ShrinkUsageTableHeader(usage_entries_202.size() - 1, NotNull()))
|
||||
EXPECT_CALL(
|
||||
*crypto_session_,
|
||||
ShrinkUsageTableHeader(usage_entries_202.size() - 1, NotNull()))
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<1>(kAnotherUsageTableHeader), Return(NO_ERROR)));
|
||||
EXPECT_CALL(*device_files_,
|
||||
StoreUsageTableInfo(kAnotherUsageTableHeader,
|
||||
SizeIs(k201UsageEntryInfoVector.size())))
|
||||
StoreUsageTableInfo(
|
||||
kAnotherUsageTableHeader,
|
||||
SizeIs(k201UsageEntryInfoVector.size())))
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_TRUE(usage_table_header_->Init(GetParam(), crypto_session_));
|
||||
@@ -946,8 +927,9 @@ TEST_F(UsageTableHeaderTest,
|
||||
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull()))
|
||||
.WillOnce(Return(INSUFFICIENT_CRYPTO_RESOURCES_3))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(expected_usage_entry_number),
|
||||
Return(NO_ERROR)));
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(expected_usage_entry_number),
|
||||
Return(NO_ERROR)));
|
||||
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kUsageTableHeader, _))
|
||||
.WillOnce(DoAll(SaveArg<1>(&final_usage_entries), Return(true)));
|
||||
@@ -1007,8 +989,9 @@ TEST_F(UsageTableHeaderTest,
|
||||
EXPECT_CALL(*crypto_session_, CreateUsageEntry(NotNull()))
|
||||
.WillOnce(Return(INSUFFICIENT_CRYPTO_RESOURCES_3))
|
||||
.WillOnce(Return(INSUFFICIENT_CRYPTO_RESOURCES_3))
|
||||
.WillOnce(DoAll(SetArgPointee<0>(expected_usage_entry_number),
|
||||
Return(NO_ERROR)));
|
||||
.WillOnce(
|
||||
DoAll(SetArgPointee<0>(expected_usage_entry_number),
|
||||
Return(NO_ERROR)));
|
||||
|
||||
EXPECT_CALL(*device_files_, StoreUsageTableInfo(kUsageTableHeader, _))
|
||||
.WillOnce(DoAll(SaveArg<1>(&final_usage_entries), Return(true)));
|
||||
@@ -1175,8 +1158,9 @@ TEST_F(UsageTableHeaderTest,
|
||||
EXPECT_CALL(*mock_usage_table_header,
|
||||
DeleteEntry(_, device_files_, NotNull()))
|
||||
.Times(1)
|
||||
.WillRepeatedly(DoAll(Invoke(this, &UsageTableHeaderTest::DeleteEntry),
|
||||
Return(NO_ERROR)));
|
||||
.WillRepeatedly(
|
||||
DoAll(Invoke(this, &UsageTableHeaderTest::DeleteEntry),
|
||||
Return(NO_ERROR)));
|
||||
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
LoadUsageEntry(usage_entry_number_to_load, usage_entry_to_load))
|
||||
@@ -1184,9 +1168,11 @@ TEST_F(UsageTableHeaderTest,
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
|
||||
// Now invoke the method under test
|
||||
EXPECT_EQ(NO_ERROR, mock_usage_table_header->LoadEntry(
|
||||
crypto_session_, usage_entry_to_load,
|
||||
usage_entry_number_to_load));
|
||||
EXPECT_EQ(NO_ERROR,
|
||||
mock_usage_table_header->LoadEntry(
|
||||
crypto_session_,
|
||||
usage_entry_to_load,
|
||||
usage_entry_number_to_load));
|
||||
}
|
||||
|
||||
TEST_F(UsageTableHeaderTest,
|
||||
@@ -1205,8 +1191,9 @@ TEST_F(UsageTableHeaderTest,
|
||||
EXPECT_CALL(*mock_usage_table_header,
|
||||
DeleteEntry(_, device_files_, NotNull()))
|
||||
.Times(2)
|
||||
.WillRepeatedly(DoAll(Invoke(this, &UsageTableHeaderTest::DeleteEntry),
|
||||
Return(NO_ERROR)));
|
||||
.WillRepeatedly(
|
||||
DoAll(Invoke(this, &UsageTableHeaderTest::DeleteEntry),
|
||||
Return(NO_ERROR)));
|
||||
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
LoadUsageEntry(usage_entry_number_to_load, usage_entry_to_load))
|
||||
@@ -1215,9 +1202,11 @@ TEST_F(UsageTableHeaderTest,
|
||||
.WillOnce(Return(NO_ERROR));
|
||||
|
||||
// Now invoke the method under test
|
||||
EXPECT_EQ(NO_ERROR, mock_usage_table_header->LoadEntry(
|
||||
crypto_session_, usage_entry_to_load,
|
||||
usage_entry_number_to_load));
|
||||
EXPECT_EQ(NO_ERROR,
|
||||
mock_usage_table_header->LoadEntry(
|
||||
crypto_session_,
|
||||
usage_entry_to_load,
|
||||
usage_entry_number_to_load));
|
||||
}
|
||||
|
||||
TEST_F(UsageTableHeaderTest, LoadEntry_LoadUsageEntryFailsThrice) {
|
||||
@@ -1235,8 +1224,9 @@ TEST_F(UsageTableHeaderTest, LoadEntry_LoadUsageEntryFailsThrice) {
|
||||
EXPECT_CALL(*mock_usage_table_header,
|
||||
DeleteEntry(_, device_files_, NotNull()))
|
||||
.Times(3)
|
||||
.WillRepeatedly(DoAll(Invoke(this, &UsageTableHeaderTest::DeleteEntry),
|
||||
Return(NO_ERROR)));
|
||||
.WillRepeatedly(
|
||||
DoAll(Invoke(this, &UsageTableHeaderTest::DeleteEntry),
|
||||
Return(NO_ERROR)));
|
||||
|
||||
EXPECT_CALL(*crypto_session_,
|
||||
LoadUsageEntry(usage_entry_number_to_load, usage_entry_to_load))
|
||||
@@ -1244,10 +1234,11 @@ TEST_F(UsageTableHeaderTest, LoadEntry_LoadUsageEntryFailsThrice) {
|
||||
.WillRepeatedly(Return(INSUFFICIENT_CRYPTO_RESOURCES_3));
|
||||
|
||||
// Now invoke the method under test
|
||||
EXPECT_EQ(
|
||||
INSUFFICIENT_CRYPTO_RESOURCES_3,
|
||||
mock_usage_table_header->LoadEntry(crypto_session_, usage_entry_to_load,
|
||||
usage_entry_number_to_load));
|
||||
EXPECT_EQ(INSUFFICIENT_CRYPTO_RESOURCES_3,
|
||||
mock_usage_table_header->LoadEntry(
|
||||
crypto_session_,
|
||||
usage_entry_to_load,
|
||||
usage_entry_number_to_load));
|
||||
}
|
||||
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_InvalidUsageEntryNumber) {
|
||||
@@ -1365,7 +1356,7 @@ TEST_F(UsageTableHeaderTest, DeleteEntry_LastOfflineEntry) {
|
||||
// # of usage entries 4 3
|
||||
TEST_F(UsageTableHeaderTest, DeleteEntry_LastSecureStopEntry) {
|
||||
std::vector<CdmUsageEntryInfo> usage_entry_info_vector;
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
const CdmUsageEntryInfo usage_entry_info_array[] = {
|
||||
kUsageEntryInfoOfflineLicense1, kUsageEntryInfoSecureStop1,
|
||||
kUsageEntryInfoStorageTypeUnknown, kUsageEntryInfoSecureStop2};
|
||||
ToVector(usage_entry_info_vector, usage_entry_info_array,
|
||||
|
||||
Reference in New Issue
Block a user