// Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. #include "fake_provisioning_server.h" #include // TODO: refactor oec_session so that these are not needed. #include #include #include #include #include #include #include #include #include #include #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_key_deriver.h" #include "oec_test_data.h" #include "privacy_crypto.h" #include "service_certificate.h" #include "string_conversions.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 = wvutil::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 = wvutil::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 = wvutil::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 = wvutil::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::DrmCertificate cert; cert.set_type(video_widevine::DrmCertificate_Type_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::SignedDrmCertificate 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"); const video_widevine::SignedProvisioningMessage::ProvisioningType provisioning_type = signed_request.provisioning_type(); LOGD("Request uses provisioning type: %d", provisioning_type); if (provisioning_type != 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. wvoec::KeyDeriver key_deriver; std::vector serialized_message_v(serialized_message.begin(), serialized_message.end()); // 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_, sizeof(wvoec::kTestKeybox.device_key_), serialized_message_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_provisioning_type(signed_request.provisioning_type()); 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. const 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( oemcrypto_core_message::features::CoreMessageFeatures::kDefaultFeatures, message, core_request_data, OEMCrypto_RSA_Private_Key, &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 signature_v; key_deriver.ServerSignBuffer(reinterpret_cast(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); static const std::string kJsonStart = "{ \"signedResponse\": \""; static const std::string kJsonEnd = "\" }"; *json_response = kJsonStart; json_response->append(wvutil::Base64SafeEncode(response_data)); json_response->append(kJsonEnd); return true; } } // namespace wvcdm