am b5a782bd: Changes JSON format for provisioning request and response to match server change.
* commit 'b5a782bdb22cb5698302665640f72cdc0b753f84': Changes JSON format for provisioning request and response to match server change.
This commit is contained in:
@@ -102,7 +102,6 @@ class CdmEngine : public TimerHandler {
|
|||||||
bool CancelSessions();
|
bool CancelSessions();
|
||||||
void CleanupProvisioningSession(const CdmSessionId& cdm_session_id);
|
void CleanupProvisioningSession(const CdmSessionId& cdm_session_id);
|
||||||
void ComposeJsonRequest(const std::string& message,
|
void ComposeJsonRequest(const std::string& message,
|
||||||
const std::string& signature,
|
|
||||||
CdmProvisioningRequest* request);
|
CdmProvisioningRequest* request);
|
||||||
|
|
||||||
// Parse a blob of multiple concatenated PSSH atoms to extract the first
|
// Parse a blob of multiple concatenated PSSH atoms to extract the first
|
||||||
|
|||||||
@@ -22,7 +22,9 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const std::string kDefaultProvisioningServerUrl =
|
const std::string kDefaultProvisioningServerUrl =
|
||||||
"http://www-googleapis-test.sandbox.google.com/certificateprovisioning/v1/devicecertificates/create";
|
"http://www-googleapis-test.sandbox.google.com/"
|
||||||
|
"certificateprovisioning/v1/devicecertificates/create"
|
||||||
|
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
@@ -340,38 +342,29 @@ void CdmEngine::CleanupProvisioningSession(const CdmSessionId& cdm_session_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function converts message and signature into base64 format.
|
* This function converts SignedProvisioningRequest into base64 format.
|
||||||
* It then wraps it in JSON format expected by the Apiary frontend.
|
* It then wraps it in JSON format expected by the Apiary frontend.
|
||||||
* Apiary requires the base64 encoding to replace '+' with minus '-',
|
* Apiary requires the base64 encoding to replace '+' with minus '-',
|
||||||
* and '/' with underscore '_'; opposite to stubby's.
|
* and '/' with underscore '_'; opposite to stubby's.
|
||||||
*
|
*
|
||||||
* Returns the JSON formated string in *request.
|
* Returns the JSON formated string in *request.
|
||||||
* The JSON formated request takes the following format:
|
* The JSON formated request takes the following format:
|
||||||
* {
|
*
|
||||||
* 'signedRequest': {
|
* {'signedRequest':'base64 encoded message'}
|
||||||
* 'message': 'base64 encoded message',
|
|
||||||
* 'signature': 'base64 encoded signature'
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
*/
|
*/
|
||||||
void CdmEngine::ComposeJsonRequest(
|
void CdmEngine::ComposeJsonRequest(
|
||||||
const std::string& message,
|
const std::string& message,
|
||||||
const std::string& signature,
|
|
||||||
CdmProvisioningRequest* request) {
|
CdmProvisioningRequest* request) {
|
||||||
|
|
||||||
// performs base64 encoding for message
|
// performs base64 encoding for message
|
||||||
std::vector<uint8_t> message_vector(message.begin(), message.end());
|
std::vector<uint8_t> message_vector(message.begin(), message.end());
|
||||||
std::string message_b64 = Base64SafeEncode(message_vector);
|
std::string message_b64 = Base64SafeEncode(message_vector);
|
||||||
|
|
||||||
// performs base64 encoding for signature
|
request->assign("{'signedRequest':'");
|
||||||
std::vector<uint8_t> signature_vector(signature.begin(), signature.end());
|
|
||||||
std::string signature_b64 = Base64SafeEncode(signature_vector);
|
|
||||||
|
|
||||||
request->assign("{'signedRequest':{'message':'");
|
|
||||||
request->append(message_b64);
|
request->append(message_b64);
|
||||||
request->append("','signature':'");
|
request->append("'}");
|
||||||
request->append(signature_b64);
|
|
||||||
request->append("'}}");
|
LOGD("json request:\r\n%s", request->c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -458,27 +451,33 @@ CdmResponseType CdmEngine::GetProvisioningRequest(
|
|||||||
std::string the_nonce(reinterpret_cast<char*>(&nonce), sizeof(nonce));
|
std::string the_nonce(reinterpret_cast<char*>(&nonce), sizeof(nonce));
|
||||||
provisioning_request.set_nonce(the_nonce);
|
provisioning_request.set_nonce(the_nonce);
|
||||||
|
|
||||||
// Serializes the provisioning request.
|
std::string serialized_message;
|
||||||
std::string serialized_request;
|
provisioning_request.SerializeToString(&serialized_message);
|
||||||
provisioning_request.SerializeToString(&serialized_request);
|
|
||||||
|
|
||||||
// Derives signing and encryption keys and constructs signature.
|
// Derives signing and encryption keys and constructs signature.
|
||||||
std::string request_signature;
|
std::string request_signature;
|
||||||
if (!crypto_session->PrepareRequest(serialized_request,
|
if (!crypto_session->PrepareRequest(serialized_message,
|
||||||
&request_signature, true)) {
|
&request_signature, true)) {
|
||||||
request->clear();
|
request->clear();
|
||||||
CleanupProvisioningSession(cdm_session_id);
|
CleanupProvisioningSession(cdm_session_id);
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (request_signature.empty()) {
|
if (request_signature.empty()) {
|
||||||
request->clear();
|
request->clear();
|
||||||
CleanupProvisioningSession(cdm_session_id);
|
CleanupProvisioningSession(cdm_session_id);
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SignedProvisioningMessage signed_provisioning_msg;
|
||||||
|
signed_provisioning_msg.set_message(serialized_message);
|
||||||
|
signed_provisioning_msg.set_signature(request_signature);
|
||||||
|
|
||||||
|
std::string serialized_request;
|
||||||
|
signed_provisioning_msg.SerializeToString(&serialized_request);
|
||||||
|
|
||||||
// converts request into JSON string
|
// converts request into JSON string
|
||||||
ComposeJsonRequest(serialized_request, request_signature, request);
|
ComposeJsonRequest(serialized_request, request);
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -527,26 +526,18 @@ bool CdmEngine::ParseJsonResponse(
|
|||||||
CdmResponseType CdmEngine::HandleProvisioningResponse(
|
CdmResponseType CdmEngine::HandleProvisioningResponse(
|
||||||
CdmProvisioningResponse& response) {
|
CdmProvisioningResponse& response) {
|
||||||
if (response.empty()) {
|
if (response.empty()) {
|
||||||
LOGE("CdmEngine::HandleProvisioningResponse: Empty provisioning response.");
|
LOGE("Empty provisioning response.");
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
// Extracts response from JSON string, decodes base64 signed message
|
// Extracts signed response from JSON string, decodes base64 signed response
|
||||||
const std::string kMessageStart = "\"message\": \"";
|
const std::string kMessageStart = "\"signedResponse\": \"";
|
||||||
const std::string kMessageEnd = "\",";
|
const std::string kMessageEnd = "\"";
|
||||||
std::string signed_message;
|
std::string serialized_signed_response;
|
||||||
if (!ParseJsonResponse(response, kMessageStart, kMessageEnd, &signed_message)) {
|
if (!ParseJsonResponse(response, kMessageStart, kMessageEnd,
|
||||||
LOGE("Fails to extract signed message from JSON response");
|
&serialized_signed_response)) {
|
||||||
return UNKNOWN_ERROR;
|
LOGE("Fails to extract signed serialized response from JSON response");
|
||||||
}
|
|
||||||
|
|
||||||
// Extracts signature from JSON string, decodes base64 signature
|
|
||||||
const std::string kSignatureStart = "\"signature\": \"";
|
|
||||||
const std::string kSignatureEnd = "\"";
|
|
||||||
std::string signature;
|
|
||||||
if (!ParseJsonResponse(response, kSignatureStart, kSignatureEnd, &signature)) {
|
|
||||||
LOGE("Fails to extract signature from JSON response");
|
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -568,7 +559,8 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
|
|||||||
CdmSessionId cdm_session_id = provisioning_session_->session_id();
|
CdmSessionId cdm_session_id = provisioning_session_->session_id();
|
||||||
CryptoSession* crypto_session = crypto_engine->FindSession(cdm_session_id);
|
CryptoSession* crypto_session = crypto_engine->FindSession(cdm_session_id);
|
||||||
if (!crypto_session) {
|
if (!crypto_session) {
|
||||||
LOGE("HandleProvisioningResponse: fails to find %s", cdm_session_id.c_str());
|
LOGE("HandleProvisioningResponse: fails to find %s",
|
||||||
|
cdm_session_id.c_str());
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,23 +568,38 @@ CdmResponseType CdmEngine::HandleProvisioningResponse(
|
|||||||
// Authenticates provisioning response using D1s (server key derived from
|
// Authenticates provisioning response using D1s (server key derived from
|
||||||
// the provisioing request's input). Validate provisioning response and
|
// the provisioing request's input). Validate provisioning response and
|
||||||
// stores private device RSA key and certificate.
|
// stores private device RSA key and certificate.
|
||||||
|
SignedProvisioningMessage signed_response;
|
||||||
|
if (!signed_response.ParseFromString(serialized_signed_response)) {
|
||||||
|
LOGE("Fails to parse signed serialized response");
|
||||||
|
CleanupProvisioningSession(cdm_session_id);
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!signed_response.has_signature() || !signed_response.has_message()) {
|
||||||
|
LOGE("Invalid response - signature or message not found");
|
||||||
|
CleanupProvisioningSession(cdm_session_id);
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& signed_message = signed_response.message();
|
||||||
ProvisioningResponse provisioning_response;
|
ProvisioningResponse provisioning_response;
|
||||||
|
|
||||||
if (!provisioning_response.ParseFromString(signed_message)) {
|
if (!provisioning_response.ParseFromString(signed_message)) {
|
||||||
LOGE("HandleProvisioningResponse: fails to parse signed message");
|
LOGE("Fails to parse signed message");
|
||||||
CleanupProvisioningSession(cdm_session_id);
|
CleanupProvisioningSession(cdm_session_id);
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!provisioning_response.has_device_rsa_key()) {
|
if (!provisioning_response.has_device_rsa_key()) {
|
||||||
LOGE("HandleProvisioningResponse: invalid response - key not found");
|
LOGE("Invalid response - key not found");
|
||||||
CleanupProvisioningSession(cdm_session_id);
|
CleanupProvisioningSession(cdm_session_id);
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& enc_rsa_key = provisioning_response.device_rsa_key();
|
const std::string& enc_rsa_key = provisioning_response.device_rsa_key();
|
||||||
const std::string& rsa_key_iv = provisioning_response.device_rsa_key_iv();
|
|
||||||
const std::string& nonce = provisioning_response.nonce();
|
const std::string& nonce = provisioning_response.nonce();
|
||||||
|
const std::string& rsa_key_iv = provisioning_response.device_rsa_key_iv();
|
||||||
|
const std::string& signature = signed_response.signature();
|
||||||
|
|
||||||
std::string wrapped_rsa_key;
|
std::string wrapped_rsa_key;
|
||||||
if (!crypto_session->RewrapDeviceRSAKey(signed_message,
|
if (!crypto_session->RewrapDeviceRSAKey(signed_message,
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ wvcdm::KeyId g_wrong_key_id;
|
|||||||
int g_use_full_path = 0; // cannot use boolean in getopt_long
|
int g_use_full_path = 0; // cannot use boolean in getopt_long
|
||||||
|
|
||||||
const std::string kDefaultProvisioningServerUrl =
|
const std::string kDefaultProvisioningServerUrl =
|
||||||
"http://www-googleapis-test.sandbox.google.com/certificateprovisioning/v1/devicecertificates/create";
|
"http://www-googleapis-test.sandbox.google.com/"
|
||||||
|
"certificateprovisioning/v1/devicecertificates/create"
|
||||||
|
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
@@ -56,7 +58,7 @@ class WvCdmRequestLicenseTest : public testing::Test {
|
|||||||
app_parameters,
|
app_parameters,
|
||||||
&key_msg_,
|
&key_msg_,
|
||||||
&server_url), wvcdm::KEY_MESSAGE);
|
&server_url), wvcdm::KEY_MESSAGE);
|
||||||
EXPECT_EQ((size_t)0, server_url.size());
|
EXPECT_EQ(0, static_cast<int>(server_url.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateRenewalRequest(const std::string& key_system,
|
void GenerateRenewalRequest(const std::string& key_system,
|
||||||
@@ -71,7 +73,7 @@ class WvCdmRequestLicenseTest : public testing::Test {
|
|||||||
app_parameters,
|
app_parameters,
|
||||||
&key_msg_,
|
&key_msg_,
|
||||||
&server_url), wvcdm::KEY_MESSAGE);
|
&server_url), wvcdm::KEY_MESSAGE);
|
||||||
EXPECT_NE((size_t)0, server_url.size());
|
EXPECT_NE(0, static_cast<int>(server_url.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// posts a request and extracts the drm message from the response
|
// posts a request and extracts the drm message from the response
|
||||||
@@ -122,9 +124,11 @@ class WvCdmRequestLicenseTest : public testing::Test {
|
|||||||
url_request.PostCertRequest(key_msg_);
|
url_request.PostCertRequest(key_msg_);
|
||||||
std::string response;
|
std::string response;
|
||||||
int resp_bytes = url_request.GetResponse(response);
|
int resp_bytes = url_request.GetResponse(response);
|
||||||
LOGD("size=%u, response start: %s", response.size(),
|
if (resp_bytes) {
|
||||||
response.substr(0, 1024).c_str());
|
LOGD("size=%u, response start:\t\rn%s", response.size(),
|
||||||
LOGD("end: %s", response.substr(response.size() - 256).c_str());
|
response.substr(0, 1024).c_str());
|
||||||
|
LOGD("end:\r\n%s", response.substr(response.size() - 256).c_str());
|
||||||
|
}
|
||||||
LOGD("end %d bytes response dump", resp_bytes);
|
LOGD("end %d bytes response dump", resp_bytes);
|
||||||
|
|
||||||
// Youtube server returns 400 for invalid message while play server returns
|
// Youtube server returns 400 for invalid message while play server returns
|
||||||
|
|||||||
Reference in New Issue
Block a user