blob: c9d506f788f4941068be8182c1c2c8fe28780a3d [file] [log] [blame]
Shawn Willden274bb552020-09-30 22:39:22 -06001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "VtsRemotelyProvisionableComponentTests"
18
Max Bires261a0492021-04-19 18:55:56 -070019#include <AndroidRemotelyProvisionedComponentDevice.h>
Shawn Willden274bb552020-09-30 22:39:22 -060020#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
21#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
22#include <android/binder_manager.h>
23#include <cppbor_parse.h>
Shawn Willden274bb552020-09-30 22:39:22 -060024#include <gmock/gmock.h>
Max Bires9704ff62021-04-07 11:12:01 -070025#include <keymaster/cppcose/cppcose.h>
Shawn Willden274bb552020-09-30 22:39:22 -060026#include <keymaster/keymaster_configuration.h>
David Drysdalef0d516d2021-03-22 07:51:43 +000027#include <keymint_support/authorization_set.h>
28#include <openssl/ec.h>
29#include <openssl/ec_key.h>
30#include <openssl/x509.h>
Shawn Willden274bb552020-09-30 22:39:22 -060031#include <remote_prov/remote_prov_utils.h>
Seth Moore42c11332021-07-02 15:38:17 -070032#include <vector>
Shawn Willden274bb552020-09-30 22:39:22 -060033
David Drysdalef0d516d2021-03-22 07:51:43 +000034#include "KeyMintAidlTestBase.h"
35
Shawn Willden274bb552020-09-30 22:39:22 -060036namespace aidl::android::hardware::security::keymint::test {
37
38using ::std::string;
39using ::std::vector;
40
41namespace {
42
43#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070044 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060045 INSTANTIATE_TEST_SUITE_P( \
46 PerInstance, name, \
47 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
48 ::android::PrintInstanceNameToString)
49
50using bytevec = std::vector<uint8_t>;
51using testing::MatchesRegex;
52using namespace remote_prov;
53using namespace keymaster;
54
55bytevec 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
David Drysdalee99ed862021-03-15 16:43:06 +000060ErrMsgOr<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
David Drysdalecceca9f2021-03-12 15:49:47 +000084ErrMsgOr<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
Seth Moore19acbe92021-06-23 15:15:52 -0700107ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
108 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000109 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 }
Seth Moore19acbe92021-06-23 15:15:52 -0700130 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000131}
132
David Drysdale4d3c2982021-03-31 18:21:40 +0100133string 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
141bool 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
Shawn Willden274bb552020-09-30 22:39:22 -0600157} // namespace
158
159class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
160 public:
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
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
178using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
179
180INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
181
182/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000183 * 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.
Shawn Willden274bb552020-09-30 22:39:22 -0600185 */
Max Bires126869a2021-02-21 18:32:59 -0800186TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600187 MacedPublicKey macedPubKey;
188 bytevec privateKeyBlob;
189 bool testMode = false;
190 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
191 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000192 vector<uint8_t> coseKeyData;
193 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100194}
195
196/**
197 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
198 */
199TEST_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
David Drysdalef0d516d2021-03-22 07:51:43 +0000218 AttestationKey attestKey;
219 attestKey.keyBlob = std::move(privateKeyBlob);
220 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600221
David Drysdalef0d516d2021-03-22 07:51:43 +0000222 // Generate an ECDSA key that is attested by the generated P256 keypair.
223 AuthorizationSet keyDesc = AuthorizationSetBuilder()
224 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100225 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000226 .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
David Drysdale7dff4fc2021-12-10 10:10:52 +0000239 int32_t aidl_version = 0;
240 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000241 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
242 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000243 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000244 info.securityLevel,
245 attested_key_cert_chain[0].encodedCertificate));
246
247 // Attestation by itself is not valid (last entry is not self-signed).
248 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
249
250 // The signature over the attested key should correspond to the P256 public key.
251 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
252 ASSERT_TRUE(key_cert.get());
253 EVP_PKEY_Ptr signing_pubkey;
254 p256_pub_key(coseKeyData, &signing_pubkey);
255 ASSERT_TRUE(signing_pubkey.get());
256
257 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
258 << "Verification of attested certificate failed "
259 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600260}
261
262/**
263 * Generate and validate a test-mode key.
264 */
Max Bires126869a2021-02-21 18:32:59 -0800265TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600266 MacedPublicKey macedPubKey;
267 bytevec privateKeyBlob;
268 bool testMode = true;
269 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
270 ASSERT_TRUE(status.isOk());
271
David Drysdalec8400772021-03-11 12:35:11 +0000272 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600273}
274
275class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
276 protected:
David Drysdalec8400772021-03-11 12:35:11 +0000277 CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
Seth Moore19acbe92021-06-23 15:15:52 -0700278 generateTestEekChain(3);
David Drysdalecceca9f2021-03-12 15:49:47 +0000279 }
280
Seth Moore19acbe92021-06-23 15:15:52 -0700281 void generateTestEekChain(size_t eekLength) {
David Drysdalecceca9f2021-03-12 15:49:47 +0000282 auto chain = generateEekChain(eekLength, eekId_);
Shawn Willden274bb552020-09-30 22:39:22 -0600283 EXPECT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700284 if (chain) testEekChain_ = chain.moveValue();
285 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600286 }
287
288 void generateKeys(bool testMode, size_t numKeys) {
289 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
290 cborKeysToSign_ = cppbor::Array();
291
292 for (auto& key : keysToSign_) {
293 bytevec privateKeyBlob;
294 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
295 ASSERT_TRUE(status.isOk()) << status.getMessage();
296
David Drysdalec8400772021-03-11 12:35:11 +0000297 vector<uint8_t> payload_value;
298 check_maced_pubkey(key, testMode, &payload_value);
299 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600300 }
301 }
302
David Drysdalef6fc5a62021-03-31 16:14:31 +0100303 void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
Seth Moore42c11332021-07-02 15:38:17 -0700304 const bytevec& keysToSignMac, const ProtectedData& protectedData,
305 std::vector<BccEntryData>* bccOutput = nullptr) {
David Drysdalec8400772021-03-11 12:35:11 +0000306 auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
307 ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
308 ASSERT_TRUE(parsedProtectedData->asArray());
309 ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
310
311 auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
312 ASSERT_TRUE(senderPubkey) << senderPubkey.message();
313 EXPECT_EQ(senderPubkey->second, eekId_);
314
Seth Moore19acbe92021-06-23 15:15:52 -0700315 auto sessionKey =
316 x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
317 senderPubkey->first, false /* senderIsA */);
David Drysdalec8400772021-03-11 12:35:11 +0000318 ASSERT_TRUE(sessionKey) << sessionKey.message();
319
320 auto protectedDataPayload =
321 decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
322 ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
323
324 auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
325 ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
326 ASSERT_TRUE(parsedPayload->asArray());
327 EXPECT_EQ(parsedPayload->asArray()->size(), 2U);
328
329 auto& signedMac = parsedPayload->asArray()->get(0);
330 auto& bcc = parsedPayload->asArray()->get(1);
331 ASSERT_TRUE(signedMac && signedMac->asArray());
332 ASSERT_TRUE(bcc && bcc->asArray());
333
334 // BCC is [ pubkey, + BccEntry]
335 auto bccContents = validateBcc(bcc->asArray());
336 ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
337 ASSERT_GT(bccContents->size(), 0U);
338
David Drysdalef6fc5a62021-03-31 16:14:31 +0100339 auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
340 ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
341 ASSERT_TRUE(deviceInfoMap->asMap());
342
David Drysdalec8400772021-03-11 12:35:11 +0000343 auto& signingKey = bccContents->back().pubKey;
Seth Moore798188a2021-06-17 10:58:27 -0700344 auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
David Drysdalef6fc5a62021-03-31 16:14:31 +0100345 cppbor::Array() // SignedMacAad
David Drysdalec8400772021-03-11 12:35:11 +0000346 .add(challenge_)
David Drysdalef6fc5a62021-03-31 16:14:31 +0100347 .add(std::move(deviceInfoMap))
Max Bires8dff0b32021-05-26 13:05:09 -0700348 .add(keysToSignMac)
David Drysdalec8400772021-03-11 12:35:11 +0000349 .encode());
350 ASSERT_TRUE(macKey) << macKey.message();
351
352 auto coseMac0 = cppbor::Array()
353 .add(cppbor::Map() // protected
354 .add(ALGORITHM, HMAC_256)
355 .canonicalize()
356 .encode())
357 .add(cppbor::Map()) // unprotected
358 .add(keysToSign.encode()) // payload (keysToSign)
359 .add(keysToSignMac); // tag
360
361 auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
362 ASSERT_TRUE(macPayload) << macPayload.message();
Seth Moore42c11332021-07-02 15:38:17 -0700363
364 if (bccOutput) {
365 *bccOutput = std::move(*bccContents);
366 }
David Drysdalec8400772021-03-11 12:35:11 +0000367 }
368
Shawn Willden274bb552020-09-30 22:39:22 -0600369 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700370 size_t testEekLength_;
371 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000372 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600373 std::vector<MacedPublicKey> keysToSign_;
374 cppbor::Array cborKeysToSign_;
375};
376
377/**
378 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
379 * content.
380 */
Max Bires126869a2021-02-21 18:32:59 -0800381TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600382 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000383 for (size_t eekLength : {2, 3, 7}) {
384 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700385 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600386
David Drysdalecceca9f2021-03-12 15:49:47 +0000387 bytevec keysToSignMac;
388 DeviceInfo deviceInfo;
389 ProtectedData protectedData;
390 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700391 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000392 &protectedData, &keysToSignMac);
393 ASSERT_TRUE(status.isOk()) << status.getMessage();
394
David Drysdalef6fc5a62021-03-31 16:14:31 +0100395 checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000396 }
Shawn Willden274bb552020-09-30 22:39:22 -0600397}
398
399/**
Seth Moore42c11332021-07-02 15:38:17 -0700400 * Ensure that test mode outputs a unique BCC root key every time we request a
401 * certificate request. Else, it's possible that the test mode API could be used
402 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
403 * device public key multiple times.
404 */
405TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
406 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700407
408 bytevec keysToSignMac;
409 DeviceInfo deviceInfo;
410 ProtectedData protectedData;
411 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700412 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
413 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700414 ASSERT_TRUE(status.isOk()) << status.getMessage();
415
416 std::vector<BccEntryData> firstBcc;
417 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
418 &firstBcc);
419
Seth Moore19acbe92021-06-23 15:15:52 -0700420 status = provisionable_->generateCertificateRequest(
421 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
422 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700423 ASSERT_TRUE(status.isOk()) << status.getMessage();
424
425 std::vector<BccEntryData> secondBcc;
426 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
427 &secondBcc);
428
429 // Verify that none of the keys in the first BCC are repeated in the second one.
430 for (const auto& i : firstBcc) {
431 for (auto& j : secondBcc) {
432 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
433 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
434 }
435 }
436}
437
438/**
Seth Moore19acbe92021-06-23 15:15:52 -0700439 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
440 * is not run by default. Not all devices are GMS devices, and therefore they do not all
441 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600442 */
Seth Moore19acbe92021-06-23 15:15:52 -0700443TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600444 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000445
Seth Moore19acbe92021-06-23 15:15:52 -0700446 bytevec keysToSignMac;
447 DeviceInfo deviceInfo;
448 ProtectedData protectedData;
449 auto status = provisionable_->generateCertificateRequest(
450 testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
451 &protectedData, &keysToSignMac);
452 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600453}
454
455/**
456 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
457 */
Max Bires126869a2021-02-21 18:32:59 -0800458TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600459 bool testMode = true;
460 generateKeys(testMode, 4 /* numKeys */);
461
David Drysdalecceca9f2021-03-12 15:49:47 +0000462 for (size_t eekLength : {2, 3, 7}) {
463 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700464 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600465
David Drysdalecceca9f2021-03-12 15:49:47 +0000466 bytevec keysToSignMac;
467 DeviceInfo deviceInfo;
468 ProtectedData protectedData;
469 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700470 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000471 &keysToSignMac);
472 ASSERT_TRUE(status.isOk()) << status.getMessage();
473
David Drysdalef6fc5a62021-03-31 16:14:31 +0100474 checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000475 }
Shawn Willden274bb552020-09-30 22:39:22 -0600476}
477
478/**
Seth Moore19acbe92021-06-23 15:15:52 -0700479 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
480 * is not run by default. Not all devices are GMS devices, and therefore they do not all
481 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600482 */
Seth Moore19acbe92021-06-23 15:15:52 -0700483TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600484 bool testMode = false;
485 generateKeys(testMode, 4 /* numKeys */);
486
Seth Moore19acbe92021-06-23 15:15:52 -0700487 bytevec keysToSignMac;
488 DeviceInfo deviceInfo;
489 ProtectedData protectedData;
490 auto status = provisionable_->generateCertificateRequest(
491 testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
492 &keysToSignMac);
493 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000494}
495
496/**
David Drysdalee99ed862021-03-15 16:43:06 +0000497 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
498 */
499TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
500 bool testMode = true;
501 generateKeys(testMode, 1 /* numKeys */);
502 MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
503
504 bytevec keysToSignMac;
505 DeviceInfo deviceInfo;
506 ProtectedData protectedData;
507 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700508 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
509 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000510 ASSERT_FALSE(status.isOk()) << status.getMessage();
511 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
512}
513
514/**
515 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
516 */
517TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700518 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000519 generateKeys(testMode, 1 /* numKeys */);
520 MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
521
522 bytevec keysToSignMac;
523 DeviceInfo deviceInfo;
524 ProtectedData protectedData;
525 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700526 testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
527 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000528 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700529 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000530}
531
532/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000533 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
534 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000535 */
536TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
537 bool testMode = false;
538 generateKeys(testMode, 4 /* numKeys */);
539
Seth Moore19acbe92021-06-23 15:15:52 -0700540 auto prodEekChain = getProdEekChain();
541 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
542 ASSERT_NE(parsedChain, nullptr) << parseErr;
543 ASSERT_NE(parsedChain->asArray(), nullptr);
544
545 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
546 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000547 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000548
549 bytevec keysToSignMac;
550 DeviceInfo deviceInfo;
551 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700552 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
553 challenge_, &deviceInfo,
554 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000555 ASSERT_FALSE(status.isOk());
556 ASSERT_EQ(status.getServiceSpecificError(),
557 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
558 }
559}
560
561/**
562 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
563 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000564 */
565TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
566 bool testMode = false;
567 generateKeys(testMode, 4 /* numKeys */);
568
569 // Build an EEK chain that omits the first self-signed cert.
570 auto truncatedChain = cppbor::Array();
Seth Moore19acbe92021-06-23 15:15:52 -0700571 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
David Drysdalecceca9f2021-03-12 15:49:47 +0000572 ASSERT_TRUE(chain);
573 auto eekChain = chain->asArray();
574 ASSERT_NE(eekChain, nullptr);
575 for (size_t ii = 1; ii < eekChain->size(); ii++) {
576 truncatedChain.add(eekChain->get(ii)->clone());
577 }
578
Shawn Willden274bb552020-09-30 22:39:22 -0600579 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700580 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600581 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000582 auto status = provisionable_->generateCertificateRequest(
583 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
584 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600585 ASSERT_FALSE(status.isOk());
586 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
587}
588
589/**
590 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
591 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
592 */
Max Bires126869a2021-02-21 18:32:59 -0800593TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600594 generateKeys(false /* testMode */, 2 /* numKeys */);
595
596 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700597 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600598 ProtectedData protectedData;
Max Biresfdbb9042021-03-23 12:43:38 -0700599 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700600 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700601 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600602 ASSERT_FALSE(status.isOk());
603 ASSERT_EQ(status.getServiceSpecificError(),
604 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
605}
606
607/**
608 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
609 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
610 */
Max Bires126869a2021-02-21 18:32:59 -0800611TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600612 generateKeys(true /* testMode */, 2 /* numKeys */);
613
614 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700615 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600616 ProtectedData protectedData;
617 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700618 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000619 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600620 ASSERT_FALSE(status.isOk());
621 ASSERT_EQ(status.getServiceSpecificError(),
622 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
623}
624
625INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
626
627} // namespace aidl::android::hardware::security::keymint::test