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 <cppbor_parse.h>
24 #include <gmock/gmock.h>
25 #include <keymaster/cppcose/cppcose.h>
26 #include <keymaster/keymaster_configuration.h>
27 #include <keymint_support/authorization_set.h>
28 #include <openssl/ec.h>
29 #include <openssl/ec_key.h>
30 #include <openssl/x509.h>
31 #include <remote_prov/remote_prov_utils.h>
32 #include <vector>
33 
34 #include "KeyMintAidlTestBase.h"
35 
36 namespace aidl::android::hardware::security::keymint::test {
37 
38 using ::std::string;
39 using ::std::vector;
40 
41 namespace {
42 
43 #define INSTANTIATE_REM_PROV_AIDL_TEST(name)                                         \
44     GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name);                             \
45     INSTANTIATE_TEST_SUITE_P(                                                        \
46             PerInstance, name,                                                       \
47             testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
48             ::android::PrintInstanceNameToString)
49 
50 using bytevec = std::vector<uint8_t>;
51 using testing::MatchesRegex;
52 using namespace remote_prov;
53 using namespace keymaster;
54 
string_to_bytevec(const char * s)55 bytevec string_to_bytevec(const char* s) {
56     const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
57     return bytevec(p, p + strlen(s));
58 }
59 
corrupt_maced_key(const MacedPublicKey & macedPubKey)60 ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
61     auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
62     if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
63         return "COSE Mac0 parse failed";
64     }
65     auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
66     auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
67     auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
68     auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
69     if (!protParams || !unprotParams || !payload || !tag) {
70         return "Invalid COSE_Sign1: missing content";
71     }
72     auto corruptMac0 = cppbor::Array();
73     corruptMac0.add(protParams->clone());
74     corruptMac0.add(unprotParams->clone());
75     corruptMac0.add(payload->clone());
76     vector<uint8_t> tagData = tag->value();
77     tagData[0] ^= 0x08;
78     tagData[tagData.size() - 1] ^= 0x80;
79     corruptMac0.add(cppbor::Bstr(tagData));
80 
81     return MacedPublicKey{corruptMac0.encode()};
82 }
83 
corrupt_sig(const cppbor::Array * coseSign1)84 ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
85     if (coseSign1->size() != kCoseSign1EntryCount) {
86         return "Invalid COSE_Sign1, wrong entry count";
87     }
88     const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
89     const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
90     const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
91     const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
92     if (!protectedParams || !unprotectedParams || !payload || !signature) {
93         return "Invalid COSE_Sign1: missing content";
94     }
95 
96     auto corruptSig = cppbor::Array();
97     corruptSig.add(protectedParams->clone());
98     corruptSig.add(unprotectedParams->clone());
99     corruptSig.add(payload->clone());
100     vector<uint8_t> sigData = signature->value();
101     sigData[0] ^= 0x08;
102     corruptSig.add(cppbor::Bstr(sigData));
103 
104     return std::move(corruptSig);
105 }
106 
corrupt_sig_chain(const bytevec & encodedEekChain,int which)107 ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
108     auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
109     if (!chain || !chain->asArray()) {
110         return "EekChain parse failed";
111     }
112 
113     cppbor::Array* eekChain = chain->asArray();
114     if (which >= eekChain->size()) {
115         return "selected sig out of range";
116     }
117     auto corruptChain = cppbor::Array();
118 
119     for (int ii = 0; ii < eekChain->size(); ++ii) {
120         if (ii == which) {
121             auto sig = corrupt_sig(eekChain->get(which)->asArray());
122             if (!sig) {
123                 return "Failed to build corrupted signature" + sig.moveMessage();
124             }
125             corruptChain.add(sig.moveValue());
126         } else {
127             corruptChain.add(eekChain->get(ii)->clone());
128         }
129     }
130     return corruptChain.encode();
131 }
132 
device_suffix(const string & name)133 string device_suffix(const string& name) {
134     size_t pos = name.find('/');
135     if (pos == string::npos) {
136         return name;
137     }
138     return name.substr(pos + 1);
139 }
140 
matching_keymint_device(const string & rp_name,std::shared_ptr<IKeyMintDevice> * keyMint)141 bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
142     string rp_suffix = device_suffix(rp_name);
143 
144     vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
145     for (const string& km_name : km_names) {
146         // If the suffix of the KeyMint instance equals the suffix of the
147         // RemotelyProvisionedComponent instance, assume they match.
148         if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
149             ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
150             *keyMint = IKeyMintDevice::fromBinder(binder);
151             return true;
152         }
153     }
154     return false;
155 }
156 
157 }  // namespace
158 
159 class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
160   public:
SetUp()161     virtual void SetUp() override {
162         if (AServiceManager_isDeclared(GetParam().c_str())) {
163             ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
164             provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
165         }
166         ASSERT_NE(provisionable_, nullptr);
167     }
168 
build_params()169     static vector<string> build_params() {
170         auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
171         return params;
172     }
173 
174   protected:
175     std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
176 };
177 
178 using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
179 
180 INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
181 
182 /**
183  * Generate and validate a production-mode key.  MAC tag can't be verified, but
184  * the private key blob should be usable in KeyMint operations.
185  */
TEST_P(GenerateKeyTests,generateEcdsaP256Key_prodMode)186 TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
187     MacedPublicKey macedPubKey;
188     bytevec privateKeyBlob;
189     bool testMode = false;
190     auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
191     ASSERT_TRUE(status.isOk());
192     vector<uint8_t> coseKeyData;
193     check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
194 }
195 
196 /**
197  * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
198  */
TEST_P(GenerateKeyTests,generateAndUseEcdsaP256Key_prodMode)199 TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
200     // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
201     std::shared_ptr<IKeyMintDevice> keyMint;
202     if (!matching_keymint_device(GetParam(), &keyMint)) {
203         // No matching IKeyMintDevice.
204         GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
205         return;
206     }
207     KeyMintHardwareInfo info;
208     ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
209 
210     MacedPublicKey macedPubKey;
211     bytevec privateKeyBlob;
212     bool testMode = false;
213     auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
214     ASSERT_TRUE(status.isOk());
215     vector<uint8_t> coseKeyData;
216     check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
217 
218     AttestationKey attestKey;
219     attestKey.keyBlob = std::move(privateKeyBlob);
220     attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
221 
222     // Generate an ECDSA key that is attested by the generated P256 keypair.
223     AuthorizationSet keyDesc = AuthorizationSetBuilder()
224                                        .Authorization(TAG_NO_AUTH_REQUIRED)
225                                        .EcdsaSigningKey(256)
226                                        .AttestationChallenge("foo")
227                                        .AttestationApplicationId("bar")
228                                        .Digest(Digest::NONE)
229                                        .SetDefaultValidity();
230     KeyCreationResult creationResult;
231     auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
232     ASSERT_TRUE(result.isOk());
233     vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
234     vector<KeyCharacteristics> attested_key_characteristics =
235             std::move(creationResult.keyCharacteristics);
236     vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
237     EXPECT_EQ(attested_key_cert_chain.size(), 1);
238 
239     AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
240     AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
241     EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced,
242                                           info.securityLevel,
243                                           attested_key_cert_chain[0].encodedCertificate));
244 
245     // Attestation by itself is not valid (last entry is not self-signed).
246     EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
247 
248     // The signature over the attested key should correspond to the P256 public key.
249     X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
250     ASSERT_TRUE(key_cert.get());
251     EVP_PKEY_Ptr signing_pubkey;
252     p256_pub_key(coseKeyData, &signing_pubkey);
253     ASSERT_TRUE(signing_pubkey.get());
254 
255     ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
256             << "Verification of attested certificate failed "
257             << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
258 }
259 
260 /**
261  * Generate and validate a test-mode key.
262  */
TEST_P(GenerateKeyTests,generateEcdsaP256Key_testMode)263 TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
264     MacedPublicKey macedPubKey;
265     bytevec privateKeyBlob;
266     bool testMode = true;
267     auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
268     ASSERT_TRUE(status.isOk());
269 
270     check_maced_pubkey(macedPubKey, testMode, nullptr);
271 }
272 
273 class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
274   protected:
CertificateRequestTest()275     CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
276         generateTestEekChain(3);
277     }
278 
generateTestEekChain(size_t eekLength)279     void generateTestEekChain(size_t eekLength) {
280         auto chain = generateEekChain(eekLength, eekId_);
281         EXPECT_TRUE(chain) << chain.message();
282         if (chain) testEekChain_ = chain.moveValue();
283         testEekLength_ = eekLength;
284     }
285 
generateKeys(bool testMode,size_t numKeys)286     void generateKeys(bool testMode, size_t numKeys) {
287         keysToSign_ = std::vector<MacedPublicKey>(numKeys);
288         cborKeysToSign_ = cppbor::Array();
289 
290         for (auto& key : keysToSign_) {
291             bytevec privateKeyBlob;
292             auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
293             ASSERT_TRUE(status.isOk()) << status.getMessage();
294 
295             vector<uint8_t> payload_value;
296             check_maced_pubkey(key, testMode, &payload_value);
297             cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
298         }
299     }
300 
checkProtectedData(const DeviceInfo & deviceInfo,const cppbor::Array & keysToSign,const bytevec & keysToSignMac,const ProtectedData & protectedData,std::vector<BccEntryData> * bccOutput=nullptr)301     void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
302                             const bytevec& keysToSignMac, const ProtectedData& protectedData,
303                             std::vector<BccEntryData>* bccOutput = nullptr) {
304         auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
305         ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
306         ASSERT_TRUE(parsedProtectedData->asArray());
307         ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
308 
309         auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
310         ASSERT_TRUE(senderPubkey) << senderPubkey.message();
311         EXPECT_EQ(senderPubkey->second, eekId_);
312 
313         auto sessionKey =
314                 x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
315                                       senderPubkey->first, false /* senderIsA */);
316         ASSERT_TRUE(sessionKey) << sessionKey.message();
317 
318         auto protectedDataPayload =
319                 decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
320         ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
321 
322         auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
323         ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
324         ASSERT_TRUE(parsedPayload->asArray());
325         EXPECT_EQ(parsedPayload->asArray()->size(), 2U);
326 
327         auto& signedMac = parsedPayload->asArray()->get(0);
328         auto& bcc = parsedPayload->asArray()->get(1);
329         ASSERT_TRUE(signedMac && signedMac->asArray());
330         ASSERT_TRUE(bcc && bcc->asArray());
331 
332         // BCC is [ pubkey, + BccEntry]
333         auto bccContents = validateBcc(bcc->asArray());
334         ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
335         ASSERT_GT(bccContents->size(), 0U);
336 
337         auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
338         ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
339         ASSERT_TRUE(deviceInfoMap->asMap());
340 
341         auto& signingKey = bccContents->back().pubKey;
342         auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
343                                               cppbor::Array()  // SignedMacAad
344                                                       .add(challenge_)
345                                                       .add(std::move(deviceInfoMap))
346                                                       .add(keysToSignMac)
347                                                       .encode());
348         ASSERT_TRUE(macKey) << macKey.message();
349 
350         auto coseMac0 = cppbor::Array()
351                                 .add(cppbor::Map()  // protected
352                                              .add(ALGORITHM, HMAC_256)
353                                              .canonicalize()
354                                              .encode())
355                                 .add(cppbor::Map())        // unprotected
356                                 .add(keysToSign.encode())  // payload (keysToSign)
357                                 .add(keysToSignMac);       // tag
358 
359         auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
360         ASSERT_TRUE(macPayload) << macPayload.message();
361 
362         if (bccOutput) {
363             *bccOutput = std::move(*bccContents);
364         }
365     }
366 
367     bytevec eekId_;
368     size_t testEekLength_;
369     EekChain testEekChain_;
370     bytevec challenge_;
371     std::vector<MacedPublicKey> keysToSign_;
372     cppbor::Array cborKeysToSign_;
373 };
374 
375 /**
376  * Generate an empty certificate request in test mode, and decrypt and verify the structure and
377  * content.
378  */
TEST_P(CertificateRequestTest,EmptyRequest_testMode)379 TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
380     bool testMode = true;
381     for (size_t eekLength : {2, 3, 7}) {
382         SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
383         generateTestEekChain(eekLength);
384 
385         bytevec keysToSignMac;
386         DeviceInfo deviceInfo;
387         ProtectedData protectedData;
388         auto status = provisionable_->generateCertificateRequest(
389                 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
390                 &protectedData, &keysToSignMac);
391         ASSERT_TRUE(status.isOk()) << status.getMessage();
392 
393         checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
394     }
395 }
396 
397 /**
398  * Ensure that test mode outputs a unique BCC root key every time we request a
399  * certificate request. Else, it's possible that the test mode API could be used
400  * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
401  * device public key multiple times.
402  */
TEST_P(CertificateRequestTest,NewKeyPerCallInTestMode)403 TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
404     constexpr bool testMode = true;
405 
406     bytevec keysToSignMac;
407     DeviceInfo deviceInfo;
408     ProtectedData protectedData;
409     auto status = provisionable_->generateCertificateRequest(
410             testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
411             &protectedData, &keysToSignMac);
412     ASSERT_TRUE(status.isOk()) << status.getMessage();
413 
414     std::vector<BccEntryData> firstBcc;
415     checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
416                        &firstBcc);
417 
418     status = provisionable_->generateCertificateRequest(
419             testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
420             &protectedData, &keysToSignMac);
421     ASSERT_TRUE(status.isOk()) << status.getMessage();
422 
423     std::vector<BccEntryData> secondBcc;
424     checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
425                        &secondBcc);
426 
427     // Verify that none of the keys in the first BCC are repeated in the second one.
428     for (const auto& i : firstBcc) {
429         for (auto& j : secondBcc) {
430             ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
431                     << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
432         }
433     }
434 }
435 
436 /**
437  * Generate an empty certificate request in prod mode. This test must be run explicitly, and
438  * is not run by default. Not all devices are GMS devices, and therefore they do not all
439  * trust the Google EEK root.
440  */
TEST_P(CertificateRequestTest,DISABLED_EmptyRequest_prodMode)441 TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
442     bool testMode = false;
443 
444     bytevec keysToSignMac;
445     DeviceInfo deviceInfo;
446     ProtectedData protectedData;
447     auto status = provisionable_->generateCertificateRequest(
448             testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
449             &protectedData, &keysToSignMac);
450     EXPECT_TRUE(status.isOk());
451 }
452 
453 /**
454  * Generate a non-empty certificate request in test mode.  Decrypt, parse and validate the contents.
455  */
TEST_P(CertificateRequestTest,NonEmptyRequest_testMode)456 TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
457     bool testMode = true;
458     generateKeys(testMode, 4 /* numKeys */);
459 
460     for (size_t eekLength : {2, 3, 7}) {
461         SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
462         generateTestEekChain(eekLength);
463 
464         bytevec keysToSignMac;
465         DeviceInfo deviceInfo;
466         ProtectedData protectedData;
467         auto status = provisionable_->generateCertificateRequest(
468                 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
469                 &keysToSignMac);
470         ASSERT_TRUE(status.isOk()) << status.getMessage();
471 
472         checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
473     }
474 }
475 
476 /**
477  * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
478  * is not run by default. Not all devices are GMS devices, and therefore they do not all
479  * trust the Google EEK root.
480  */
TEST_P(CertificateRequestTest,DISABLED_NonEmptyRequest_prodMode)481 TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
482     bool testMode = false;
483     generateKeys(testMode, 4 /* numKeys */);
484 
485     bytevec keysToSignMac;
486     DeviceInfo deviceInfo;
487     ProtectedData protectedData;
488     auto status = provisionable_->generateCertificateRequest(
489             testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
490             &keysToSignMac);
491     EXPECT_TRUE(status.isOk());
492 }
493 
494 /**
495  * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
496  */
TEST_P(CertificateRequestTest,NonEmptyRequestCorruptMac_testMode)497 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
498     bool testMode = true;
499     generateKeys(testMode, 1 /* numKeys */);
500     MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
501 
502     bytevec keysToSignMac;
503     DeviceInfo deviceInfo;
504     ProtectedData protectedData;
505     auto status = provisionable_->generateCertificateRequest(
506             testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
507             &protectedData, &keysToSignMac);
508     ASSERT_FALSE(status.isOk()) << status.getMessage();
509     EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
510 }
511 
512 /**
513  * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
514  */
TEST_P(CertificateRequestTest,NonEmptyRequestCorruptMac_prodMode)515 TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
516     bool testMode = false;
517     generateKeys(testMode, 1 /* numKeys */);
518     MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
519 
520     bytevec keysToSignMac;
521     DeviceInfo deviceInfo;
522     ProtectedData protectedData;
523     auto status = provisionable_->generateCertificateRequest(
524             testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
525             &protectedData, &keysToSignMac);
526     ASSERT_FALSE(status.isOk()) << status.getMessage();
527     EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
528 }
529 
530 /**
531  * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
532  * Confirm that the request is rejected.
533  */
TEST_P(CertificateRequestTest,NonEmptyCorruptEekRequest_prodMode)534 TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
535     bool testMode = false;
536     generateKeys(testMode, 4 /* numKeys */);
537 
538     auto prodEekChain = getProdEekChain();
539     auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
540     ASSERT_NE(parsedChain, nullptr) << parseErr;
541     ASSERT_NE(parsedChain->asArray(), nullptr);
542 
543     for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
544         auto chain = corrupt_sig_chain(prodEekChain, ii);
545         ASSERT_TRUE(chain) << chain.message();
546 
547         bytevec keysToSignMac;
548         DeviceInfo deviceInfo;
549         ProtectedData protectedData;
550         auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
551                                                                  challenge_, &deviceInfo,
552                                                                  &protectedData, &keysToSignMac);
553         ASSERT_FALSE(status.isOk());
554         ASSERT_EQ(status.getServiceSpecificError(),
555                   BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
556     }
557 }
558 
559 /**
560  * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
561  * Confirm that the request is rejected.
562  */
TEST_P(CertificateRequestTest,NonEmptyIncompleteEekRequest_prodMode)563 TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
564     bool testMode = false;
565     generateKeys(testMode, 4 /* numKeys */);
566 
567     // Build an EEK chain that omits the first self-signed cert.
568     auto truncatedChain = cppbor::Array();
569     auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
570     ASSERT_TRUE(chain);
571     auto eekChain = chain->asArray();
572     ASSERT_NE(eekChain, nullptr);
573     for (size_t ii = 1; ii < eekChain->size(); ii++) {
574         truncatedChain.add(eekChain->get(ii)->clone());
575     }
576 
577     bytevec keysToSignMac;
578     DeviceInfo deviceInfo;
579     ProtectedData protectedData;
580     auto status = provisionable_->generateCertificateRequest(
581             testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
582             &keysToSignMac);
583     ASSERT_FALSE(status.isOk());
584     ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
585 }
586 
587 /**
588  * Generate a non-empty certificate request in test mode, with prod keys.  Must fail with
589  * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
590  */
TEST_P(CertificateRequestTest,NonEmptyRequest_prodKeyInTestCert)591 TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
592     generateKeys(false /* testMode */, 2 /* numKeys */);
593 
594     bytevec keysToSignMac;
595     DeviceInfo deviceInfo;
596     ProtectedData protectedData;
597     auto status = provisionable_->generateCertificateRequest(
598             true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
599             &protectedData, &keysToSignMac);
600     ASSERT_FALSE(status.isOk());
601     ASSERT_EQ(status.getServiceSpecificError(),
602               BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
603 }
604 
605 /**
606  * Generate a non-empty certificate request in prod mode, with test keys.  Must fail with
607  * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
608  */
TEST_P(CertificateRequestTest,NonEmptyRequest_testKeyInProdCert)609 TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
610     generateKeys(true /* testMode */, 2 /* numKeys */);
611 
612     bytevec keysToSignMac;
613     DeviceInfo deviceInfo;
614     ProtectedData protectedData;
615     auto status = provisionable_->generateCertificateRequest(
616             false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
617             &protectedData, &keysToSignMac);
618     ASSERT_FALSE(status.isOk());
619     ASSERT_EQ(status.getServiceSpecificError(),
620               BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
621 }
622 
623 INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
624 
625 }  // namespace aidl::android::hardware::security::keymint::test
626