• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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