From 68187b9f023964f996fd9b4dd9919fac02a7781e Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Mon, 27 Sep 2021 18:17:04 -0700 Subject: [PATCH 1/4] Fix -Wshorten-64-to-32 errors in BoringSSL interactions (This is a merge from the Widevine Repo of http://go/wvgerrit/134310.) This patch fixes code that would trigger -Wshorten-64-to-32 by implicitly narrowing a variable from 64 to 32 bits. Most of the time, it does this by making the implicit conversion explicit. The cause of most of these is that OpenSSL uses "int" for the length of things rather than size_t. (While BoringSSL sometimes uses int and sometimes uses size_t.) One exception is LogBoringSSLError(). We have a couple copies of this function around, and they varied slightly. This patch brings them all in-line, which conveniently also removes any code in them that would deal with integer variables. GetRandBytes() now takes a size_t and downcasts to BoringSSL's native int internally, so that callers can pass in a size_t value as they would expect. There's also an interesting case in oec_session_util.cpp. Because BoringSSL and OpenSSL disagree about the width of an error code, we have to use the "auto" type for a temporary variable that holds an error, in order to retain compatibility with both. Bug: 194971260 Test: x86-64 Test: x86-64-openssl Change-Id: I88bc62b4cda396f8a1eabd1a3cb7d1b03f47a33f --- .../cdm/core/src/privacy_crypto_boringssl.cpp | 17 +++++----- libwvdrmengine/cdm/core/test/http_socket.cpp | 13 ++++---- libwvdrmengine/cdm/core/test/test_base.cpp | 2 +- .../oemcrypto/test/oec_key_deriver.cpp | 13 +++++--- .../oemcrypto/test/oec_session_util.cpp | 32 +++++++++++-------- .../oemcrypto/test/oec_session_util.h | 6 ++-- 6 files changed, 47 insertions(+), 36 deletions(-) diff --git a/libwvdrmengine/cdm/core/src/privacy_crypto_boringssl.cpp b/libwvdrmengine/cdm/core/src/privacy_crypto_boringssl.cpp index 13156209..522a8837 100644 --- a/libwvdrmengine/cdm/core/src/privacy_crypto_boringssl.cpp +++ b/libwvdrmengine/cdm/core/src/privacy_crypto_boringssl.cpp @@ -29,7 +29,7 @@ const int kRsaPkcs1OaepPaddingLength = 41; RSA* GetKey(const std::string& serialized_key) { BIO* bio = BIO_new_mem_buf(const_cast(serialized_key.data()), - serialized_key.size()); + static_cast(serialized_key.size())); if (bio == nullptr) { LOGE("BIO_new_mem_buf failed: returned null"); return nullptr; @@ -123,11 +123,11 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out, } out->resize(in.size() + AES_BLOCK_SIZE); - int out_length = out->size(); + int out_length = static_cast(out->size()); if (EVP_EncryptUpdate( evp_cipher_ctx, reinterpret_cast(&(*out)[0]), &out_length, reinterpret_cast(const_cast(in.data())), - in.size()) == 0) { + static_cast(in.size())) == 0) { LOGE("AES CBC encryption failure: %s", ERR_error_string(ERR_get_error(), nullptr)); EVP_CIPHER_CTX_free(evp_cipher_ctx); @@ -195,7 +195,7 @@ bool RsaPublicKey::Encrypt(const std::string& clear_message, encrypted_message->assign(rsa_size, 0); if (RSA_public_encrypt( - clear_message.size(), + static_cast(clear_message.size()), const_cast( reinterpret_cast(clear_message.data())), reinterpret_cast(&(*encrypted_message)[0]), key, @@ -212,9 +212,9 @@ bool RsaPublicKey::Encrypt(const std::string& clear_message, // LogBoringSSLError is a callback from BoringSSL which is called with each // error in the thread's error queue. -static int LogBoringSSLError(const char* msg, size_t /* len */, - void* /* ctx */) { - LOGE(" %s", msg); +static int LogBoringSSLError(const char* msg, size_t /* length */, + void* /* user_data */) { + LOGE(" BoringSSL Error: %s", msg); return 1; } @@ -345,7 +345,8 @@ bool ExtractExtensionValueFromCertificate(const std::string& cert, return false; } - X509* const intermediate_cert = sk_X509_value(certs, cert_index); + X509* const intermediate_cert = + sk_X509_value(certs, static_cast(cert_index)); if (intermediate_cert == nullptr) { LOGE("Unable to get intermediate cert"); return false; diff --git a/libwvdrmengine/cdm/core/test/http_socket.cpp b/libwvdrmengine/cdm/core/test/http_socket.cpp index 0bce6275..886ec687 100644 --- a/libwvdrmengine/cdm/core/test/http_socket.cpp +++ b/libwvdrmengine/cdm/core/test/http_socket.cpp @@ -66,10 +66,10 @@ SSL_CTX* InitSslContext() { return ctx; } -static int LogBoringSslError(const char* message, size_t length, +static int LogBoringSslError(const char* message, size_t /* length */, void* /* user_data */) { LOGE(" BoringSSL Error: %s", message); - return length; + return 1; } bool IsRetryableSslError(int ssl_error) { @@ -433,7 +433,7 @@ int HttpSocket::Read(char* data, int len, int timeout_in_ms) { if (secure_connect_) { read = SSL_read(ssl_, data, to_read); } else { - read = recv(socket_fd_, data, to_read, 0); + read = static_cast(recv(socket_fd_, data, to_read, 0)); } if (read > 0) { @@ -490,10 +490,11 @@ int HttpSocket::Write(const char* data, int len, int timeout_in_ms) { } while (to_send > 0) { int sent; - if (secure_connect_) + if (secure_connect_) { sent = SSL_write(ssl_, data, to_send); - else - sent = send(socket_fd_, data, to_send, 0); + } else { + sent = static_cast(send(socket_fd_, data, to_send, 0)); + } if (sent > 0) { to_send -= sent; diff --git a/libwvdrmengine/cdm/core/test/test_base.cpp b/libwvdrmengine/cdm/core/test/test_base.cpp index a256c42e..86100bf5 100644 --- a/libwvdrmengine/cdm/core/test/test_base.cpp +++ b/libwvdrmengine/cdm/core/test/test_base.cpp @@ -199,7 +199,7 @@ std::string WvCdmTestBase::SignHMAC(const std::string& message, const std::vector& key) { uint8_t signature[SHA256_DIGEST_LENGTH]; unsigned int md_len = SHA256_DIGEST_LENGTH; - HMAC(EVP_sha256(), &key[0], key.size(), + HMAC(EVP_sha256(), &key[0], static_cast(key.size()), reinterpret_cast(message.data()), message.size(), signature, &md_len); std::string result(signature, signature + SHA256_DIGEST_LENGTH); diff --git a/libwvdrmengine/oemcrypto/test/oec_key_deriver.cpp b/libwvdrmengine/oemcrypto/test/oec_key_deriver.cpp index f6abdb6a..17415478 100644 --- a/libwvdrmengine/oemcrypto/test/oec_key_deriver.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_key_deriver.cpp @@ -147,8 +147,9 @@ void KeyDeriver::ServerSignBuffer(const uint8_t* data, size_t data_length, ASSERT_EQ(mac_key_server_.size(), MAC_KEY_SIZE); signature->assign(SHA256_DIGEST_LENGTH, 0); unsigned int sig_len = SHA256_DIGEST_LENGTH; - ASSERT_TRUE(HMAC(EVP_sha256(), mac_key_server_.data(), mac_key_server_.size(), - data, data_length, signature->data(), &sig_len)); + ASSERT_TRUE(HMAC(EVP_sha256(), mac_key_server_.data(), + static_cast(mac_key_server_.size()), data, data_length, + signature->data(), &sig_len)); } void KeyDeriver::ClientSignBuffer(const vector& buffer, @@ -156,8 +157,9 @@ void KeyDeriver::ClientSignBuffer(const vector& buffer, ASSERT_EQ(mac_key_client_.size(), MAC_KEY_SIZE); signature->assign(SHA256_DIGEST_LENGTH, 0); unsigned int sig_len = SHA256_DIGEST_LENGTH; - ASSERT_TRUE(HMAC(EVP_sha256(), mac_key_client_.data(), mac_key_client_.size(), - buffer.data(), buffer.size(), signature->data(), &sig_len)); + ASSERT_TRUE(HMAC(EVP_sha256(), mac_key_client_.data(), + static_cast(mac_key_client_.size()), buffer.data(), + buffer.size(), signature->data(), &sig_len)); } void KeyDeriver::ClientSignPstReport(const vector& pst_report_buffer, @@ -165,7 +167,8 @@ void KeyDeriver::ClientSignPstReport(const vector& pst_report_buffer, ASSERT_EQ(mac_key_client_.size(), MAC_KEY_SIZE); signature->assign(SHA_DIGEST_LENGTH, 0); unsigned int sig_len = SHA_DIGEST_LENGTH; - ASSERT_TRUE(HMAC(EVP_sha1(), mac_key_client_.data(), mac_key_client_.size(), + ASSERT_TRUE(HMAC(EVP_sha1(), mac_key_client_.data(), + static_cast(mac_key_client_.size()), &pst_report_buffer[SHA_DIGEST_LENGTH], pst_report_buffer.size() - SHA_DIGEST_LENGTH, signature->data(), &sig_len)); diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp index 6a3b85cd..a5775ea3 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.cpp +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.cpp @@ -112,9 +112,9 @@ OEMCryptoResult DecryptCTR(OEMCrypto_SESSION session_id, const uint8_t* key, } // namespace -int GetRandBytes(unsigned char* buf, int num) { +int GetRandBytes(unsigned char* buf, size_t num) { // returns 1 on success, -1 if not supported, or 0 if other failure. - return RAND_bytes(buf, num); + return RAND_bytes(buf, static_cast(num)); } // Does the boilerplate to fill out sample and subsample descriptions for @@ -162,7 +162,9 @@ void ctr128_inc64(int64_t increaseBy, uint8_t* iv) { uint32_t htonl_fnc(uint32_t x) { return htonl(x); } void dump_boringssl_error() { - while (unsigned long err = ERR_get_error()) { + // BoringSSL and OpenSSL disagree about what the type of an error code is, so + // we must use "auto" here. + while (auto err = ERR_get_error()) { char buffer[120]; ERR_error_string_n(err, buffer, sizeof(buffer)); cout << "BoringSSL Error -- " << buffer << "\n"; @@ -1373,7 +1375,8 @@ void Session::GenerateDerivedKeysFromSessionKey() { } void Session::TestDecryptCTR(bool select_key_first, - OEMCryptoResult expected_result, int key_index) { + OEMCryptoResult expected_result, + size_t key_index) { OEMCryptoResult select_result = OEMCrypto_SUCCESS; if (select_key_first) { // Select the key (from FillSimpleMessage) @@ -1433,7 +1436,7 @@ void Session::TestDecryptResult(OEMCryptoResult expected_result, } } -void Session::TestSelectExpired(unsigned int key_index) { +void Session::TestSelectExpired(size_t key_index) { if (global_features.api_version >= 13) { OEMCryptoResult status = OEMCrypto_SelectKey( session_id(), license().keys[key_index].key_id, @@ -1477,7 +1480,7 @@ void Session::LoadOEMCert(bool verify_cert) { // Load the public cert's key into public_rsa_ and verify, if requested for (size_t i = 0; certs && i < static_cast(sk_X509_num(certs)); ++i) { - X509* x509_cert = sk_X509_value(certs, i); + X509* x509_cert = sk_X509_value(certs, static_cast(i)); boringssl_ptr pubkey(X509_get_pubkey(x509_cert)); ASSERT_TRUE(pubkey.NotNull()); if (i == 0) { @@ -1493,7 +1496,8 @@ void Session::LoadOEMCert(bool verify_cert) { X509_NAME* name = X509_get_subject_name(x509_cert); printf(" OEM Certificate Name: %s\n", - X509_NAME_oneline(name, buffer.data(), buffer.size())); + X509_NAME_oneline(name, buffer.data(), + static_cast(buffer.size()))); boringssl_ptr store(X509_STORE_new()); ASSERT_TRUE(store.NotNull()); boringssl_ptr store_ctx( @@ -1523,7 +1527,8 @@ void Session::PreparePublicKey(const uint8_t* rsa_key, size_t rsa_key_length) { rsa_key_length = sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048); } uint8_t* p = const_cast(rsa_key); - boringssl_ptr bio(BIO_new_mem_buf(p, rsa_key_length)); + boringssl_ptr bio( + BIO_new_mem_buf(p, static_cast(rsa_key_length))); ASSERT_TRUE(bio.NotNull()); boringssl_ptr pkcs8_pki( d2i_PKCS8_PRIV_KEY_INFO_bio(bio.get(), nullptr)); @@ -1621,8 +1626,9 @@ void Session::VerifyRSASignature(const vector& message, int size; // RSA_public_decrypt decrypts the signature, and then verifies that // it was padded with RSA PKCS1 padding. - size = RSA_public_decrypt(signature_length, signature, padded_digest.data(), - public_rsa_, RSA_PKCS1_PADDING); + size = RSA_public_decrypt(static_cast(signature_length), signature, + padded_digest.data(), public_rsa_, + RSA_PKCS1_PADDING); EXPECT_GT(size, 0); padded_digest.resize(size); EXPECT_EQ(message, padded_digest); @@ -1639,9 +1645,9 @@ bool Session::GenerateRSASessionKey(vector* session_key, } *session_key = wvcdm::a2b_hex("6fa479c731d2770b6a61a5d1420bb9d1"); enc_session_key->assign(RSA_size(public_rsa_), 0); - int status = RSA_public_encrypt(session_key->size(), &(session_key->front()), - &(enc_session_key->front()), public_rsa_, - RSA_PKCS1_OAEP_PADDING); + int status = RSA_public_encrypt( + static_cast(session_key->size()), &(session_key->front()), + &(enc_session_key->front()), public_rsa_, RSA_PKCS1_OAEP_PADDING); int size = static_cast(RSA_size(public_rsa_)); if (status != size) { cout << "GenerateRSASessionKey error encrypting session key.\n"; diff --git a/libwvdrmengine/oemcrypto/test/oec_session_util.h b/libwvdrmengine/oemcrypto/test/oec_session_util.h index d2bde5e8..49716bf9 100644 --- a/libwvdrmengine/oemcrypto/test/oec_session_util.h +++ b/libwvdrmengine/oemcrypto/test/oec_session_util.h @@ -117,7 +117,7 @@ struct EntitledContentKeyData { }; // returns 1 on success, -1 if not supported, or 0 if other failure. -int GetRandBytes(unsigned char* buf, int num); +int GetRandBytes(unsigned char* buf, size_t num); void GenerateSimpleSampleDescription(const std::vector& in, std::vector& out, @@ -534,10 +534,10 @@ class Session { // Encrypt some data and pass to OEMCrypto_DecryptCENC to verify decryption. void TestDecryptCTR(bool select_key_first = true, OEMCryptoResult expected_result = OEMCrypto_SUCCESS, - int key_index = 0); + size_t key_index = 0); // Verify that an attempt to select an expired key either succeeds, or gives // an actionable error code. - void TestSelectExpired(unsigned int key_index); + void TestSelectExpired(size_t key_index); // Calls OEMCrypto_GetOEMPublicCertificate and OEMCrypto_LoadOEMPrivateKey and // loads the OEM cert's public rsa key into public_rsa_. void LoadOEMCert(bool verify_cert = false); From fe23bc40dc950051415a04c8f919b81e01aa05db Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Tue, 28 Sep 2021 10:08:40 -0700 Subject: [PATCH 2/4] Update OEM Certificate scripts for Python 3 (This is a merge from the Widevine repo of http://go/wvgerrit/131084.) This patch updates the OEM Certificate scripts to work in Python 3. Previously, the scripts were nominally Python-2-only, though I actually couldn't get them to run in either Python 2 or 3. The following changes were necessary to make the scripts work in Python 3: 1) print() is now a function, not a keyword. 2) xrange() is now range(). 3) StringIO is now part of the io package. 4) Python 3 no longer lets you mix strings and byte buffers indiscriminately. As such, the code needed to be made more crisp about when it is treating a file or other blob of data as binary vs. text. Many instances of StringIO had to become BytesIO, and several literals had to be turned into byte literals. Passphrase command-line parameters are now parsed to UTF-8 bytes during argument parsing. Bug: 151736642 Test: oem_certificate_test.py Change-Id: I8ea5d0fda2ea5a2c0289be7612be0b4e508c4abf --- .../oem_certificate.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) mode change 100644 => 100755 libwvdrmengine/oem_certificate_generator/oem_certificate.py diff --git a/libwvdrmengine/oem_certificate_generator/oem_certificate.py b/libwvdrmengine/oem_certificate_generator/oem_certificate.py old mode 100644 new mode 100755 index 8d17c98b..71e77895 --- a/libwvdrmengine/oem_certificate_generator/oem_certificate.py +++ b/libwvdrmengine/oem_certificate_generator/oem_certificate.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 # Copyright 2017 Google LLC. All Rights Reserved. """OEM certificate generation tool. @@ -110,7 +111,7 @@ class X509CertificateChain(object): x509_stack = pkcs7.d.sign.cert certificates = [] - for i in xrange(backend._lib.sk_X509_num(x509_stack)): + for i in range(backend._lib.sk_X509_num(x509_stack)): x509_value = backend._ffi.gc( backend._lib.X509_dup(backend._lib.sk_X509_value(x509_stack, i)), backend._lib.X509_free) @@ -134,6 +135,10 @@ class X509CertificateChain(object): return backend._read_mem_bio(bio) +# Type for argparse to accept byte buffers on the command line +def utf8_bytes(utf8_str): + return utf8_str.encode('utf-8') + def _multiple_of_1024(key_size_str): """argparse custom type function for key size.""" key_size = int(key_size_str) @@ -299,9 +304,9 @@ def generate_leaf_certificate(args): def secure_erase(args): """Subparser handler for secure erasing of a file.""" length = args.file.tell() - for _ in xrange(args.passes): + for _ in range(args.passes): args.file.seek(0) - for _ in xrange(length): + for _ in range(length): args.file.write(os.urandom(1)) args.file.close() os.remove(args.file.name) @@ -403,6 +408,7 @@ def create_parser(): '--output_private_key_file', type=argparse.FileType('wb'), required=True) parser_csr.add_argument( '--passphrase', + type=utf8_bytes, help=('specify an optional passphrase to encrypt the private key. The ' 'private key is not encrypted if omitted.')) parser_csr.set_defaults(func=generate_csr) @@ -429,7 +435,7 @@ def create_parser(): '--root_certificate_file', type=argparse.FileType('rb'), required=True) parser_intermediate_cert.add_argument( '--root_private_key_file', type=argparse.FileType('rb'), required=True) - parser_intermediate_cert.add_argument('--root_private_key_passphrase') + parser_intermediate_cert.add_argument('--root_private_key_passphrase', type=utf8_bytes) parser_intermediate_cert.add_argument( '--output_certificate_file', type=argparse.FileType('wb'), required=True) parser_intermediate_cert.set_defaults(func=generate_intermediate_certificate) @@ -460,13 +466,14 @@ def create_parser(): '--intermediate_private_key_file', type=argparse.FileType('rb'), required=True) - parser_leaf_cert.add_argument('--intermediate_private_key_passphrase') + parser_leaf_cert.add_argument('--intermediate_private_key_passphrase', type=utf8_bytes) parser_leaf_cert.add_argument( '--output_certificate_file', type=argparse.FileType('wb'), required=True) parser_leaf_cert.add_argument( '--output_private_key_file', type=argparse.FileType('wb'), required=True) parser_leaf_cert.add_argument( '--passphrase', + type=utf8_bytes, help=('specify an optional passphrase to encrypt the private key. The ' 'private key is not encrypted if omitted.')) parser_leaf_cert.set_defaults(func=generate_leaf_certificate) @@ -497,7 +504,7 @@ def main(): args = sys.argv[1:] config_file_name = 'oem_certificate.cfg' if os.path.isfile(config_file_name): - print 'Load from args default configuration file: ', config_file_name + print('Load from args default configuration file: ', config_file_name) args.append('@' + config_file_name) parser_args = create_parser().parse_args(args) parser_args.func(parser_args) From bbb023db2660da899a0b5b374ffb3695d3ca4027 Mon Sep 17 00:00:00 2001 From: "John W. Bruce" Date: Mon, 4 Oct 2021 17:22:10 -0700 Subject: [PATCH 3/4] Use size_t for length in wvcrc32 (This is a merge of http://go/wvgerrit/134311.) This patch widens the variable type used for lengths in wvcrc32 from int to size_t. This fixes code that would trigger -Wshorten-64-to-32 by implicitly narrowing a variable from 64 to 32 bits. Bug: 194971260 Test: x86-64 Change-Id: I2887c18ff2a2c6dd3d65f966d9d1203fb050f736 --- libwvdrmengine/oemcrypto/test/wvcrc.cpp | 120 ++++++++++-------------- libwvdrmengine/oemcrypto/test/wvcrc32.h | 6 +- 2 files changed, 53 insertions(+), 73 deletions(-) diff --git a/libwvdrmengine/oemcrypto/test/wvcrc.cpp b/libwvdrmengine/oemcrypto/test/wvcrc.cpp index 1f0fbcf1..ea6de411 100644 --- a/libwvdrmengine/oemcrypto/test/wvcrc.cpp +++ b/libwvdrmengine/oemcrypto/test/wvcrc.cpp @@ -11,73 +11,52 @@ namespace wvoec { #define INIT_CRC32 0xffffffff -uint32_t wvrunningcrc32(const uint8_t* p_begin, int i_count, uint32_t i_crc) { - static uint32_t CRC32[256] = { - 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, - 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, - 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, - 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, - 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, - 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, - 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, - 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd, - 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, - 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, - 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81, - 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, - 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, - 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95, - 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, - 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, - 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae, - 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, - 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, - 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, - 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, - 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, - 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066, - 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, - 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, - 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692, - 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, - 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, - 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e, - 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, - 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, - 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a, - 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, - 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, - 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, - 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, - 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, - 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b, - 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, - 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, - 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, - 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, - 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, - 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3, - 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, - 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, - 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f, - 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, - 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, - 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, - 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, - 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, - 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30, - 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, - 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, - 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, - 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, - 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, - 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18, - 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, - 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, - 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c, - 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, - 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 - }; +uint32_t wvrunningcrc32(const uint8_t* p_begin, size_t i_count, + uint32_t i_crc) { + constexpr uint32_t CRC32[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; /* Calculate the CRC */ while (i_count > 0) { @@ -89,7 +68,7 @@ uint32_t wvrunningcrc32(const uint8_t* p_begin, int i_count, uint32_t i_crc) { return(i_crc); } -uint32_t wvcrc32(const uint8_t* p_begin, int i_count) { +uint32_t wvcrc32(const uint8_t* p_begin, size_t i_count) { return(wvrunningcrc32(p_begin, i_count, INIT_CRC32)); } @@ -97,11 +76,12 @@ uint32_t wvcrc32Init() { return INIT_CRC32; } -uint32_t wvcrc32Cont(const uint8_t* p_begin, int i_count, uint32_t prev_crc) { +uint32_t wvcrc32Cont(const uint8_t* p_begin, size_t i_count, + uint32_t prev_crc) { return(wvrunningcrc32(p_begin, i_count, prev_crc)); } -uint32_t wvcrc32n(const uint8_t* p_begin, int i_count) { +uint32_t wvcrc32n(const uint8_t* p_begin, size_t i_count) { return htonl(wvrunningcrc32(p_begin, i_count, INIT_CRC32)); } diff --git a/libwvdrmengine/oemcrypto/test/wvcrc32.h b/libwvdrmengine/oemcrypto/test/wvcrc32.h index 9cf72af1..bf005057 100644 --- a/libwvdrmengine/oemcrypto/test/wvcrc32.h +++ b/libwvdrmengine/oemcrypto/test/wvcrc32.h @@ -11,12 +11,12 @@ namespace wvoec { -uint32_t wvcrc32(const uint8_t* p_begin, int i_count); +uint32_t wvcrc32(const uint8_t* p_begin, size_t i_count); uint32_t wvcrc32Init(); -uint32_t wvcrc32Cont(const uint8_t* p_begin, int i_count, uint32_t prev_crc); +uint32_t wvcrc32Cont(const uint8_t* p_begin, size_t i_count, uint32_t prev_crc); // Convert to network byte order -uint32_t wvcrc32n(const uint8_t* p_begin, int i_count); +uint32_t wvcrc32n(const uint8_t* p_begin, size_t i_count); } // namespace wvoec From c554b30716dfa8021c4ac3bfae55d49134905a8d Mon Sep 17 00:00:00 2001 From: Alex Dale Date: Fri, 1 Oct 2021 16:51:59 -0700 Subject: [PATCH 4/4] Synced license protocol protos to g3 latests. [ Merge of http://go/wvgerrit/128023 ] Several of the messages in license_protocol.proto have fallen out of sync with their source-of-truth in Google3. This change updates most of the proto messages used by the CDM. None of these changes immediately affect the CDM. Bug: 192286204 Test: Build service and unit tests Change-Id: I83414167d51f2443fe39f02ab160341918e409c9 --- .../cdm/core/src/license_protocol.proto | 267 +++++++++++------- 1 file changed, 163 insertions(+), 104 deletions(-) diff --git a/libwvdrmengine/cdm/core/src/license_protocol.proto b/libwvdrmengine/cdm/core/src/license_protocol.proto index 1ad2ce1a..18cc26e5 100644 --- a/libwvdrmengine/cdm/core/src/license_protocol.proto +++ b/libwvdrmengine/cdm/core/src/license_protocol.proto @@ -1,6 +1,3 @@ -// ---------------------------------------------------------------------------- -// license_protocol.proto -// ---------------------------------------------------------------------------- // Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. @@ -71,6 +68,51 @@ message LicenseIdentification { optional LicenseType type = 4; optional int32 version = 5; optional bytes provider_session_token = 6; + // Set by the SDK representing the rental duration from the initial license. + optional int64 original_rental_duration_seconds = 7; + // Set by the SDK representing the playback duration from the initial license. + optional int64 original_playback_duration_seconds = 8; + // Set by the SDK representing the start time of the initial license in + // seconds (UTC). This is from the original license's license_start_time, + // which is from the LicenseRequest.request_time when set, or set by the + // server to be the time that the original license was processed. + optional int64 original_start_time_seconds = 9; +} + +// This message is used to indicate the license cateogry spec for a license as +// a part of initial license issuance. +message LicenseCategorySpec { + // Possible license categories. + enum LicenseCategory { + // By default, License is used for single content. + SINGLE_CONTENT_LICENSE_DEFAULT = 0; + // License is used for multiple contents (could be a combination of + // single contents and groups of contents). + MULTI_CONTENT_LICENSE = 1; + // License is used for contents logically grouped. + GROUP_LICENSE = 2; + } + // Optional. License category indicates if license is used for single + // content, multiple contents (could be a combination of + // single contents and groups of contents) or a group of contents. + optional LicenseCategory license_category = 1; + // Optional. Content or group ID covered by the license. + oneof content_or_group_id { + // Content_id would be present if it is a license for single content. + bytes content_id = 2; + // Group_id would be present if the license is a multi_content_license or + // group_license. Group Id could be the name of a group of contents, + // defined by licensor. + bytes group_id = 3; + } +} + +message ProxyInfo { + // Indicates SDK type(Including UNKNOWN_SERVICE_TYPE, LICENSE_PROXY_SDK, + // CAS_PROXY_SDK). + optional DrmCertificate.ServiceType sdk_type = 1; + // Indicates the version of SDK. + optional string sdk_version = 2; } message License { @@ -144,12 +186,16 @@ message License { message KeyContainer { enum KeyType { - SIGNING = 1; // Exactly one key of this type must appear. + SIGNING = 1; // No more than one signing key may appear. CONTENT = 2; // Content key. KEY_CONTROL = 3; // Key control block for license renewals. No key. OPERATOR_SESSION = 4; // wrapped keys for auxiliary crypto operations. ENTITLEMENT = 5; // Entitlement keys. OEM_CONTENT = 6; // Partner-specific content key. + // Public signing key provided by content providers. Currently used by CAS + // for verifying the received ECM/EMM signature. Only EC key is supported + // for now. + PROVIDER_ECM_VERIFIER_PUBLIC_KEY = 7; } // The SecurityLevel enumeration allows the server to communicate the level @@ -176,8 +222,6 @@ message License { } message KeyControl { - // |key_control| is documented in: - // Widevine Modular DRM Security Integration Guide for CENC // If present, the key control must be communicated to the secure // environment prior to any usage. This message is automatically generated // by the Widevine License Server SDK. @@ -223,6 +267,9 @@ message License { optional bool disable_analog_output = 4 [default = false]; // Optional requirement to indicate digital output is not allowed. optional bool disable_digital_output = 5 [default = false]; + // Optional. If set, it indicates digital video recording (DVR) is + // allowed. + optional bool allow_record = 6 [default = false]; } message VideoResolutionConstraint { @@ -243,6 +290,28 @@ message License { optional bool allow_signature_verify = 4 [default = false]; } + // KeyCategorySpec message is used to identify if current key is generated + // for a single content or a group of contents. Currently it is only used in + // CAS request. + message KeyCategorySpec { + // Represents what kind of content a key is used for. + enum KeyCategory { + // By default, key is created for single content. + SINGLE_CONTENT_KEY_DEFAULT = 0; + // Key is created for a group of contents. + GROUP_KEY = 1; + } + // Indicate if the current key is created for single content or for group + // use. + optional KeyCategory key_category = 1; + // Id for key category. If it is a key for single content, this id + // represents the content_id. Otherwise, it represents a group_id. + oneof content_or_group_id { + bytes content_id = 2; + bytes group_id = 3; + } + } + optional bytes id = 1; optional bytes iv = 2; optional bytes key = 3; @@ -268,6 +337,10 @@ message License { // Optional not limited to commonly known track types such as SD, HD. // It can be some provider defined label to identify the track. optional string track_label = 12; + // Optional. It is used to identify if current key is generated for a + // single content or a group of contents. Currently it is only used in CAS + // request. + optional KeyCategorySpec key_category_spec = 13; } optional LicenseIdentification id = 1; @@ -288,8 +361,6 @@ message License { // 8 byte verification field "HDCPDATA" followed by unsigned 32 bit minimum // HDCP SRM version (whether the version is for HDCP1 SRM or HDCP2 SRM // depends on client max_hdcp_version). - // Additional details can be found in Widevine Modular DRM Security - // Integration Guide for CENC. optional bytes srm_requirement = 8; // If present this contains a signed SRM file (either HDCP1 SRM or HDCP2 SRM // depending on client max_hdcp_version) that should be installed on the @@ -301,6 +372,10 @@ message License { [default = PLATFORM_NO_VERIFICATION]; // IDs of the groups for which keys are delivered in this license, if any. repeated bytes group_ids = 11; + // Optional. LicenseCategorySpec is used to indicate the license cateogry for + // a license. It could be used as a part of initial license issuance or shown + // as a part of license in license response. + optional LicenseCategorySpec license_category_spec = 12; } enum ProtocolVersion { @@ -386,6 +461,8 @@ message LicenseError { // The service is currently unavailable due to the backend being down // or similar circumstances. SERVICE_UNAVAILABLE = 3; + // The device credentials are expired. The device must re-provision. + EXPIRED_DRM_DEVICE_CERTIFICATE = 4; } optional Error error_code = 1; } @@ -438,8 +515,9 @@ message SignedMessage { enum SessionKeyType { UNDEFINED = 0; WRAPPED_AES_KEY = 1; - EPHERMERAL_ECC_PUBLIC_KEY = 2; + EPHEMERAL_ECC_PUBLIC_KEY = 2; } + optional MessageType type = 1; optional bytes msg = 2; // Required field that contains the signature of the bytes of msg. @@ -469,6 +547,11 @@ message SignedMessage { // The core message is the simple serialization of fields used by OEMCrypto. // This field was introduced in OEMCrypto API v16. optional bytes oemcrypto_core_message = 9; + // Optional field that indicates the hash algorithm used in signature scheme. + optional HashAlgorithmProto hash_algorithm = 10; + // If true it indicates that a LICENSE message session key was based on an + // alternate key provided by the client credentials. + optional bool using_secondary_key = 11; } // ---------------------------------------------------------------------------- @@ -493,20 +576,44 @@ enum HashAlgorithmProto { // Public protocol buffer definitions for Widevine Device Certificate // Provisioning protocol. +// A KeyToCertify contains a client generated public key to be incorporated into +// a signed certificate. +message PublicKeyToCertify { + // A KeyType indicates a high level key type. + enum KeyType { + KEY_TYPE_UNSPECIFIED = 0; + RSA = 1; + ECC = 2; + } + + // |public_key| contains the bytes of a PKCS#1 ASN.1 DER-encoded public key. + optional bytes public_key = 1; + // KeyType contains a highlevel hint to use in parsing the serialized key + // contained in |public_key|. If the key is an EC key, curve parameters can be + // extracted from the deserialized key. + // Keys are expected to match the certificate key type in the device + // record. + optional KeyType key_type = 2; + // The signature of |public_key|. + // Keys that are signed using ECDSA or RSA should hash the message using + // SHA-256. + optional bytes signature = 3; +} + // ProvisioningOptions specifies the type of certificate to specify and // in the case of X509 certificates, the certificate authority to use. message ProvisioningOptions { enum CertificateType { - WIDEVINE_DRM = 0; // Default. The original certificate type. - X509 = 1; // X.509 certificate. + WIDEVINE_DRM = 0; // Default. The original certificate type. + X509 = 1; // X.509 certificate. WIDEVINE_KEYBOX = 2; } optional CertificateType certificate_type = 1 [default = WIDEVINE_DRM]; // Contains the application-specific name used to identify the certificate - // authority for signing the generated certificate. This is required if the - // certificate type is X509. + // authority for signing the generated certificate. This is required if and + // only if the certificate type is X509. optional string certificate_authority = 2; // System ID for OTA keybox provisioning. Requires device secure boot. optional uint32 system_id = 3; @@ -565,6 +672,10 @@ message ProvisioningRequest { optional EncryptedSessionKeys encrypted_session_keys = 8; // The custom request for Android Attestation OTA. optional AndroidAttestationOtaKeyboxRequest android_ota_keybox_request = 9; + // Specifies the public key that should be certified by the provisioning + // server. The client holds the private key. If specified, the response no + // longer needs to contain server generated |device_rsa_key|. + optional PublicKeyToCertify certificate_public_key = 10; } // Provisioning response sent by the provisioning server to client devices. @@ -627,8 +738,7 @@ message ProvisioningResponse { } // Protocol-specific context data used to hold the state of the server in -// stateful provisioning protocols. For more information, please refer to -// "Widevine DRM Provisioning using Third-Part and Stateful Protocols". +// stateful provisioning protocols. message ProvisioningContext { // Serialized ProvisioningContextKeyData. Required. optional bytes key_data = 1; @@ -643,6 +753,8 @@ message SignedProvisioningContext { // RSASSA-PSS signature of provisioning_context. Signed with service private // key. optional bytes signature = 2; + // Optional field that indicates the hash algorithm used in signature scheme. + optional HashAlgorithmProto hash_algorithm = 3; } // Cryptographic tokens to be used for ProvisioningContext. @@ -664,25 +776,27 @@ message SignedProvisioningMessage { // implementation. E.g. embedded in the ProvisioningResponse rather than // returning a 400 error to the caller. VERSION_1_1 = 2; - // Version 2 will implement a larger change of the protocol definition - // in protobufs. This will provide a cleaner separation between protocols. - VERSION_2 = 3; } enum ProvisioningType { // This enum was renamed to avoid confusion PROVISIONING_TYPE_UNSPECIFIED = 0; SERVICE_CERTIFICATE_REQUEST = 1; // Service certificate request. PROVISIONING_20 = 2; // Keybox factory-provisioned devices. - PROVISIONING_30 = 3; // OEM certificate factory-provisioned devices. + PROVISIONING_30 = 3; // OEM certificate factory-provisioned devices. + // Devices use Boot Certificate Chain (BCC) to provision an OEM certificate. + PROVISIONING_40 = 5; + // These are provisioning methods that are only supported by internal + // Widevine services. They should not be exposed in the SDK. ARCPP_PROVISIONING = 4; // ChromeOS/Arc++ devices. // Android-Attestation-based OTA keyboxes. ANDROID_ATTESTATION_KEYBOX_OTA = 6; - INTEL_SIGMA_101 = 101; // Intel Sigma 1.0.1 protocol. + INTEL_SIGMA_101 = 101; // Intel Sigma 1.0.1 protocol. + INTEL_SIGMA_210 = 210; // Intel Sigma 2.1.0 protocol. } // Serialized protobuf message for the corresponding protocol and stage of // the provisioning exchange. ProvisioningRequest or ProvisioningResponse - // in the case of Provisioning 2.0, 3.0 and ARCPP_PROVISIONING. Required. + // in the case of Provisioning 2.0, 3.0, 4.0 and ARCPP_PROVISIONING. Required. optional bytes message = 1; // HMAC-SHA256 (Keybox) or RSASSA-PSS (OEM) signature of message. Required // for provisioning 2.0 and 3.0. For ARCPP_PROVISIONING, only used in @@ -721,6 +835,7 @@ message ClientIdentification { DRM_DEVICE_CERTIFICATE = 1; REMOTE_ATTESTATION_CERTIFICATE = 2; OEM_DEVICE_CERTIFICATE = 3; + BOOT_CERTIFICATE_CHAIN = 4; } message NameValue { @@ -738,6 +853,13 @@ message ClientIdentification { HDCP_V2_1 = 3; HDCP_V2_2 = 4; HDCP_V2_3 = 5; + // The existing HDCP_V1 will be used for backwards compatibility with pre + // OEM crypto v17. + HDCP_V1_0 = 6; + HDCP_V1_1 = 7; + HDCP_V1_2 = 8; + HDCP_V1_3 = 9; + HDCP_V1_4 = 10; HDCP_NO_DIGITAL_OUTPUT = 0xff; } @@ -762,8 +884,7 @@ message ClientIdentification { optional HdcpVersion max_hdcp_version = 4 [default = HDCP_NONE]; optional uint32 oem_crypto_api_version = 5; // Client has hardware support for protecting the usage table, such as - // storing the generation number in secure memory. For Details, see: - // Widevine Modular DRM Security Integration Guide for CENC + // storing the generation number in secure memory. optional bool anti_rollback_usage_table = 6 [default = false]; // The client shall report |srm_version| if available. optional uint32 srm_version = 7; @@ -779,8 +900,7 @@ message ClientIdentification { // quality of content to serve. Currently defined tiers are // 1 (low), 2 (medium) and 3 (high). Any other value indicates that // the resource rating is unavailable or reporting erroneous values - // for that device. For details see, - // Widevine Modular DRM Security Integration Guide for CENC + // for that device. optional uint32 resource_rating_tier = 12 [default = 0]; } @@ -805,7 +925,7 @@ message ClientIdentification { // Serialized VmpData message. Optional. optional bytes vmp_data = 7; // Optional field that may contain additional provisioning credentials. - repeated ClientCredentials device_credentials = 8; + optional ClientCredentials device_credentials = 8; } // EncryptedClientIdentification message used to hold ClientIdentification @@ -953,6 +1073,8 @@ message DrmCertificate { // signed_drm_certificate.proto // ---------------------------------------------------------------------------- // Description of section: +// Signed device certificate definition. + // DrmCertificate signed by a higher (CA) DRM certificate. message SignedDrmCertificate { // Serialized certificate. Required. @@ -966,80 +1088,6 @@ message SignedDrmCertificate { optional HashAlgorithmProto hash_algorithm = 4; } -// ---------------------------------------------------------------------------- -// provisioned_device_info.proto -// ---------------------------------------------------------------------------- -// Description of section: -// Provisioned device info format definitions. - -// Contains device model information for a provisioned device. -message ProvisionedDeviceInfo { - enum WvSecurityLevel { - // Defined in "Widevine Security Integration Guide for DASH on Android" - LEVEL_UNSPECIFIED = 0; - LEVEL_1 = 1; - LEVEL_2 = 2; - LEVEL_3 = 3; - } - - // Widevine initial provisioning / bootstrapping method. DRM certificates are - // required for retrieving licenses, so if a DRM certificate is not initially - // provisioned, then the provisioned credentials will be used to provision - // a DRM certificate via the Widevine Provisioning Service. - enum ProvisioningMethod { - // Don't use this. - PROVISIONING_METHOD_UNSPECIFIED = 0; - // Factory-provisioned device-unique keybox. - FACTORY_KEYBOX = 1; - // Factory-provisioned device-unique OEM certificate. - FACTORY_OEM_DEVICE_CERTIFICATE = 2; - // Factory-provisioned model-group OEM certificate. - FACTORY_OEM_GROUP_CERTIFICATE = 3; - // Factory-provisioned model-group DRM certificate (Level-3 "baked in"). - FACTORY_DRM_GROUP_CERTIFICATE = 4; - // OTA-provisioned keybox (Level-1 ARC++). - OTA_KEYBOX = 5; - // OTA-provisioned device-unique OEM certificate. - OTA_OEM_DEVICE_CERTIFICATE = 6; - // OTA-provisioned model-group OEM certificate. - OTA_OEM_GROUP_CERTIFICATE = 7; - // OTA-provisioned device-unique DRM certificate (Bedrock). - OTA_DRM_DEVICE_CERTIFICATE = 8; - } - // Represents additional devices that are associated with the device. These - // are devices that have the systemID, but a different 'manufacturer'/'model' - // etc. - message ModelInfo { - // Represents the device manufacturer. Typically, this will be Philips, LG, - // Sharp, etc. - optional string manufacturer = 1; - // Model of the device. - optional string model = 2; - } - // Widevine system ID for the device. Mandatory. - optional uint32 system_id = 1; - // Name of system-on-a-chip. Optional. - optional string soc = 2; - // First registered manufacturer. Optional. - optional string manufacturer = 3; - // First registered manufacturer's model name. Matches "brand" in device - // metadata. Optional. - optional string model = 4; - // First registered type of device (Phone, Tablet, TV, etc). - optional string device_type = 5; - // First registered device model year. Optional. - optional uint32 model_year = 6; - // Widevine-defined security level. Optional. - optional WvSecurityLevel security_level = 7 [default = LEVEL_UNSPECIFIED]; - // True if the certificate corresponds to a test (non production) device. - // Optional. - optional bool test_device = 8 [default = false]; - // Indicates the type of device root of trust which was factory provisioned. - optional ProvisioningMethod provisioning_method = 9; - // A list of ModelInfo using the same system_id. - repeated ModelInfo model_info = 10; -} - // ---------------------------------------------------------------------------- // widevine_pssh.proto // ---------------------------------------------------------------------------- @@ -1067,7 +1115,7 @@ message WidevinePsshData { optional uint32 entitlement_key_size_bytes = 5 [default = 32]; } - // Entitlement or content key IDs. Can onnly present in SINGLE or ENTITLEMENT + // Entitlement or content key IDs. Can only present in SINGLE or ENTITLEMENT // PSSHs. May be repeated to facilitate delivery of multiple keys in a // single license. Cannot be used in conjunction with content_id or // group_ids, which are the preferred mechanism. @@ -1108,8 +1156,8 @@ message WidevinePsshData { // Group identifiers for all groups to which the content belongs. This can // be used to deliver licenses to unlock multiple titles / channels. - // Optional, and may only be present in ENTITLEMENT and ENTITLED_KEY PSSHs, and - // not in conjunction with key_ids. + // Optional, and may only be present in ENTITLEMENT and ENTITLED_KEY PSSHs, + // and not in conjunction with key_ids. repeated bytes group_ids = 13; // Copy/copies of the content key used to decrypt the media stream in which @@ -1125,11 +1173,22 @@ message WidevinePsshData { // Current values are "HDR". optional string video_feature = 15; + // Audiofeature identifier, which is used in conjunction with |content_id| + // to determine the set of keys to be returned in the license. Cannot be + // present in conjunction with |key_ids|. + // Current values are "commentary". + optional string audio_feature = 16; + + // Entitlement period index for media using entitlement key rotation. Can only + // present in ENTITLEMENT PSSHs. It always corresponds to the entitlement key + // period. + optional uint32 entitlement_period_index = 17; + //////////////////////////// Deprecated Fields //////////////////////////// enum Algorithm { UNENCRYPTED = 0; AESCTR = 1; - }; + } optional Algorithm algorithm = 1 [deprecated = true]; optional string provider = 3 [deprecated = true]; optional string track_type = 5 [deprecated = true];