blob: 544393a49970d156b54272b694de44e858b14184 [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>
Seth Moorefc86bf42021-12-09 14:07:04 -080023#include <binder/IServiceManager.h>
Shawn Willden274bb552020-09-30 22:39:22 -060024#include <cppbor_parse.h>
Shawn Willden274bb552020-09-30 22:39:22 -060025#include <gmock/gmock.h>
Max Bires9704ff62021-04-07 11:12:01 -070026#include <keymaster/cppcose/cppcose.h>
Shawn Willden274bb552020-09-30 22:39:22 -060027#include <keymaster/keymaster_configuration.h>
David Drysdalef0d516d2021-03-22 07:51:43 +000028#include <keymint_support/authorization_set.h>
29#include <openssl/ec.h>
30#include <openssl/ec_key.h>
31#include <openssl/x509.h>
Shawn Willden274bb552020-09-30 22:39:22 -060032#include <remote_prov/remote_prov_utils.h>
Seth Moorefc86bf42021-12-09 14:07:04 -080033#include <set>
Seth Moore42c11332021-07-02 15:38:17 -070034#include <vector>
Shawn Willden274bb552020-09-30 22:39:22 -060035
David Drysdalef0d516d2021-03-22 07:51:43 +000036#include "KeyMintAidlTestBase.h"
37
Shawn Willden274bb552020-09-30 22:39:22 -060038namespace aidl::android::hardware::security::keymint::test {
39
40using ::std::string;
41using ::std::vector;
42
43namespace {
44
Seth Moorefc86bf42021-12-09 14:07:04 -080045constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
46
Shawn Willden274bb552020-09-30 22:39:22 -060047#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070048 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060049 INSTANTIATE_TEST_SUITE_P( \
50 PerInstance, name, \
51 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
52 ::android::PrintInstanceNameToString)
53
Seth Moorefc86bf42021-12-09 14:07:04 -080054using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060055using bytevec = std::vector<uint8_t>;
56using testing::MatchesRegex;
57using namespace remote_prov;
58using namespace keymaster;
59
Max Bires8b09c502022-01-30 20:03:16 -080060std::set<std::string> getAllowedVbStates() {
61 return {"green", "yellow", "orange"};
62}
63
64std::set<std::string> getAllowedBootloaderStates() {
65 return {"locked", "unlocked"};
66}
67
68std::set<std::string> getAllowedSecurityLevels() {
69 return {"tee", "strongbox"};
70}
71
72std::set<std::string> getAllowedAttIdStates() {
73 return {"locked", "open"};
74}
75
Shawn Willden274bb552020-09-30 22:39:22 -060076bytevec 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
David Drysdalee99ed862021-03-15 16:43:06 +000081ErrMsgOr<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
David Drysdalecceca9f2021-03-12 15:49:47 +0000105ErrMsgOr<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
Seth Moore19acbe92021-06-23 15:15:52 -0700128ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
129 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000130 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 }
Seth Moore19acbe92021-06-23 15:15:52 -0700151 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000152}
153
David Drysdale4d3c2982021-03-31 18:21:40 +0100154string 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
162bool 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
Shawn Willden274bb552020-09-30 22:39:22 -0600178} // namespace
179
180class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
181 public:
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 }
189
190 static vector<string> build_params() {
191 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
192 return params;
193 }
194
195 protected:
196 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
197};
198
Seth Moorefc86bf42021-12-09 14:07:04 -0800199/**
200 * Verify that every implementation reports a different unique id.
201 */
202TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
203 std::set<std::string> uniqueIds;
204 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
205 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
206 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
207 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
208 IRemotelyProvisionedComponent::fromBinder(binder);
209 ASSERT_NE(rpc, nullptr);
210
211 RpcHardwareInfo hwInfo;
212 ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
213
214 int32_t version;
215 ASSERT_TRUE(rpc->getInterfaceVersion(&version).isOk());
216 if (version >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
217 ASSERT_TRUE(hwInfo.uniqueId);
218 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
219 EXPECT_TRUE(wasInserted);
220 } else {
221 ASSERT_FALSE(hwInfo.uniqueId);
222 }
223 }
224}
225
226using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
227
228INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
229
230/**
231 * Verify that a valid curve is reported by the implementation.
232 */
233TEST_P(GetHardwareInfoTests, supportsValidCurve) {
234 RpcHardwareInfo hwInfo;
235 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
236
237 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
238 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
239 << "Invalid curve: " << hwInfo.supportedEekCurve;
240}
241
242/**
243 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
244 */
245TEST_P(GetHardwareInfoTests, uniqueId) {
246 int32_t version;
247 ASSERT_TRUE(provisionable_->getInterfaceVersion(&version).isOk());
248
249 if (version < VERSION_WITH_UNIQUE_ID_SUPPORT) {
250 return;
251 }
252
253 RpcHardwareInfo hwInfo;
254 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
255 ASSERT_TRUE(hwInfo.uniqueId);
256 EXPECT_GE(hwInfo.uniqueId->size(), 1);
257 EXPECT_LE(hwInfo.uniqueId->size(), 32);
258}
259
Shawn Willden274bb552020-09-30 22:39:22 -0600260using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
261
262INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
263
264/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000265 * Generate and validate a production-mode key. MAC tag can't be verified, but
266 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600267 */
Max Bires126869a2021-02-21 18:32:59 -0800268TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600269 MacedPublicKey macedPubKey;
270 bytevec privateKeyBlob;
271 bool testMode = false;
272 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
273 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000274 vector<uint8_t> coseKeyData;
275 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100276}
277
278/**
279 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
280 */
281TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
282 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
283 std::shared_ptr<IKeyMintDevice> keyMint;
284 if (!matching_keymint_device(GetParam(), &keyMint)) {
285 // No matching IKeyMintDevice.
286 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
287 return;
288 }
289 KeyMintHardwareInfo info;
290 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
291
292 MacedPublicKey macedPubKey;
293 bytevec privateKeyBlob;
294 bool testMode = false;
295 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
296 ASSERT_TRUE(status.isOk());
297 vector<uint8_t> coseKeyData;
298 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
299
David Drysdalef0d516d2021-03-22 07:51:43 +0000300 AttestationKey attestKey;
301 attestKey.keyBlob = std::move(privateKeyBlob);
302 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600303
David Drysdalef0d516d2021-03-22 07:51:43 +0000304 // Generate an ECDSA key that is attested by the generated P256 keypair.
305 AuthorizationSet keyDesc = AuthorizationSetBuilder()
306 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100307 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000308 .AttestationChallenge("foo")
309 .AttestationApplicationId("bar")
310 .Digest(Digest::NONE)
311 .SetDefaultValidity();
312 KeyCreationResult creationResult;
313 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
314 ASSERT_TRUE(result.isOk());
315 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
316 vector<KeyCharacteristics> attested_key_characteristics =
317 std::move(creationResult.keyCharacteristics);
318 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
319 EXPECT_EQ(attested_key_cert_chain.size(), 1);
320
David Drysdale7dff4fc2021-12-10 10:10:52 +0000321 int32_t aidl_version = 0;
322 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000323 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
324 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000325 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000326 info.securityLevel,
327 attested_key_cert_chain[0].encodedCertificate));
328
329 // Attestation by itself is not valid (last entry is not self-signed).
330 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
331
332 // The signature over the attested key should correspond to the P256 public key.
333 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
334 ASSERT_TRUE(key_cert.get());
335 EVP_PKEY_Ptr signing_pubkey;
336 p256_pub_key(coseKeyData, &signing_pubkey);
337 ASSERT_TRUE(signing_pubkey.get());
338
339 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
340 << "Verification of attested certificate failed "
341 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600342}
343
344/**
345 * Generate and validate a test-mode key.
346 */
Max Bires126869a2021-02-21 18:32:59 -0800347TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600348 MacedPublicKey macedPubKey;
349 bytevec privateKeyBlob;
350 bool testMode = true;
351 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
352 ASSERT_TRUE(status.isOk());
353
David Drysdalec8400772021-03-11 12:35:11 +0000354 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600355}
356
357class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
358 protected:
David Drysdalec8400772021-03-11 12:35:11 +0000359 CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(32)) {
Seth Moore19acbe92021-06-23 15:15:52 -0700360 generateTestEekChain(3);
David Drysdalecceca9f2021-03-12 15:49:47 +0000361 }
362
Seth Moore19acbe92021-06-23 15:15:52 -0700363 void generateTestEekChain(size_t eekLength) {
David Drysdalecceca9f2021-03-12 15:49:47 +0000364 auto chain = generateEekChain(eekLength, eekId_);
Shawn Willden274bb552020-09-30 22:39:22 -0600365 EXPECT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700366 if (chain) testEekChain_ = chain.moveValue();
367 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600368 }
369
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
David Drysdalec8400772021-03-11 12:35:11 +0000379 vector<uint8_t> payload_value;
380 check_maced_pubkey(key, testMode, &payload_value);
381 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600382 }
383 }
384
David Drysdalef6fc5a62021-03-31 16:14:31 +0100385 void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
Seth Moore42c11332021-07-02 15:38:17 -0700386 const bytevec& keysToSignMac, const ProtectedData& protectedData,
387 std::vector<BccEntryData>* bccOutput = nullptr) {
David Drysdalec8400772021-03-11 12:35:11 +0000388 auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
389 ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
390 ASSERT_TRUE(parsedProtectedData->asArray());
391 ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
392
393 auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
394 ASSERT_TRUE(senderPubkey) << senderPubkey.message();
395 EXPECT_EQ(senderPubkey->second, eekId_);
396
Seth Moore19acbe92021-06-23 15:15:52 -0700397 auto sessionKey =
398 x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
399 senderPubkey->first, false /* senderIsA */);
David Drysdalec8400772021-03-11 12:35:11 +0000400 ASSERT_TRUE(sessionKey) << sessionKey.message();
401
402 auto protectedDataPayload =
403 decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
404 ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
405
406 auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
407 ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
408 ASSERT_TRUE(parsedPayload->asArray());
409 EXPECT_EQ(parsedPayload->asArray()->size(), 2U);
410
411 auto& signedMac = parsedPayload->asArray()->get(0);
412 auto& bcc = parsedPayload->asArray()->get(1);
413 ASSERT_TRUE(signedMac && signedMac->asArray());
414 ASSERT_TRUE(bcc && bcc->asArray());
415
416 // BCC is [ pubkey, + BccEntry]
417 auto bccContents = validateBcc(bcc->asArray());
418 ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
419 ASSERT_GT(bccContents->size(), 0U);
420
David Drysdalef6fc5a62021-03-31 16:14:31 +0100421 auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
422 ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
423 ASSERT_TRUE(deviceInfoMap->asMap());
Max Bires8c255e62022-02-02 12:03:28 -0800424 checkDeviceInfo(deviceInfoMap->asMap(), deviceInfo.deviceInfo);
David Drysdalec8400772021-03-11 12:35:11 +0000425 auto& signingKey = bccContents->back().pubKey;
Max Birese74f0bc2022-03-16 13:58:27 -0700426 deviceInfoMap->asMap()->canonicalize();
Seth Moore798188a2021-06-17 10:58:27 -0700427 auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
David Drysdalef6fc5a62021-03-31 16:14:31 +0100428 cppbor::Array() // SignedMacAad
David Drysdalec8400772021-03-11 12:35:11 +0000429 .add(challenge_)
David Drysdalef6fc5a62021-03-31 16:14:31 +0100430 .add(std::move(deviceInfoMap))
Max Bires8dff0b32021-05-26 13:05:09 -0700431 .add(keysToSignMac)
David Drysdalec8400772021-03-11 12:35:11 +0000432 .encode());
433 ASSERT_TRUE(macKey) << macKey.message();
434
435 auto coseMac0 = cppbor::Array()
436 .add(cppbor::Map() // protected
437 .add(ALGORITHM, HMAC_256)
438 .canonicalize()
439 .encode())
440 .add(cppbor::Map()) // unprotected
441 .add(keysToSign.encode()) // payload (keysToSign)
442 .add(keysToSignMac); // tag
443
444 auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
445 ASSERT_TRUE(macPayload) << macPayload.message();
Seth Moore42c11332021-07-02 15:38:17 -0700446
447 if (bccOutput) {
448 *bccOutput = std::move(*bccContents);
449 }
David Drysdalec8400772021-03-11 12:35:11 +0000450 }
451
Max Bires8b09c502022-01-30 20:03:16 -0800452 void checkType(const cppbor::Map* devInfo, uint8_t majorType, std::string entryName) {
453 const auto& val = devInfo->get(entryName);
454 ASSERT_TRUE(val) << entryName << " does not exist";
455 ASSERT_EQ(val->type(), majorType) << entryName << " has the wrong type.";
456 switch (majorType) {
457 case cppbor::TSTR:
Max Birese74f0bc2022-03-16 13:58:27 -0700458 EXPECT_GT(val->asTstr()->value().size(), 0);
Max Bires8b09c502022-01-30 20:03:16 -0800459 break;
460 case cppbor::BSTR:
Max Birese74f0bc2022-03-16 13:58:27 -0700461 EXPECT_GT(val->asBstr()->value().size(), 0);
Max Bires8b09c502022-01-30 20:03:16 -0800462 break;
463 default:
464 break;
465 }
466 }
467
Max Bires8c255e62022-02-02 12:03:28 -0800468 void checkDeviceInfo(const cppbor::Map* deviceInfo, bytevec deviceInfoBytes) {
Max Birese74f0bc2022-03-16 13:58:27 -0700469 EXPECT_EQ(deviceInfo->clone()->asMap()->canonicalize().encode(), deviceInfoBytes)
470 << "DeviceInfo ordering is non-canonical.";
Max Bires8b09c502022-01-30 20:03:16 -0800471 const auto& version = deviceInfo->get("version");
472 ASSERT_TRUE(version);
473 ASSERT_TRUE(version->asUint());
474 RpcHardwareInfo info;
475 provisionable_->getHardwareInfo(&info);
476 ASSERT_EQ(version->asUint()->value(), info.versionNumber);
477 std::set<std::string> allowList;
478 switch (version->asUint()->value()) {
479 // These fields became mandated in version 2.
480 case 2:
481 checkType(deviceInfo, cppbor::TSTR, "brand");
482 checkType(deviceInfo, cppbor::TSTR, "manufacturer");
483 checkType(deviceInfo, cppbor::TSTR, "product");
484 checkType(deviceInfo, cppbor::TSTR, "model");
485 checkType(deviceInfo, cppbor::TSTR, "device");
486 // TODO: Refactor the KeyMint code that validates these fields and include it here.
487 checkType(deviceInfo, cppbor::TSTR, "vb_state");
488 allowList = getAllowedVbStates();
Max Birese74f0bc2022-03-16 13:58:27 -0700489 EXPECT_NE(allowList.find(deviceInfo->get("vb_state")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800490 allowList.end());
491 checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
492 allowList = getAllowedBootloaderStates();
Max Birese74f0bc2022-03-16 13:58:27 -0700493 EXPECT_NE(allowList.find(deviceInfo->get("bootloader_state")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800494 allowList.end());
495 checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
Max Bires8b09c502022-01-30 20:03:16 -0800496 checkType(deviceInfo, cppbor::UINT, "system_patch_level");
497 checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
498 checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
499 checkType(deviceInfo, cppbor::UINT, "fused");
Max Birese74f0bc2022-03-16 13:58:27 -0700500 EXPECT_LT(deviceInfo->get("fused")->asUint()->value(), 2); // Must be 0 or 1.
Max Bires8b09c502022-01-30 20:03:16 -0800501 checkType(deviceInfo, cppbor::TSTR, "security_level");
502 allowList = getAllowedSecurityLevels();
Max Birese74f0bc2022-03-16 13:58:27 -0700503 EXPECT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800504 allowList.end());
Max Bires9c28a1e2022-02-03 19:14:06 -0800505 if (deviceInfo->get("security_level")->asTstr()->value() == "tee") {
506 checkType(deviceInfo, cppbor::TSTR, "os_version");
507 }
Max Bires8b09c502022-01-30 20:03:16 -0800508 break;
509 case 1:
510 checkType(deviceInfo, cppbor::TSTR, "security_level");
511 allowList = getAllowedSecurityLevels();
Max Birese74f0bc2022-03-16 13:58:27 -0700512 EXPECT_NE(allowList.find(deviceInfo->get("security_level")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800513 allowList.end());
514 if (version->asUint()->value() == 1) {
515 checkType(deviceInfo, cppbor::TSTR, "att_id_state");
516 allowList = getAllowedAttIdStates();
Max Birese74f0bc2022-03-16 13:58:27 -0700517 EXPECT_NE(allowList.find(deviceInfo->get("att_id_state")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800518 allowList.end());
519 }
520 break;
521 default:
522 FAIL() << "Unrecognized version: " << version->asUint()->value();
523 }
524 }
525
Shawn Willden274bb552020-09-30 22:39:22 -0600526 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700527 size_t testEekLength_;
528 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000529 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600530 std::vector<MacedPublicKey> keysToSign_;
531 cppbor::Array cborKeysToSign_;
532};
533
534/**
535 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
536 * content.
537 */
Max Bires126869a2021-02-21 18:32:59 -0800538TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600539 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000540 for (size_t eekLength : {2, 3, 7}) {
541 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700542 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600543
David Drysdalecceca9f2021-03-12 15:49:47 +0000544 bytevec keysToSignMac;
545 DeviceInfo deviceInfo;
546 ProtectedData protectedData;
547 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700548 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000549 &protectedData, &keysToSignMac);
550 ASSERT_TRUE(status.isOk()) << status.getMessage();
551
David Drysdalef6fc5a62021-03-31 16:14:31 +0100552 checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000553 }
Shawn Willden274bb552020-09-30 22:39:22 -0600554}
555
556/**
Seth Moore42c11332021-07-02 15:38:17 -0700557 * Ensure that test mode outputs a unique BCC root key every time we request a
558 * certificate request. Else, it's possible that the test mode API could be used
559 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
560 * device public key multiple times.
561 */
562TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
563 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700564
565 bytevec keysToSignMac;
566 DeviceInfo deviceInfo;
567 ProtectedData protectedData;
568 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700569 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
570 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700571 ASSERT_TRUE(status.isOk()) << status.getMessage();
572
573 std::vector<BccEntryData> firstBcc;
574 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
575 &firstBcc);
576
Seth Moore19acbe92021-06-23 15:15:52 -0700577 status = provisionable_->generateCertificateRequest(
578 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
579 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700580 ASSERT_TRUE(status.isOk()) << status.getMessage();
581
582 std::vector<BccEntryData> secondBcc;
583 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
584 &secondBcc);
585
586 // Verify that none of the keys in the first BCC are repeated in the second one.
587 for (const auto& i : firstBcc) {
588 for (auto& j : secondBcc) {
589 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
590 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
591 }
592 }
593}
594
595/**
Seth Moore19acbe92021-06-23 15:15:52 -0700596 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
597 * is not run by default. Not all devices are GMS devices, and therefore they do not all
598 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600599 */
Seth Moore19acbe92021-06-23 15:15:52 -0700600TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600601 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000602
Seth Moore19acbe92021-06-23 15:15:52 -0700603 bytevec keysToSignMac;
604 DeviceInfo deviceInfo;
605 ProtectedData protectedData;
606 auto status = provisionable_->generateCertificateRequest(
607 testMode, {} /* keysToSign */, getProdEekChain(), challenge_, &deviceInfo,
608 &protectedData, &keysToSignMac);
609 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600610}
611
612/**
613 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
614 */
Max Bires126869a2021-02-21 18:32:59 -0800615TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600616 bool testMode = true;
617 generateKeys(testMode, 4 /* numKeys */);
618
David Drysdalecceca9f2021-03-12 15:49:47 +0000619 for (size_t eekLength : {2, 3, 7}) {
620 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700621 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600622
David Drysdalecceca9f2021-03-12 15:49:47 +0000623 bytevec keysToSignMac;
624 DeviceInfo deviceInfo;
625 ProtectedData protectedData;
626 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700627 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000628 &keysToSignMac);
629 ASSERT_TRUE(status.isOk()) << status.getMessage();
630
David Drysdalef6fc5a62021-03-31 16:14:31 +0100631 checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000632 }
Shawn Willden274bb552020-09-30 22:39:22 -0600633}
634
635/**
Seth Moore19acbe92021-06-23 15:15:52 -0700636 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
637 * is not run by default. Not all devices are GMS devices, and therefore they do not all
638 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600639 */
Seth Moore19acbe92021-06-23 15:15:52 -0700640TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600641 bool testMode = false;
642 generateKeys(testMode, 4 /* numKeys */);
643
Seth Moore19acbe92021-06-23 15:15:52 -0700644 bytevec keysToSignMac;
645 DeviceInfo deviceInfo;
646 ProtectedData protectedData;
647 auto status = provisionable_->generateCertificateRequest(
648 testMode, keysToSign_, getProdEekChain(), challenge_, &deviceInfo, &protectedData,
649 &keysToSignMac);
650 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000651}
652
653/**
David Drysdalee99ed862021-03-15 16:43:06 +0000654 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
655 */
656TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
657 bool testMode = true;
658 generateKeys(testMode, 1 /* numKeys */);
659 MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
660
661 bytevec keysToSignMac;
662 DeviceInfo deviceInfo;
663 ProtectedData protectedData;
664 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700665 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
666 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000667 ASSERT_FALSE(status.isOk()) << status.getMessage();
668 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
669}
670
671/**
672 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
673 */
674TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700675 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000676 generateKeys(testMode, 1 /* numKeys */);
677 MacedPublicKey keyWithCorruptMac = corrupt_maced_key(keysToSign_[0]).moveValue();
678
679 bytevec keysToSignMac;
680 DeviceInfo deviceInfo;
681 ProtectedData protectedData;
682 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700683 testMode, {keyWithCorruptMac}, getProdEekChain(), challenge_, &deviceInfo,
684 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000685 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700686 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000687}
688
689/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000690 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
691 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000692 */
693TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
694 bool testMode = false;
695 generateKeys(testMode, 4 /* numKeys */);
696
Seth Moore19acbe92021-06-23 15:15:52 -0700697 auto prodEekChain = getProdEekChain();
698 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
699 ASSERT_NE(parsedChain, nullptr) << parseErr;
700 ASSERT_NE(parsedChain->asArray(), nullptr);
701
702 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
703 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000704 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000705
706 bytevec keysToSignMac;
707 DeviceInfo deviceInfo;
708 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700709 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
710 challenge_, &deviceInfo,
711 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000712 ASSERT_FALSE(status.isOk());
713 ASSERT_EQ(status.getServiceSpecificError(),
714 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
715 }
716}
717
718/**
719 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
720 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000721 */
722TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
723 bool testMode = false;
724 generateKeys(testMode, 4 /* numKeys */);
725
726 // Build an EEK chain that omits the first self-signed cert.
727 auto truncatedChain = cppbor::Array();
Seth Moore19acbe92021-06-23 15:15:52 -0700728 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain());
David Drysdalecceca9f2021-03-12 15:49:47 +0000729 ASSERT_TRUE(chain);
730 auto eekChain = chain->asArray();
731 ASSERT_NE(eekChain, nullptr);
732 for (size_t ii = 1; ii < eekChain->size(); ii++) {
733 truncatedChain.add(eekChain->get(ii)->clone());
734 }
735
Shawn Willden274bb552020-09-30 22:39:22 -0600736 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700737 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600738 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000739 auto status = provisionable_->generateCertificateRequest(
740 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
741 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600742 ASSERT_FALSE(status.isOk());
743 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
744}
745
746/**
747 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
748 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
749 */
Max Bires126869a2021-02-21 18:32:59 -0800750TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600751 generateKeys(false /* testMode */, 2 /* numKeys */);
752
753 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700754 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600755 ProtectedData protectedData;
Max Biresfdbb9042021-03-23 12:43:38 -0700756 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700757 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700758 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600759 ASSERT_FALSE(status.isOk());
760 ASSERT_EQ(status.getServiceSpecificError(),
761 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
762}
763
764/**
765 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
766 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
767 */
Max Bires126869a2021-02-21 18:32:59 -0800768TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600769 generateKeys(true /* testMode */, 2 /* numKeys */);
770
771 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700772 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600773 ProtectedData protectedData;
774 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700775 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000776 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600777 ASSERT_FALSE(status.isOk());
778 ASSERT_EQ(status.getServiceSpecificError(),
779 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
780}
781
782INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
783
784} // namespace aidl::android::hardware::security::keymint::test