blob: af951e8861736112a2112f7eba0a5daf6fdf8b85 [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) \
44 INSTANTIATE_TEST_SUITE_P( \
45 PerInstance, name, \
46 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
47 ::android::PrintInstanceNameToString)
48
49using bytevec = std::vector<uint8_t>;
50using testing::MatchesRegex;
51using namespace remote_prov;
52using namespace keymaster;
53
54bytevec string_to_bytevec(const char* s) {
55 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
56 return bytevec(p, p + strlen(s));
57}
58
David Drysdalee99ed862021-03-15 16:43:06 +000059ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
60 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
61 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
62 return "COSE Mac0 parse failed";
63 }
64 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
65 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
66 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
67 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
68 if (!protParams || !unprotParams || !payload || !tag) {
69 return "Invalid COSE_Sign1: missing content";
70 }
71 auto corruptMac0 = cppbor::Array();
72 corruptMac0.add(protParams->clone());
73 corruptMac0.add(unprotParams->clone());
74 corruptMac0.add(payload->clone());
75 vector<uint8_t> tagData = tag->value();
76 tagData[0] ^= 0x08;
77 tagData[tagData.size() - 1] ^= 0x80;
78 corruptMac0.add(cppbor::Bstr(tagData));
79
80 return MacedPublicKey{corruptMac0.encode()};
81}
82
David Drysdalecceca9f2021-03-12 15:49:47 +000083ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
84 if (coseSign1->size() != kCoseSign1EntryCount) {
85 return "Invalid COSE_Sign1, wrong entry count";
86 }
87 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
88 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
89 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
90 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
91 if (!protectedParams || !unprotectedParams || !payload || !signature) {
92 return "Invalid COSE_Sign1: missing content";
93 }
94
95 auto corruptSig = cppbor::Array();
96 corruptSig.add(protectedParams->clone());
97 corruptSig.add(unprotectedParams->clone());
98 corruptSig.add(payload->clone());
99 vector<uint8_t> sigData = signature->value();
100 sigData[0] ^= 0x08;
101 corruptSig.add(cppbor::Bstr(sigData));
102
103 return std::move(corruptSig);
104}
105
Seth Moore19acbe92021-06-23 15:15:52 -0700106ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
107 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000108 if (!chain || !chain->asArray()) {
109 return "EekChain parse failed";
110 }
111
112 cppbor::Array* eekChain = chain->asArray();
113 if (which >= eekChain->size()) {
114 return "selected sig out of range";
115 }
116 auto corruptChain = cppbor::Array();
117
118 for (int ii = 0; ii < eekChain->size(); ++ii) {
119 if (ii == which) {
120 auto sig = corrupt_sig(eekChain->get(which)->asArray());
121 if (!sig) {
122 return "Failed to build corrupted signature" + sig.moveMessage();
123 }
124 corruptChain.add(sig.moveValue());
125 } else {
126 corruptChain.add(eekChain->get(ii)->clone());
127 }
128 }
Seth Moore19acbe92021-06-23 15:15:52 -0700129 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000130}
131
David Drysdale4d3c2982021-03-31 18:21:40 +0100132string device_suffix(const string& name) {
133 size_t pos = name.find('/');
134 if (pos == string::npos) {
135 return name;
136 }
137 return name.substr(pos + 1);
138}
139
140bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
141 string rp_suffix = device_suffix(rp_name);
142
143 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
144 for (const string& km_name : km_names) {
145 // If the suffix of the KeyMint instance equals the suffix of the
146 // RemotelyProvisionedComponent instance, assume they match.
147 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
148 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
149 *keyMint = IKeyMintDevice::fromBinder(binder);
150 return true;
151 }
152 }
153 return false;
154}
155
Shawn Willden274bb552020-09-30 22:39:22 -0600156} // namespace
157
158class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
159 public:
160 virtual void SetUp() override {
161 if (AServiceManager_isDeclared(GetParam().c_str())) {
162 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
163 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
164 }
165 ASSERT_NE(provisionable_, nullptr);
166 }
167
168 static vector<string> build_params() {
169 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
170 return params;
171 }
172
173 protected:
174 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
175};
176
177using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
178
179INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
180
181/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000182 * Generate and validate a production-mode key. MAC tag can't be verified, but
183 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600184 */
Max Bires126869a2021-02-21 18:32:59 -0800185TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600186 MacedPublicKey macedPubKey;
187 bytevec privateKeyBlob;
188 bool testMode = false;
189 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
190 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000191 vector<uint8_t> coseKeyData;
192 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100193}
194
195/**
196 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
197 */
198TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
199 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
200 std::shared_ptr<IKeyMintDevice> keyMint;
201 if (!matching_keymint_device(GetParam(), &keyMint)) {
202 // No matching IKeyMintDevice.
203 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
204 return;
205 }
206 KeyMintHardwareInfo info;
207 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
208
209 MacedPublicKey macedPubKey;
210 bytevec privateKeyBlob;
211 bool testMode = false;
212 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
213 ASSERT_TRUE(status.isOk());
214 vector<uint8_t> coseKeyData;
215 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
216
David Drysdalef0d516d2021-03-22 07:51:43 +0000217 AttestationKey attestKey;
218 attestKey.keyBlob = std::move(privateKeyBlob);
219 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600220
David Drysdalef0d516d2021-03-22 07:51:43 +0000221 // Generate an ECDSA key that is attested by the generated P256 keypair.
222 AuthorizationSet keyDesc = AuthorizationSetBuilder()
223 .Authorization(TAG_NO_AUTH_REQUIRED)
224 .EcdsaSigningKey(256)
225 .AttestationChallenge("foo")
226 .AttestationApplicationId("bar")
227 .Digest(Digest::NONE)
228 .SetDefaultValidity();
229 KeyCreationResult creationResult;
230 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
231 ASSERT_TRUE(result.isOk());
232 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
233 vector<KeyCharacteristics> attested_key_characteristics =
234 std::move(creationResult.keyCharacteristics);
235 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
236 EXPECT_EQ(attested_key_cert_chain.size(), 1);
237
238 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
239 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
240 EXPECT_TRUE(verify_attestation_record("foo", "bar", sw_enforced, hw_enforced,
241 info.securityLevel,
242 attested_key_cert_chain[0].encodedCertificate));
243
244 // Attestation by itself is not valid (last entry is not self-signed).
245 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
246
247 // The signature over the attested key should correspond to the P256 public key.
248 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
249 ASSERT_TRUE(key_cert.get());
250 EVP_PKEY_Ptr signing_pubkey;
251 p256_pub_key(coseKeyData, &signing_pubkey);
252 ASSERT_TRUE(signing_pubkey.get());
253
254 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
255 << "Verification of attested certificate failed "
256 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600257}
258
259/**
260 * Generate and validate a test-mode key.
261 */
Max Bires126869a2021-02-21 18:32:59 -0800262TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600263 MacedPublicKey macedPubKey;
264 bytevec privateKeyBlob;
265 bool testMode = true;
266 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
267 ASSERT_TRUE(status.isOk());
268
David Drysdalec8400772021-03-11 12:35:11 +0000269 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600270}
271
272class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
273 protected:
David Drysdalec8400772021-03-11 12:35:11 +0000274 CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
Seth Moore19acbe92021-06-23 15:15:52 -0700275 generateTestEekChain(3);
David Drysdalecceca9f2021-03-12 15:49:47 +0000276 }
277
Seth Moore19acbe92021-06-23 15:15:52 -0700278 void generateTestEekChain(size_t eekLength) {
David Drysdalecceca9f2021-03-12 15:49:47 +0000279 auto chain = generateEekChain(eekLength, eekId_);
Shawn Willden274bb552020-09-30 22:39:22 -0600280 EXPECT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700281 if (chain) testEekChain_ = chain.moveValue();
282 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600283 }
284
285 void generateKeys(bool testMode, size_t numKeys) {
286 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
287 cborKeysToSign_ = cppbor::Array();
288
289 for (auto& key : keysToSign_) {
290 bytevec privateKeyBlob;
291 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
292 ASSERT_TRUE(status.isOk()) << status.getMessage();
293
David Drysdalec8400772021-03-11 12:35:11 +0000294 vector<uint8_t> payload_value;
295 check_maced_pubkey(key, testMode, &payload_value);
296 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600297 }
298 }
299
David Drysdalef6fc5a62021-03-31 16:14:31 +0100300 void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
Seth Moore42c11332021-07-02 15:38:17 -0700301 const bytevec& keysToSignMac, const ProtectedData& protectedData,
302 std::vector<BccEntryData>* bccOutput = nullptr) {
David Drysdalec8400772021-03-11 12:35:11 +0000303 auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
304 ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
305 ASSERT_TRUE(parsedProtectedData->asArray());
306 ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
307
308 auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
309 ASSERT_TRUE(senderPubkey) << senderPubkey.message();
310 EXPECT_EQ(senderPubkey->second, eekId_);
311
Seth Moore19acbe92021-06-23 15:15:52 -0700312 auto sessionKey =
313 x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
314 senderPubkey->first, false /* senderIsA */);
David Drysdalec8400772021-03-11 12:35:11 +0000315 ASSERT_TRUE(sessionKey) << sessionKey.message();
316
317 auto protectedDataPayload =
318 decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
319 ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
320
321 auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
322 ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
323 ASSERT_TRUE(parsedPayload->asArray());
324 EXPECT_EQ(parsedPayload->asArray()->size(), 2U);
325
326 auto& signedMac = parsedPayload->asArray()->get(0);
327 auto& bcc = parsedPayload->asArray()->get(1);
328 ASSERT_TRUE(signedMac && signedMac->asArray());
329 ASSERT_TRUE(bcc && bcc->asArray());
330
331 // BCC is [ pubkey, + BccEntry]
332 auto bccContents = validateBcc(bcc->asArray());
333 ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
334 ASSERT_GT(bccContents->size(), 0U);
335
David Drysdalef6fc5a62021-03-31 16:14:31 +0100336 auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
337 ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
338 ASSERT_TRUE(deviceInfoMap->asMap());
339
David Drysdalec8400772021-03-11 12:35:11 +0000340 auto& signingKey = bccContents->back().pubKey;
Seth Moore798188a2021-06-17 10:58:27 -0700341 auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
David Drysdalef6fc5a62021-03-31 16:14:31 +0100342 cppbor::Array() // SignedMacAad
David Drysdalec8400772021-03-11 12:35:11 +0000343 .add(challenge_)
David Drysdalef6fc5a62021-03-31 16:14:31 +0100344 .add(std::move(deviceInfoMap))
Max Bires8dff0b32021-05-26 13:05:09 -0700345 .add(keysToSignMac)
David Drysdalec8400772021-03-11 12:35:11 +0000346 .encode());
347 ASSERT_TRUE(macKey) << macKey.message();
348
349 auto coseMac0 = cppbor::Array()
350 .add(cppbor::Map() // protected
351 .add(ALGORITHM, HMAC_256)
352 .canonicalize()
353 .encode())
354 .add(cppbor::Map()) // unprotected
355 .add(keysToSign.encode()) // payload (keysToSign)
356 .add(keysToSignMac); // tag
357
358 auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
359 ASSERT_TRUE(macPayload) << macPayload.message();
Seth Moore42c11332021-07-02 15:38:17 -0700360
361 if (bccOutput) {
362 *bccOutput = std::move(*bccContents);
363 }
David Drysdalec8400772021-03-11 12:35:11 +0000364 }
365
Shawn Willden274bb552020-09-30 22:39:22 -0600366 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700367 size_t testEekLength_;
368 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000369 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600370 std::vector<MacedPublicKey> keysToSign_;
371 cppbor::Array cborKeysToSign_;
372};
373
374/**
375 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
376 * content.
377 */
Max Bires126869a2021-02-21 18:32:59 -0800378TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600379 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000380 for (size_t eekLength : {2, 3, 7}) {
381 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700382 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600383
David Drysdalecceca9f2021-03-12 15:49:47 +0000384 bytevec keysToSignMac;
385 DeviceInfo deviceInfo;
386 ProtectedData protectedData;
387 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700388 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000389 &protectedData, &keysToSignMac);
390 ASSERT_TRUE(status.isOk()) << status.getMessage();
391
David Drysdalef6fc5a62021-03-31 16:14:31 +0100392 checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000393 }
Shawn Willden274bb552020-09-30 22:39:22 -0600394}
395
396/**
Seth Moore42c11332021-07-02 15:38:17 -0700397 * Ensure that test mode outputs a unique BCC root key every time we request a
398 * certificate request. Else, it's possible that the test mode API could be used
399 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
400 * device public key multiple times.
401 */
402TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
403 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700404
405 bytevec keysToSignMac;
406 DeviceInfo deviceInfo;
407 ProtectedData protectedData;
408 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700409 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
410 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700411 ASSERT_TRUE(status.isOk()) << status.getMessage();
412
413 std::vector<BccEntryData> firstBcc;
414 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
415 &firstBcc);
416
Seth Moore19acbe92021-06-23 15:15:52 -0700417 status = provisionable_->generateCertificateRequest(
418 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
419 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700420 ASSERT_TRUE(status.isOk()) << status.getMessage();
421
422 std::vector<BccEntryData> secondBcc;
423 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
424 &secondBcc);
425
426 // Verify that none of the keys in the first BCC are repeated in the second one.
427 for (const auto& i : firstBcc) {
428 for (auto& j : secondBcc) {
429 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
430 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
431 }
432 }
433}
434
435/**
Seth Moore19acbe92021-06-23 15:15:52 -0700436 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
437 * is not run by default. Not all devices are GMS devices, and therefore they do not all
438 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600439 */
Seth Moore19acbe92021-06-23 15:15:52 -0700440TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600441 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000442
Seth Moore19acbe92021-06-23 15:15:52 -0700443 bytevec keysToSignMac;
444 DeviceInfo deviceInfo;
445 ProtectedData protectedData;
446 auto status = provisionable_->generateCertificateRequest(
447 testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
448 &protectedData, &keysToSignMac);
449 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600450}
451
452/**
453 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
454 */
Max Bires126869a2021-02-21 18:32:59 -0800455TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600456 bool testMode = true;
457 generateKeys(testMode, 4 /* numKeys */);
458
David Drysdalecceca9f2021-03-12 15:49:47 +0000459 for (size_t eekLength : {2, 3, 7}) {
460 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700461 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600462
David Drysdalecceca9f2021-03-12 15:49:47 +0000463 bytevec keysToSignMac;
464 DeviceInfo deviceInfo;
465 ProtectedData protectedData;
466 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700467 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000468 &keysToSignMac);
469 ASSERT_TRUE(status.isOk()) << status.getMessage();
470
David Drysdalef6fc5a62021-03-31 16:14:31 +0100471 checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000472 }
Shawn Willden274bb552020-09-30 22:39:22 -0600473}
474
475/**
Seth Moore19acbe92021-06-23 15:15:52 -0700476 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
477 * is not run by default. Not all devices are GMS devices, and therefore they do not all
478 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600479 */
Seth Moore19acbe92021-06-23 15:15:52 -0700480TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600481 bool testMode = false;
482 generateKeys(testMode, 4 /* numKeys */);
483
Seth Moore19acbe92021-06-23 15:15:52 -0700484 bytevec keysToSignMac;
485 DeviceInfo deviceInfo;
486 ProtectedData protectedData;
487 auto status = provisionable_->generateCertificateRequest(
488 testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
489 &keysToSignMac);
490 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000491}
492
493/**
David Drysdalee99ed862021-03-15 16:43:06 +0000494 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
495 */
496TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
497 bool testMode = true;
498 generateKeys(testMode, 1 /* numKeys */);
499 MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
500
501 bytevec keysToSignMac;
502 DeviceInfo deviceInfo;
503 ProtectedData protectedData;
504 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700505 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
506 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000507 ASSERT_FALSE(status.isOk()) << status.getMessage();
508 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
509}
510
511/**
512 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
513 */
514TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700515 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000516 generateKeys(testMode, 1 /* numKeys */);
517 MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
518
519 bytevec keysToSignMac;
520 DeviceInfo deviceInfo;
521 ProtectedData protectedData;
522 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700523 testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
524 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000525 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700526 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000527}
528
529/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000530 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
531 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000532 */
533TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
534 bool testMode = false;
535 generateKeys(testMode, 4 /* numKeys */);
536
Seth Moore19acbe92021-06-23 15:15:52 -0700537 auto prodEekChain = getProdEekChain();
538 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
539 ASSERT_NE(parsedChain, nullptr) << parseErr;
540 ASSERT_NE(parsedChain->asArray(), nullptr);
541
542 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
543 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000544 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000545
546 bytevec keysToSignMac;
547 DeviceInfo deviceInfo;
548 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700549 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
550 challenge_, &deviceInfo,
551 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000552 ASSERT_FALSE(status.isOk());
553 ASSERT_EQ(status.getServiceSpecificError(),
554 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
555 }
556}
557
558/**
559 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
560 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000561 */
562TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
563 bool testMode = false;
564 generateKeys(testMode, 4 /* numKeys */);
565
566 // Build an EEK chain that omits the first self-signed cert.
567 auto truncatedChain = cppbor::Array();
Seth Moore19acbe92021-06-23 15:15:52 -0700568 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
David Drysdalecceca9f2021-03-12 15:49:47 +0000569 ASSERT_TRUE(chain);
570 auto eekChain = chain->asArray();
571 ASSERT_NE(eekChain, nullptr);
572 for (size_t ii = 1; ii < eekChain->size(); ii++) {
573 truncatedChain.add(eekChain->get(ii)->clone());
574 }
575
Shawn Willden274bb552020-09-30 22:39:22 -0600576 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700577 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600578 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000579 auto status = provisionable_->generateCertificateRequest(
580 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
581 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600582 ASSERT_FALSE(status.isOk());
583 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
584}
585
586/**
587 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
588 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
589 */
Max Bires126869a2021-02-21 18:32:59 -0800590TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600591 generateKeys(false /* testMode */, 2 /* numKeys */);
592
593 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700594 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600595 ProtectedData protectedData;
Max Biresfdbb9042021-03-23 12:43:38 -0700596 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700597 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700598 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600599 ASSERT_FALSE(status.isOk());
600 ASSERT_EQ(status.getServiceSpecificError(),
601 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
602}
603
604/**
605 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
606 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
607 */
Max Bires126869a2021-02-21 18:32:59 -0800608TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600609 generateKeys(true /* testMode */, 2 /* numKeys */);
610
611 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700612 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600613 ProtectedData protectedData;
614 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700615 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000616 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600617 ASSERT_FALSE(status.isOk());
618 ASSERT_EQ(status.getServiceSpecificError(),
619 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
620}
621
622INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
623
624} // namespace aidl::android::hardware::security::keymint::test