blob: 9b21e4e98b8a8faf3c8ae98fe768e1ec7a7562d5 [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
Seth Mooref1f62152022-09-13 12:00:30 -070017#include <memory>
Seth Moore2fc6f832022-09-13 16:10:11 -070018#include <string>
Shawn Willden274bb552020-09-30 22:39:22 -060019#define LOG_TAG "VtsRemotelyProvisionableComponentTests"
20
Max Bires261a0492021-04-19 18:55:56 -070021#include <AndroidRemotelyProvisionedComponentDevice.h>
Shawn Willden274bb552020-09-30 22:39:22 -060022#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
23#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
24#include <android/binder_manager.h>
Seth Moorefc86bf42021-12-09 14:07:04 -080025#include <binder/IServiceManager.h>
Shawn Willden274bb552020-09-30 22:39:22 -060026#include <cppbor_parse.h>
Shawn Willden274bb552020-09-30 22:39:22 -060027#include <gmock/gmock.h>
Max Bires9704ff62021-04-07 11:12:01 -070028#include <keymaster/cppcose/cppcose.h>
Shawn Willden274bb552020-09-30 22:39:22 -060029#include <keymaster/keymaster_configuration.h>
David Drysdalef0d516d2021-03-22 07:51:43 +000030#include <keymint_support/authorization_set.h>
31#include <openssl/ec.h>
32#include <openssl/ec_key.h>
33#include <openssl/x509.h>
Shawn Willden274bb552020-09-30 22:39:22 -060034#include <remote_prov/remote_prov_utils.h>
Max Bires757ed422022-09-07 16:20:31 -070035#include <optional>
Seth Moorefc86bf42021-12-09 14:07:04 -080036#include <set>
Seth Moore42c11332021-07-02 15:38:17 -070037#include <vector>
Shawn Willden274bb552020-09-30 22:39:22 -060038
David Drysdalef0d516d2021-03-22 07:51:43 +000039#include "KeyMintAidlTestBase.h"
40
Shawn Willden274bb552020-09-30 22:39:22 -060041namespace aidl::android::hardware::security::keymint::test {
42
43using ::std::string;
44using ::std::vector;
45
46namespace {
47
Seth Moorefc86bf42021-12-09 14:07:04 -080048constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
49
Shawn Willden274bb552020-09-30 22:39:22 -060050#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070051 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060052 INSTANTIATE_TEST_SUITE_P( \
53 PerInstance, name, \
54 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
55 ::android::PrintInstanceNameToString)
56
Seth Moorefc86bf42021-12-09 14:07:04 -080057using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060058using bytevec = std::vector<uint8_t>;
59using testing::MatchesRegex;
60using namespace remote_prov;
61using namespace keymaster;
62
63bytevec string_to_bytevec(const char* s) {
64 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
65 return bytevec(p, p + strlen(s));
66}
67
David Drysdalee99ed862021-03-15 16:43:06 +000068ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
69 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
70 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
71 return "COSE Mac0 parse failed";
72 }
73 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
74 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
75 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
76 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
77 if (!protParams || !unprotParams || !payload || !tag) {
78 return "Invalid COSE_Sign1: missing content";
79 }
80 auto corruptMac0 = cppbor::Array();
81 corruptMac0.add(protParams->clone());
82 corruptMac0.add(unprotParams->clone());
83 corruptMac0.add(payload->clone());
84 vector<uint8_t> tagData = tag->value();
85 tagData[0] ^= 0x08;
86 tagData[tagData.size() - 1] ^= 0x80;
87 corruptMac0.add(cppbor::Bstr(tagData));
88
89 return MacedPublicKey{corruptMac0.encode()};
90}
91
David Drysdalecceca9f2021-03-12 15:49:47 +000092ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
93 if (coseSign1->size() != kCoseSign1EntryCount) {
94 return "Invalid COSE_Sign1, wrong entry count";
95 }
96 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
97 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
98 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
99 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
100 if (!protectedParams || !unprotectedParams || !payload || !signature) {
101 return "Invalid COSE_Sign1: missing content";
102 }
103
104 auto corruptSig = cppbor::Array();
105 corruptSig.add(protectedParams->clone());
106 corruptSig.add(unprotectedParams->clone());
107 corruptSig.add(payload->clone());
108 vector<uint8_t> sigData = signature->value();
109 sigData[0] ^= 0x08;
110 corruptSig.add(cppbor::Bstr(sigData));
111
112 return std::move(corruptSig);
113}
114
Seth Moore19acbe92021-06-23 15:15:52 -0700115ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
116 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000117 if (!chain || !chain->asArray()) {
118 return "EekChain parse failed";
119 }
120
121 cppbor::Array* eekChain = chain->asArray();
122 if (which >= eekChain->size()) {
123 return "selected sig out of range";
124 }
125 auto corruptChain = cppbor::Array();
126
127 for (int ii = 0; ii < eekChain->size(); ++ii) {
128 if (ii == which) {
129 auto sig = corrupt_sig(eekChain->get(which)->asArray());
130 if (!sig) {
131 return "Failed to build corrupted signature" + sig.moveMessage();
132 }
133 corruptChain.add(sig.moveValue());
134 } else {
135 corruptChain.add(eekChain->get(ii)->clone());
136 }
137 }
Seth Moore19acbe92021-06-23 15:15:52 -0700138 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000139}
140
David Drysdale4d3c2982021-03-31 18:21:40 +0100141string device_suffix(const string& name) {
142 size_t pos = name.find('/');
143 if (pos == string::npos) {
144 return name;
145 }
146 return name.substr(pos + 1);
147}
148
149bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
150 string rp_suffix = device_suffix(rp_name);
151
152 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
153 for (const string& km_name : km_names) {
154 // If the suffix of the KeyMint instance equals the suffix of the
155 // RemotelyProvisionedComponent instance, assume they match.
156 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
157 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
158 *keyMint = IKeyMintDevice::fromBinder(binder);
159 return true;
160 }
161 }
162 return false;
163}
164
Shawn Willden274bb552020-09-30 22:39:22 -0600165} // namespace
166
167class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
168 public:
169 virtual void SetUp() override {
170 if (AServiceManager_isDeclared(GetParam().c_str())) {
171 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
172 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
173 }
174 ASSERT_NE(provisionable_, nullptr);
subrahmanyamanfb213d62022-02-02 23:10:55 +0000175 ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600176 }
177
178 static vector<string> build_params() {
179 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
180 return params;
181 }
182
183 protected:
184 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000185 RpcHardwareInfo rpcHardwareInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600186};
187
Seth Moorefc86bf42021-12-09 14:07:04 -0800188/**
189 * Verify that every implementation reports a different unique id.
190 */
191TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
192 std::set<std::string> uniqueIds;
193 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
194 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
195 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
196 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
197 IRemotelyProvisionedComponent::fromBinder(binder);
198 ASSERT_NE(rpc, nullptr);
199
200 RpcHardwareInfo hwInfo;
201 ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
202
Tri Vodd12c482022-10-12 22:41:28 +0000203 if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800204 ASSERT_TRUE(hwInfo.uniqueId);
205 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
206 EXPECT_TRUE(wasInserted);
207 } else {
208 ASSERT_FALSE(hwInfo.uniqueId);
209 }
210 }
211}
212
213using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
214
215INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
216
217/**
218 * Verify that a valid curve is reported by the implementation.
219 */
220TEST_P(GetHardwareInfoTests, supportsValidCurve) {
221 RpcHardwareInfo hwInfo;
222 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
223
224 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
225 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
226 << "Invalid curve: " << hwInfo.supportedEekCurve;
227}
228
229/**
230 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
231 */
232TEST_P(GetHardwareInfoTests, uniqueId) {
Tri Vodd12c482022-10-12 22:41:28 +0000233 if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800234 return;
235 }
236
237 RpcHardwareInfo hwInfo;
238 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
239 ASSERT_TRUE(hwInfo.uniqueId);
240 EXPECT_GE(hwInfo.uniqueId->size(), 1);
241 EXPECT_LE(hwInfo.uniqueId->size(), 32);
242}
243
Shawn Willden274bb552020-09-30 22:39:22 -0600244using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
245
246INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
247
248/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000249 * Generate and validate a production-mode key. MAC tag can't be verified, but
250 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600251 */
Max Bires126869a2021-02-21 18:32:59 -0800252TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600253 MacedPublicKey macedPubKey;
254 bytevec privateKeyBlob;
255 bool testMode = false;
256 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
257 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000258 vector<uint8_t> coseKeyData;
259 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100260}
261
262/**
263 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
264 */
265TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
266 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
267 std::shared_ptr<IKeyMintDevice> keyMint;
268 if (!matching_keymint_device(GetParam(), &keyMint)) {
269 // No matching IKeyMintDevice.
270 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
271 return;
272 }
273 KeyMintHardwareInfo info;
274 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
275
276 MacedPublicKey macedPubKey;
277 bytevec privateKeyBlob;
278 bool testMode = false;
279 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
280 ASSERT_TRUE(status.isOk());
281 vector<uint8_t> coseKeyData;
282 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
283
David Drysdalef0d516d2021-03-22 07:51:43 +0000284 AttestationKey attestKey;
285 attestKey.keyBlob = std::move(privateKeyBlob);
286 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600287
David Drysdalef0d516d2021-03-22 07:51:43 +0000288 // Generate an ECDSA key that is attested by the generated P256 keypair.
289 AuthorizationSet keyDesc = AuthorizationSetBuilder()
290 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100291 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000292 .AttestationChallenge("foo")
293 .AttestationApplicationId("bar")
294 .Digest(Digest::NONE)
295 .SetDefaultValidity();
296 KeyCreationResult creationResult;
297 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
298 ASSERT_TRUE(result.isOk());
299 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
300 vector<KeyCharacteristics> attested_key_characteristics =
301 std::move(creationResult.keyCharacteristics);
302 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
303 EXPECT_EQ(attested_key_cert_chain.size(), 1);
304
David Drysdale7dff4fc2021-12-10 10:10:52 +0000305 int32_t aidl_version = 0;
306 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000307 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
308 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000309 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000310 info.securityLevel,
311 attested_key_cert_chain[0].encodedCertificate));
312
313 // Attestation by itself is not valid (last entry is not self-signed).
314 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
315
316 // The signature over the attested key should correspond to the P256 public key.
317 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
318 ASSERT_TRUE(key_cert.get());
319 EVP_PKEY_Ptr signing_pubkey;
320 p256_pub_key(coseKeyData, &signing_pubkey);
321 ASSERT_TRUE(signing_pubkey.get());
322
323 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
324 << "Verification of attested certificate failed "
325 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600326}
327
328/**
329 * Generate and validate a test-mode key.
330 */
Max Bires126869a2021-02-21 18:32:59 -0800331TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600332 MacedPublicKey macedPubKey;
333 bytevec privateKeyBlob;
334 bool testMode = true;
335 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
336 ASSERT_TRUE(status.isOk());
337
David Drysdalec8400772021-03-11 12:35:11 +0000338 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600339}
340
341class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
342 protected:
Max Bires89c74882022-03-27 21:06:11 -0700343 CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
David Drysdalecceca9f2021-03-12 15:49:47 +0000344
Seth Moore19acbe92021-06-23 15:15:52 -0700345 void generateTestEekChain(size_t eekLength) {
subrahmanyamanfb213d62022-02-02 23:10:55 +0000346 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
David Drysdale08696a72022-03-10 10:43:25 +0000347 ASSERT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700348 if (chain) testEekChain_ = chain.moveValue();
349 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600350 }
351
352 void generateKeys(bool testMode, size_t numKeys) {
353 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
354 cborKeysToSign_ = cppbor::Array();
355
356 for (auto& key : keysToSign_) {
357 bytevec privateKeyBlob;
358 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
359 ASSERT_TRUE(status.isOk()) << status.getMessage();
360
David Drysdalec8400772021-03-11 12:35:11 +0000361 vector<uint8_t> payload_value;
362 check_maced_pubkey(key, testMode, &payload_value);
363 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600364 }
365 }
366
367 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700368 size_t testEekLength_;
369 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000370 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600371 std::vector<MacedPublicKey> keysToSign_;
372 cppbor::Array cborKeysToSign_;
373};
374
375/**
376 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
377 * content.
378 */
Max Bires126869a2021-02-21 18:32:59 -0800379TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600380 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000381 for (size_t eekLength : {2, 3, 7}) {
382 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700383 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600384
David Drysdalecceca9f2021-03-12 15:49:47 +0000385 bytevec keysToSignMac;
386 DeviceInfo deviceInfo;
387 ProtectedData protectedData;
388 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700389 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000390 &protectedData, &keysToSignMac);
391 ASSERT_TRUE(status.isOk()) << status.getMessage();
392
Seth Moore2fc6f832022-09-13 16:10:11 -0700393 auto result = verifyProductionProtectedData(
394 deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
395 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
396 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000397 }
Shawn Willden274bb552020-09-30 22:39:22 -0600398}
399
400/**
Seth Moore42c11332021-07-02 15:38:17 -0700401 * Ensure that test mode outputs a unique BCC root key every time we request a
402 * certificate request. Else, it's possible that the test mode API could be used
403 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
404 * device public key multiple times.
405 */
406TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
407 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700408
409 bytevec keysToSignMac;
410 DeviceInfo deviceInfo;
411 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000412 generateTestEekChain(3);
Seth Moore42c11332021-07-02 15:38:17 -0700413 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700414 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
415 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700416 ASSERT_TRUE(status.isOk()) << status.getMessage();
417
Seth Moore2fc6f832022-09-13 16:10:11 -0700418 auto firstBcc = verifyProductionProtectedData(
419 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
420 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
421 ASSERT_TRUE(firstBcc) << firstBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700422
Seth Moore19acbe92021-06-23 15:15:52 -0700423 status = provisionable_->generateCertificateRequest(
424 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
425 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700426 ASSERT_TRUE(status.isOk()) << status.getMessage();
427
Seth Moore2fc6f832022-09-13 16:10:11 -0700428 auto secondBcc = verifyProductionProtectedData(
429 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
430 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
431 ASSERT_TRUE(secondBcc) << secondBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700432
433 // Verify that none of the keys in the first BCC are repeated in the second one.
Seth Moore2fc6f832022-09-13 16:10:11 -0700434 for (const auto& i : *firstBcc) {
435 for (auto& j : *secondBcc) {
Seth Moore42c11332021-07-02 15:38:17 -0700436 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
437 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
438 }
439 }
440}
441
442/**
Seth Moore19acbe92021-06-23 15:15:52 -0700443 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
444 * is not run by default. Not all devices are GMS devices, and therefore they do not all
445 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600446 */
Seth Moore19acbe92021-06-23 15:15:52 -0700447TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600448 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000449
Seth Moore19acbe92021-06-23 15:15:52 -0700450 bytevec keysToSignMac;
451 DeviceInfo deviceInfo;
452 ProtectedData protectedData;
453 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000454 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
455 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700456 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600457}
458
459/**
460 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
461 */
Max Bires126869a2021-02-21 18:32:59 -0800462TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600463 bool testMode = true;
464 generateKeys(testMode, 4 /* numKeys */);
465
David Drysdalecceca9f2021-03-12 15:49:47 +0000466 for (size_t eekLength : {2, 3, 7}) {
467 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700468 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600469
David Drysdalecceca9f2021-03-12 15:49:47 +0000470 bytevec keysToSignMac;
471 DeviceInfo deviceInfo;
472 ProtectedData protectedData;
473 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700474 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000475 &keysToSignMac);
476 ASSERT_TRUE(status.isOk()) << status.getMessage();
477
Seth Moore2fc6f832022-09-13 16:10:11 -0700478 auto result = verifyProductionProtectedData(
479 deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
480 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
481 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000482 }
Shawn Willden274bb552020-09-30 22:39:22 -0600483}
484
485/**
Seth Moore19acbe92021-06-23 15:15:52 -0700486 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
487 * is not run by default. Not all devices are GMS devices, and therefore they do not all
488 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600489 */
Seth Moore19acbe92021-06-23 15:15:52 -0700490TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600491 bool testMode = false;
492 generateKeys(testMode, 4 /* numKeys */);
493
Seth Moore19acbe92021-06-23 15:15:52 -0700494 bytevec keysToSignMac;
495 DeviceInfo deviceInfo;
496 ProtectedData protectedData;
497 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000498 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
499 &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700500 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000501}
502
503/**
David Drysdalee99ed862021-03-15 16:43:06 +0000504 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
505 */
506TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
507 bool testMode = true;
508 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000509 auto result = corrupt_maced_key(keysToSign_[0]);
510 ASSERT_TRUE(result) << result.moveMessage();
511 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000512
513 bytevec keysToSignMac;
514 DeviceInfo deviceInfo;
515 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000516 generateTestEekChain(3);
David Drysdalee99ed862021-03-15 16:43:06 +0000517 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700518 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
519 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000520 ASSERT_FALSE(status.isOk()) << status.getMessage();
521 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
522}
523
524/**
525 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
526 */
527TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700528 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000529 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000530 auto result = corrupt_maced_key(keysToSign_[0]);
531 ASSERT_TRUE(result) << result.moveMessage();
532 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000533
534 bytevec keysToSignMac;
535 DeviceInfo deviceInfo;
536 ProtectedData protectedData;
537 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000538 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
539 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000540 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700541 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000542}
543
544/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000545 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
546 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000547 */
548TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
549 bool testMode = false;
550 generateKeys(testMode, 4 /* numKeys */);
551
subrahmanyamanfb213d62022-02-02 23:10:55 +0000552 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
Seth Moore19acbe92021-06-23 15:15:52 -0700553 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
554 ASSERT_NE(parsedChain, nullptr) << parseErr;
555 ASSERT_NE(parsedChain->asArray(), nullptr);
556
557 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
558 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000559 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000560
561 bytevec keysToSignMac;
562 DeviceInfo deviceInfo;
563 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700564 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
565 challenge_, &deviceInfo,
566 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000567 ASSERT_FALSE(status.isOk());
568 ASSERT_EQ(status.getServiceSpecificError(),
569 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
570 }
571}
572
573/**
574 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
575 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000576 */
577TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
578 bool testMode = false;
579 generateKeys(testMode, 4 /* numKeys */);
580
581 // Build an EEK chain that omits the first self-signed cert.
582 auto truncatedChain = cppbor::Array();
subrahmanyamanfb213d62022-02-02 23:10:55 +0000583 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
David Drysdalecceca9f2021-03-12 15:49:47 +0000584 ASSERT_TRUE(chain);
585 auto eekChain = chain->asArray();
586 ASSERT_NE(eekChain, nullptr);
587 for (size_t ii = 1; ii < eekChain->size(); ii++) {
588 truncatedChain.add(eekChain->get(ii)->clone());
589 }
590
Shawn Willden274bb552020-09-30 22:39:22 -0600591 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700592 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600593 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000594 auto status = provisionable_->generateCertificateRequest(
595 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
596 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600597 ASSERT_FALSE(status.isOk());
598 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
599}
600
601/**
602 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
603 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
604 */
Max Bires126869a2021-02-21 18:32:59 -0800605TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600606 generateKeys(false /* testMode */, 2 /* numKeys */);
607
608 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700609 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600610 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000611 generateTestEekChain(3);
Max Biresfdbb9042021-03-23 12:43:38 -0700612 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700613 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700614 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600615 ASSERT_FALSE(status.isOk());
616 ASSERT_EQ(status.getServiceSpecificError(),
617 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
618}
619
620/**
621 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
622 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
623 */
Max Bires126869a2021-02-21 18:32:59 -0800624TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600625 generateKeys(true /* testMode */, 2 /* numKeys */);
626
627 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700628 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600629 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000630 generateTestEekChain(3);
Shawn Willden274bb552020-09-30 22:39:22 -0600631 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700632 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000633 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600634 ASSERT_FALSE(status.isOk());
635 ASSERT_EQ(status.getServiceSpecificError(),
636 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
637}
638
639INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
640
641} // namespace aidl::android::hardware::security::keymint::test