Internal factory tool implements CSR v3
Widevine internal BCC extraction tool to extract CSR v3 for testing purpose. The difference it has from the factory tool is it doesn't rely on Widevine IRPC HAL. It just extracts BCC/CSR in the specified format from cli. Test: Extract CSR v3 on Pixel 7 and upload Bug: 268246995 Change-Id: I52abe09f991c89c6e7601bcef4d980f24c020c9f
This commit is contained in:
@@ -6,45 +6,50 @@
|
|||||||
|
|
||||||
#define LOG_TAG "wv_factory_extraction_tool"
|
#define LOG_TAG "wv_factory_extraction_tool"
|
||||||
|
|
||||||
|
#include <sys/random.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <sys/random.h>
|
|
||||||
|
|
||||||
#include "WidevineProvisioner.h"
|
#include "WidevineProvisioner.h"
|
||||||
|
|
||||||
constexpr size_t kChallengeSize = 16;
|
constexpr size_t kChallengeSize = 32;
|
||||||
|
|
||||||
// The Google root key for the Endpoint Encryption Key chain, encoded as COSE_Sign1
|
// The Google root key for the Endpoint Encryption Key chain, encoded as
|
||||||
|
// COSE_Sign1
|
||||||
inline constexpr uint8_t kCoseEncodedRootCert[] = {
|
inline constexpr uint8_t kCoseEncodedRootCert[] = {
|
||||||
0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x2a, 0xa4, 0x01, 0x01, 0x03, 0x27, 0x20, 0x06,
|
0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x2a, 0xa4, 0x01, 0x01, 0x03,
|
||||||
0x21, 0x58, 0x20, 0x99, 0xb9, 0xee, 0xdd, 0x5e, 0xe4, 0x52, 0xf6, 0x85, 0xc6, 0x4c, 0x62,
|
0x27, 0x20, 0x06, 0x21, 0x58, 0x20, 0x99, 0xb9, 0xee, 0xdd, 0x5e, 0xe4,
|
||||||
0xdc, 0x3e, 0x61, 0xab, 0x57, 0x48, 0x7d, 0x75, 0x37, 0x29, 0xad, 0x76, 0x80, 0x32, 0xd2,
|
0x52, 0xf6, 0x85, 0xc6, 0x4c, 0x62, 0xdc, 0x3e, 0x61, 0xab, 0x57, 0x48,
|
||||||
0xb3, 0xcb, 0x63, 0x58, 0xd9, 0x58, 0x40, 0x1e, 0x22, 0x08, 0x4b, 0xa4, 0xb7, 0xa4, 0xc8,
|
0x7d, 0x75, 0x37, 0x29, 0xad, 0x76, 0x80, 0x32, 0xd2, 0xb3, 0xcb, 0x63,
|
||||||
0xd7, 0x4e, 0x03, 0x0e, 0xfe, 0xb8, 0xaf, 0x14, 0x4c, 0xa7, 0x3b, 0x6f, 0xa5, 0xcd, 0xdc,
|
0x58, 0xd9, 0x58, 0x40, 0x1e, 0x22, 0x08, 0x4b, 0xa4, 0xb7, 0xa4, 0xc8,
|
||||||
0xda, 0x79, 0xc6, 0x2b, 0x64, 0xfe, 0x99, 0x39, 0xaf, 0x76, 0xe7, 0x80, 0xfa, 0x66, 0x00,
|
0xd7, 0x4e, 0x03, 0x0e, 0xfe, 0xb8, 0xaf, 0x14, 0x4c, 0xa7, 0x3b, 0x6f,
|
||||||
0x85, 0x0d, 0x07, 0x98, 0x2a, 0xac, 0x91, 0x5c, 0xa7, 0x25, 0x14, 0x49, 0x06, 0x34, 0x75,
|
0xa5, 0xcd, 0xdc, 0xda, 0x79, 0xc6, 0x2b, 0x64, 0xfe, 0x99, 0x39, 0xaf,
|
||||||
0xca, 0x8a, 0x27, 0x7a, 0xd9, 0xe3, 0x5a, 0x49, 0xeb, 0x02, 0x03};
|
0x76, 0xe7, 0x80, 0xfa, 0x66, 0x00, 0x85, 0x0d, 0x07, 0x98, 0x2a, 0xac,
|
||||||
|
0x91, 0x5c, 0xa7, 0x25, 0x14, 0x49, 0x06, 0x34, 0x75, 0xca, 0x8a, 0x27,
|
||||||
|
0x7a, 0xd9, 0xe3, 0x5a, 0x49, 0xeb, 0x02, 0x03};
|
||||||
|
|
||||||
// The Google Endpoint Encryption Key certificate, encoded as COSE_Sign1
|
// The Google Endpoint Encryption Key certificate, encoded as COSE_Sign1
|
||||||
inline constexpr uint8_t kCoseEncodedGeekCert[] = {
|
inline constexpr uint8_t kCoseEncodedGeekCert[] = {
|
||||||
0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x4e, 0xa5, 0x01, 0x01, 0x02, 0x58, 0x20,
|
0x84, 0x43, 0xa1, 0x01, 0x27, 0xa0, 0x58, 0x4e, 0xa5, 0x01, 0x01, 0x02,
|
||||||
0xd0, 0xae, 0xc1, 0x15, 0xca, 0x2a, 0xcf, 0x73, 0xae, 0x6b, 0xcc, 0xcb, 0xd1, 0x96,
|
0x58, 0x20, 0xd0, 0xae, 0xc1, 0x15, 0xca, 0x2a, 0xcf, 0x73, 0xae, 0x6b,
|
||||||
0x1d, 0x65, 0xe8, 0xb1, 0xdd, 0xd7, 0x4a, 0x1a, 0x37, 0xb9, 0x43, 0x3a, 0x97, 0xd5,
|
0xcc, 0xcb, 0xd1, 0x96, 0x1d, 0x65, 0xe8, 0xb1, 0xdd, 0xd7, 0x4a, 0x1a,
|
||||||
0x99, 0xdf, 0x98, 0x08, 0x03, 0x38, 0x18, 0x20, 0x04, 0x21, 0x58, 0x20, 0xbe, 0x85,
|
0x37, 0xb9, 0x43, 0x3a, 0x97, 0xd5, 0x99, 0xdf, 0x98, 0x08, 0x03, 0x38,
|
||||||
0xe7, 0x46, 0xc4, 0xa3, 0x42, 0x5a, 0x40, 0xd9, 0x36, 0x3a, 0xa6, 0x15, 0xd0, 0x2c,
|
0x18, 0x20, 0x04, 0x21, 0x58, 0x20, 0xbe, 0x85, 0xe7, 0x46, 0xc4, 0xa3,
|
||||||
0x58, 0x7e, 0x3d, 0xdc, 0x33, 0x02, 0x32, 0xd2, 0xfc, 0x5e, 0x1e, 0x87, 0x25, 0x5f,
|
0x42, 0x5a, 0x40, 0xd9, 0x36, 0x3a, 0xa6, 0x15, 0xd0, 0x2c, 0x58, 0x7e,
|
||||||
0x72, 0x60, 0x58, 0x40, 0x9b, 0xcf, 0x90, 0xe2, 0x2e, 0x4b, 0xab, 0xd1, 0x18, 0xb1,
|
0x3d, 0xdc, 0x33, 0x02, 0x32, 0xd2, 0xfc, 0x5e, 0x1e, 0x87, 0x25, 0x5f,
|
||||||
0x0e, 0x8e, 0x5d, 0x20, 0x27, 0x4b, 0x84, 0x58, 0xfe, 0xfc, 0x32, 0x90, 0x7e, 0x72,
|
0x72, 0x60, 0x58, 0x40, 0x9b, 0xcf, 0x90, 0xe2, 0x2e, 0x4b, 0xab, 0xd1,
|
||||||
0x05, 0x83, 0xbc, 0xd7, 0x82, 0xbe, 0xfa, 0x64, 0x78, 0x2d, 0x54, 0x10, 0x4b, 0xc0,
|
0x18, 0xb1, 0x0e, 0x8e, 0x5d, 0x20, 0x27, 0x4b, 0x84, 0x58, 0xfe, 0xfc,
|
||||||
0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35, 0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2,
|
0x32, 0x90, 0x7e, 0x72, 0x05, 0x83, 0xbc, 0xd7, 0x82, 0xbe, 0xfa, 0x64,
|
||||||
0xf5, 0x4f, 0xa5, 0xd4, 0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04};
|
0x78, 0x2d, 0x54, 0x10, 0x4b, 0xc0, 0x31, 0xbf, 0x6b, 0xe8, 0x1e, 0x35,
|
||||||
|
0xe2, 0xf0, 0x2d, 0xce, 0x6c, 0x2f, 0x4f, 0xf2, 0xf5, 0x4f, 0xa5, 0xd4,
|
||||||
|
0x83, 0xad, 0x96, 0xa2, 0xf1, 0x87, 0x58, 0x04};
|
||||||
|
|
||||||
std::vector<uint8_t> generateChallenge() {
|
std::vector<uint8_t> generateChallenge() {
|
||||||
std::vector<uint8_t> challenge(kChallengeSize);
|
std::vector<uint8_t> challenge(kChallengeSize);
|
||||||
@@ -70,10 +75,10 @@ std::vector<uint8_t> generateChallenge() {
|
|||||||
|
|
||||||
std::vector<uint8_t> getEekChain() {
|
std::vector<uint8_t> getEekChain() {
|
||||||
cppbor::Array chain;
|
cppbor::Array chain;
|
||||||
chain.add(cppbor::EncodedItem(
|
chain.add(cppbor::EncodedItem(std::vector<uint8_t>(
|
||||||
std::vector<uint8_t>(std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert))));
|
std::begin(kCoseEncodedRootCert), std::end(kCoseEncodedRootCert))));
|
||||||
chain.add(cppbor::EncodedItem(
|
chain.add(cppbor::EncodedItem(std::vector<uint8_t>(
|
||||||
std::vector<uint8_t>(std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert))));
|
std::begin(kCoseEncodedGeekCert), std::end(kCoseEncodedGeekCert))));
|
||||||
return chain.encode();
|
return chain.encode();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,20 +86,23 @@ cppbor::Array composeCertificateRequest(
|
|||||||
const std::vector<uint8_t>& protectedData,
|
const std::vector<uint8_t>& protectedData,
|
||||||
const std::vector<uint8_t>& verifiedDeviceInfo,
|
const std::vector<uint8_t>& verifiedDeviceInfo,
|
||||||
const std::vector<uint8_t>& challenge) {
|
const std::vector<uint8_t>& challenge) {
|
||||||
cppbor::Array macedKeysToSign = cppbor::Array()
|
cppbor::Array macedKeysToSign =
|
||||||
.add(std::vector<uint8_t>(0)) // empty protected headers as bstr
|
cppbor::Array()
|
||||||
.add(cppbor::Map()) // empty unprotected headers
|
.add(std::vector<uint8_t>(0)) // empty protected headers as bstr
|
||||||
.add(cppbor::Null()) // nil for the payload
|
.add(cppbor::Map()) // empty unprotected headers
|
||||||
.add(std::vector<uint8_t>(0)); // MAC as returned from the HAL
|
.add(cppbor::Null()) // nil for the payload
|
||||||
|
.add(std::vector<uint8_t>(0)); // MAC as returned from the HAL
|
||||||
|
|
||||||
cppbor::Array deviceInfo =
|
cppbor::Array deviceInfo = cppbor::Array()
|
||||||
cppbor::Array().add(cppbor::EncodedItem(verifiedDeviceInfo)).add(cppbor::Map()); // Empty device info
|
.add(cppbor::EncodedItem(verifiedDeviceInfo))
|
||||||
|
.add(cppbor::Map()); // Empty device info
|
||||||
|
|
||||||
cppbor::Array certificateRequest = cppbor::Array()
|
cppbor::Array certificateRequest =
|
||||||
.add(std::move(deviceInfo))
|
cppbor::Array()
|
||||||
.add(challenge)
|
.add(std::move(deviceInfo))
|
||||||
.add(cppbor::EncodedItem(protectedData))
|
.add(challenge)
|
||||||
.add(std::move(macedKeysToSign));
|
.add(cppbor::EncodedItem(protectedData))
|
||||||
|
.add(std::move(macedKeysToSign));
|
||||||
return certificateRequest;
|
return certificateRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,37 +111,51 @@ cppbor::Array getCsr(widevine::WidevineProvisioner& provisioner) {
|
|||||||
std::vector<uint8_t> verifiedDeviceInfo;
|
std::vector<uint8_t> verifiedDeviceInfo;
|
||||||
std::vector<uint8_t> protectedData;
|
std::vector<uint8_t> protectedData;
|
||||||
|
|
||||||
if (!provisioner.GenerateCertificateRequest(false, getEekChain(),
|
if (!provisioner.GenerateCertificateRequest(
|
||||||
verifiedDeviceInfo,
|
false, getEekChain(), verifiedDeviceInfo, protectedData)) {
|
||||||
protectedData)) {
|
std::cerr << "Failed to generate certificate request." << std::endl;
|
||||||
std::cerr << "Failed to generate certificate request." << std::endl;
|
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
auto csr =
|
auto csr =
|
||||||
composeCertificateRequest(protectedData, verifiedDeviceInfo, challenge);
|
composeCertificateRequest(protectedData, verifiedDeviceInfo, challenge);
|
||||||
|
return csr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> getCsrV3(widevine::WidevineProvisioner& provisioner) {
|
||||||
|
const std::vector<uint8_t> challenge = generateChallenge();
|
||||||
|
std::vector<uint8_t> csr;
|
||||||
|
|
||||||
|
if (!provisioner.GenerateCertificateRequestV2(challenge, &csr)) {
|
||||||
|
std::cerr << "Failed to generate certificate request v2." << std::endl;
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
return csr;
|
return csr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
if (argc<2) {
|
if (argc < 2) {
|
||||||
fprintf(stderr,"%s <bcc|device_info>\n",argv[0]);
|
fprintf(stderr, "%s <bcc|device_info>\n", argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
widevine::WidevineProvisioner provisioner;
|
widevine::WidevineProvisioner provisioner;
|
||||||
if (!std::strcmp(argv[1],"bcc")) {
|
if (!std::strcmp(argv[1], "bcc")) {
|
||||||
auto bcc = provisioner.GetBcc();
|
auto bcc = provisioner.GetBcc();
|
||||||
fwrite(bcc.data(), 1 , bcc.size(), stdout);
|
fwrite(bcc.data(), 1, bcc.size(), stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
} else if (!std::strcmp(argv[1],"device_info")) {
|
} else if (!std::strcmp(argv[1], "device_info")) {
|
||||||
std::vector<uint8_t> deviceInfo;
|
std::vector<uint8_t> deviceInfo;
|
||||||
if (provisioner.GetDeviceInfo(deviceInfo)) {
|
if (provisioner.GetDeviceInfo(deviceInfo)) {
|
||||||
fwrite(deviceInfo.data(), 1 , deviceInfo.size(), stdout);
|
fwrite(deviceInfo.data(), 1, deviceInfo.size(), stdout);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
} else if (!std::strcmp(argv[1],"csr")) {
|
} else if (!std::strcmp(argv[1], "csr")) {
|
||||||
auto csr = getCsr(provisioner);
|
auto csr = getCsr(provisioner);
|
||||||
auto bytes = csr.encode();
|
auto bytes = csr.encode();
|
||||||
std::copy(bytes.begin(), bytes.end(), std::ostream_iterator<char>(std::cout));
|
std::copy(bytes.begin(), bytes.end(),
|
||||||
|
std::ostream_iterator<char>(std::cout));
|
||||||
|
} else if (!std::strcmp(argv[1], "csr_v3")) {
|
||||||
|
auto csr = getCsrV3(provisioner);
|
||||||
|
std::copy(csr.begin(), csr.end(), std::ostream_iterator<char>(std::cout));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,6 @@
|
|||||||
|
|
||||||
namespace widevine {
|
namespace widevine {
|
||||||
|
|
||||||
struct VerifiedDeviceInfo {
|
|
||||||
std::vector<uint8_t> device_info;
|
|
||||||
// Used by Interface of Remote Provisioning Component (IRPC) v3 for CSR
|
|
||||||
// uploading
|
|
||||||
std::vector<uint8_t> signed_csr_payload;
|
|
||||||
};
|
|
||||||
|
|
||||||
class OEMCryptoInterface {
|
class OEMCryptoInterface {
|
||||||
public:
|
public:
|
||||||
OEMCryptoInterface() = default;
|
OEMCryptoInterface() = default;
|
||||||
@@ -40,7 +33,13 @@ class OEMCryptoInterface {
|
|||||||
// Retrieves the verified device information of the OEMCrypto library from
|
// Retrieves the verified device information of the OEMCrypto library from
|
||||||
// OEMCrypto implementation.
|
// OEMCrypto implementation.
|
||||||
OEMCryptoResult GetVerifiedDeviceInformation(
|
OEMCryptoResult GetVerifiedDeviceInformation(
|
||||||
VerifiedDeviceInfo& verified_device_info);
|
std::vector<uint8_t>& verified_device_info);
|
||||||
|
|
||||||
|
// Generates device registration CSR payload and signs it with the leaf cert
|
||||||
|
// of BCC.
|
||||||
|
OEMCryptoResult GetSignedCsrPayload(const std::vector<uint8_t>& challenge,
|
||||||
|
const std::vector<uint8_t>& device_info,
|
||||||
|
std::vector<uint8_t>& signed_csr_payload);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef OEMCryptoResult (*Initialize_t)();
|
typedef OEMCryptoResult (*Initialize_t)();
|
||||||
@@ -50,8 +49,11 @@ class OEMCryptoInterface {
|
|||||||
size_t* additional_signature_size);
|
size_t* additional_signature_size);
|
||||||
typedef OEMCryptoResult (*BuildInformation_t)(char* buffer,
|
typedef OEMCryptoResult (*BuildInformation_t)(char* buffer,
|
||||||
size_t* buffer_length);
|
size_t* buffer_length);
|
||||||
typedef OEMCryptoResult (*GetDeviceInformation_t)(
|
typedef OEMCryptoResult (*GetDeviceInformation_t)(uint8_t* device_info,
|
||||||
uint8_t* device_info, size_t* device_info_length,
|
size_t* device_info_length);
|
||||||
|
typedef OEMCryptoResult (*GetDeviceSignedCsrPayload_t)(
|
||||||
|
const uint8_t* challenge, size_t challenge_length,
|
||||||
|
const uint8_t* device_info, size_t device_info_length,
|
||||||
uint8_t* signed_csr_payload, size_t* signed_csr_payload_length);
|
uint8_t* signed_csr_payload, size_t* signed_csr_payload_length);
|
||||||
|
|
||||||
Initialize_t Initialize = nullptr;
|
Initialize_t Initialize = nullptr;
|
||||||
@@ -59,6 +61,7 @@ class OEMCryptoInterface {
|
|||||||
GetBootCertificateChain_t GetBootCertificateChain = nullptr;
|
GetBootCertificateChain_t GetBootCertificateChain = nullptr;
|
||||||
BuildInformation_t BuildInformation = nullptr;
|
BuildInformation_t BuildInformation = nullptr;
|
||||||
GetDeviceInformation_t GetDeviceInformation = nullptr;
|
GetDeviceInformation_t GetDeviceInformation = nullptr;
|
||||||
|
GetDeviceSignedCsrPayload_t GetDeviceSignedCsrPayload = nullptr;
|
||||||
|
|
||||||
void* handle_ = nullptr;
|
void* handle_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ class WidevineProvisioner {
|
|||||||
bool GenerateCertificateRequest(
|
bool GenerateCertificateRequest(
|
||||||
bool testMode, const std::vector<uint8_t>& endpointEncCertChain,
|
bool testMode, const std::vector<uint8_t>& endpointEncCertChain,
|
||||||
std::vector<uint8_t>& deviceInfo, std::vector<uint8_t>& protectedData);
|
std::vector<uint8_t>& deviceInfo, std::vector<uint8_t>& protectedData);
|
||||||
|
bool GenerateCertificateRequestV2(const std::vector<uint8_t>& challenge,
|
||||||
|
std::vector<uint8_t>* csr);
|
||||||
bool GetDeviceInfo(std::vector<uint8_t>& device_info);
|
bool GetDeviceInfo(std::vector<uint8_t>& device_info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -46,6 +47,7 @@ class WidevineProvisioner {
|
|||||||
void InitializeCryptoInterface();
|
void InitializeCryptoInterface();
|
||||||
bool GetDeviceInfoCommon(cppbor::Map& device_info_map);
|
bool GetDeviceInfoCommon(cppbor::Map& device_info_map);
|
||||||
bool TryAddVerifiedDeviceInfo(cppbor::Map& device_info_map);
|
bool TryAddVerifiedDeviceInfo(cppbor::Map& device_info_map);
|
||||||
|
bool GetDeviceInfoV2(cppbor::Map& device_info_map);
|
||||||
|
|
||||||
std::unique_ptr<OEMCryptoInterface> crypto_interface_;
|
std::unique_ptr<OEMCryptoInterface> crypto_interface_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -81,6 +81,7 @@ bool OEMCryptoInterface::Init(const std::string& oemcrypto_path) {
|
|||||||
LOAD_SYM(GetBootCertificateChain);
|
LOAD_SYM(GetBootCertificateChain);
|
||||||
LOAD_SYM(BuildInformation);
|
LOAD_SYM(BuildInformation);
|
||||||
LOAD_SYM_IF_EXIST(GetDeviceInformation);
|
LOAD_SYM_IF_EXIST(GetDeviceInformation);
|
||||||
|
LOAD_SYM_IF_EXIST(GetDeviceSignedCsrPayload);
|
||||||
|
|
||||||
OEMCryptoResult status = Initialize();
|
OEMCryptoResult status = Initialize();
|
||||||
if (status != OEMCrypto_SUCCESS) {
|
if (status != OEMCrypto_SUCCESS) {
|
||||||
@@ -145,7 +146,7 @@ OEMCryptoResult OEMCryptoInterface::GetOEMCryptoBuildInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
OEMCryptoResult OEMCryptoInterface::GetVerifiedDeviceInformation(
|
OEMCryptoResult OEMCryptoInterface::GetVerifiedDeviceInformation(
|
||||||
VerifiedDeviceInfo& verified_device_info) {
|
std::vector<uint8_t>& verified_device_info) {
|
||||||
if (handle_ == nullptr) {
|
if (handle_ == nullptr) {
|
||||||
return OEMCrypto_ERROR_INIT_FAILED;
|
return OEMCrypto_ERROR_INIT_FAILED;
|
||||||
}
|
}
|
||||||
@@ -153,27 +154,46 @@ OEMCryptoResult OEMCryptoInterface::GetVerifiedDeviceInformation(
|
|||||||
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
verified_device_info.device_info.resize(0);
|
verified_device_info.resize(0);
|
||||||
size_t device_info_size = 0;
|
size_t verified_device_info_size = 0;
|
||||||
verified_device_info.signed_csr_payload.resize(0);
|
OEMCryptoResult result = GetDeviceInformation(verified_device_info.data(),
|
||||||
size_t signed_csr_payload_size = 0;
|
&verified_device_info_size);
|
||||||
|
|
||||||
OEMCryptoResult result = GetDeviceInformation(
|
|
||||||
verified_device_info.device_info.data(), &device_info_size,
|
|
||||||
verified_device_info.signed_csr_payload.data(), &signed_csr_payload_size);
|
|
||||||
LOGI("GetVerifiedDeviceInformation first attempt result %d", result);
|
LOGI("GetVerifiedDeviceInformation first attempt result %d", result);
|
||||||
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
|
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
|
||||||
verified_device_info.device_info.resize(device_info_size);
|
verified_device_info.resize(verified_device_info_size);
|
||||||
verified_device_info.signed_csr_payload.resize(signed_csr_payload_size);
|
result = GetDeviceInformation(verified_device_info.data(),
|
||||||
result = GetDeviceInformation(
|
&verified_device_info_size);
|
||||||
verified_device_info.device_info.data(), &device_info_size,
|
verified_device_info.resize(verified_device_info_size);
|
||||||
verified_device_info.signed_csr_payload.data(),
|
|
||||||
&signed_csr_payload_size);
|
|
||||||
verified_device_info.device_info.resize(device_info_size);
|
|
||||||
verified_device_info.signed_csr_payload.resize(signed_csr_payload_size);
|
|
||||||
LOGI("GetVerifiedDeviceInformation second attempt result %d", result);
|
LOGI("GetVerifiedDeviceInformation second attempt result %d", result);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
OEMCryptoResult OEMCryptoInterface::GetSignedCsrPayload(
|
||||||
|
const std::vector<uint8_t>& challenge,
|
||||||
|
const std::vector<uint8_t>& device_info,
|
||||||
|
std::vector<uint8_t>& signed_csr_payload) {
|
||||||
|
if (handle_ == nullptr) {
|
||||||
|
return OEMCrypto_ERROR_INIT_FAILED;
|
||||||
|
}
|
||||||
|
if (GetDeviceSignedCsrPayload == nullptr) {
|
||||||
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t signed_csr_payload_size = signed_csr_payload.size();
|
||||||
|
OEMCryptoResult result = GetDeviceSignedCsrPayload(
|
||||||
|
challenge.data(), challenge.size(), device_info.data(),
|
||||||
|
device_info.size(), signed_csr_payload.data(), &signed_csr_payload_size);
|
||||||
|
LOGI("GetDeviceSignedCsrPayload first attempt result %d", result);
|
||||||
|
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
|
||||||
|
signed_csr_payload.resize(signed_csr_payload_size);
|
||||||
|
result = GetDeviceSignedCsrPayload(challenge.data(), challenge.size(),
|
||||||
|
device_info.data(), device_info.size(),
|
||||||
|
signed_csr_payload.data(),
|
||||||
|
&signed_csr_payload_size);
|
||||||
|
signed_csr_payload.resize(signed_csr_payload_size);
|
||||||
|
LOGI("GetDeviceSignedCsrPayload second attempt result %d", result);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ std::vector<uint8_t> WidevineProvisioner::GetBcc() {
|
|||||||
std::vector<uint8_t> bcc;
|
std::vector<uint8_t> bcc;
|
||||||
OEMCryptoResult result = crypto_interface_->GetBcc(bcc);
|
OEMCryptoResult result = crypto_interface_->GetBcc(bcc);
|
||||||
if (result != OEMCrypto_SUCCESS) {
|
if (result != OEMCrypto_SUCCESS) {
|
||||||
LOGE("Failed to get BCC.");
|
LOGE("Failed to get BCC, result = %d", result);
|
||||||
}
|
}
|
||||||
return bcc;
|
return bcc;
|
||||||
}
|
}
|
||||||
@@ -58,7 +58,7 @@ bool WidevineProvisioner::GenerateCertificateRequest(
|
|||||||
std::vector<uint8_t> bcc;
|
std::vector<uint8_t> bcc;
|
||||||
OEMCryptoResult result = crypto_interface_->GetBcc(bcc);
|
OEMCryptoResult result = crypto_interface_->GetBcc(bcc);
|
||||||
if (result != OEMCrypto_SUCCESS) {
|
if (result != OEMCrypto_SUCCESS) {
|
||||||
LOGE("Failed to get BCC.");
|
LOGE("Failed to get BCC, result = %d", result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ bool WidevineProvisioner::GenerateCertificateRequest(
|
|||||||
|
|
||||||
bool WidevineProvisioner::TryAddVerifiedDeviceInfo(
|
bool WidevineProvisioner::TryAddVerifiedDeviceInfo(
|
||||||
cppbor::Map& device_info_map) {
|
cppbor::Map& device_info_map) {
|
||||||
VerifiedDeviceInfo verified_device_info;
|
std::vector<uint8_t> verified_device_info;
|
||||||
OEMCryptoResult result =
|
OEMCryptoResult result =
|
||||||
crypto_interface_->GetVerifiedDeviceInformation(verified_device_info);
|
crypto_interface_->GetVerifiedDeviceInformation(verified_device_info);
|
||||||
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
||||||
@@ -82,30 +82,22 @@ bool WidevineProvisioner::TryAddVerifiedDeviceInfo(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (result != OEMCrypto_SUCCESS) {
|
if (result != OEMCrypto_SUCCESS) {
|
||||||
LOGE("Failed to get verified device information.");
|
LOGE("Failed to get verified device information, result = %d", result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto [parsed, _, err] = cppbor::parse(
|
auto [parsed, _, err] = cppbor::parse(
|
||||||
reinterpret_cast<const uint8_t*>(verified_device_info.device_info.data()),
|
reinterpret_cast<const uint8_t*>(verified_device_info.data()),
|
||||||
verified_device_info.device_info.size());
|
verified_device_info.size());
|
||||||
if (!parsed || !parsed->asMap()) {
|
if (!parsed || !parsed->asMap()) {
|
||||||
LOGE("Failed to parse the verified device info cbor: %s", err.c_str());
|
LOGE("Failed to parse the verified device info cbor: %s", err.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const cppbor::Map* verified_device_info_map = parsed->asMap();
|
const cppbor::Map* verified_device_info_map = parsed->asMap();
|
||||||
auto& make = verified_device_info_map->get("manufacturer");
|
for (size_t i = 0; i < verified_device_info_map->size(); i++) {
|
||||||
if (make && make->asTstr() && make->asTstr()->value() != "") {
|
auto& [key_item, value_item] = (*verified_device_info_map)[i];
|
||||||
device_info_map.add("manufacturer", make->asTstr()->value());
|
LOGI("Found device info %s", key_item->asTstr()->value().data());
|
||||||
|
device_info_map.add(key_item->clone(), value_item->clone());
|
||||||
}
|
}
|
||||||
auto& model = verified_device_info_map->get("model");
|
|
||||||
if (model && model->asTstr() && model->asTstr()->value() != "") {
|
|
||||||
device_info_map.add("model", model->asTstr()->value());
|
|
||||||
}
|
|
||||||
auto& fused = verified_device_info_map->get("fused");
|
|
||||||
if (fused && fused->asUint()) {
|
|
||||||
device_info_map.add("fused", fused->asUint()->value());
|
|
||||||
}
|
|
||||||
device_info_map.canonicalize();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,13 +164,11 @@ bool WidevineProvisioner::GetDeviceInfoCommon(cppbor::Map& device_info_map) {
|
|||||||
OEMCryptoResult result =
|
OEMCryptoResult result =
|
||||||
crypto_interface_->GetOEMCryptoBuildInfo(oemcrypto_build_info);
|
crypto_interface_->GetOEMCryptoBuildInfo(oemcrypto_build_info);
|
||||||
if (result != OEMCrypto_SUCCESS) {
|
if (result != OEMCrypto_SUCCESS) {
|
||||||
LOGE("Failed to get oemcrypto build info.");
|
LOGE("Failed to get oemcrypto build info, result = %d", result);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
device_info_map.add(cppbor::Tstr("oemcrypto_build_info"),
|
device_info_map.add(cppbor::Tstr("oemcrypto_build_info"),
|
||||||
cppbor::Tstr(oemcrypto_build_info));
|
cppbor::Tstr(oemcrypto_build_info));
|
||||||
|
|
||||||
device_info_map.canonicalize();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +176,6 @@ bool WidevineProvisioner::GetDeviceInfo(std::vector<uint8_t>& device_info) {
|
|||||||
auto device_info_map = cppbor::Map();
|
auto device_info_map = cppbor::Map();
|
||||||
device_info_map.add(cppbor::Tstr("type"), cppbor::Tstr("widevine"));
|
device_info_map.add(cppbor::Tstr("type"), cppbor::Tstr("widevine"));
|
||||||
device_info_map.add(cppbor::Tstr("version"), cppbor::Uint(2));
|
device_info_map.add(cppbor::Tstr("version"), cppbor::Uint(2));
|
||||||
device_info_map.canonicalize();
|
|
||||||
if (!GetDeviceInfoCommon(device_info_map)) return false;
|
if (!GetDeviceInfoCommon(device_info_map)) return false;
|
||||||
device_info = device_info_map.canonicalize().encode();
|
device_info = device_info_map.canonicalize().encode();
|
||||||
return true;
|
return true;
|
||||||
@@ -318,6 +307,50 @@ cppbor::Array WidevineProvisioner::BuildCertReqRecipients(
|
|||||||
.add(cppbor::Null())); // No ciphertext
|
.add(cppbor::Null())); // No ciphertext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WidevineProvisioner::GetDeviceInfoV2(cppbor::Map& device_info_map) {
|
||||||
|
if (!GetDeviceInfoCommon(device_info_map)) return false;
|
||||||
|
device_info_map.canonicalize();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WidevineProvisioner::GenerateCertificateRequestV2(
|
||||||
|
const std::vector<uint8_t>& challenge, std::vector<uint8_t>* csr) {
|
||||||
|
if (csr == nullptr) {
|
||||||
|
LOGE("CSR is null.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Prepare BCC
|
||||||
|
std::vector<uint8_t> bcc;
|
||||||
|
OEMCryptoResult result = crypto_interface_->GetBcc(bcc);
|
||||||
|
if (result != OEMCrypto_SUCCESS) {
|
||||||
|
LOGE("Failed to get BCC, result = %d", result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Prepare device info
|
||||||
|
auto device_info_map = cppbor::Map();
|
||||||
|
if (!GetDeviceInfoV2(device_info_map)) {
|
||||||
|
LOGE("Failed to get device_info.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Prepare signed CSR payload
|
||||||
|
auto device_info = device_info_map.encode();
|
||||||
|
std::vector<uint8_t> signed_csr_payload;
|
||||||
|
result = crypto_interface_->GetSignedCsrPayload(challenge, device_info,
|
||||||
|
signed_csr_payload);
|
||||||
|
if (result != OEMCrypto_SUCCESS) {
|
||||||
|
LOGE("Failed to get the signed CSR payload, result = %d", result);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// https://source.corp.google.com/android-internal/hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
|
||||||
|
*csr = cppbor::Array()
|
||||||
|
.add(1 /* version */)
|
||||||
|
.add(cppbor::Map() /* UdsCerts */)
|
||||||
|
.add(cppbor::EncodedItem(std::move(bcc)))
|
||||||
|
.add(cppbor::EncodedItem(std::move(signed_csr_payload)))
|
||||||
|
.encode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void WidevineProvisioner::InitializeCryptoInterface() {
|
void WidevineProvisioner::InitializeCryptoInterface() {
|
||||||
std::string oemcrypto_path;
|
std::string oemcrypto_path;
|
||||||
if (!wvcdm::Properties::GetOEMCryptoPath(&oemcrypto_path)) {
|
if (!wvcdm::Properties::GetOEMCryptoPath(&oemcrypto_path)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user