Add BccParser to internal factory upload tool
Add a Bcc parser which prints the public keys in dice chain and a few other key properties. Borrowed code from https://source.corp.google.com/piper///depot/google3/video/widevine/keysmith/provisioning/provisioning40/boot_certificate_chain_parser.cc and modified locally to build an executable tool. Sample output from new pixel device: ROOT DEVICE PUBLIC KEY: key encoding format: DEVICE_KEY_OCTET_PAIR key algorithm type: ECDSA_SHA384 curve: P384 public key bytes: 04de874f6067bde6604b2d7a5d51ad28e6335d4524de4314ba6e594e6c95ccefeb17066a0b2f86b16591815c184694d7c54f02549e390e98e9e244e9cd73e616ffd9160371936b7c57e42617a3b497265bc84a0870fae4542e9f35b350383f4ebf CDI PUBLIC KEY 1: Issuer: 6a680468c33e5a9a95730632070f76e016f971a9 Subject: 5fbc8ab87c4a23ae660ea38461fea5bbc375a08c key encoding format: DEVICE_KEY_OCTET_PAIR key algorithm type: ECDSA_SHA384 curve: P384 public key bytes: 04dfa00e8f96d25400a7824c44a27ba141520629820a7348d48b6fa9b616e6f6793df08288c81985864b07b08fbce4beca3f0297b4b1965be3c26aa493d98ef20f18b2cf2c751ed77b170e04a2a7712f7509b22ac9b504965bd0a963c5947ccc2e CDI PUBLIC KEY 2: Issuer: 5fbc8ab87c4a23ae660ea38461fea5bbc375a08c Subject: 34a2c88d0edfd43663d47357e64280f26ebe5baa key encoding format: DEVICE_KEY_OCTET_PAIR key algorithm type: ECDSA_SHA384 curve: P384 public key bytes: 047717658a703114cd4d287162b3d75ff366b0d7dcd330bdab7fe61bcb1d50b2dd897a2ae6e878100839a3a47b966339bbb1220e76af68832035954ba39266563357fae446b734aefdf8b1295db59ac1ee9692841fee0b62b6d32651c817b34116 CDI PUBLIC KEY 3: Issuer: 34a2c88d0edfd43663d47357e64280f26ebe5baa Subject: 0b657b3c2448a5e0669953f9d5bdd90b431bbff2 key encoding format: DEVICE_KEY_OCTET_PAIR key algorithm type: ECDSA_SHA384 curve: P384 public key bytes: 041a11632576b82a1ead43a6744c6601c869dc8cbc519332f588ad79d01754964b595c4f83a7168c0f494715bedefa87cb699df4d41849fe140ab95252e55808908cc02708bc86b4d3a6a0f4dc6c49d138d67a5d3406ae25773ae182972656599c Test: parse BCC and Dice chain on pixel existing/new devices Bug: 279688624 Change-Id: Ia77a1d9f8f467992b998549572270da2c56b38b8
This commit is contained in:
@@ -29,6 +29,7 @@ cc_binary {
|
||||
"cli.cpp",
|
||||
"src/log.cpp",
|
||||
"src/properties_android.cpp",
|
||||
"src/BccParser.cpp",
|
||||
"src/WidevineProvisioner.cpp",
|
||||
"src/WidevineOemcryptoInterface.cpp",
|
||||
],
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "BccParser.h"
|
||||
#include "WidevineProvisioner.h"
|
||||
#include "log.h"
|
||||
#include "properties.h"
|
||||
@@ -161,7 +162,7 @@ std::unique_ptr<cppbor::Array> getCsrV3(
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "%s <bcc|device_info>\n", argv[0]);
|
||||
fprintf(stderr, "%s <bcc|bcc_str|device_info|csr|csr_v3>\n", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
widevine::WidevineProvisioner provisioner;
|
||||
@@ -169,6 +170,12 @@ int main(int argc, char** argv) {
|
||||
auto bcc = provisioner.GetBcc();
|
||||
fwrite(bcc.data(), 1, bcc.size(), stdout);
|
||||
fflush(stdout);
|
||||
} else if (!std::strcmp(argv[1], "bcc_str")) {
|
||||
auto bcc = provisioner.GetBcc();
|
||||
widevine::BccParser bcc_parser;
|
||||
std::string parsed_bcc = bcc_parser.Parse(bcc);
|
||||
std::copy(parsed_bcc.begin(), parsed_bcc.end(),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
} else if (!std::strcmp(argv[1], "device_info")) {
|
||||
std::vector<uint8_t> deviceInfo;
|
||||
if (provisioner.GetDeviceInfo(deviceInfo)) {
|
||||
|
||||
49
libwvdrmengine/tools/factory_upload_tool/include/BccParser.h
Normal file
49
libwvdrmengine/tools/factory_upload_tool/include/BccParser.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef BCC_PARSER_H_
|
||||
#define BCC_PARSER_H_
|
||||
|
||||
#include <cppbor.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace widevine {
|
||||
|
||||
// BccParser processes a Provisioning 4.0 device root of trust. It extracts
|
||||
// relevant pieces of information and outputs to std::string.
|
||||
// Relevant documents:
|
||||
// Android definition: go/remote-provisioning-hal#bcc.
|
||||
// Google Dice Profile: go/dice-profile
|
||||
class BccParser {
|
||||
public:
|
||||
explicit BccParser() {}
|
||||
virtual ~BccParser() = default;
|
||||
BccParser(const BccParser&) = delete;
|
||||
BccParser& operator=(const BccParser&) = delete;
|
||||
// Parse and verify a client generated root of trust. This message is part of
|
||||
// an attestation model conforming to the Google Open Dice Profile. This
|
||||
// message is received from a client device to attest it is a valid Widevine
|
||||
// device.
|
||||
virtual std::string Parse(const std::vector<uint8_t>& bcc);
|
||||
|
||||
private:
|
||||
// Process and print CoseKey PubKeyEd25519 / PubKeyECDSA256.
|
||||
bool ProcessDevicePublicKeyInfo(std::stringstream& ss,
|
||||
const cppbor::Map& public_key_info_map);
|
||||
|
||||
// Process and print the DiceChainEntryPayload, which contains subject public
|
||||
// key.
|
||||
bool ProcessDiceChainEntryPayload(std::stringstream& ss,
|
||||
std::string& payload);
|
||||
};
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
#endif // BCC_PARSER_H_
|
||||
@@ -0,0 +1,54 @@
|
||||
// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#ifndef DICE_CBOR_CONSTANTS_H_
|
||||
#define DICE_CBOR_CONSTANTS_H_
|
||||
|
||||
namespace widevine {
|
||||
|
||||
// The BCC is encoded using RFC 8949- Concise Binary Object Representation
|
||||
// (CBOR).
|
||||
|
||||
// The full definition of the following enums can be found here:
|
||||
// go/remote-provisioning-hal#bcc.
|
||||
|
||||
// The device key is encoded in a cbor map. The key values are a mix of
|
||||
// positive and negative integer values.
|
||||
enum {
|
||||
MAP_KEY_DEVICE_KEY_TYPE = 1,
|
||||
MAP_KEY_DEVICE_KEY_ALGORITHM = 3,
|
||||
MAP_KEY_DEVICE_KEY_OPS = 4,
|
||||
MAP_KEY_DEVICE_KEY_CURVE = -1,
|
||||
MAP_KEY_DEVICE_KEY_BYTES_0 = -2,
|
||||
MAP_KEY_DEVICE_KEY_BYTES_1 = -3,
|
||||
};
|
||||
|
||||
// The device key may be encoded in the BCC as either X,Y elliptic curve
|
||||
// coordinates, or as raw bytes. The value is identified using
|
||||
// MAP_KEY_DEVICE_KEY_TYPE.
|
||||
enum {
|
||||
DEVICE_KEY_ENCODING_UNKNOWN = 0,
|
||||
DEVICE_KEY_BYTE_STRING = 1,
|
||||
DEVICE_KEY_OCTET_PAIR = 2,
|
||||
};
|
||||
|
||||
// Android/Widevine Dice Attestation allows two signing models. This is
|
||||
// identified using MAP_KEY_DEVICE_KEY_ALGORITHM.
|
||||
enum {
|
||||
DEVICE_KEY_ALGORITHM_ES256 = -7, // EC key with SHA-256
|
||||
DEVICE_KEY_ALGORITHM_EDDSA = -8, // Pure ED25519.
|
||||
DEVICE_KEY_ALGORITHM_ES384 = -35, // EC key with SHA-384
|
||||
};
|
||||
|
||||
// The curve used to generate the device public key is identified using the
|
||||
// MAP_KEY_DEVICE_KEY_CURVE.
|
||||
enum {
|
||||
DEVICE_KEY_CURVE_P256 = 1,
|
||||
DEVICE_KEY_CURVE_P384 = 2,
|
||||
DEVICE_KEY_CURVE_ED25519 = 6,
|
||||
};
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
#endif // DICE_CBOR_CONSTANTS_H_
|
||||
373
libwvdrmengine/tools/factory_upload_tool/src/BccParser.cpp
Normal file
373
libwvdrmengine/tools/factory_upload_tool/src/BccParser.cpp
Normal file
@@ -0,0 +1,373 @@
|
||||
// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary
|
||||
// source code may only be used and distributed under the Widevine License
|
||||
// Agreement.
|
||||
|
||||
#include "BccParser.h"
|
||||
|
||||
#include <cppbor.h>
|
||||
#include <cppbor_parse.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "DiceCborConstants.h"
|
||||
|
||||
namespace widevine {
|
||||
namespace {
|
||||
|
||||
// Sized to hold a P256 public key uncompressed point compatible with X9.62.
|
||||
// The key is formatted in an Z/X/Y format in which Z == 0x04 and X and Y are
|
||||
// the public key coordinates. X and Y are each 32 bytes.
|
||||
constexpr int kP256KeyCoordinateSizeBytes = 256 / 8;
|
||||
// Sized to hold a P384 public key uncompressed point compatible with X9.62.
|
||||
// The key is formatted in an Z/X/Y format in which Z == 0x04 and X and Y are
|
||||
// the public key coordinates. X and Y are each 48 bytes.
|
||||
constexpr int kP384KeyCoordinateSizeBytes = 384 / 8;
|
||||
constexpr int kMarshaledP384KeySizeBytes = kP384KeyCoordinateSizeBytes * 2 + 1;
|
||||
constexpr int kMaxMarshaledECKeySizeBytes = kMarshaledP384KeySizeBytes;
|
||||
constexpr char kMarshaledECKeyZValue = 0x04;
|
||||
constexpr int kED25519KeyDataItemSizeBytes = 32;
|
||||
// The Issuer field key in BccEntryPayload.
|
||||
constexpr int64_t kIssuer = 1;
|
||||
// The Subject field key in BccEntryPayload.
|
||||
constexpr int64_t kSubject = 2;
|
||||
// The SubjectPublicKey field key in BccEntryPayload.
|
||||
constexpr int64_t kSubjectPublicKey = -4670552;
|
||||
|
||||
std::string TypeNameFromType(cppbor::MajorType type) {
|
||||
switch (type) {
|
||||
case cppbor::UINT:
|
||||
return "UINT";
|
||||
case cppbor::NINT:
|
||||
return "NINT";
|
||||
case cppbor::BSTR:
|
||||
return "BSTR";
|
||||
case cppbor::TSTR:
|
||||
return "TSTR";
|
||||
case cppbor::ARRAY:
|
||||
return "ARRAY";
|
||||
case cppbor::MAP:
|
||||
return "MAP";
|
||||
case cppbor::SEMANTIC:
|
||||
return "SEMANTIC";
|
||||
case cppbor::SIMPLE:
|
||||
return "SIMPLE";
|
||||
default:
|
||||
return "undefined type";
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetIssuerSubjectFromBccEntryPayload(
|
||||
const cppbor::Map* bcc_entry_payload) {
|
||||
std::string issuer = "Issuer: ";
|
||||
std::string subject = "Subject: ";
|
||||
for (size_t i = 0; i < bcc_entry_payload->size(); ++i) {
|
||||
const auto& entry = (*bcc_entry_payload)[i];
|
||||
if (entry.first == nullptr || entry.first->asInt() == nullptr ||
|
||||
entry.second == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (entry.first->asInt()->value() == kIssuer) {
|
||||
issuer += (entry.second->asTstr()->value() + "\n");
|
||||
} else if (entry.first->asInt()->value() == kSubject) {
|
||||
subject += (entry.second->asTstr()->value() + "\n");
|
||||
}
|
||||
}
|
||||
return issuer + subject;
|
||||
}
|
||||
|
||||
const cppbor::Bstr* GetSubjectPublicKeyFromBccEntryPayload(
|
||||
const cppbor::Map* bcc_entry_payload) {
|
||||
for (size_t i = 0; i < bcc_entry_payload->size(); ++i) {
|
||||
const auto& entry = (*bcc_entry_payload)[i];
|
||||
if (entry.first == nullptr || entry.first->asInt() == nullptr ||
|
||||
entry.second == nullptr) {
|
||||
continue;
|
||||
}
|
||||
if (entry.first->asInt()->value() == kSubjectPublicKey) {
|
||||
return entry.second->asBstr();
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// BCC/DiceCertChain definition:
|
||||
// https://source.corp.google.com/android-internal/hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
|
||||
std::string BccParser::Parse(const std::vector<uint8_t>& bcc) {
|
||||
std::stringstream ss;
|
||||
auto [parsed_bcc, _, err_msg] = cppbor::parse(bcc);
|
||||
if (parsed_bcc == nullptr) {
|
||||
ss << "Failed to parse input BCC: " << err_msg.c_str() << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
if (parsed_bcc->asArray() == nullptr) {
|
||||
ss << "Input BCC is not a CBOR array: "
|
||||
<< TypeNameFromType(parsed_bcc->type()) << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
const cppbor::Array* bcc_array = parsed_bcc->asArray();
|
||||
if (bcc_array->size() < 2) {
|
||||
ss << "Input BCC should contain at least two elements, actual: "
|
||||
<< bcc_array->size() << "\n";
|
||||
return ss.str();
|
||||
}
|
||||
// The first element in the array contains the root device public key
|
||||
// definition.
|
||||
ss << "ROOT DEVICE PUBLIC KEY: \n";
|
||||
const cppbor::Map* device_public_key_info = (*bcc_array)[0]->asMap();
|
||||
if (device_public_key_info == nullptr) {
|
||||
ss << "Invalid dice cert chain type for the first element"
|
||||
<< "\n";
|
||||
return ss.str();
|
||||
}
|
||||
if (!ProcessDevicePublicKeyInfo(ss, *device_public_key_info)) {
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Parse each certificate in the chain. The structure of thr entries are
|
||||
// COSE_Sign1 (untagged).
|
||||
for (size_t i = 1; i < bcc_array->size(); ++i) {
|
||||
ss << "\nCDI PUBLIC KEY " << i << ": \n";
|
||||
const cppbor::Array* bcc_entry = (*bcc_array)[i]->asArray();
|
||||
if (bcc_entry == nullptr) {
|
||||
ss << "Invalid dice cert chain type"
|
||||
<< "\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
// Skip CoseSign1 signature verification here, only extract pub keys
|
||||
if (bcc_entry->size() != 4 || (*bcc_entry)[0]->type() != cppbor::BSTR ||
|
||||
(*bcc_entry)[1]->type() != cppbor::MAP ||
|
||||
(*bcc_entry)[2]->type() != cppbor::BSTR ||
|
||||
(*bcc_entry)[3]->type() != cppbor::BSTR) {
|
||||
ss << "Invalid signature array"
|
||||
<< "\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
const std::vector<uint8_t>& key_payload =
|
||||
(*bcc_entry)[2]->asBstr()->value();
|
||||
std::string payload(key_payload.begin(), key_payload.end());
|
||||
if (!ProcessDiceChainEntryPayload(ss, payload)) {
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
bool BccParser::ProcessDevicePublicKeyInfo(
|
||||
std::stringstream& ss, const cppbor::Map& public_key_info_map) {
|
||||
int key_encoding_format = DEVICE_KEY_ENCODING_UNKNOWN;
|
||||
std::string device_key_bytes_0;
|
||||
std::string device_key_bytes_1;
|
||||
for (size_t index = 0; index < public_key_info_map.size(); ++index) {
|
||||
std::pair<const std::unique_ptr<cppbor::Item>&,
|
||||
const std::unique_ptr<cppbor::Item>&>
|
||||
entry = public_key_info_map[index];
|
||||
if (entry.first->type() != cppbor::NINT &&
|
||||
entry.first->type() != cppbor::UINT) {
|
||||
ss << "Invalid map key type " << TypeNameFromType(entry.first->type())
|
||||
<< " in device key info"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
int map_key = entry.first->type() == cppbor::NINT
|
||||
? entry.first->asNint()->value()
|
||||
: entry.first->asInt()->value();
|
||||
switch (map_key) {
|
||||
case MAP_KEY_DEVICE_KEY_TYPE: {
|
||||
if (entry.second->type() != cppbor::UINT) {
|
||||
ss << "Invalid map value type "
|
||||
<< TypeNameFromType(entry.second->type()) << " for device key"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
ss << "key encoding format: ";
|
||||
int64_t value = entry.second->asUint()->value();
|
||||
switch (value) {
|
||||
case DEVICE_KEY_OCTET_PAIR:
|
||||
key_encoding_format = DEVICE_KEY_OCTET_PAIR;
|
||||
ss << "DEVICE_KEY_OCTET_PAIR"
|
||||
<< "\n";
|
||||
break;
|
||||
case DEVICE_KEY_BYTE_STRING:
|
||||
key_encoding_format = DEVICE_KEY_BYTE_STRING;
|
||||
ss << "DEVICE_KEY_BYTE_STRING"
|
||||
<< "\n";
|
||||
break;
|
||||
default:
|
||||
ss << "Unhandled cbor value for device key format: " << value
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
case MAP_KEY_DEVICE_KEY_ALGORITHM: {
|
||||
if (entry.second->type() != cppbor::NINT) {
|
||||
ss << "Invalid map value type "
|
||||
<< TypeNameFromType(entry.second->type())
|
||||
<< " for device key algorithm"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
ss << "key algorithm type: ";
|
||||
int64_t value = entry.second->asNint()->value();
|
||||
switch (value) {
|
||||
case DEVICE_KEY_ALGORITHM_ES256:
|
||||
ss << "ECDSA_SHA256";
|
||||
break;
|
||||
case DEVICE_KEY_ALGORITHM_ES384:
|
||||
ss << "ECDSA_SHA384";
|
||||
break;
|
||||
case DEVICE_KEY_ALGORITHM_EDDSA:
|
||||
ss << "EDDSA";
|
||||
break;
|
||||
}
|
||||
ss << "\n";
|
||||
} break;
|
||||
case MAP_KEY_DEVICE_KEY_OPS:
|
||||
// The OPS is an array. Ignored for now.
|
||||
break;
|
||||
case MAP_KEY_DEVICE_KEY_CURVE: {
|
||||
if (entry.second->type() != cppbor::UINT) {
|
||||
ss << "Invalid map value type "
|
||||
<< TypeNameFromType(entry.second->type())
|
||||
<< " for device key curve"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
ss << "curve: ";
|
||||
int64_t value = entry.second->asUint()->value();
|
||||
switch (value) {
|
||||
case DEVICE_KEY_CURVE_ED25519:
|
||||
ss << "ED25519";
|
||||
break;
|
||||
case DEVICE_KEY_CURVE_P256:
|
||||
ss << "P256";
|
||||
break;
|
||||
case DEVICE_KEY_CURVE_P384:
|
||||
ss << "P384";
|
||||
break;
|
||||
default:
|
||||
ss << "Invalid map value " << value << " for device key curve"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
ss << "\n";
|
||||
} break;
|
||||
case MAP_KEY_DEVICE_KEY_BYTES_0:
|
||||
case MAP_KEY_DEVICE_KEY_BYTES_1:
|
||||
// BCC encodes keys as either two X, Y octet strings or a single
|
||||
// octet string. The format used depends on the key type.
|
||||
if (entry.second->type() != cppbor::BSTR) {
|
||||
ss << "Unexpected cbor type for device key bytes"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
const std::vector<uint8_t>& key_bytes = entry.second->asBstr()->value();
|
||||
// Key byte length depends upon the key type.
|
||||
if (key_bytes.size() != kED25519KeyDataItemSizeBytes &&
|
||||
key_bytes.size() != kP256KeyCoordinateSizeBytes &&
|
||||
key_bytes.size() != kP384KeyCoordinateSizeBytes) {
|
||||
ss << "Malformed device public key data size of" << key_bytes.size()
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
std::string& key_bytes_str = map_key == MAP_KEY_DEVICE_KEY_BYTES_0
|
||||
? device_key_bytes_0
|
||||
: device_key_bytes_1;
|
||||
key_bytes_str.assign(key_bytes.begin(), key_bytes.end());
|
||||
}
|
||||
}
|
||||
if (device_key_bytes_0.empty() ||
|
||||
(key_encoding_format == DEVICE_KEY_OCTET_PAIR &&
|
||||
device_key_bytes_1.empty())) {
|
||||
ss << "Malformed device public key definition. Missing device public key "
|
||||
"bytes"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
std::string device_key_bytes;
|
||||
if (key_encoding_format == DEVICE_KEY_OCTET_PAIR) {
|
||||
// Key is an ECDSA elliptic key. We need to return the ANSI X9.62
|
||||
// marshaled public key. Generate the marshaled key if needed. The
|
||||
// marshaled key is needed to create an ECPublicKey object.
|
||||
// std::string* device_key_bytes = public_key_info.mutable_key_bytes();
|
||||
device_key_bytes.reserve(kMaxMarshaledECKeySizeBytes);
|
||||
device_key_bytes.resize(1);
|
||||
device_key_bytes[0] = kMarshaledECKeyZValue;
|
||||
device_key_bytes.append(device_key_bytes_0);
|
||||
device_key_bytes.append(device_key_bytes_1);
|
||||
} else {
|
||||
device_key_bytes = device_key_bytes_0;
|
||||
}
|
||||
std::ostringstream ss_hex;
|
||||
ss_hex << std::setfill('0');
|
||||
for (size_t i = 0; i < device_key_bytes.size(); i++) {
|
||||
ss_hex << std::setw(2) << std::hex << static_cast<int>(device_key_bytes[i]);
|
||||
}
|
||||
ss << "public key bytes: " << ss_hex.str() << "\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BccParser::ProcessDiceChainEntryPayload(std::stringstream& ss,
|
||||
std::string& payload) {
|
||||
if (payload.empty()) {
|
||||
ss << "Empty bcc entry payload"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
auto parse_result = cppbor::parse(
|
||||
reinterpret_cast<const uint8_t*>(payload.data()),
|
||||
reinterpret_cast<const uint8_t*>(payload.data() + payload.size()));
|
||||
std::unique_ptr<cppbor::Item> item = std::move(std::get<0>(parse_result));
|
||||
std::string error_message = std::get<2>(parse_result);
|
||||
if (item == nullptr || !error_message.empty()) {
|
||||
ss << "Unable to parse bcc entry payload: " << error_message << "\n";
|
||||
return false;
|
||||
}
|
||||
if (item->type() != cppbor::MAP) {
|
||||
ss << "Unexpected bcc entry payload type"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string issuer_subject =
|
||||
GetIssuerSubjectFromBccEntryPayload(item->asMap());
|
||||
ss << issuer_subject;
|
||||
|
||||
const cppbor::Bstr* subject_public_key =
|
||||
GetSubjectPublicKeyFromBccEntryPayload(item->asMap());
|
||||
if (subject_public_key == nullptr) {
|
||||
ss << "Bcc entry payload has no subject public key"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now parse the serialized subject public key.
|
||||
parse_result = cppbor::parse(
|
||||
subject_public_key->value().data(),
|
||||
subject_public_key->value().data() + subject_public_key->value().size());
|
||||
item = std::move(std::get<0>(parse_result));
|
||||
error_message = std::get<2>(parse_result);
|
||||
if (item == nullptr || !error_message.empty()) {
|
||||
ss << "Unable to parse serialized subject public key: " << error_message
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
const cppbor::Map* subject_public_key_info = item->asMap();
|
||||
if (subject_public_key_info == nullptr) {
|
||||
ss << "Invalid subject public key type"
|
||||
<< "\n";
|
||||
return false;
|
||||
}
|
||||
return ProcessDevicePublicKeyInfo(ss, *subject_public_key_info);
|
||||
}
|
||||
|
||||
} // namespace widevine
|
||||
Reference in New Issue
Block a user