Add Privacy Mode and Serivce Certificate Support

This merges the following changes from the Widevine CDM repository:

da001b6  Add Privacy mode and service certificate
  This adds support to the CDM for privacy mode and service certificates.

92bf200  Add support for using Youtube Content Protection server for testing
  Enables testing with Youtube Content Protection server. Google Play license
  server is still the default. Select YTCP server by using the flag -icp
    e.g. adb shell '/system/bin/request_license_test -icp'

85dcd60  Fixes to enable privacy mode
  These includes changes to use PKCS7 padding, corrected root CA formatting
  and changes to integration test. Also refactored service certificate
  handling.

989971c  Correction to request license test
  Corrected PropertySetTest to provision when needed. Also added disabled
  privacy tests to run against YTCP staging server until GooglePlay
  integration is complete.

Bug: 10109249
Change-Id: If81d68c65d743d77a485406f48d1be41a74de0af
This commit is contained in:
Rahul Frias
2013-08-15 11:36:20 -07:00
parent f6c2a60485
commit a2e15186e5
12 changed files with 290 additions and 222 deletions

View File

@@ -443,9 +443,6 @@ CdmResponseType CdmLicense::HandleKeyResponse(
return KEY_ERROR;
}
if (service_certificate_response_pending_)
return CdmLicense::HandleServiceCertificateResponse(license_response);
SignedMessage signed_response;
if (!signed_response.ParseFromString(license_response)) {
LOGE(
@@ -454,8 +451,17 @@ CdmResponseType CdmLicense::HandleKeyResponse(
return KEY_ERROR;
}
if (signed_response.type() == SignedMessage::ERROR) {
return HandleKeyErrorResponse(signed_response);
switch (signed_response.type()) {
case SignedMessage::LICENSE:
break;
case SignedMessage::SERVICE_CERTIFICATE:
return CdmLicense::HandleServiceCertificateResponse(signed_response);
case SignedMessage::ERROR:
return HandleKeyErrorResponse(signed_response);
default:
LOGE("CdmLicense::HandleKeyResponse: unrecognized signed message type: %d"
, signed_response.type());
return KEY_ERROR;
}
if (!signed_response.has_signature()) {
@@ -652,40 +658,12 @@ bool CdmLicense::PrepareServiceCertificateRequest(CdmKeyMessage* signed_request,
signed_message.set_type(SignedMessage::SERVICE_CERTIFICATE_REQUEST);
signed_message.SerializeToString(signed_request);
*server_url = server_url_;
service_certificate_response_pending_ = true;
return true;
}
CdmResponseType CdmLicense::HandleServiceCertificateResponse(
const CdmKeyResponse& service_certificate_response) {
if (!initialized_) {
LOGE("CdmLicense::HandleServiceCertificateResponse: not initialized");
return KEY_ERROR;
}
if (service_certificate_response.empty()) {
LOGE(
"CdmLicense::HandleServiceCertificateResponse: empty service "
"certificate response");
return KEY_ERROR;
}
SignedMessage signed_response;
if (!signed_response.ParseFromString(service_certificate_response))
return KEY_ERROR;
switch (signed_response.type()) {
case SignedMessage::ERROR:
return HandleKeyErrorResponse(signed_response);
case SignedMessage::SERVICE_CERTIFICATE:
break; // expected message type
default:
LOGE(
"CdmLicense::HandleServiceCertificateResponse: unexpected signed"
"message type: %d",
signed_response.type());
return KEY_ERROR;
}
const video_widevine_server::sdk::SignedMessage& signed_response) {
SignedDeviceCertificate signed_service_certificate;
if (!signed_service_certificate.ParseFromString(signed_response.msg())) {
@@ -696,12 +674,12 @@ CdmResponseType CdmLicense::HandleServiceCertificateResponse(
}
RsaPublicKey root_ca_key;
std::vector<uint8_t> ca_public_key(
std::string ca_public_key(
&kServiceCertificateCAPublicKey[0],
&kServiceCertificateCAPublicKey[sizeof(kServiceCertificateCAPublicKey)]);
if (!root_ca_key.Init(b2a_hex(ca_public_key))) {
if (!root_ca_key.Init(ca_public_key)) {
LOGE(
"CdmLicense::HandleServiceCertificateResponse: public key"
"CdmLicense::HandleServiceCertificateResponse: public key "
"initialization failed");
return KEY_ERROR;
}

View File

@@ -11,17 +11,15 @@
#include "privacy_crypto.h"
#include "log.h"
#include "openssl/aes.h"
#include "openssl/bio.h"
#include "openssl/err.h"
#include "openssl/evp.h"
#include "openssl/pem.h"
#include "openssl/rsa.h"
#include "openssl/sha.h"
namespace {
const int kPssSaltLength = 20;
const int kRsaPkcs1OaepPaddingLength = 41;
const int kBitsInAByte = 8;
} // namespace
namespace wvcdm {
@@ -35,8 +33,10 @@ bool AesCbcKey::Init(const std::string& key) {
LOGE("AesCbcKey::Init: unexpected key size: %d", key.size());
return false;
}
if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(&key[0]),
key.size() * kBitsInAByte, &key_) != 0) {
EVP_CIPHER_CTX_init(&ctx_);
if (EVP_EncryptInit(&ctx_, EVP_aes_128_cbc(),
reinterpret_cast<const uint8_t*>(&key[0]), NULL) == 0) {
LOGE("AesCbcKey::Init: AES CBC key setup failure: %s",
ERR_error_string(ERR_get_error(), NULL));
return false;
@@ -51,10 +51,6 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out,
LOGE("AesCbcKey::Encrypt: no cleartext provided");
return false;
}
if (in.size() % AES_BLOCK_SIZE) {
LOGE("AesCbcKey::Encrypt: cleartext not a block multiple: %d", in.size());
return false;
}
if (iv == NULL) {
LOGE("AesCbcKey::Encrypt: initialization vector destination not provided");
return false;
@@ -72,11 +68,33 @@ bool AesCbcKey::Encrypt(const std::string& in, std::string* out,
return false;
}
out->resize(in.size());
if (EVP_EncryptInit(&ctx_, NULL, NULL,
reinterpret_cast<const uint8_t*>(iv->data())) == 0) {
LOGE("AesCbcKey::Encrypt: AES CBC iv setup failure: %s",
ERR_error_string(ERR_get_error(), NULL));
return false;
}
AES_cbc_encrypt(reinterpret_cast<const uint8_t*>(&in[0]),
reinterpret_cast<uint8_t*>(&out[0]), in.size(), &key_,
reinterpret_cast<uint8_t*>(&iv[0]), AES_ENCRYPT);
out->resize(in.size() + AES_BLOCK_SIZE);
int out_length = out->size();
if (EVP_EncryptUpdate(
&ctx_, reinterpret_cast<uint8_t*>(&(*out)[0]), &out_length,
reinterpret_cast<uint8_t*>(const_cast<char*>(in.data())),
in.size()) == 0) {
LOGE("AesCbcKey::Encrypt: encryption failure: %s",
ERR_error_string(ERR_get_error(), NULL));
return false;
}
int padding = 0;
if (EVP_EncryptFinal(&ctx_, reinterpret_cast<uint8_t*>(&(*out)[out_length]),
&padding) == 0) {
LOGE("AesCbcKey::Encrypt: PKCS7 padding failure: %s",
ERR_error_string(ERR_get_error(), NULL));
return false;
}
out->resize(out_length + padding);
return true;
}
@@ -103,7 +121,8 @@ bool RsaPublicKey::Init(const std::string& serialized_key) {
BIO_free(bio);
if (key_ == NULL) {
LOGE("RsaPublicKey::Init: RSA key deserialization failure");
LOGE("RsaPublicKey::Init: RSA key deserialization failure: %s",
ERR_error_string(ERR_get_error(), NULL));
return false;
}