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:
Fred Gylys-Colwell
2020-01-18 10:11:24 -08:00
parent 7e2619e379
commit 7665614b2e
132 changed files with 12331 additions and 9341 deletions

View File

@@ -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;

View File

@@ -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*());

View 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

View 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_

View File

@@ -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

View File

@@ -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

View File

@@ -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_

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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,