1 /*
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
19 #include <AndroidRemotelyProvisionedComponentDevice.h>
20 #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 <binder/IServiceManager.h>
24 #include <cppbor_parse.h>
25 #include <gmock/gmock.h>
26 #include <keymaster/cppcose/cppcose.h>
27 #include <keymaster/keymaster_configuration.h>
28 #include <keymint_support/authorization_set.h>
29 #include <openssl/ec.h>
30 #include <openssl/ec_key.h>
31 #include <openssl/x509.h>
32 #include <remote_prov/remote_prov_utils.h>
33 #include <set>
34 #include <vector>
35
36 #include "KeyMintAidlTestBase.h"
37
38 namespace aidl::android::hardware::security::keymint::test {
39
40 using ::std::string;
41 using ::std::vector;
42
43 namespace {
44
45 constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
46
47 #define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
48 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
49 INSTANTIATE_TEST_SUITE_P( \
50 PerInstance, name, \
51 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
52 ::android::PrintInstanceNameToString)
53
54 using ::android::sp;
55 using bytevec = std::vector<uint8_t>;
56 using testing::MatchesRegex;
57 using namespace remote_prov;
58 using namespace keymaster;
59
getAllowedVbStates()60 std::set<std::string> getAllowedVbStates() {
61 return {"green", "yellow", "orange"};
62 }
63
getAllowedBootloaderStates()64 std::set<std::string> getAllowedBootloaderStates() {
65 return {"locked", "unlocked"};
66 }
67
getAllowedSecurityLevels()68 std::set<std::string> getAllowedSecurityLevels() {
69 return {"tee", "strongbox"};
70 }
71
getAllowedAttIdStates()72 std::set<std::string> getAllowedAttIdStates() {
73 return {"locked", "open"};
74 }
75
string_to_bytevec(const char * s)76 bytevec string_to_bytevec(const char* s) {
77 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
78 return bytevec(p, p + strlen(s));
79 }
80
corrupt_maced_key(const MacedPublicKey & macedPubKey)81 ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
82 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
83 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
84 return "COSE Mac0 parse failed";
85 }
86 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
87 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
88 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
89 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
90 if (!protParams || !unprotParams || !payload || !tag) {
91 return "Invalid COSE_Sign1: missing content";
92 }
93 auto corruptMac0 = cppbor::Array();
94 corruptMac0.add(protParams->clone());
95 corruptMac0.add(unprotParams->clone());
96 corruptMac0.add(payload->clone());
97 vector<uint8_t> tagData = tag->value();
98 tagData[0] ^= 0x08;
99 tagData[tagData.size() - 1] ^= 0x80;
100 corruptMac0.add(cppbor::Bstr(tagData));
101
102 return MacedPublicKey{corruptMac0.encode()};
103 }
104
corrupt_sig(const cppbor::Array * coseSign1)105 ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
106 if (coseSign1->size() != kCoseSign1EntryCount) {
107 return "Invalid COSE_Sign1, wrong entry count";
108 }
109 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
110 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
111 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
112 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
113 if (!protectedParams || !unprotectedParams || !payload || !signature) {
114 return "Invalid COSE_Sign1: missing content";
115 }
116
117 auto corruptSig = cppbor::Array();
118 corruptSig.add(protectedParams->clone());
119 corruptSig.add(unprotectedParams->clone());
120 corruptSig.add(payload->clone());
121 vector<uint8_t> sigData = signature->value();
122 sigData[0] ^= 0x08;
123 corruptSig.add(cppbor::Bstr(sigData));
124
125 return std::move(corruptSig);
126 }
127
corrupt_sig_chain(const bytevec & encodedEekChain,int which)128 ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
129 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
130 if (!chain || !chain->asArray()) {
131 return "EekChain parse failed";
132 }
133
134 cppbor::Array* eekChain = chain->asArray();
135 if (which >= eekChain->size()) {
136 return "selected sig out of range";
137 }
138 auto corruptChain = cppbor::Array();
139
140 for (int ii = 0; ii < eekChain->size(); ++ii) {
141 if (ii == which) {
142 auto sig = corrupt_sig(eekChain->get(which)->asArray());
143 if (!sig) {
144 return "Failed to build corrupted signature" + sig.moveMessage();
145 }
146 corruptChain.add(sig.moveValue());
147 } else {
148 corruptChain.add(eekChain->get(ii)->clone());
149 }
150 }
151 return corruptChain.encode();
152 }
153
device_suffix(const string & name)154 string device_suffix(const string& name) {
155 size_t pos = name.find('/');
156 if (pos == string::npos) {
157 return name;
158 }
159 return name.substr(pos + 1);
160 }
161
matching_keymint_device(const string & rp_name,std::shared_ptr<IKeyMintDevice> * keyMint)162 bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
163 string rp_suffix = device_suffix(rp_name);
164
165 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
166 for (const string& km_name : km_names) {
167 // If the suffix of the KeyMint instance equals the suffix of the
168 // RemotelyProvisionedComponent instance, assume they match.
169 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
170 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
171 *keyMint = IKeyMintDevice::fromBinder(binder);
172 return true;
173 }
174 }
175 return false;
176 }
177
178 } // namespace
179
180 class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
181 public:
SetUp()182 virtual void SetUp() override {
183 if (AServiceManager_isDeclared(GetParam().c_str())) {
184 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
185 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
186 }
187 ASSERT_NE(provisionable_, nullptr);
188 ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
189 }
190
build_params()191 static vector<string> build_params() {
192 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
193 return params;
194 }
195
196 protected:
197 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
198 RpcHardwareInfo rpcHardwareInfo;
199 };
200
201 /**
202 * Verify that every implementation reports a different unique id.
203 */
TEST(NonParameterizedTests,eachRpcHasAUniqueId)204 TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
205 std::set<std::string> uniqueIds;
206 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
207 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
208 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
209 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
210 IRemotelyProvisionedComponent::fromBinder(binder);
211 ASSERT_NE(rpc, nullptr);
212
213 RpcHardwareInfo hwInfo;
214 ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
215
216 int32_t version;
217 ASSERT_TRUE(rpc->getInterfaceVersion(&version).isOk());
218 if (version >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
219 ASSERT_TRUE(hwInfo.uniqueId);
220 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
221 EXPECT_TRUE(wasInserted);
222 } else {
223 ASSERT_FALSE(hwInfo.uniqueId);
224 }
225 }
226 }
227
228 using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
229
230 INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
231
232 /**
233 * Verify that a valid curve is reported by the implementation.
234 */
TEST_P(GetHardwareInfoTests,supportsValidCurve)235 TEST_P(GetHardwareInfoTests, supportsValidCurve) {
236 RpcHardwareInfo hwInfo;
237 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
238
239 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
240 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
241 << "Invalid curve: " << hwInfo.supportedEekCurve;
242 }
243
244 /**
245 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
246 */
TEST_P(GetHardwareInfoTests,uniqueId)247 TEST_P(GetHardwareInfoTests, uniqueId) {
248 int32_t version;
249 ASSERT_TRUE(provisionable_->getInterfaceVersion(&version).isOk());
250
251 if (version < VERSION_WITH_UNIQUE_ID_SUPPORT) {
252 return;
253 }
254
255 RpcHardwareInfo hwInfo;
256 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
257 ASSERT_TRUE(hwInfo.uniqueId);
258 EXPECT_GE(hwInfo.uniqueId->size(), 1);
259 EXPECT_LE(hwInfo.uniqueId->size(), 32);
260 }
261
262 using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
263
264 INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
265
266 /**
267 * Generate and validate a production-mode key. MAC tag can't be verified, but
268 * the private key blob should be usable in KeyMint operations.
269 */
TEST_P(GenerateKeyTests,generateEcdsaP256Key_prodMode)270 TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
271 MacedPublicKey macedPubKey;
272 bytevec privateKeyBlob;
273 bool testMode = false;
274 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
275 ASSERT_TRUE(status.isOk());
276 vector<uint8_t> coseKeyData;
277 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
278 }
279
280 /**
281 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
282 */
TEST_P(GenerateKeyTests,generateAndUseEcdsaP256Key_prodMode)283 TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
284 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
285 std::shared_ptr<IKeyMintDevice> keyMint;
286 if (!matching_keymint_device(GetParam(), &keyMint)) {
287 // No matching IKeyMintDevice.
288 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
289 return;
290 }
291 KeyMintHardwareInfo info;
292 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
293
294 MacedPublicKey macedPubKey;
295 bytevec privateKeyBlob;
296 bool testMode = false;
297 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
298 ASSERT_TRUE(status.isOk());
299 vector<uint8_t> coseKeyData;
300 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
301
302 AttestationKey attestKey;
303 attestKey.keyBlob = std::move(privateKeyBlob);
304 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
305
306 // Generate an ECDSA key that is attested by the generated P256 keypair.
307 AuthorizationSet keyDesc = AuthorizationSetBuilder()
308 .Authorization(TAG_NO_AUTH_REQUIRED)
309 .EcdsaSigningKey(EcCurve::P_256)
310 .AttestationChallenge("foo")
311 .AttestationApplicationId("bar")
312 .Digest(Digest::NONE)
313 .SetDefaultValidity();
314 KeyCreationResult creationResult;
315 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
316 ASSERT_TRUE(result.isOk());
317 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
318 vector<KeyCharacteristics> attested_key_characteristics =
319 std::move(creationResult.keyCharacteristics);
320 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
321 EXPECT_EQ(attested_key_cert_chain.size(), 1);
322
323 int32_t aidl_version = 0;
324 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
325 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
326 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
327 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
328 info.securityLevel,
329 attested_key_cert_chain[0].encodedCertificate));
330
331 // Attestation by itself is not valid (last entry is not self-signed).
332 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
333
334 // The signature over the attested key should correspond to the P256 public key.
335 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
336 ASSERT_TRUE(key_cert.get());
337 EVP_PKEY_Ptr signing_pubkey;
338 p256_pub_key(coseKeyData, &signing_pubkey);
339 ASSERT_TRUE(signing_pubkey.get());
340
341 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
342 << "Verification of attested certificate failed "
343 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
344 }
345
346 /**
347 * Generate and validate a test-mode key.
348 */
TEST_P(GenerateKeyTests,generateEcdsaP256Key_testMode)349 TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
350 MacedPublicKey macedPubKey;
351 bytevec privateKeyBlob;
352 bool testMode = true;
353 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
354 ASSERT_TRUE(status.isOk());
355
356 check_maced_pubkey(macedPubKey, testMode, nullptr);
357 }
358
359 class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
360 protected:
CertificateRequestTest()361 CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
362
generateTestEekChain(size_t eekLength)363 void generateTestEekChain(size_t eekLength) {
364 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
365 ASSERT_TRUE(chain) << chain.message();
366 if (chain) testEekChain_ = chain.moveValue();
367 testEekLength_ = eekLength;
368 }
369
generateKeys(bool testMode,size_t numKeys)370 void generateKeys(bool testMode, size_t numKeys) {
371 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
372 cborKeysToSign_ = cppbor::Array();
373
374 for (auto& key : keysToSign_) {
375 bytevec privateKeyBlob;
376 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
377 ASSERT_TRUE(status.isOk()) << status.getMessage();
378
379 vector<uint8_t> payload_value;
380 check_maced_pubkey(key, testMode, &payload_value);
381 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
382 }
383 }
384
getSessionKey(ErrMsgOr<std::pair<bytevec,bytevec>> & senderPubkey)385 ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey) {
386 if (rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
387 rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
388 return x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
389 senderPubkey->first, false /* senderIsA */);
390 } else {
391 return ECDH_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
392 senderPubkey->first, false /* senderIsA */);
393 }
394 }
395
checkProtectedData(const DeviceInfo & deviceInfo,const cppbor::Array & keysToSign,const bytevec & keysToSignMac,const ProtectedData & protectedData,std::vector<BccEntryData> * bccOutput=nullptr)396 void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
397 const bytevec& keysToSignMac, const ProtectedData& protectedData,
398 std::vector<BccEntryData>* bccOutput = nullptr) {
399 auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
400 ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
401 ASSERT_TRUE(parsedProtectedData->asArray());
402 ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
403
404 auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
405 ASSERT_TRUE(senderPubkey) << senderPubkey.message();
406 EXPECT_EQ(senderPubkey->second, eekId_);
407
408 auto sessionKey = getSessionKey(senderPubkey);
409 ASSERT_TRUE(sessionKey) << sessionKey.message();
410
411 auto protectedDataPayload =
412 decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
413 ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
414
415 auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
416 ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
417 ASSERT_TRUE(parsedPayload->asArray());
418 // Strongbox may contain additional certificate chain.
419 EXPECT_LE(parsedPayload->asArray()->size(), 3U);
420
421 auto& signedMac = parsedPayload->asArray()->get(0);
422 auto& bcc = parsedPayload->asArray()->get(1);
423 ASSERT_TRUE(signedMac && signedMac->asArray());
424 ASSERT_TRUE(bcc && bcc->asArray());
425
426 // BCC is [ pubkey, + BccEntry]
427 auto bccContents = validateBcc(bcc->asArray());
428 ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
429 ASSERT_GT(bccContents->size(), 0U);
430
431 auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
432 ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
433 ASSERT_TRUE(deviceInfoMap->asMap());
434 checkDeviceInfo(deviceInfoMap->asMap(), deviceInfo.deviceInfo);
435 auto& signingKey = bccContents->back().pubKey;
436 deviceInfoMap->asMap()->canonicalize();
437 auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
438 cppbor::Array() // SignedMacAad
439 .add(challenge_)
440 .add(std::move(deviceInfoMap))
441 .add(keysToSignMac)
442 .encode());
443 ASSERT_TRUE(macKey) << macKey.message();
444
445 auto coseMac0 = cppbor::Array()
446 .add(cppbor::Map() // protected
447 .add(ALGORITHM, HMAC_256)
448 .canonicalize()
449 .encode())
450 .add(cppbor::Map()) // unprotected
451 .add(keysToSign.encode()) // payload (keysToSign)
452 .add(keysToSignMac); // tag
453
454 auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
455 ASSERT_TRUE(macPayload) << macPayload.message();
456
457 if (bccOutput) {
458 *bccOutput = std::move(*bccContents);
459 }
460 }
461
checkType(const cppbor::Map * devInfo,uint8_t majorType,std::string entryName)462 void checkType(const cppbor::Map* devInfo, uint8_t majorType, std::string entryName) {
463 const auto& val = devInfo->get(entryName);
464 ASSERT_TRUE(val) << entryName << " does not exist";
465 ASSERT_EQ(val->type(), majorType) << entryName << " has the wrong type.";
466 switch (majorType) {
467 case cppbor::TSTR:
468 EXPECT_GT(val->asTstr()->value().size(), 0);
469 break;
470 case cppbor::BSTR:
471 EXPECT_GT(val->asBstr()->value().size(), 0);
472 break;
473 default:
474 break;
475 }
476 }
477
checkDeviceInfo(const cppbor::Map * deviceInfo,bytevec deviceInfoBytes)478 void checkDeviceInfo(const cppbor::Map* deviceInfo, bytevec deviceInfoBytes) {
479 EXPECT_EQ(deviceInfo->clone()->asMap()->canonicalize().encode(), deviceInfoBytes)
480 << "DeviceInfo ordering is non-canonical.";
481 const auto& version = deviceInfo->get("version");
482 ASSERT_TRUE(version);
483 ASSERT_TRUE(version->asUint());
484 RpcHardwareInfo info;
485 provisionable_->getHardwareInfo(&info);
486 ASSERT_EQ(version->asUint()->value(), info.versionNumber);
487 std::set<std::string> allowList;
488 switch (version->asUint()->value()) {
489 // These fields became mandated in version 2.
490 case 2:
491 checkType(deviceInfo, cppbor::TSTR, "brand");
492 checkType(deviceInfo, cppbor::TSTR, "manufacturer");
493 checkType(deviceInfo, cppbor::TSTR, "product");
494 checkType(deviceInfo, cppbor::TSTR, "model");
495 checkType(deviceInfo, cppbor::TSTR, "device");
496 // TODO: Refactor the KeyMint code that validates these fields and include it here.
497 checkType(deviceInfo, cppbor::TSTR, "vb_state");
498 allowList = getAllowedVbStates();
499 EXPECT_NE(allowList.find(deviceInfo->get("vb_state")->asTstr()->value()),
500 allowList.end());
501 checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
502 allowList = getAllowedBootloaderStates();
503 EXPECT_NE(allowList.find(deviceInfo->get("bootloader_state")->asTstr()->value()),
504 allowList.end());
505 checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
506 checkType(deviceInfo, cppbor::UINT, "system_patch_level");
507 checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
508 checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
509 checkType(deviceInfo, cppbor::UINT, "fused");
510 EXPECT_LT(deviceInfo->get("fused")->asUint()->value(), 2); // Must be 0 or 1.
511 checkType(deviceInfo, cppbor::TSTR, "security_level");
512 allowList = getAllowedSecurityLevels();
513 EXPECT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
514 allowList.end());
515 if (deviceInfo->get("security_level")->asTstr()->value() == "tee") {
516 checkType(deviceInfo, cppbor::TSTR, "os_version");
517 }
518 break;
519 case 1:
520 checkType(deviceInfo, cppbor::TSTR, "security_level");
521 allowList = getAllowedSecurityLevels();
522 EXPECT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
523 allowList.end());
524 if (version->asUint()->value() == 1) {
525 checkType(deviceInfo, cppbor::TSTR, "att_id_state");
526 allowList = getAllowedAttIdStates();
527 EXPECT_NE(allowList.find(deviceInfo->get("att_id_state")->asTstr()->value()),
528 allowList.end());
529 }
530 break;
531 default:
532 FAIL() << "Unrecognized version: " << version->asUint()->value();
533 }
534 }
535
536 bytevec eekId_;
537 size_t testEekLength_;
538 EekChain testEekChain_;
539 bytevec challenge_;
540 std::vector<MacedPublicKey> keysToSign_;
541 cppbor::Array cborKeysToSign_;
542 };
543
544 /**
545 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
546 * content.
547 */
TEST_P(CertificateRequestTest,EmptyRequest_testMode)548 TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
549 bool testMode = true;
550 for (size_t eekLength : {2, 3, 7}) {
551 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
552 generateTestEekChain(eekLength);
553
554 bytevec keysToSignMac;
555 DeviceInfo deviceInfo;
556 ProtectedData protectedData;
557 auto status = provisionable_->generateCertificateRequest(
558 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
559 &protectedData, &keysToSignMac);
560 ASSERT_TRUE(status.isOk()) << status.getMessage();
561
562 checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
563 }
564 }
565
566 /**
567 * Ensure that test mode outputs a unique BCC root key every time we request a
568 * certificate request. Else, it's possible that the test mode API could be used
569 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
570 * device public key multiple times.
571 */
TEST_P(CertificateRequestTest,NewKeyPerCallInTestMode)572 TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
573 constexpr bool testMode = true;
574
575 bytevec keysToSignMac;
576 DeviceInfo deviceInfo;
577 ProtectedData protectedData;
578 generateTestEekChain(3);
579 auto status = provisionable_->generateCertificateRequest(
580 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
581 &protectedData, &keysToSignMac);
582 ASSERT_TRUE(status.isOk()) << status.getMessage();
583
584 std::vector<BccEntryData> firstBcc;
585 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
586 &firstBcc);
587
588 status = provisionable_->generateCertificateRequest(
589 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
590 &protectedData, &keysToSignMac);
591 ASSERT_TRUE(status.isOk()) << status.getMessage();
592
593 std::vector<BccEntryData> secondBcc;
594 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
595 &secondBcc);
596
597 // Verify that none of the keys in the first BCC are repeated in the second one.
598 for (const auto& i : firstBcc) {
599 for (auto& j : secondBcc) {
600 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
601 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
602 }
603 }
604 }
605
606 /**
607 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
608 * is not run by default. Not all devices are GMS devices, and therefore they do not all
609 * trust the Google EEK root.
610 */
TEST_P(CertificateRequestTest,DISABLED_EmptyRequest_prodMode)611 TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
612 bool testMode = false;
613
614 bytevec keysToSignMac;
615 DeviceInfo deviceInfo;
616 ProtectedData protectedData;
617 auto status = provisionable_->generateCertificateRequest(
618 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
619 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
620 EXPECT_TRUE(status.isOk());
621 }
622
623 /**
624 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
625 */
TEST_P(CertificateRequestTest,NonEmptyRequest_testMode)626 TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
627 bool testMode = true;
628 generateKeys(testMode, 4 /* numKeys */);
629
630 for (size_t eekLength : {2, 3, 7}) {
631 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
632 generateTestEekChain(eekLength);
633
634 bytevec keysToSignMac;
635 DeviceInfo deviceInfo;
636 ProtectedData protectedData;
637 auto status = provisionable_->generateCertificateRequest(
638 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
639 &keysToSignMac);
640 ASSERT_TRUE(status.isOk()) << status.getMessage();
641
642 checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
643 }
644 }
645
646 /**
647 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
648 * is not run by default. Not all devices are GMS devices, and therefore they do not all
649 * trust the Google EEK root.
650 */
TEST_P(CertificateRequestTest,DISABLED_NonEmptyRequest_prodMode)651 TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
652 bool testMode = false;
653 generateKeys(testMode, 4 /* numKeys */);
654
655 bytevec keysToSignMac;
656 DeviceInfo deviceInfo;
657 ProtectedData protectedData;
658 auto status = provisionable_->generateCertificateRequest(
659 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
660 &deviceInfo, &protectedData, &keysToSignMac);
661 EXPECT_TRUE(status.isOk());
662 }
663
664 /**
665 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
666 */
TEST_P(CertificateRequestTest,NonEmptyRequestCorruptMac_testMode)667 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
668 bool testMode = true;
669 generateKeys(testMode, 1 /* numKeys */);
670 auto result = corrupt_maced_key(keysToSign_[0]);
671 ASSERT_TRUE(result) << result.moveMessage();
672 MacedPublicKey keyWithCorruptMac = result.moveValue();
673
674 bytevec keysToSignMac;
675 DeviceInfo deviceInfo;
676 ProtectedData protectedData;
677 generateTestEekChain(3);
678 auto status = provisionable_->generateCertificateRequest(
679 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
680 &protectedData, &keysToSignMac);
681 ASSERT_FALSE(status.isOk()) << status.getMessage();
682 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
683 }
684
685 /**
686 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
687 */
TEST_P(CertificateRequestTest,NonEmptyRequestCorruptMac_prodMode)688 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
689 bool testMode = false;
690 generateKeys(testMode, 1 /* numKeys */);
691 auto result = corrupt_maced_key(keysToSign_[0]);
692 ASSERT_TRUE(result) << result.moveMessage();
693 MacedPublicKey keyWithCorruptMac = result.moveValue();
694
695 bytevec keysToSignMac;
696 DeviceInfo deviceInfo;
697 ProtectedData protectedData;
698 auto status = provisionable_->generateCertificateRequest(
699 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
700 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
701 ASSERT_FALSE(status.isOk()) << status.getMessage();
702 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
703 }
704
705 /**
706 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
707 * Confirm that the request is rejected.
708 */
TEST_P(CertificateRequestTest,NonEmptyCorruptEekRequest_prodMode)709 TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
710 bool testMode = false;
711 generateKeys(testMode, 4 /* numKeys */);
712
713 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
714 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
715 ASSERT_NE(parsedChain, nullptr) << parseErr;
716 ASSERT_NE(parsedChain->asArray(), nullptr);
717
718 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
719 auto chain = corrupt_sig_chain(prodEekChain, ii);
720 ASSERT_TRUE(chain) << chain.message();
721
722 bytevec keysToSignMac;
723 DeviceInfo deviceInfo;
724 ProtectedData protectedData;
725 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
726 challenge_, &deviceInfo,
727 &protectedData, &keysToSignMac);
728 ASSERT_FALSE(status.isOk());
729 ASSERT_EQ(status.getServiceSpecificError(),
730 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
731 }
732 }
733
734 /**
735 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
736 * Confirm that the request is rejected.
737 */
TEST_P(CertificateRequestTest,NonEmptyIncompleteEekRequest_prodMode)738 TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
739 bool testMode = false;
740 generateKeys(testMode, 4 /* numKeys */);
741
742 // Build an EEK chain that omits the first self-signed cert.
743 auto truncatedChain = cppbor::Array();
744 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
745 ASSERT_TRUE(chain);
746 auto eekChain = chain->asArray();
747 ASSERT_NE(eekChain, nullptr);
748 for (size_t ii = 1; ii < eekChain->size(); ii++) {
749 truncatedChain.add(eekChain->get(ii)->clone());
750 }
751
752 bytevec keysToSignMac;
753 DeviceInfo deviceInfo;
754 ProtectedData protectedData;
755 auto status = provisionable_->generateCertificateRequest(
756 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
757 &keysToSignMac);
758 ASSERT_FALSE(status.isOk());
759 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
760 }
761
762 /**
763 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
764 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
765 */
TEST_P(CertificateRequestTest,NonEmptyRequest_prodKeyInTestCert)766 TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
767 generateKeys(false /* testMode */, 2 /* numKeys */);
768
769 bytevec keysToSignMac;
770 DeviceInfo deviceInfo;
771 ProtectedData protectedData;
772 generateTestEekChain(3);
773 auto status = provisionable_->generateCertificateRequest(
774 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
775 &protectedData, &keysToSignMac);
776 ASSERT_FALSE(status.isOk());
777 ASSERT_EQ(status.getServiceSpecificError(),
778 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
779 }
780
781 /**
782 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
783 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
784 */
TEST_P(CertificateRequestTest,NonEmptyRequest_testKeyInProdCert)785 TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
786 generateKeys(true /* testMode */, 2 /* numKeys */);
787
788 bytevec keysToSignMac;
789 DeviceInfo deviceInfo;
790 ProtectedData protectedData;
791 generateTestEekChain(3);
792 auto status = provisionable_->generateCertificateRequest(
793 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
794 &protectedData, &keysToSignMac);
795 ASSERT_FALSE(status.isOk());
796 ASSERT_EQ(status.getServiceSpecificError(),
797 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
798 }
799
800 INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
801
802 } // namespace aidl::android::hardware::security::keymint::test
803