blob: eba5b919595298732c229f83e35b8ac53ed104cf [file] [log] [blame]
Shawn Willden274bb552020-09-30 22:39:22 -06001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "VtsRemotelyProvisionableComponentTests"
18
Max Bires261a0492021-04-19 18:55:56 -070019#include <AndroidRemotelyProvisionedComponentDevice.h>
Shawn Willden274bb552020-09-30 22:39:22 -060020#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
21#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
22#include <android/binder_manager.h>
23#include <cppbor_parse.h>
Shawn Willden274bb552020-09-30 22:39:22 -060024#include <gmock/gmock.h>
Max Bires9704ff62021-04-07 11:12:01 -070025#include <keymaster/cppcose/cppcose.h>
Shawn Willden274bb552020-09-30 22:39:22 -060026#include <keymaster/keymaster_configuration.h>
David Drysdalef0d516d2021-03-22 07:51:43 +000027#include <keymint_support/authorization_set.h>
28#include <openssl/ec.h>
29#include <openssl/ec_key.h>
30#include <openssl/x509.h>
Shawn Willden274bb552020-09-30 22:39:22 -060031#include <remote_prov/remote_prov_utils.h>
Seth Moore42c11332021-07-02 15:38:17 -070032#include <vector>
Shawn Willden274bb552020-09-30 22:39:22 -060033
David Drysdalef0d516d2021-03-22 07:51:43 +000034#include "KeyMintAidlTestBase.h"
35
Shawn Willden274bb552020-09-30 22:39:22 -060036namespace aidl::android::hardware::security::keymint::test {
37
38using ::std::string;
39using ::std::vector;
40
41namespace {
42
43#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070044 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060045 INSTANTIATE_TEST_SUITE_P( \
46 PerInstance, name, \
47 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
48 ::android::PrintInstanceNameToString)
49
50using bytevec = std::vector<uint8_t>;
51using testing::MatchesRegex;
52using namespace remote_prov;
53using namespace keymaster;
54
Max Bires8b09c502022-01-30 20:03:16 -080055std::set<std::string> getAllowedVbStates() {
56 return {"green", "yellow", "orange"};
57}
58
59std::set<std::string> getAllowedBootloaderStates() {
60 return {"locked", "unlocked"};
61}
62
63std::set<std::string> getAllowedSecurityLevels() {
64 return {"tee", "strongbox"};
65}
66
67std::set<std::string> getAllowedAttIdStates() {
68 return {"locked", "open"};
69}
70
Shawn Willden274bb552020-09-30 22:39:22 -060071bytevec string_to_bytevec(const char* s) {
72 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
73 return bytevec(p, p + strlen(s));
74}
75
David Drysdalee99ed862021-03-15 16:43:06 +000076ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
77 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
78 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
79 return "COSE Mac0 parse failed";
80 }
81 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
82 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
83 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
84 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
85 if (!protParams || !unprotParams || !payload || !tag) {
86 return "Invalid COSE_Sign1: missing content";
87 }
88 auto corruptMac0 = cppbor::Array();
89 corruptMac0.add(protParams->clone());
90 corruptMac0.add(unprotParams->clone());
91 corruptMac0.add(payload->clone());
92 vector<uint8_t> tagData = tag->value();
93 tagData[0] ^= 0x08;
94 tagData[tagData.size() - 1] ^= 0x80;
95 corruptMac0.add(cppbor::Bstr(tagData));
96
97 return MacedPublicKey{corruptMac0.encode()};
98}
99
David Drysdalecceca9f2021-03-12 15:49:47 +0000100ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
101 if (coseSign1->size() != kCoseSign1EntryCount) {
102 return "Invalid COSE_Sign1, wrong entry count";
103 }
104 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
105 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
106 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
107 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
108 if (!protectedParams || !unprotectedParams || !payload || !signature) {
109 return "Invalid COSE_Sign1: missing content";
110 }
111
112 auto corruptSig = cppbor::Array();
113 corruptSig.add(protectedParams->clone());
114 corruptSig.add(unprotectedParams->clone());
115 corruptSig.add(payload->clone());
116 vector<uint8_t> sigData = signature->value();
117 sigData[0] ^= 0x08;
118 corruptSig.add(cppbor::Bstr(sigData));
119
120 return std::move(corruptSig);
121}
122
Seth Moore19acbe92021-06-23 15:15:52 -0700123ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
124 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000125 if (!chain || !chain->asArray()) {
126 return "EekChain parse failed";
127 }
128
129 cppbor::Array* eekChain = chain->asArray();
130 if (which >= eekChain->size()) {
131 return "selected sig out of range";
132 }
133 auto corruptChain = cppbor::Array();
134
135 for (int ii = 0; ii < eekChain->size(); ++ii) {
136 if (ii == which) {
137 auto sig = corrupt_sig(eekChain->get(which)->asArray());
138 if (!sig) {
139 return "Failed to build corrupted signature" + sig.moveMessage();
140 }
141 corruptChain.add(sig.moveValue());
142 } else {
143 corruptChain.add(eekChain->get(ii)->clone());
144 }
145 }
Seth Moore19acbe92021-06-23 15:15:52 -0700146 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000147}
148
David Drysdale4d3c2982021-03-31 18:21:40 +0100149string device_suffix(const string& name) {
150 size_t pos = name.find('/');
151 if (pos == string::npos) {
152 return name;
153 }
154 return name.substr(pos + 1);
155}
156
157bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
158 string rp_suffix = device_suffix(rp_name);
159
160 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
161 for (const string& km_name : km_names) {
162 // If the suffix of the KeyMint instance equals the suffix of the
163 // RemotelyProvisionedComponent instance, assume they match.
164 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
165 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
166 *keyMint = IKeyMintDevice::fromBinder(binder);
167 return true;
168 }
169 }
170 return false;
171}
172
Shawn Willden274bb552020-09-30 22:39:22 -0600173} // namespace
174
175class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
176 public:
177 virtual void SetUp() override {
178 if (AServiceManager_isDeclared(GetParam().c_str())) {
179 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
180 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
181 }
182 ASSERT_NE(provisionable_, nullptr);
183 }
184
185 static vector<string> build_params() {
186 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
187 return params;
188 }
189
190 protected:
191 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
192};
193
194using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
195
196INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
197
198/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000199 * Generate and validate a production-mode key. MAC tag can't be verified, but
200 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600201 */
Max Bires126869a2021-02-21 18:32:59 -0800202TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600203 MacedPublicKey macedPubKey;
204 bytevec privateKeyBlob;
205 bool testMode = false;
206 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
207 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000208 vector<uint8_t> coseKeyData;
209 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100210}
211
212/**
213 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
214 */
215TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
216 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
217 std::shared_ptr<IKeyMintDevice> keyMint;
218 if (!matching_keymint_device(GetParam(), &keyMint)) {
219 // No matching IKeyMintDevice.
220 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
221 return;
222 }
223 KeyMintHardwareInfo info;
224 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
225
226 MacedPublicKey macedPubKey;
227 bytevec privateKeyBlob;
228 bool testMode = false;
229 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
230 ASSERT_TRUE(status.isOk());
231 vector<uint8_t> coseKeyData;
232 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
233
David Drysdalef0d516d2021-03-22 07:51:43 +0000234 AttestationKey attestKey;
235 attestKey.keyBlob = std::move(privateKeyBlob);
236 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600237
David Drysdalef0d516d2021-03-22 07:51:43 +0000238 // Generate an ECDSA key that is attested by the generated P256 keypair.
239 AuthorizationSet keyDesc = AuthorizationSetBuilder()
240 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100241 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000242 .AttestationChallenge("foo")
243 .AttestationApplicationId("bar")
244 .Digest(Digest::NONE)
245 .SetDefaultValidity();
246 KeyCreationResult creationResult;
247 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
248 ASSERT_TRUE(result.isOk());
249 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
250 vector<KeyCharacteristics> attested_key_characteristics =
251 std::move(creationResult.keyCharacteristics);
252 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
253 EXPECT_EQ(attested_key_cert_chain.size(), 1);
254
David Drysdale7dff4fc2021-12-10 10:10:52 +0000255 int32_t aidl_version = 0;
256 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000257 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
258 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000259 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000260 info.securityLevel,
261 attested_key_cert_chain[0].encodedCertificate));
262
263 // Attestation by itself is not valid (last entry is not self-signed).
264 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
265
266 // The signature over the attested key should correspond to the P256 public key.
267 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
268 ASSERT_TRUE(key_cert.get());
269 EVP_PKEY_Ptr signing_pubkey;
270 p256_pub_key(coseKeyData, &signing_pubkey);
271 ASSERT_TRUE(signing_pubkey.get());
272
273 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
274 << "Verification of attested certificate failed "
275 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600276}
277
278/**
279 * Generate and validate a test-mode key.
280 */
Max Bires126869a2021-02-21 18:32:59 -0800281TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600282 MacedPublicKey macedPubKey;
283 bytevec privateKeyBlob;
284 bool testMode = true;
285 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
286 ASSERT_TRUE(status.isOk());
287
David Drysdalec8400772021-03-11 12:35:11 +0000288 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600289}
290
291class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
292 protected:
David Drysdalec8400772021-03-11 12:35:11 +0000293 CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
Seth Moore19acbe92021-06-23 15:15:52 -0700294 generateTestEekChain(3);
David Drysdalecceca9f2021-03-12 15:49:47 +0000295 }
296
Seth Moore19acbe92021-06-23 15:15:52 -0700297 void generateTestEekChain(size_t eekLength) {
David Drysdalecceca9f2021-03-12 15:49:47 +0000298 auto chain = generateEekChain(eekLength, eekId_);
Shawn Willden274bb552020-09-30 22:39:22 -0600299 EXPECT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700300 if (chain) testEekChain_ = chain.moveValue();
301 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600302 }
303
304 void generateKeys(bool testMode, size_t numKeys) {
305 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
306 cborKeysToSign_ = cppbor::Array();
307
308 for (auto& key : keysToSign_) {
309 bytevec privateKeyBlob;
310 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
311 ASSERT_TRUE(status.isOk()) << status.getMessage();
312
David Drysdalec8400772021-03-11 12:35:11 +0000313 vector<uint8_t> payload_value;
314 check_maced_pubkey(key, testMode, &payload_value);
315 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600316 }
317 }
318
David Drysdalef6fc5a62021-03-31 16:14:31 +0100319 void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
Seth Moore42c11332021-07-02 15:38:17 -0700320 const bytevec& keysToSignMac, const ProtectedData& protectedData,
321 std::vector<BccEntryData>* bccOutput = nullptr) {
David Drysdalec8400772021-03-11 12:35:11 +0000322 auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
323 ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
324 ASSERT_TRUE(parsedProtectedData->asArray());
325 ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
326
327 auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
328 ASSERT_TRUE(senderPubkey) << senderPubkey.message();
329 EXPECT_EQ(senderPubkey->second, eekId_);
330
Seth Moore19acbe92021-06-23 15:15:52 -0700331 auto sessionKey =
332 x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
333 senderPubkey->first, false /* senderIsA */);
David Drysdalec8400772021-03-11 12:35:11 +0000334 ASSERT_TRUE(sessionKey) << sessionKey.message();
335
336 auto protectedDataPayload =
337 decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
338 ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
339
340 auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
341 ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
342 ASSERT_TRUE(parsedPayload->asArray());
343 EXPECT_EQ(parsedPayload->asArray()->size(), 2U);
344
345 auto& signedMac = parsedPayload->asArray()->get(0);
346 auto& bcc = parsedPayload->asArray()->get(1);
347 ASSERT_TRUE(signedMac && signedMac->asArray());
348 ASSERT_TRUE(bcc && bcc->asArray());
349
350 // BCC is [ pubkey, + BccEntry]
351 auto bccContents = validateBcc(bcc->asArray());
352 ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
353 ASSERT_GT(bccContents->size(), 0U);
354
David Drysdalef6fc5a62021-03-31 16:14:31 +0100355 auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
356 ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
357 ASSERT_TRUE(deviceInfoMap->asMap());
358
Max Bires8b09c502022-01-30 20:03:16 -0800359 checkDeviceInfo(deviceInfoMap->asMap());
360
David Drysdalec8400772021-03-11 12:35:11 +0000361 auto& signingKey = bccContents->back().pubKey;
Seth Moore798188a2021-06-17 10:58:27 -0700362 auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
David Drysdalef6fc5a62021-03-31 16:14:31 +0100363 cppbor::Array() // SignedMacAad
David Drysdalec8400772021-03-11 12:35:11 +0000364 .add(challenge_)
David Drysdalef6fc5a62021-03-31 16:14:31 +0100365 .add(std::move(deviceInfoMap))
Max Bires8dff0b32021-05-26 13:05:09 -0700366 .add(keysToSignMac)
David Drysdalec8400772021-03-11 12:35:11 +0000367 .encode());
368 ASSERT_TRUE(macKey) << macKey.message();
369
370 auto coseMac0 = cppbor::Array()
371 .add(cppbor::Map() // protected
372 .add(ALGORITHM, HMAC_256)
373 .canonicalize()
374 .encode())
375 .add(cppbor::Map()) // unprotected
376 .add(keysToSign.encode()) // payload (keysToSign)
377 .add(keysToSignMac); // tag
378
379 auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
380 ASSERT_TRUE(macPayload) << macPayload.message();
Seth Moore42c11332021-07-02 15:38:17 -0700381
382 if (bccOutput) {
383 *bccOutput = std::move(*bccContents);
384 }
David Drysdalec8400772021-03-11 12:35:11 +0000385 }
386
Max Bires8b09c502022-01-30 20:03:16 -0800387 void checkType(const cppbor::Map* devInfo, uint8_t majorType, std::string entryName) {
388 const auto& val = devInfo->get(entryName);
389 ASSERT_TRUE(val) << entryName << " does not exist";
390 ASSERT_EQ(val->type(), majorType) << entryName << " has the wrong type.";
391 switch (majorType) {
392 case cppbor::TSTR:
393 ASSERT_GT(val->asTstr()->value().size(), 0);
394 break;
395 case cppbor::BSTR:
396 ASSERT_GT(val->asBstr()->value().size(), 0);
397 break;
398 default:
399 break;
400 }
401 }
402
403 void checkDeviceInfo(const cppbor::Map* deviceInfo) {
404 const auto& version = deviceInfo->get("version");
405 ASSERT_TRUE(version);
406 ASSERT_TRUE(version->asUint());
407 RpcHardwareInfo info;
408 provisionable_->getHardwareInfo(&info);
409 ASSERT_EQ(version->asUint()->value(), info.versionNumber);
410 std::set<std::string> allowList;
411 switch (version->asUint()->value()) {
412 // These fields became mandated in version 2.
413 case 2:
414 checkType(deviceInfo, cppbor::TSTR, "brand");
415 checkType(deviceInfo, cppbor::TSTR, "manufacturer");
416 checkType(deviceInfo, cppbor::TSTR, "product");
417 checkType(deviceInfo, cppbor::TSTR, "model");
418 checkType(deviceInfo, cppbor::TSTR, "device");
419 // TODO: Refactor the KeyMint code that validates these fields and include it here.
420 checkType(deviceInfo, cppbor::TSTR, "vb_state");
421 allowList = getAllowedVbStates();
422 ASSERT_NE(allowList.find(deviceInfo->get("vb_state")->asTstr()->value()),
423 allowList.end());
424 checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
425 allowList = getAllowedBootloaderStates();
426 ASSERT_NE(allowList.find(deviceInfo->get("bootloader_state")->asTstr()->value()),
427 allowList.end());
428 checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
429 checkType(deviceInfo, cppbor::TSTR, "os_version");
430 checkType(deviceInfo, cppbor::UINT, "system_patch_level");
431 checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
432 checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
433 checkType(deviceInfo, cppbor::UINT, "fused");
434 ASSERT_LT(deviceInfo->get("fused")->asUint()->value(), 2); // Must be 0 or 1.
435 checkType(deviceInfo, cppbor::TSTR, "security_level");
436 allowList = getAllowedSecurityLevels();
437 ASSERT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
438 allowList.end());
439 break;
440 case 1:
441 checkType(deviceInfo, cppbor::TSTR, "security_level");
442 allowList = getAllowedSecurityLevels();
443 ASSERT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
444 allowList.end());
445 if (version->asUint()->value() == 1) {
446 checkType(deviceInfo, cppbor::TSTR, "att_id_state");
447 allowList = getAllowedAttIdStates();
448 ASSERT_NE(allowList.find(deviceInfo->get("att_id_state")->asTstr()->value()),
449 allowList.end());
450 }
451 break;
452 default:
453 FAIL() << "Unrecognized version: " << version->asUint()->value();
454 }
455 }
456
Shawn Willden274bb552020-09-30 22:39:22 -0600457 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700458 size_t testEekLength_;
459 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000460 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600461 std::vector<MacedPublicKey> keysToSign_;
462 cppbor::Array cborKeysToSign_;
463};
464
465/**
466 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
467 * content.
468 */
Max Bires126869a2021-02-21 18:32:59 -0800469TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600470 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000471 for (size_t eekLength : {2, 3, 7}) {
472 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700473 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600474
David Drysdalecceca9f2021-03-12 15:49:47 +0000475 bytevec keysToSignMac;
476 DeviceInfo deviceInfo;
477 ProtectedData protectedData;
478 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700479 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000480 &protectedData, &keysToSignMac);
481 ASSERT_TRUE(status.isOk()) << status.getMessage();
482
David Drysdalef6fc5a62021-03-31 16:14:31 +0100483 checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000484 }
Shawn Willden274bb552020-09-30 22:39:22 -0600485}
486
487/**
Seth Moore42c11332021-07-02 15:38:17 -0700488 * Ensure that test mode outputs a unique BCC root key every time we request a
489 * certificate request. Else, it's possible that the test mode API could be used
490 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
491 * device public key multiple times.
492 */
493TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
494 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700495
496 bytevec keysToSignMac;
497 DeviceInfo deviceInfo;
498 ProtectedData protectedData;
499 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700500 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
501 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700502 ASSERT_TRUE(status.isOk()) << status.getMessage();
503
504 std::vector<BccEntryData> firstBcc;
505 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
506 &firstBcc);
507
Seth Moore19acbe92021-06-23 15:15:52 -0700508 status = provisionable_->generateCertificateRequest(
509 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
510 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700511 ASSERT_TRUE(status.isOk()) << status.getMessage();
512
513 std::vector<BccEntryData> secondBcc;
514 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
515 &secondBcc);
516
517 // Verify that none of the keys in the first BCC are repeated in the second one.
518 for (const auto& i : firstBcc) {
519 for (auto& j : secondBcc) {
520 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
521 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
522 }
523 }
524}
525
526/**
Seth Moore19acbe92021-06-23 15:15:52 -0700527 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
528 * is not run by default. Not all devices are GMS devices, and therefore they do not all
529 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600530 */
Seth Moore19acbe92021-06-23 15:15:52 -0700531TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600532 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000533
Seth Moore19acbe92021-06-23 15:15:52 -0700534 bytevec keysToSignMac;
535 DeviceInfo deviceInfo;
536 ProtectedData protectedData;
537 auto status = provisionable_->generateCertificateRequest(
538 testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
539 &protectedData, &keysToSignMac);
540 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600541}
542
543/**
544 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
545 */
Max Bires126869a2021-02-21 18:32:59 -0800546TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600547 bool testMode = true;
548 generateKeys(testMode, 4 /* numKeys */);
549
David Drysdalecceca9f2021-03-12 15:49:47 +0000550 for (size_t eekLength : {2, 3, 7}) {
551 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700552 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600553
David Drysdalecceca9f2021-03-12 15:49:47 +0000554 bytevec keysToSignMac;
555 DeviceInfo deviceInfo;
556 ProtectedData protectedData;
557 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700558 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000559 &keysToSignMac);
560 ASSERT_TRUE(status.isOk()) << status.getMessage();
561
David Drysdalef6fc5a62021-03-31 16:14:31 +0100562 checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000563 }
Shawn Willden274bb552020-09-30 22:39:22 -0600564}
565
566/**
Seth Moore19acbe92021-06-23 15:15:52 -0700567 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
568 * is not run by default. Not all devices are GMS devices, and therefore they do not all
569 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600570 */
Seth Moore19acbe92021-06-23 15:15:52 -0700571TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600572 bool testMode = false;
573 generateKeys(testMode, 4 /* numKeys */);
574
Seth Moore19acbe92021-06-23 15:15:52 -0700575 bytevec keysToSignMac;
576 DeviceInfo deviceInfo;
577 ProtectedData protectedData;
578 auto status = provisionable_->generateCertificateRequest(
579 testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
580 &keysToSignMac);
581 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000582}
583
584/**
David Drysdalee99ed862021-03-15 16:43:06 +0000585 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
586 */
587TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
588 bool testMode = true;
589 generateKeys(testMode, 1 /* numKeys */);
590 MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
591
592 bytevec keysToSignMac;
593 DeviceInfo deviceInfo;
594 ProtectedData protectedData;
595 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700596 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
597 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000598 ASSERT_FALSE(status.isOk()) << status.getMessage();
599 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
600}
601
602/**
603 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
604 */
605TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700606 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000607 generateKeys(testMode, 1 /* numKeys */);
608 MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
609
610 bytevec keysToSignMac;
611 DeviceInfo deviceInfo;
612 ProtectedData protectedData;
613 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700614 testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
615 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000616 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700617 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000618}
619
620/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000621 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
622 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000623 */
624TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
625 bool testMode = false;
626 generateKeys(testMode, 4 /* numKeys */);
627
Seth Moore19acbe92021-06-23 15:15:52 -0700628 auto prodEekChain = getProdEekChain();
629 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
630 ASSERT_NE(parsedChain, nullptr) << parseErr;
631 ASSERT_NE(parsedChain->asArray(), nullptr);
632
633 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
634 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000635 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000636
637 bytevec keysToSignMac;
638 DeviceInfo deviceInfo;
639 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700640 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
641 challenge_, &deviceInfo,
642 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000643 ASSERT_FALSE(status.isOk());
644 ASSERT_EQ(status.getServiceSpecificError(),
645 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
646 }
647}
648
649/**
650 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
651 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000652 */
653TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
654 bool testMode = false;
655 generateKeys(testMode, 4 /* numKeys */);
656
657 // Build an EEK chain that omits the first self-signed cert.
658 auto truncatedChain = cppbor::Array();
Seth Moore19acbe92021-06-23 15:15:52 -0700659 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
David Drysdalecceca9f2021-03-12 15:49:47 +0000660 ASSERT_TRUE(chain);
661 auto eekChain = chain->asArray();
662 ASSERT_NE(eekChain, nullptr);
663 for (size_t ii = 1; ii < eekChain->size(); ii++) {
664 truncatedChain.add(eekChain->get(ii)->clone());
665 }
666
Shawn Willden274bb552020-09-30 22:39:22 -0600667 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700668 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600669 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000670 auto status = provisionable_->generateCertificateRequest(
671 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
672 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600673 ASSERT_FALSE(status.isOk());
674 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
675}
676
677/**
678 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
679 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
680 */
Max Bires126869a2021-02-21 18:32:59 -0800681TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600682 generateKeys(false /* testMode */, 2 /* numKeys */);
683
684 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700685 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600686 ProtectedData protectedData;
Max Biresfdbb9042021-03-23 12:43:38 -0700687 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700688 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700689 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600690 ASSERT_FALSE(status.isOk());
691 ASSERT_EQ(status.getServiceSpecificError(),
692 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
693}
694
695/**
696 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
697 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
698 */
Max Bires126869a2021-02-21 18:32:59 -0800699TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600700 generateKeys(true /* testMode */, 2 /* numKeys */);
701
702 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700703 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600704 ProtectedData protectedData;
705 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700706 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000707 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600708 ASSERT_FALSE(status.isOk());
709 ASSERT_EQ(status.getServiceSpecificError(),
710 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
711}
712
713INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
714
715} // namespace aidl::android::hardware::security::keymint::test