Replaces staging provisioning server url with production server url

The default provisioning server url now points to the production server.
Also switches to the real field provisioning system ID that works
only on the production servers, and updates the unit tests to work
properly with the prod servers.

Bug: 8724358

Merge of:
  https://widevine-internal-review.googlesource.com/#/c/5270/
  https://widevine-internal-review.googlesource.com/#/c/5550/
  https://widevine-internal-review.googlesource.com/#/c/5321/
  https://widevine-internal-review.googlesource.com/#/c/5501/
from the Widevine CDM repository

Change-Id: Iff1d7349c6a84bf30c6cdd534933ae747d5cff55
This commit is contained in:
Jeff Tinker
2013-05-09 12:18:38 -07:00
parent 10a55612d0
commit 4cf8594a87
10 changed files with 216 additions and 84 deletions

View File

@@ -22,7 +22,7 @@
namespace {
const std::string kDefaultProvisioningServerUrl =
"http://www-googleapis-test.sandbox.google.com/"
"https://www.googleapis.com/"
"certificateprovisioning/v1/devicecertificates/create"
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
}

View File

@@ -22,57 +22,6 @@ std::string g_license_server;
std::string g_port;
wvcdm::KeyId g_wrong_key_id;
int g_use_full_path = 0; // cannot use boolean in getopt_long
static wvcdm::CdmProvisioningResponse kJsonResponse =
"{\"kind\": \"certificateprovisioning#certificateProvisioningResponse\","
"\"signedResponse\": {"
"\"message\": \"CtAJiVocnKtls7HO9SZtMg7-aEZosRT-qAjLnKt4FZ_5jvW-BEVBPNj1yeXh"
"o_wla-VdgYQBRsnXuONH4Rh7Kg0T1mv3ybc2VIU4imZ46nW7FsZYRxz3EwWkFelIav9JDeHBlat"
"qOKJEXtCiaySgdzNyZDDsZHxQu8Yh4ZeiHTVNHotoAiFy9qoUO0oaHpZ8xJxDkuN0u9-yauLdGy"
"F8B3u2CJjO7ztbYC1a5b8NTTDzN3hKdXy9FcR0a5R5YDzvlCWj-TeEIFSop0t4QI7bGLaubXJ_K"
"y7ppcLwM4LAOs12G4TyXa3R3A64rjF7tBdnbsA2S1ELpePWPK2jtvUu1TBWxS2bToU1PQrY8C9E"
"bDaN7TpE92sOyrW1sIGkit03thAaRjHUl_JtLyqKCFUamjsQqCi7pk_4IvoFJiYKAfE5Wf5cbP0"
"IrFW3CSkgYtO_d7jnyTUaweh9eP_8udIoUNkJjHMpglR_VJcWyIqw-hg8PqWm7AcYBUNDF0sYzM"
"uMiw2uq4RSBq8vklZ_nJjVc2GZ1pSqpaLLghDpviGUbEoGGJP4I15pveCKbyOj6TfKbeiN2jgit"
"1CaHMOmirOeSpD0gODGHQaTuVFbWQg-jgsbhht0NDHyqwmPDrCe78h2gXS6k0qDb3HL9M4QT5E4"
"-E2cZLfmvtrDokugAwf0eZM14464Oi_o6NK-Gbic8q1VnI1Y7uDctVHPAlV2NjsCVoaALtpNQZ0"
"HmaOF_jJ2RxCSyQCX1sxkRR_jeKyH10_i-GkXPokB3Z23LvHOheEVNmJJNvM9YBSw318aAiOIAo"
"Wdffrfo9j4xDs34W-ndKn344BNUq8tGmo3EVhSg6pdLPcCWSpjbgQxnBe_cwmKJVKU39GPMFV0P"
"vEeYKWljptsdUc9MH4XLomyalSPGCOkoVIwdPd1qXLhh1mmdNRm_7X-7zBezltjw42XKjtOKwBi"
"_UFmgY6i4Mjbk9ShExjWpvgKNntWepIZGZhYVP1tt4H-wqsXMfupTviHf_FaQX3cadUbO_6imfa"
"91MvnFe5v0iIi1HxsQzl0NmIByHFNUfHpzrZ0RzkmxsRY5lMLpOfdue7NJ5IZN1iVgiSS3llwa3"
"2s2Yq-gCzqv7vwdIwAxZ__gOr42LR__KCB51g9xwXdVLH71Dv_WDgDv5LJas9MVz5vv_TDo9Gqf"
"ZdEI8M2h0LbhdCVGxyYoeWVl6iHrPoeP6mJ5uaDZAAn_IdoVVPuCA8Wqmi_kbRdduwkuyasbIVx"
"dMwR7cRJz5Rl5kw36kjJtOv4wy9NU41PgNNuW1_2dWtIeKOcBJH2-5KbQbnntbKNdcPqZhTaoci"
"_3qDZtdlSqIJbDh7_4ZBkbcOHJ73jPKNOiLeDGD_rXFuPy4mAuxkZ8shXcw57xsIjz_OkB_Vr_2"
"2JhNMicnjITZDTGZzN4xyPldtOINCQGBBpUBLOaiWEFePqG9m5uWv6_NtpPt3I_YQnfUzv2RLFe"
"1pOLktoorTPWi8TH8hXnnmhHLMvd9r1Z1nISnZGmn_EhEFt-N-CCpiWAo5yQWIUA0iMqCdLHTub"
"l-tuhHyLqmiBUU9O7Ynwl12k2nqJTbbeSCt1mueee8j5bITUGZ8KAAtbIe_k0XMl5mRZWVzoBw0"
"RKmvBiWSRnOESEOdEAZw1ALRVjzEhSkDqGoIa7wkKsAIIAhIQB9n_3hOqlcEiZ4BTNiE2vRjgzd"
"aLBSKOAjCCAQoCggEBAKfruetSk8ULthZLZCoqaViWPEdlO50Bi1ChIjXCiuGNp566o74R4r_ou"
"8V7VX-Ze6p2Zpbm3iTPbB-vORaINQECi8TOA1xmxH0u7jrqHwfYX2a1EdCzp3DX5_lF2Rb44FI7"
"gKW1BwIeUDOdaMKApxZOp-jt1MBsMaMZDWgvQ5EAULzESq04zsynylaScm-IaZrY0mC3ynGz2YW"
"6TxbQKBUJsOUnpEEIDK2qlyEEESp0UFcTn2Lakda7MFI9wMAlH_qrDRdlDcLwGeD2qT8Lm4CFhV"
"cNDm3nqpONmBCJlebqSvavf5tALlIdR5CdfFV64beT8zWG1J-Rz6AGmHYgCucCAwEAASiZIDABE"
"oACFJ8UtXGiM__6SQFHXjN69lqzWfJKhplriW7m9wdCO-LEcCNFpUmzWBd1JppY11hL9AYO8OTI"
"Habeb65R51q_SjulaxlJwureJAYe-cO7RTvQvCddK9SJaDxeBe367ot_pnXvh66tksCkfvakY7W"
"igaDB8WVIaml6hmDADZgGAVfrPVWVPXMaY9LYg0r3r5PllfrmG7uXU0JcIa_0N-3MgT4QV4qIG2"
"9K9givfjELYidRpDDXu8KKcw0NYu-bTUNRaNrx6yaIpSbozen5HHBVdb5gJFB-922gr9mqY1PF_"
"-ulwvcXLn-Oa17QJ0YL1LkswDjVSC89MpJWkjW_qVlF8Rq2BQqwAggBEhCr7oe2E5WSaDltfP2r"
"q_jyGK_qu4sFIo4CMIIBCgKCAQEAmtIaWtGjInLYjdQic5DPUGUgnZah-FZVFt0SwcH90u1UhQW"
"eRgBH1psYrYqaaS8zu6vclTCT17E0WsDJlS8P8dBDlSMlyrNBZjCTDyczkI68tM5v0HXnpDCb5s"
"RaCSlP7Dl9BV_67GZPFoVuw53QCaI8cQ4RHcNVupExNRcFiCc-HSb3tZO7yyZyoB1Yx6GJnlts3"
"WA3A0DqVQIY79IGqdtTkKwydiNXVqR5ksMecqALwh9vKx6oSkxNat3I1BKQnzTY0pYChDjprabV"
"O9dAM2fYwGELJYel9qQV6LT6ar0PbKCMGa9qR-YwYiR8-SN-jpvmKL0h98bhTsC65DUQswIDAQA"
"BKJkgMAESgANZMzj1jPLFR8wnWKrTwL7dLF8qNJOPf7KDdJeqioqEkAe7mZiH3ZlQlE5EjPFGn5"
"IytduT2SdPGZoAsMEavJb_nETlELNXW16bQSPKJXr1gYrzoJ86t2ePrbXOTDQUV9pIi9yCLgWYp"
"r9PVx9osIRfd4qHg_MPEITQhlxvMvX51-_NxiQpdDf3HH-x2tMu6pELU7eruIPhBPxhrOJ9eWTK"
"54w6ygZ0-RdEgJKRSCCtTcjjom1TJ_GimvqVJZ449LeVycc23BsJDkBNE9XOARSCHK0i3VDWTg-"
"autjKClFWaVcyoNDqW6cfdODF7YyEYP8sBbYenMoJn5pizXaYvl3qc4LY8a-8HVFU6akgCvcj2w"
"vaAMOdQvh5f5m6X33lLfE0w8R4JFkqxB7UC5Ev_nPDkyX1urg76t31_9qTmQAlxdoIhmBsPziSW"
"jE3gII_qetwT7z1cPX8bGGPELwFiG5sQ6jQbHlGV-gaL2v-Peh6HZbGltsoI0wm7_N1i-BwiyUi"
"BPHgGJ8=\","
"\"signature\": \"fRiAeyze4AtvYXpxWImduHrJ1lZ4K0bRT1lk2jVIpcs=\"}}";
} // namespace
namespace wvcdm {
@@ -106,25 +55,89 @@ class WvCdmEngineTest : public testing::Test {
wvcdm::KEY_MESSAGE);
}
// concatinates all chunks into one blob
// TODO (edwinwong) move this function to url_request class as GetMessageBody
void ConcatenateChunkedResponse(const std::string http_response,
std::string* message_body) {
if (http_response.empty())
return;
message_body->clear();
const std::string kChunkedTag = "Transfer-Encoding: chunked\r\n\r\n";
size_t chunked_tag_pos = http_response.find(kChunkedTag);
if (std::string::npos != chunked_tag_pos) {
// processes chunked encoding
size_t chunk_size = 0;
size_t chunk_size_pos = chunked_tag_pos + kChunkedTag.size();
sscanf(&http_response[chunk_size_pos], "%x", &chunk_size);
if (chunk_size > http_response.size()) {
// precaution, in case we misread chunk size
LOGE("invalid chunk size %u", chunk_size);
return;
}
/*
* searches for chunks
*
* header
* chunk size\r\n <-- chunk_size_pos @ beginning of chunk size
* chunk data\r\n <-- chunk_pos @ beginning of chunk data
* chunk size\r\n
* chunk data\r\n
* 0\r\n
*/
const std::string kCrLf = "\r\n";
size_t chunk_pos = http_response.find(kCrLf, chunk_size_pos) +
kCrLf.size();
message_body->assign(&http_response[0], chunk_size_pos);
while ((chunk_size > 0) && (std::string::npos != chunk_pos)) {
message_body->append(&http_response[chunk_pos], chunk_size);
// searches for next chunk
chunk_size_pos = chunk_pos + chunk_size + kCrLf.size();
sscanf(&http_response[chunk_size_pos], "%x", &chunk_size);
if (chunk_size > http_response.size()) {
// precaution, in case we misread chunk size
LOGE("invalid chunk size %u", chunk_size);
break;
}
chunk_pos = http_response.find(kCrLf, chunk_size_pos) + kCrLf.size();
}
} else {
// response is not chunked encoded
message_body->assign(http_response);
}
}
// posts a request and extracts the drm message from the response
std::string GetKeyRequestResponse(const std::string& server_url,
const std::string& client_auth,
int expected_response) {
UrlRequest url_request(server_url + client_auth, g_port);
std::string port;
if (server_url.find("https") != std::string::npos) {
port.assign("443");
} else {
port.assign(g_port);
}
UrlRequest url_request(server_url + client_auth, port);
if (!url_request.is_connected()) {
return "";
}
url_request.PostRequest(key_msg_);
std::string response;
int resp_bytes = url_request.GetResponse(response);
LOGD("response:\r\n%s", response.c_str());
std::string http_response;
std::string message_body;
int resp_bytes = url_request.GetResponse(http_response);
if (resp_bytes) {
ConcatenateChunkedResponse(http_response, &message_body);
}
LOGD("response:\r\n%s", message_body.c_str());
LOGD("end %d bytes response dump", resp_bytes);
// Youtube server returns 400 for invalid message while play server returns
// 500, so just test inequity here for invalid message
int status_code = url_request.GetStatusCode(response);
int status_code = url_request.GetStatusCode(message_body);
if (expected_response == 200) {
EXPECT_EQ(200, status_code);
} else {
@@ -134,7 +147,7 @@ class WvCdmEngineTest : public testing::Test {
std::string drm_msg;
if (200 == status_code) {
LicenseRequest lic_request;
lic_request.GetDrmMessage(response, drm_msg);
lic_request.GetDrmMessage(message_body, drm_msg);
LOGV("drm msg: %u bytes\r\n%s", drm_msg.size(),
HexEncode(reinterpret_cast<const uint8_t*>(drm_msg.data()),
drm_msg.size()).c_str());
@@ -162,15 +175,6 @@ class WvCdmEngineTest : public testing::Test {
std::string session_id_;
};
TEST_F(WvCdmEngineTest, ProvisioningTest) {
CdmProvisioningRequest prov_request;
std::string provisioning_server_url = "";
cdm_engine_.GetProvisioningRequest(&prov_request, &provisioning_server_url);
cdm_engine_.HandleProvisioningResponse(kJsonResponse);
}
TEST_F(WvCdmEngineTest, BaseMessageTest) {
cdm_engine_.OpenSession(g_key_system, &session_id_);
GenerateKeyRequest(g_key_system, g_key_id);

View File

@@ -5,13 +5,60 @@
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include "openssl/bio.h"
#include "openssl/err.h"
#include "openssl/x509.h"
#include <string.h>
#include <sys/socket.h>
#include "log.h"
namespace wvcdm {
HttpSocket::HttpSocket() : socket_fd_(-1), timeout_enabled_(false) {}
SSL_CTX* HttpSocket::InitSslContext(void) {
const SSL_METHOD* method;
SSL_CTX* ctx;
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
method = SSLv3_client_method();
ctx = SSL_CTX_new(method);
if (NULL == ctx)
{
LOGE("failed to create SSL context");
}
return ctx;
}
void HttpSocket::ShowServerCertificate(const SSL* ssl) {
X509* cert;
char* line;
// gets the server certificate
cert = SSL_get_peer_certificate(ssl);
if (cert != NULL)
{
LOGV("server certificate:");
line = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
LOGV("subject: %s", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
LOGV("issuer: %s", line);
free(line);
X509_free(cert);
}
else
LOGE("Failed to get server certificate");
}
HttpSocket::HttpSocket() :
secure_connect_(true),
socket_fd_(-1),
ssl_(NULL),
ssl_ctx_(NULL),
timeout_enabled_(false) {
SSL_library_init();
}
HttpSocket::~HttpSocket()
{
@@ -24,6 +71,16 @@ void HttpSocket::CloseSocket()
close(socket_fd_);
socket_fd_ = -1;
}
if (secure_connect_) {
if (ssl_) {
SSL_free(ssl_);
ssl_ = NULL;
}
if (ssl_ctx_) {
CloseSslContext(ssl_ctx_);
ssl_ctx_ = NULL;
}
}
}
// Extracts the domain name and resource path from the input url parameter.
@@ -65,6 +122,10 @@ void HttpSocket::GetDomainNameAndPathFromUrl(const std::string& url,
bool HttpSocket::Connect(const char* url, const std::string& port, bool enable_timeout)
{
secure_connect_ = (strstr(url, "https") != NULL) ? true : false;
if (secure_connect_)
ssl_ctx_ = InitSslContext();
GetDomainNameAndPathFromUrl(url, domain_name_, resource_path_);
socket_fd_ = socket(AF_INET, SOCK_STREAM, 0);
@@ -102,6 +163,26 @@ bool HttpSocket::Connect(const char* url, const std::string& port, bool enable_t
if (addr_info != NULL) {
freeaddrinfo(addr_info);
}
// secures connection
if (secure_connect_ && ssl_ctx_) {
ssl_ = SSL_new(ssl_ctx_);
if (ssl_) {
BIO* a_bio = BIO_new_socket(socket_fd_, BIO_NOCLOSE);
if (a_bio) {
SSL_set_bio(ssl_, a_bio, a_bio);
int ret = SSL_connect(ssl_);
if (1 != ret) {
char buf[256];
LOGE("SSL_connect error:%s", ERR_error_string(ERR_get_error(), buf));
}
} else {
LOGE("BIO_new_socket error");
}
} else {
LOGE("failed SSL_new");
}
}
return status;
}
@@ -148,7 +229,11 @@ int HttpSocket::Read(char* data, int len, int timeout_in_ms)
}
}
read = recv(socket_fd_, data, to_read, 0);
if (secure_connect_)
read = SSL_read(ssl_, data, to_read);
else
read = recv(socket_fd_, data, to_read, 0);
if (read > 0) {
to_read -= read;
data += read;
@@ -175,7 +260,11 @@ int HttpSocket::Write(const char* data, int len)
int sent = 0;
int to_send = len;
while (to_send > 0) {
sent = send(socket_fd_, data, to_send, 0);
if (secure_connect_)
sent = SSL_write(ssl_, data, to_send);
else
sent = send(socket_fd_, data, to_send, 0);
if (sent > 0) {
to_send -= sent;
data += sent;

View File

@@ -4,6 +4,7 @@
#define CDM_TEST_HTTP_SOCKET_H_
#include <string>
#include "openssl/ssl.h"
#include "wv_cdm_types.h"
namespace wvcdm {
@@ -26,9 +27,16 @@ class HttpSocket {
int Write(const char* data, int len);
private:
void CloseSslContext(SSL_CTX* ctx) const { if (ctx) SSL_CTX_free(ctx); }
SSL_CTX* InitSslContext(void);
void ShowServerCertificate(const SSL* ssl);
std::string domain_name_;
bool secure_connect_;
std::string resource_path_;
int socket_fd_;
SSL* ssl_;
SSL_CTX* ssl_ctx_;
bool timeout_enabled_;
CORE_DISALLOW_COPY_AND_ASSIGN(HttpSocket);

View File

@@ -24,8 +24,16 @@ std::string g_port;
wvcdm::KeyId g_wrong_key_id;
int g_use_full_path = 0; // cannot use boolean in getopt_long
const std::string kDefaultProvisioningServerUrl =
"http://www-googleapis-test.sandbox.google.com/"
// returns production-rooted certificates that have test bit set, this test
// uses this url
const std::string kProductionTestProvisioningServerUrl =
"https://www.googleapis.com/"
"certificateprovisioning/v1exttest/devicecertificates/create"
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
// url returned by GetProvisioningRequest()
const std::string kProductionProvisioningServerUrl =
"https://www.googleapis.com/"
"certificateprovisioning/v1/devicecertificates/create"
"?key=AIzaSyB-5OLKTx2iU5mko18DfdwK5611JIjbUhE";
} // namespace
@@ -156,7 +164,13 @@ class WvCdmRequestLicenseTest : public testing::Test {
std::string GetKeyRequestResponse(const std::string& server_url,
const std::string& client_auth,
int expected_response) {
UrlRequest url_request(server_url + client_auth, g_port);
std::string port;
if (server_url.find("https") != std::string::npos) {
port.assign("443");
} else {
port.assign(g_port);
}
UrlRequest url_request(server_url + client_auth, port);
if (!url_request.is_connected()) {
return "";
@@ -191,10 +205,17 @@ class WvCdmRequestLicenseTest : public testing::Test {
return drm_msg;
}
// posts a request and extracts the drm message from the response
// Posts a request and extracts the signed provisioning message from
// the HTTP response.
std::string GetCertRequestResponse(const std::string& server_url,
int expected_response) {
UrlRequest url_request(server_url, g_port);
std::string port;
if (server_url.find("https") != std::string::npos) {
port.assign("443");
} else {
port.assign(g_port);
}
UrlRequest url_request(server_url, port);
if (!url_request.is_connected()) {
return "";
@@ -247,10 +268,13 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) {
decryptor_.OpenSession(g_key_system, &session_id_);
std::string provisioning_server_url = "";
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(&key_msg_, &provisioning_server_url));
EXPECT_STREQ(provisioning_server_url.data(), kDefaultProvisioningServerUrl.data());
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(&key_msg_,
&provisioning_server_url));
EXPECT_STREQ(provisioning_server_url.data(),
kProductionProvisioningServerUrl.data());
std::string response = GetCertRequestResponse(kDefaultProvisioningServerUrl, 200);
std::string response = GetCertRequestResponse(
kProductionTestProvisioningServerUrl, 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(response));
decryptor_.CloseSession(session_id_);
@@ -260,13 +284,19 @@ TEST_F(WvCdmRequestLicenseTest, ProvisioningRetryTest) {
decryptor_.OpenSession(g_key_system, &session_id_);
std::string provisioning_server_url = "";
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(&key_msg_, &provisioning_server_url));
EXPECT_STREQ(provisioning_server_url.data(), kDefaultProvisioningServerUrl.data());
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(&key_msg_,
&provisioning_server_url));
EXPECT_STREQ(provisioning_server_url.data(),
kProductionProvisioningServerUrl.data());
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.GetProvisioningRequest(&key_msg_, &provisioning_server_url));
EXPECT_STREQ(provisioning_server_url.data(), kDefaultProvisioningServerUrl.data());
EXPECT_EQ(wvcdm::NO_ERROR,
decryptor_.GetProvisioningRequest(
&key_msg_, &provisioning_server_url));
EXPECT_STREQ(provisioning_server_url.data(),
kProductionProvisioningServerUrl.data());
std::string response = GetCertRequestResponse(kDefaultProvisioningServerUrl, 200);
std::string response = GetCertRequestResponse(
kProductionTestProvisioningServerUrl, 200);
EXPECT_NE(0, static_cast<int>(response.size()));
EXPECT_EQ(wvcdm::NO_ERROR, decryptor_.HandleProvisioningResponse(response));
decryptor_.CloseSession(session_id_);

View File

@@ -19,6 +19,7 @@ LOCAL_SRC_FILES := \
LOCAL_C_INCLUDES := \
bionic \
external/gtest/include \
external/openssl/include \
external/stlport/stlport \
$(LOCAL_PATH)/core/test/include \
vendor/widevine/libwvdrmengine/test/gmock/include \
@@ -47,6 +48,7 @@ LOCAL_SHARED_LIBRARIES := \
libcutils \
libdl \
liblog \
libssl \
libstlport \
libutils

View File

@@ -13,7 +13,6 @@ adb shell /system/bin/policy_engine_unittest
adb shell /system/bin/libwvdrmmediacrypto_test
adb shell /system/bin/libwvdrmdrmplugin_test
adb shell /system/bin/cdm_engine_test
adb shell /system/bin/oemcrypto_test
adb shell /system/bin/file_store_unittest
adb shell /system/bin/device_files_unittest
adb shell /system/bin/timer_unittest