[ Merge of http://go/wvgerrit/149469 ] Created a new test for stressing OEMCrypto's ability to generate OTA Keybox provisioning requests. This forces the TA to retrieve keys from KM, generate certificate and sign the request. This is intended to find any unexpected system degradation within the device's TA(s). Bug: 227542259 Test: oemcrypto_test Change-Id: Ib34f2f801a7fe74ca67aa0a16f68f9ae326de24e
351 lines
18 KiB
C++
351 lines
18 KiB
C++
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine License
|
|
// Agreement.
|
|
//
|
|
|
|
#include <arpa/inet.h>
|
|
#include <gtest/gtest.h>
|
|
#include <openssl/sha.h>
|
|
|
|
#include "OEMCryptoCENC.h"
|
|
#include "arraysize.h"
|
|
#include "log.h"
|
|
#include "oec_key_deriver.h"
|
|
#include "oec_session_util.h"
|
|
#include "oec_test_data.h"
|
|
#include "oemcrypto_session_tests_helper.h"
|
|
#include "oemcrypto_types.h"
|
|
#include "platform.h"
|
|
#include "string_conversions.h"
|
|
|
|
using namespace std;
|
|
|
|
namespace wvoec {
|
|
namespace {
|
|
const std::string kOption2Label = "WV_KB_REPROV_V02";
|
|
constexpr size_t kLabelLength = 16u;
|
|
constexpr size_t kDeviceIdLength = 32u;
|
|
constexpr size_t kMinimumRequestLength =
|
|
kLabelLength // Start with a label.
|
|
+ kDeviceIdLength // Fixed length device id.
|
|
+ sizeof(uint32_t) // cert length.
|
|
// variable cert length.
|
|
+ HMAC_SHA256_SIGNATURE_SIZE; // signature.
|
|
static const uint8_t TestKeyPKCS8[] = {
|
|
0x30, 0x82, 0x04, 0xbf, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a,
|
|
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82,
|
|
0x04, 0xa9, 0x30, 0x82, 0x04, 0xa5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01,
|
|
0x01, 0x00, 0xa6, 0x33, 0x7f, 0x22, 0x05, 0xae, 0xcf, 0xae, 0x29, 0x67,
|
|
0xa9, 0x3a, 0xe7, 0x08, 0xbf, 0x61, 0x92, 0x62, 0x4a, 0xd4, 0x82, 0x37,
|
|
0x4d, 0x08, 0xa1, 0x77, 0x9f, 0x31, 0xa8, 0x92, 0xc5, 0x8b, 0x85, 0x84,
|
|
0x12, 0x66, 0x52, 0xe6, 0x4b, 0x4c, 0xde, 0xdd, 0x43, 0x85, 0x53, 0xd1,
|
|
0x0c, 0x79, 0x2c, 0xcf, 0x38, 0x4b, 0x72, 0x50, 0xf4, 0x34, 0x15, 0x0b,
|
|
0xbe, 0x06, 0xf7, 0x60, 0x66, 0xda, 0xea, 0x40, 0x25, 0x38, 0x3e, 0xeb,
|
|
0x6e, 0x13, 0x1b, 0xd0, 0x04, 0xd9, 0x4a, 0xa0, 0x7c, 0x7a, 0xb8, 0x64,
|
|
0xde, 0xdb, 0x55, 0x93, 0xed, 0xb9, 0x93, 0x89, 0x83, 0x61, 0x2f, 0x23,
|
|
0x15, 0x91, 0x28, 0xd2, 0x7a, 0x02, 0x69, 0x12, 0x70, 0x19, 0xea, 0xfc,
|
|
0x31, 0xd5, 0xdd, 0x85, 0xeb, 0x81, 0x2f, 0xae, 0xb3, 0x48, 0x94, 0xbe,
|
|
0x57, 0x3b, 0xac, 0x0a, 0x4f, 0x9e, 0x24, 0x2e, 0xae, 0x4e, 0x13, 0x53,
|
|
0x34, 0xe1, 0xcd, 0x66, 0xcc, 0xa6, 0x3a, 0x89, 0x8c, 0x43, 0xef, 0x65,
|
|
0xe7, 0x40, 0xc5, 0x09, 0xb8, 0x36, 0xd6, 0xcd, 0x41, 0xdf, 0x29, 0xbb,
|
|
0x23, 0xa2, 0x54, 0xa5, 0x9f, 0x37, 0x6c, 0xbd, 0x8d, 0xd6, 0x8c, 0x33,
|
|
0xa5, 0xd8, 0x4a, 0xc9, 0x08, 0x35, 0x41, 0xfb, 0xb0, 0x8f, 0x74, 0xdc,
|
|
0xbd, 0x35, 0x01, 0x65, 0xe1, 0x06, 0x6d, 0x41, 0xf4, 0x81, 0x4a, 0xfc,
|
|
0xc3, 0xb3, 0x1c, 0xb7, 0x18, 0xdc, 0x29, 0x4e, 0xea, 0x1b, 0x98, 0xd5,
|
|
0x7d, 0x51, 0x60, 0xcd, 0xfd, 0xdb, 0x74, 0x39, 0x43, 0xa7, 0xc7, 0x0d,
|
|
0xe8, 0x8c, 0xd9, 0xc7, 0xb9, 0xdc, 0x42, 0x08, 0x34, 0x43, 0x2f, 0xf2,
|
|
0x5b, 0xb6, 0x3e, 0x6a, 0x37, 0xb9, 0x08, 0x6a, 0xdf, 0x43, 0x32, 0x0e,
|
|
0x38, 0xd3, 0x3a, 0xeb, 0x13, 0x74, 0xd2, 0x02, 0x36, 0xed, 0xa0, 0x7c,
|
|
0xc8, 0x55, 0xc5, 0xbf, 0x58, 0xbd, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02,
|
|
0x82, 0x01, 0x01, 0x00, 0x85, 0x0f, 0x93, 0x88, 0x34, 0x8e, 0x89, 0x3d,
|
|
0x01, 0x6f, 0x39, 0xa0, 0xab, 0xd9, 0x68, 0x07, 0x80, 0xff, 0xea, 0xb3,
|
|
0x0a, 0x71, 0xa5, 0xdd, 0xf4, 0x0f, 0xe6, 0x47, 0x06, 0x94, 0x43, 0x4d,
|
|
0xf9, 0x9e, 0x0c, 0x71, 0x19, 0x8b, 0xc0, 0xdb, 0x91, 0x4e, 0x0a, 0x41,
|
|
0xd3, 0x21, 0xf9, 0xdf, 0x85, 0xcd, 0x7d, 0x5f, 0x81, 0xed, 0x68, 0x25,
|
|
0xce, 0x77, 0xb1, 0x32, 0xb8, 0x98, 0xd8, 0xa0, 0x09, 0x8d, 0x43, 0x7f,
|
|
0x2d, 0x78, 0xa5, 0x8e, 0xec, 0xe4, 0x75, 0x0d, 0x56, 0x5e, 0xf8, 0x69,
|
|
0xf3, 0xf8, 0xe6, 0x27, 0x29, 0xf3, 0x9e, 0x0e, 0xc6, 0x1d, 0x01, 0x2f,
|
|
0x2c, 0x62, 0xe5, 0x60, 0x6b, 0x13, 0x5f, 0x95, 0x50, 0x73, 0xef, 0x86,
|
|
0x00, 0x88, 0xda, 0x89, 0x43, 0xaa, 0x75, 0x2a, 0xdf, 0x76, 0xf9, 0x98,
|
|
0x71, 0x65, 0x96, 0x47, 0x72, 0xec, 0x6a, 0x63, 0xcc, 0xca, 0x06, 0xc7,
|
|
0xb6, 0x58, 0x8d, 0x3e, 0x8a, 0x87, 0x4f, 0x5a, 0x5c, 0x1d, 0x82, 0x40,
|
|
0x61, 0x13, 0xed, 0x6d, 0x21, 0x88, 0x1d, 0xb7, 0x70, 0xda, 0xc9, 0x9d,
|
|
0xb2, 0x29, 0x44, 0x0a, 0xf2, 0xdb, 0xaa, 0x1e, 0xdb, 0x0a, 0x92, 0xf8,
|
|
0x42, 0x1d, 0xe6, 0x75, 0x6a, 0xce, 0x2f, 0xd2, 0xea, 0x9d, 0x71, 0x98,
|
|
0x27, 0x0d, 0xf2, 0xc9, 0x60, 0x85, 0x31, 0x88, 0x1c, 0x91, 0x55, 0xe3,
|
|
0xf8, 0x7e, 0xe6, 0xcf, 0x7b, 0x66, 0x27, 0x45, 0x1e, 0xaa, 0x0a, 0x5a,
|
|
0xfe, 0x07, 0x0a, 0x3a, 0xfd, 0x04, 0xdc, 0xae, 0x5a, 0xf3, 0xc5, 0x3d,
|
|
0x18, 0x36, 0x49, 0x97, 0x5c, 0x42, 0xef, 0x9e, 0x4a, 0xcd, 0xa7, 0x23,
|
|
0xca, 0x17, 0xc4, 0x09, 0x55, 0x15, 0xd4, 0x23, 0x7c, 0x19, 0xb2, 0x24,
|
|
0x87, 0x8f, 0x75, 0x70, 0xca, 0xb4, 0x98, 0x33, 0x8a, 0xf2, 0xdd, 0x15,
|
|
0x8d, 0x27, 0x76, 0xe4, 0xbb, 0xbb, 0x23, 0x2d, 0x02, 0x81, 0x81, 0x00,
|
|
0xdc, 0x3b, 0x21, 0x8d, 0xf2, 0x17, 0xff, 0xc1, 0xc6, 0xfb, 0xe2, 0xdb,
|
|
0x29, 0xed, 0x9e, 0xfd, 0xb6, 0xd5, 0xe7, 0x23, 0x29, 0x86, 0xdc, 0x65,
|
|
0xfc, 0x8b, 0x86, 0x39, 0x52, 0x1e, 0xa4, 0x30, 0x72, 0x14, 0x12, 0x24,
|
|
0x72, 0xb4, 0x97, 0x77, 0x61, 0x7c, 0x34, 0x5a, 0x0a, 0x1d, 0x12, 0xfe,
|
|
0xc7, 0x1f, 0x06, 0x79, 0x8c, 0xf5, 0x41, 0xdd, 0x79, 0x8f, 0xeb, 0x17,
|
|
0xf3, 0x32, 0x32, 0x13, 0x37, 0xee, 0x73, 0xeb, 0x82, 0xfa, 0x7b, 0x55,
|
|
0x16, 0xb0, 0x3e, 0x2f, 0x6f, 0xb6, 0xa6, 0x38, 0x99, 0xaf, 0xde, 0xfd,
|
|
0x3a, 0x48, 0xa2, 0x95, 0x70, 0x14, 0x06, 0xf9, 0x10, 0x0f, 0x48, 0x72,
|
|
0x0d, 0x48, 0x69, 0xfc, 0x81, 0xf1, 0x07, 0x5c, 0x99, 0x44, 0xe9, 0x02,
|
|
0xd5, 0x61, 0x36, 0x31, 0x64, 0x02, 0x5a, 0x1d, 0x3e, 0xae, 0xde, 0x08,
|
|
0xd2, 0xde, 0x42, 0xac, 0xf1, 0xe1, 0x38, 0x9f, 0x02, 0x81, 0x81, 0x00,
|
|
0xc1, 0x31, 0xe3, 0x45, 0xec, 0x53, 0xa5, 0x56, 0xe0, 0xc1, 0xe3, 0xf2,
|
|
0xeb, 0xb0, 0xe5, 0x84, 0xdd, 0x56, 0x59, 0x7c, 0xf4, 0x65, 0x66, 0x8c,
|
|
0x9c, 0x66, 0x55, 0x2a, 0x2c, 0x3c, 0x46, 0xf7, 0xac, 0x36, 0xd8, 0x2f,
|
|
0x27, 0x97, 0x57, 0x64, 0x6e, 0xc7, 0x5f, 0x43, 0xf9, 0x82, 0x27, 0xf3,
|
|
0xc4, 0xfa, 0xc6, 0xb1, 0xea, 0x2d, 0xcc, 0x36, 0x3a, 0x37, 0x22, 0xb6,
|
|
0x7e, 0x6a, 0x25, 0xab, 0x1a, 0xd2, 0x3e, 0x38, 0x38, 0x9d, 0x04, 0xc0,
|
|
0xc7, 0x4a, 0xa2, 0x38, 0xb4, 0xcf, 0x9c, 0x97, 0x4c, 0x03, 0x76, 0x37,
|
|
0x86, 0x09, 0x1e, 0x25, 0x2b, 0x67, 0x8e, 0x7b, 0xce, 0x3d, 0x50, 0xf6,
|
|
0x7a, 0x8b, 0x00, 0x23, 0x48, 0xda, 0x6e, 0xbe, 0x4c, 0x23, 0xdb, 0x9c,
|
|
0x4f, 0x3f, 0xa9, 0x18, 0x59, 0xf6, 0xc4, 0x33, 0xc5, 0xaa, 0x75, 0x40,
|
|
0xf7, 0xba, 0xfc, 0x83, 0x40, 0x36, 0x85, 0x23, 0x02, 0x81, 0x80, 0x68,
|
|
0xd9, 0xf6, 0x35, 0xc0, 0x87, 0x50, 0x8b, 0x0f, 0x93, 0xa9, 0x04, 0x33,
|
|
0x48, 0x20, 0xa4, 0x26, 0xc2, 0x5c, 0x53, 0x4f, 0x58, 0x17, 0xe2, 0xae,
|
|
0x84, 0x37, 0x19, 0x5f, 0x51, 0x9b, 0x56, 0x3d, 0x59, 0xf4, 0xf1, 0x49,
|
|
0x73, 0x55, 0x91, 0xce, 0xe5, 0xf5, 0x7e, 0xd0, 0xc5, 0xda, 0xdf, 0x56,
|
|
0x2a, 0x1d, 0x49, 0x0d, 0xa5, 0x4f, 0x00, 0x84, 0xf9, 0xd2, 0x32, 0x0a,
|
|
0xe5, 0x61, 0x15, 0xe9, 0x51, 0x2b, 0xfb, 0x7a, 0xd6, 0x8a, 0x95, 0x8e,
|
|
0x41, 0xc6, 0xb9, 0x8a, 0xf4, 0x68, 0xdb, 0x15, 0xc0, 0xb7, 0xe7, 0xd4,
|
|
0x31, 0xf4, 0xc6, 0x35, 0x20, 0x33, 0xd9, 0xac, 0x9d, 0xba, 0x1e, 0x22,
|
|
0xd8, 0xd1, 0x2d, 0x19, 0x28, 0x8a, 0x1a, 0xba, 0x16, 0x26, 0xe1, 0xe4,
|
|
0x79, 0x6d, 0xf5, 0xc1, 0xe9, 0xa4, 0xc1, 0xbb, 0xb0, 0x41, 0xa1, 0xed,
|
|
0xd3, 0x47, 0xe7, 0x53, 0x19, 0xa9, 0x7d, 0x02, 0x81, 0x81, 0x00, 0xb4,
|
|
0xd6, 0x5e, 0xb7, 0xd7, 0xe3, 0xe0, 0x13, 0x37, 0x65, 0x26, 0x5a, 0xff,
|
|
0x75, 0x61, 0x12, 0x02, 0x20, 0xce, 0xb9, 0x21, 0x07, 0x3d, 0x7b, 0x86,
|
|
0xf6, 0x5e, 0xe7, 0x8f, 0xea, 0x88, 0x3f, 0x53, 0x4b, 0x2f, 0x06, 0xcc,
|
|
0x97, 0x64, 0x2d, 0x55, 0x68, 0x77, 0xea, 0xe7, 0xc5, 0x86, 0x62, 0x2e,
|
|
0xd2, 0xd2, 0x64, 0x3d, 0x20, 0xcb, 0x53, 0x43, 0x20, 0xd2, 0xf4, 0x61,
|
|
0xd6, 0x38, 0x16, 0x36, 0x8f, 0xef, 0xbf, 0xae, 0x76, 0x83, 0xb9, 0x73,
|
|
0x92, 0x8f, 0xd0, 0x66, 0xa7, 0x23, 0x1b, 0x98, 0x02, 0x71, 0x88, 0xbd,
|
|
0x85, 0x11, 0x5b, 0x97, 0x8a, 0x62, 0x9b, 0xce, 0xcc, 0x24, 0x59, 0xe3,
|
|
0x10, 0xf3, 0x7b, 0x13, 0xb9, 0xab, 0x09, 0xa3, 0xb9, 0xb8, 0xda, 0x52,
|
|
0x6f, 0xf3, 0x77, 0x20, 0xd6, 0xd4, 0x86, 0xe5, 0x92, 0x8e, 0x18, 0xd7,
|
|
0x0a, 0x87, 0x4c, 0xd0, 0x31, 0x78, 0x63, 0x02, 0x81, 0x81, 0x00, 0xc2,
|
|
0x8c, 0xea, 0xa2, 0x9b, 0xfa, 0x42, 0x98, 0x70, 0x5a, 0xf9, 0x73, 0x78,
|
|
0xee, 0xd6, 0x2b, 0x3e, 0x5b, 0xf4, 0x2f, 0x84, 0x60, 0x71, 0x9b, 0xce,
|
|
0xf4, 0x9b, 0x88, 0x25, 0x0a, 0x29, 0x41, 0x4b, 0x4d, 0x36, 0xcf, 0xd9,
|
|
0x86, 0xac, 0x75, 0xa2, 0xed, 0x56, 0x5b, 0x6e, 0x87, 0x1e, 0x32, 0x04,
|
|
0x13, 0xaf, 0xa5, 0x1e, 0xf5, 0x0f, 0x9d, 0x93, 0x4a, 0x29, 0x90, 0x23,
|
|
0x0e, 0xf9, 0x8e, 0xfd, 0x2d, 0xfe, 0x2b, 0x79, 0xa6, 0x03, 0x6c, 0xcd,
|
|
0x01, 0xee, 0xba, 0x69, 0xb3, 0xb9, 0xd4, 0xc8, 0x99, 0x0f, 0x72, 0xba,
|
|
0x59, 0x22, 0xdc, 0x2d, 0xc3, 0x97, 0x8c, 0xa7, 0xb3, 0xbf, 0x60, 0xe1,
|
|
0x61, 0xe5, 0xd4, 0x51, 0x6f, 0x36, 0x9c, 0x9a, 0xb8, 0x1b, 0x52, 0xec,
|
|
0x13, 0xf3, 0xa7, 0xdb, 0xdb, 0x5d, 0x89, 0x2d, 0xd7, 0x02, 0x96, 0xaf,
|
|
0xeb, 0x72, 0x8d, 0xd5, 0x56, 0x3b, 0x3a};
|
|
|
|
constexpr size_t kInitialOtaKeyboxRequestSize = 8 * 1024; // 8 kB.
|
|
// TODO(fredgc): Make sure that partners can use a test cert when
|
|
// |use_test_key| parameter of OEMCrypto_GenerateOTARequest() is true.
|
|
constexpr uint32_t kUseTestKey = 1;
|
|
|
|
// TODO(fredgc): duplicate code. Move to common util package.
|
|
// Return a printable string from data. If all the characters are printable,
|
|
// then just use the string. Otherwise, convert to hex.
|
|
std::string MaybeHex(const uint8_t* data, size_t length) {
|
|
for (size_t i = 0; i < length; i++) {
|
|
if (!isprint(data[i])) return "0x" + wvutil::HexEncode(data, length);
|
|
}
|
|
return std::string(reinterpret_cast<const char*>(data), length);
|
|
}
|
|
std::string MaybeHex(const std::vector<uint8_t>& data) {
|
|
return MaybeHex(data.data(), data.size());
|
|
}
|
|
|
|
std::vector<uint8_t> GetModelKey(const std::vector<uint8_t>& device_id) {
|
|
std::vector<uint8_t> keymint_key(
|
|
TestKeyPKCS8, TestKeyPKCS8 + wvutil::ArraySize(TestKeyPKCS8));
|
|
keymint_key.insert(keymint_key.end(), device_id.begin(), device_id.end());
|
|
std::vector<uint8_t> key(SHA256_DIGEST_LENGTH);
|
|
SHA256(keymint_key.data(), keymint_key.size(), key.data());
|
|
key.resize(wvoec::KEY_SIZE); // Truncate to standard AES 128 key.
|
|
return key;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
class OTAKeyboxProvisioningTest : public ::testing::Test, public SessionUtil {
|
|
protected:
|
|
void SetUp() override {
|
|
::testing::Test::SetUp();
|
|
const ::testing::TestInfo* const test_info =
|
|
::testing::UnitTest::GetInstance()->current_test_info();
|
|
LOGD("Running test %s.%s", test_info->test_case_name(), test_info->name());
|
|
OEMCrypto_SetSandbox(kTestSandbox, sizeof(kTestSandbox));
|
|
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_Initialize());
|
|
}
|
|
|
|
void TearDown() override {
|
|
OEMCrypto_Terminate();
|
|
::testing::Test::TearDown();
|
|
}
|
|
};
|
|
|
|
TEST_F(OTAKeyboxProvisioningTest, BasicTest) {
|
|
OEMCryptoResult result = OEMCrypto_IsKeyboxValid();
|
|
if (result == OEMCrypto_SUCCESS) {
|
|
cout << " "
|
|
<< "Keybox valid after initialization. Skipping rest of test." << endl;
|
|
return;
|
|
}
|
|
if (result != OEMCrypto_ERROR_NEEDS_KEYBOX_PROVISIONING) {
|
|
cout << " "
|
|
<< "OTA Keybox functions not supported. Skipping rest of test."
|
|
<< endl;
|
|
return;
|
|
}
|
|
cout << " "
|
|
<< "OTA Keybox functions supported. Device needs provisioning." << endl;
|
|
|
|
size_t request_length = 0;
|
|
std::vector<uint8_t> request;
|
|
|
|
OEMCrypto_SESSION session_id;
|
|
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session_id));
|
|
|
|
ASSERT_EQ(OEMCrypto_ERROR_SHORT_BUFFER,
|
|
OEMCrypto_GenerateOTARequest(session_id, nullptr, &request_length,
|
|
kUseTestKey));
|
|
ASSERT_NE(request_length, 0u);
|
|
request.resize(request_length);
|
|
ASSERT_EQ(OEMCrypto_SUCCESS,
|
|
OEMCrypto_GenerateOTARequest(session_id, request.data(),
|
|
&request_length, kUseTestKey));
|
|
ASSERT_GT(request_length, kMinimumRequestLength);
|
|
request.resize(request_length);
|
|
// First 16 bytes should match the label for Option 1 or 2.
|
|
// TODO(fredgc): Write tests for Option 1 -- only Option 2 is tested now.
|
|
EXPECT_EQ(kOption2Label.length(), kLabelLength);
|
|
const uint8_t* label_ptr = request.data();
|
|
EXPECT_EQ(kOption2Label, std::string(label_ptr, label_ptr + kLabelLength));
|
|
// Next 32 bytes are the device id.
|
|
const uint8_t* device_id_ptr = label_ptr + kLabelLength;
|
|
const std::vector<uint8_t> device_id(device_id_ptr,
|
|
device_id_ptr + kDeviceIdLength);
|
|
LOGD("Device id is %s", MaybeHex(device_id).c_str());
|
|
// Next 4 bytes say that this is a cert.
|
|
uint32_t cert_length;
|
|
const uint8_t* cert_length_ptr = device_id_ptr + kDeviceIdLength;
|
|
memcpy(&cert_length, cert_length_ptr, sizeof(uint32_t));
|
|
cert_length = ntohl(cert_length);
|
|
LOGD("Cert Length is 0x%x = %u", cert_length, cert_length);
|
|
ASSERT_EQ(request_length, kMinimumRequestLength + cert_length);
|
|
const uint8_t* cert_ptr = cert_length_ptr + sizeof(uint32_t);
|
|
const std::vector<uint8_t> cert(cert_ptr, cert_ptr + cert_length);
|
|
LOGD("x509 attestation cert = %s", MaybeHex(cert).c_str());
|
|
const uint8_t* signature_ptr = cert_ptr + cert_length;
|
|
const std::vector<uint8_t> signature(
|
|
signature_ptr, signature_ptr + HMAC_SHA256_SIGNATURE_SIZE);
|
|
|
|
#if 0
|
|
// This unit test only works with the test model key.
|
|
const std::vector<uint8_t> model_key =
|
|
wvcdm::a2b_hex("0102030405060708090a0b0c0d0e0f10");
|
|
#else
|
|
// This unit test only works with the test cert's private key.
|
|
const std::vector<uint8_t> model_key = GetModelKey(device_id);
|
|
#endif
|
|
// The server should derive the same set of keys as the client.
|
|
const std::string mac_label = "WV_SIGN";
|
|
std::vector<uint8_t> mac_context(mac_label.begin(), mac_label.end());
|
|
mac_context.push_back(0);
|
|
std::copy(cert.begin(), cert.end(), std::back_inserter(mac_context));
|
|
std::copy(device_id.begin(), device_id.end(),
|
|
std::back_inserter(mac_context));
|
|
uint32_t bit_size = MAC_KEY_SIZE * 8 * 2;
|
|
std::string bit_size_string = wvutil::EncodeUint32(bit_size);
|
|
std::copy(bit_size_string.begin(), bit_size_string.end(),
|
|
std::back_inserter(mac_context));
|
|
std::string enc_label = "WV_ENCRYPT";
|
|
std::vector<uint8_t> enc_context(enc_label.begin(), enc_label.end());
|
|
enc_context.push_back(0);
|
|
std::copy(cert.begin(), cert.end(), std::back_inserter(enc_context));
|
|
std::copy(device_id.begin(), device_id.end(),
|
|
std::back_inserter(enc_context));
|
|
bit_size = KEY_SIZE * 8;
|
|
bit_size_string = wvutil::EncodeUint32(bit_size);
|
|
std::copy(bit_size_string.begin(), bit_size_string.end(),
|
|
std::back_inserter(enc_context));
|
|
KeyDeriver keys;
|
|
keys.DeriveKeys(model_key.data(), mac_context, enc_context);
|
|
const std::vector<uint8_t> message(
|
|
request.data(),
|
|
request.data() + request.size() - HMAC_SHA256_SIGNATURE_SIZE);
|
|
// Once the keys have been derived, the server should verify the signature.
|
|
std::vector<uint8_t> computed_signature;
|
|
keys.ClientSignBuffer(message, &computed_signature);
|
|
ASSERT_EQ(signature, computed_signature);
|
|
|
|
// The server should randomly pick an iv.
|
|
uint8_t iv[wvoec::KEY_IV_SIZE];
|
|
EXPECT_EQ(GetRandBytes(iv, KEY_IV_SIZE), 1);
|
|
// Encrypt the keybox.
|
|
std::vector<uint8_t> encrypted_keybox(sizeof(WidevineKeybox));
|
|
keys.CBCEncrypt(reinterpret_cast<const uint8_t*>(&kTestKeybox),
|
|
encrypted_keybox.data(), sizeof(WidevineKeybox), iv);
|
|
std::vector<uint8_t> response(iv, iv + wvoec::KEY_IV_SIZE);
|
|
std::copy(encrypted_keybox.begin(), encrypted_keybox.end(),
|
|
std::back_inserter(response));
|
|
std::vector<uint8_t> response_signature;
|
|
// Sign the iv + encrypted keybox.
|
|
keys.ServerSignBuffer(response.data(), response.size(), &response_signature);
|
|
std::copy(response_signature.begin(), response_signature.end(),
|
|
std::back_inserter(response));
|
|
// Finally, send the response back to the device.
|
|
EXPECT_EQ(OEMCrypto_SUCCESS,
|
|
OEMCrypto_ProcessOTAKeybox(session_id, response.data(),
|
|
response.size(), kUseTestKey));
|
|
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_CloseSession(session_id));
|
|
// After installation, the keybox should be valid.
|
|
EXPECT_EQ(OEMCrypto_IsKeyboxValid(), OEMCrypto_SUCCESS);
|
|
}
|
|
|
|
TEST_F(OTAKeyboxProvisioningTest, StressTest) {
|
|
static constexpr size_t kStressRequestCount = 1000;
|
|
const OEMCrypto_ProvisioningMethod method = OEMCrypto_GetProvisioningMethod();
|
|
if (method != OEMCrypto_Keybox) {
|
|
std::cout << "Skipping for non keybox-based devices: method = "
|
|
<< ProvisioningMethodName(method) << std::endl;
|
|
GTEST_SKIP() << "Device is not keybox based: method = "
|
|
<< ProvisioningMethodName(method);
|
|
return;
|
|
}
|
|
OEMCrypto_SESSION session_id;
|
|
ASSERT_EQ(OEMCrypto_SUCCESS, OEMCrypto_OpenSession(&session_id))
|
|
<< "Failed to open OTA keybox session";
|
|
// First request is to ensure operation is supported.
|
|
std::vector<uint8_t> request(kInitialOtaKeyboxRequestSize);
|
|
size_t request_size = request.size();
|
|
OEMCryptoResult result = OEMCrypto_GenerateOTARequest(
|
|
session_id, request.data(), &request_size, kUseTestKey);
|
|
if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) {
|
|
// Not a failure, just skip the test.
|
|
OEMCrypto_CloseSession(session_id);
|
|
std::cout << "Skipping for device which do not support "
|
|
<< "OTA keybox provisioning" << std::endl;
|
|
GTEST_SKIP() << "OTA Keybox not supported";
|
|
return;
|
|
}
|
|
|
|
for (size_t i = 0; i < kStressRequestCount; i++) {
|
|
request.resize(kInitialOtaKeyboxRequestSize);
|
|
request_size = request.size();
|
|
result = OEMCrypto_GenerateOTARequest(session_id, request.data(),
|
|
&request_size, kUseTestKey);
|
|
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
|
|
request.resize(request_size);
|
|
result = OEMCrypto_GenerateOTARequest(session_id, request.data(),
|
|
&request_size, kUseTestKey);
|
|
}
|
|
if (result != OEMCrypto_SUCCESS) {
|
|
OEMCrypto_CloseSession(session_id);
|
|
std::cout << "Failed on attempt " << (i + 1) << std::endl;
|
|
FAIL() << "Failed to generate request: i = " << i;
|
|
return;
|
|
}
|
|
}
|
|
OEMCrypto_CloseSession(session_id);
|
|
}
|
|
} // namespace wvoec
|