blob: 2e282e0925fe22c7bf3fefbe58e857ed3794f11b [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>
Max Bires757ed422022-09-07 16:20:31 -070033#include <optional>
Seth Moorefc86bf42021-12-09 14:07:04 -080034#include <set>
Seth Moore42c11332021-07-02 15:38:17 -070035#include <vector>
Shawn Willden274bb552020-09-30 22:39:22 -060036
David Drysdalef0d516d2021-03-22 07:51:43 +000037#include "KeyMintAidlTestBase.h"
38
Shawn Willden274bb552020-09-30 22:39:22 -060039namespace aidl::android::hardware::security::keymint::test {
40
41using ::std::string;
42using ::std::vector;
43
44namespace {
45
Seth Moorefc86bf42021-12-09 14:07:04 -080046constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
47
Shawn Willden274bb552020-09-30 22:39:22 -060048#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070049 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060050 INSTANTIATE_TEST_SUITE_P( \
51 PerInstance, name, \
52 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
53 ::android::PrintInstanceNameToString)
54
Seth Moorefc86bf42021-12-09 14:07:04 -080055using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060056using bytevec = std::vector<uint8_t>;
57using testing::MatchesRegex;
58using namespace remote_prov;
59using namespace keymaster;
60
Max Bires8b09c502022-01-30 20:03:16 -080061std::set<std::string> getAllowedVbStates() {
62 return {"green", "yellow", "orange"};
63}
64
65std::set<std::string> getAllowedBootloaderStates() {
66 return {"locked", "unlocked"};
67}
68
69std::set<std::string> getAllowedSecurityLevels() {
70 return {"tee", "strongbox"};
71}
72
73std::set<std::string> getAllowedAttIdStates() {
74 return {"locked", "open"};
75}
76
Max Bires757ed422022-09-07 16:20:31 -070077std::set<std::string> getAttestationIdEntrySet() {
78 return {"brand", "manufacturer", "product", "model", "device"};
79}
80
Shawn Willden274bb552020-09-30 22:39:22 -060081bytevec string_to_bytevec(const char* s) {
82 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
83 return bytevec(p, p + strlen(s));
84}
85
David Drysdalee99ed862021-03-15 16:43:06 +000086ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
87 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
88 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
89 return "COSE Mac0 parse failed";
90 }
91 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
92 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
93 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
94 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
95 if (!protParams || !unprotParams || !payload || !tag) {
96 return "Invalid COSE_Sign1: missing content";
97 }
98 auto corruptMac0 = cppbor::Array();
99 corruptMac0.add(protParams->clone());
100 corruptMac0.add(unprotParams->clone());
101 corruptMac0.add(payload->clone());
102 vector<uint8_t> tagData = tag->value();
103 tagData[0] ^= 0x08;
104 tagData[tagData.size() - 1] ^= 0x80;
105 corruptMac0.add(cppbor::Bstr(tagData));
106
107 return MacedPublicKey{corruptMac0.encode()};
108}
109
David Drysdalecceca9f2021-03-12 15:49:47 +0000110ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
111 if (coseSign1->size() != kCoseSign1EntryCount) {
112 return "Invalid COSE_Sign1, wrong entry count";
113 }
114 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
115 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
116 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
117 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
118 if (!protectedParams || !unprotectedParams || !payload || !signature) {
119 return "Invalid COSE_Sign1: missing content";
120 }
121
122 auto corruptSig = cppbor::Array();
123 corruptSig.add(protectedParams->clone());
124 corruptSig.add(unprotectedParams->clone());
125 corruptSig.add(payload->clone());
126 vector<uint8_t> sigData = signature->value();
127 sigData[0] ^= 0x08;
128 corruptSig.add(cppbor::Bstr(sigData));
129
130 return std::move(corruptSig);
131}
132
Seth Moore19acbe92021-06-23 15:15:52 -0700133ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
134 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000135 if (!chain || !chain->asArray()) {
136 return "EekChain parse failed";
137 }
138
139 cppbor::Array* eekChain = chain->asArray();
140 if (which >= eekChain->size()) {
141 return "selected sig out of range";
142 }
143 auto corruptChain = cppbor::Array();
144
145 for (int ii = 0; ii < eekChain->size(); ++ii) {
146 if (ii == which) {
147 auto sig = corrupt_sig(eekChain->get(which)->asArray());
148 if (!sig) {
149 return "Failed to build corrupted signature" + sig.moveMessage();
150 }
151 corruptChain.add(sig.moveValue());
152 } else {
153 corruptChain.add(eekChain->get(ii)->clone());
154 }
155 }
Seth Moore19acbe92021-06-23 15:15:52 -0700156 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000157}
158
David Drysdale4d3c2982021-03-31 18:21:40 +0100159string device_suffix(const string& name) {
160 size_t pos = name.find('/');
161 if (pos == string::npos) {
162 return name;
163 }
164 return name.substr(pos + 1);
165}
166
167bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
168 string rp_suffix = device_suffix(rp_name);
169
170 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
171 for (const string& km_name : km_names) {
172 // If the suffix of the KeyMint instance equals the suffix of the
173 // RemotelyProvisionedComponent instance, assume they match.
174 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
175 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
176 *keyMint = IKeyMintDevice::fromBinder(binder);
177 return true;
178 }
179 }
180 return false;
181}
182
Shawn Willden274bb552020-09-30 22:39:22 -0600183} // namespace
184
185class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
186 public:
187 virtual void SetUp() override {
188 if (AServiceManager_isDeclared(GetParam().c_str())) {
189 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
190 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
191 }
192 ASSERT_NE(provisionable_, nullptr);
subrahmanyamanfb213d62022-02-02 23:10:55 +0000193 ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600194 }
195
196 static vector<string> build_params() {
197 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
198 return params;
199 }
200
201 protected:
202 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000203 RpcHardwareInfo rpcHardwareInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600204};
205
Seth Moorefc86bf42021-12-09 14:07:04 -0800206/**
207 * Verify that every implementation reports a different unique id.
208 */
209TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
210 std::set<std::string> uniqueIds;
211 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
212 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
213 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
214 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
215 IRemotelyProvisionedComponent::fromBinder(binder);
216 ASSERT_NE(rpc, nullptr);
217
218 RpcHardwareInfo hwInfo;
219 ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
220
221 int32_t version;
222 ASSERT_TRUE(rpc->getInterfaceVersion(&version).isOk());
223 if (version >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
224 ASSERT_TRUE(hwInfo.uniqueId);
225 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
226 EXPECT_TRUE(wasInserted);
227 } else {
228 ASSERT_FALSE(hwInfo.uniqueId);
229 }
230 }
231}
232
233using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
234
235INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
236
237/**
238 * Verify that a valid curve is reported by the implementation.
239 */
240TEST_P(GetHardwareInfoTests, supportsValidCurve) {
241 RpcHardwareInfo hwInfo;
242 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
243
244 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
245 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
246 << "Invalid curve: " << hwInfo.supportedEekCurve;
247}
248
249/**
250 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
251 */
252TEST_P(GetHardwareInfoTests, uniqueId) {
253 int32_t version;
254 ASSERT_TRUE(provisionable_->getInterfaceVersion(&version).isOk());
255
256 if (version < VERSION_WITH_UNIQUE_ID_SUPPORT) {
257 return;
258 }
259
260 RpcHardwareInfo hwInfo;
261 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
262 ASSERT_TRUE(hwInfo.uniqueId);
263 EXPECT_GE(hwInfo.uniqueId->size(), 1);
264 EXPECT_LE(hwInfo.uniqueId->size(), 32);
265}
266
Shawn Willden274bb552020-09-30 22:39:22 -0600267using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
268
269INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
270
271/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000272 * Generate and validate a production-mode key. MAC tag can't be verified, but
273 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600274 */
Max Bires126869a2021-02-21 18:32:59 -0800275TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600276 MacedPublicKey macedPubKey;
277 bytevec privateKeyBlob;
278 bool testMode = false;
279 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
280 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000281 vector<uint8_t> coseKeyData;
282 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100283}
284
285/**
286 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
287 */
288TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
289 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
290 std::shared_ptr<IKeyMintDevice> keyMint;
291 if (!matching_keymint_device(GetParam(), &keyMint)) {
292 // No matching IKeyMintDevice.
293 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
294 return;
295 }
296 KeyMintHardwareInfo info;
297 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
298
299 MacedPublicKey macedPubKey;
300 bytevec privateKeyBlob;
301 bool testMode = false;
302 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
303 ASSERT_TRUE(status.isOk());
304 vector<uint8_t> coseKeyData;
305 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
306
David Drysdalef0d516d2021-03-22 07:51:43 +0000307 AttestationKey attestKey;
308 attestKey.keyBlob = std::move(privateKeyBlob);
309 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600310
David Drysdalef0d516d2021-03-22 07:51:43 +0000311 // Generate an ECDSA key that is attested by the generated P256 keypair.
312 AuthorizationSet keyDesc = AuthorizationSetBuilder()
313 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100314 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000315 .AttestationChallenge("foo")
316 .AttestationApplicationId("bar")
317 .Digest(Digest::NONE)
318 .SetDefaultValidity();
319 KeyCreationResult creationResult;
320 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
321 ASSERT_TRUE(result.isOk());
322 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
323 vector<KeyCharacteristics> attested_key_characteristics =
324 std::move(creationResult.keyCharacteristics);
325 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
326 EXPECT_EQ(attested_key_cert_chain.size(), 1);
327
David Drysdale7dff4fc2021-12-10 10:10:52 +0000328 int32_t aidl_version = 0;
329 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000330 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
331 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000332 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000333 info.securityLevel,
334 attested_key_cert_chain[0].encodedCertificate));
335
336 // Attestation by itself is not valid (last entry is not self-signed).
337 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
338
339 // The signature over the attested key should correspond to the P256 public key.
340 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
341 ASSERT_TRUE(key_cert.get());
342 EVP_PKEY_Ptr signing_pubkey;
343 p256_pub_key(coseKeyData, &signing_pubkey);
344 ASSERT_TRUE(signing_pubkey.get());
345
346 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
347 << "Verification of attested certificate failed "
348 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600349}
350
351/**
352 * Generate and validate a test-mode key.
353 */
Max Bires126869a2021-02-21 18:32:59 -0800354TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600355 MacedPublicKey macedPubKey;
356 bytevec privateKeyBlob;
357 bool testMode = true;
358 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
359 ASSERT_TRUE(status.isOk());
360
David Drysdalec8400772021-03-11 12:35:11 +0000361 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600362}
363
364class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
365 protected:
Max Bires89c74882022-03-27 21:06:11 -0700366 CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
David Drysdalecceca9f2021-03-12 15:49:47 +0000367
Seth Moore19acbe92021-06-23 15:15:52 -0700368 void generateTestEekChain(size_t eekLength) {
subrahmanyamanfb213d62022-02-02 23:10:55 +0000369 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
David Drysdale08696a72022-03-10 10:43:25 +0000370 ASSERT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700371 if (chain) testEekChain_ = chain.moveValue();
372 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600373 }
374
375 void generateKeys(bool testMode, size_t numKeys) {
376 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
377 cborKeysToSign_ = cppbor::Array();
378
379 for (auto& key : keysToSign_) {
380 bytevec privateKeyBlob;
381 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
382 ASSERT_TRUE(status.isOk()) << status.getMessage();
383
David Drysdalec8400772021-03-11 12:35:11 +0000384 vector<uint8_t> payload_value;
385 check_maced_pubkey(key, testMode, &payload_value);
386 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600387 }
388 }
389
subrahmanyamanfb213d62022-02-02 23:10:55 +0000390 ErrMsgOr<bytevec> getSessionKey(ErrMsgOr<std::pair<bytevec, bytevec>>& senderPubkey) {
391 if (rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_25519 ||
392 rpcHardwareInfo.supportedEekCurve == RpcHardwareInfo::CURVE_NONE) {
393 return x25519_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
394 senderPubkey->first, false /* senderIsA */);
395 } else {
396 return ECDH_HKDF_DeriveKey(testEekChain_.last_pubkey, testEekChain_.last_privkey,
397 senderPubkey->first, false /* senderIsA */);
398 }
399 }
400
David Drysdalef6fc5a62021-03-31 16:14:31 +0100401 void checkProtectedData(const DeviceInfo& deviceInfo, const cppbor::Array& keysToSign,
Seth Moore42c11332021-07-02 15:38:17 -0700402 const bytevec& keysToSignMac, const ProtectedData& protectedData,
403 std::vector<BccEntryData>* bccOutput = nullptr) {
David Drysdalec8400772021-03-11 12:35:11 +0000404 auto [parsedProtectedData, _, protDataErrMsg] = cppbor::parse(protectedData.protectedData);
405 ASSERT_TRUE(parsedProtectedData) << protDataErrMsg;
406 ASSERT_TRUE(parsedProtectedData->asArray());
407 ASSERT_EQ(parsedProtectedData->asArray()->size(), kCoseEncryptEntryCount);
408
409 auto senderPubkey = getSenderPubKeyFromCoseEncrypt(parsedProtectedData);
410 ASSERT_TRUE(senderPubkey) << senderPubkey.message();
411 EXPECT_EQ(senderPubkey->second, eekId_);
412
subrahmanyamanfb213d62022-02-02 23:10:55 +0000413 auto sessionKey = getSessionKey(senderPubkey);
David Drysdalec8400772021-03-11 12:35:11 +0000414 ASSERT_TRUE(sessionKey) << sessionKey.message();
415
416 auto protectedDataPayload =
417 decryptCoseEncrypt(*sessionKey, parsedProtectedData.get(), bytevec{} /* aad */);
418 ASSERT_TRUE(protectedDataPayload) << protectedDataPayload.message();
419
420 auto [parsedPayload, __, payloadErrMsg] = cppbor::parse(*protectedDataPayload);
421 ASSERT_TRUE(parsedPayload) << "Failed to parse payload: " << payloadErrMsg;
422 ASSERT_TRUE(parsedPayload->asArray());
subrahmanyamanfb213d62022-02-02 23:10:55 +0000423 // Strongbox may contain additional certificate chain.
424 EXPECT_LE(parsedPayload->asArray()->size(), 3U);
David Drysdalec8400772021-03-11 12:35:11 +0000425
426 auto& signedMac = parsedPayload->asArray()->get(0);
427 auto& bcc = parsedPayload->asArray()->get(1);
428 ASSERT_TRUE(signedMac && signedMac->asArray());
429 ASSERT_TRUE(bcc && bcc->asArray());
430
431 // BCC is [ pubkey, + BccEntry]
432 auto bccContents = validateBcc(bcc->asArray());
433 ASSERT_TRUE(bccContents) << "\n" << bccContents.message() << "\n" << prettyPrint(bcc.get());
434 ASSERT_GT(bccContents->size(), 0U);
435
David Drysdalef6fc5a62021-03-31 16:14:31 +0100436 auto [deviceInfoMap, __2, deviceInfoErrMsg] = cppbor::parse(deviceInfo.deviceInfo);
437 ASSERT_TRUE(deviceInfoMap) << "Failed to parse deviceInfo: " << deviceInfoErrMsg;
438 ASSERT_TRUE(deviceInfoMap->asMap());
Max Bires757ed422022-09-07 16:20:31 -0700439 checkDeviceInfo(*deviceInfoMap->asMap(), deviceInfo.deviceInfo);
David Drysdalec8400772021-03-11 12:35:11 +0000440 auto& signingKey = bccContents->back().pubKey;
Max Birese74f0bc2022-03-16 13:58:27 -0700441 deviceInfoMap->asMap()->canonicalize();
Seth Moore798188a2021-06-17 10:58:27 -0700442 auto macKey = verifyAndParseCoseSign1(signedMac->asArray(), signingKey,
David Drysdalef6fc5a62021-03-31 16:14:31 +0100443 cppbor::Array() // SignedMacAad
David Drysdalec8400772021-03-11 12:35:11 +0000444 .add(challenge_)
David Drysdalef6fc5a62021-03-31 16:14:31 +0100445 .add(std::move(deviceInfoMap))
Max Bires8dff0b32021-05-26 13:05:09 -0700446 .add(keysToSignMac)
David Drysdalec8400772021-03-11 12:35:11 +0000447 .encode());
448 ASSERT_TRUE(macKey) << macKey.message();
449
450 auto coseMac0 = cppbor::Array()
451 .add(cppbor::Map() // protected
452 .add(ALGORITHM, HMAC_256)
453 .canonicalize()
454 .encode())
455 .add(cppbor::Map()) // unprotected
456 .add(keysToSign.encode()) // payload (keysToSign)
457 .add(keysToSignMac); // tag
458
459 auto macPayload = verifyAndParseCoseMac0(&coseMac0, *macKey);
460 ASSERT_TRUE(macPayload) << macPayload.message();
Seth Moore42c11332021-07-02 15:38:17 -0700461
462 if (bccOutput) {
463 *bccOutput = std::move(*bccContents);
464 }
David Drysdalec8400772021-03-11 12:35:11 +0000465 }
466
Max Bires757ed422022-09-07 16:20:31 -0700467 std::optional<std::string> assertAttribute(const cppbor::Map& devInfo,
468 cppbor::MajorType majorType, std::string entryName) {
469 const auto& val = devInfo.get(entryName);
470 if (!val) return entryName + " is missing.\n";
471 if (val->type() != majorType) return entryName + " has the wrong type.\n";
Max Bires8b09c502022-01-30 20:03:16 -0800472 switch (majorType) {
473 case cppbor::TSTR:
Max Bires757ed422022-09-07 16:20:31 -0700474 if (val->asTstr()->value().size() <= 0) {
475 return entryName + " is present but the value is empty.\n";
476 }
Max Bires8b09c502022-01-30 20:03:16 -0800477 break;
478 case cppbor::BSTR:
Max Bires757ed422022-09-07 16:20:31 -0700479 if (val->asBstr()->value().size() <= 0) {
480 return entryName + " is present but the value is empty.\n";
481 }
Max Bires8b09c502022-01-30 20:03:16 -0800482 break;
483 default:
484 break;
485 }
Max Bires757ed422022-09-07 16:20:31 -0700486 return {};
Max Bires8b09c502022-01-30 20:03:16 -0800487 }
488
Max Bires757ed422022-09-07 16:20:31 -0700489 void checkType(const cppbor::Map& devInfo, cppbor::MajorType majorType, std::string entryName) {
490 if (auto error = assertAttribute(devInfo, majorType, entryName)) {
491 FAIL() << *error;
492 }
493 }
494
495 void checkDeviceInfo(const cppbor::Map& deviceInfo, bytevec deviceInfoBytes) {
496 EXPECT_EQ(deviceInfo.clone()->asMap()->canonicalize().encode(), deviceInfoBytes)
Max Birese74f0bc2022-03-16 13:58:27 -0700497 << "DeviceInfo ordering is non-canonical.";
Max Bires757ed422022-09-07 16:20:31 -0700498 const auto& version = deviceInfo.get("version");
Max Bires8b09c502022-01-30 20:03:16 -0800499 ASSERT_TRUE(version);
500 ASSERT_TRUE(version->asUint());
501 RpcHardwareInfo info;
502 provisionable_->getHardwareInfo(&info);
503 ASSERT_EQ(version->asUint()->value(), info.versionNumber);
504 std::set<std::string> allowList;
Max Bires757ed422022-09-07 16:20:31 -0700505 std::string problemEntries;
Max Bires8b09c502022-01-30 20:03:16 -0800506 switch (version->asUint()->value()) {
507 // These fields became mandated in version 2.
508 case 2:
Max Bires757ed422022-09-07 16:20:31 -0700509 for (auto attId : getAttestationIdEntrySet()) {
510 if (auto errMsg = assertAttribute(deviceInfo, cppbor::TSTR, attId)) {
511 problemEntries += *errMsg;
512 }
513 }
514 EXPECT_EQ("", problemEntries)
515 << problemEntries
516 << "Attestation IDs are missing or malprovisioned. If this test is being "
517 "run against an early proto or EVT build, this error is probably WAI "
518 "and indicates that Device IDs were not provisioned in the factory. If "
519 "this error is returned on a DVT or later build revision, then "
520 "something is likely wrong with the factory provisioning process.";
Max Bires8b09c502022-01-30 20:03:16 -0800521 // TODO: Refactor the KeyMint code that validates these fields and include it here.
522 checkType(deviceInfo, cppbor::TSTR, "vb_state");
523 allowList = getAllowedVbStates();
Max Bires757ed422022-09-07 16:20:31 -0700524 EXPECT_NE(allowList.find(deviceInfo.get("vb_state")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800525 allowList.end());
526 checkType(deviceInfo, cppbor::TSTR, "bootloader_state");
527 allowList = getAllowedBootloaderStates();
Max Bires757ed422022-09-07 16:20:31 -0700528 EXPECT_NE(allowList.find(deviceInfo.get("bootloader_state")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800529 allowList.end());
530 checkType(deviceInfo, cppbor::BSTR, "vbmeta_digest");
Max Bires8b09c502022-01-30 20:03:16 -0800531 checkType(deviceInfo, cppbor::UINT, "system_patch_level");
532 checkType(deviceInfo, cppbor::UINT, "boot_patch_level");
533 checkType(deviceInfo, cppbor::UINT, "vendor_patch_level");
534 checkType(deviceInfo, cppbor::UINT, "fused");
Max Bires757ed422022-09-07 16:20:31 -0700535 EXPECT_LT(deviceInfo.get("fused")->asUint()->value(), 2); // Must be 0 or 1.
Max Bires8b09c502022-01-30 20:03:16 -0800536 checkType(deviceInfo, cppbor::TSTR, "security_level");
537 allowList = getAllowedSecurityLevels();
Max Bires757ed422022-09-07 16:20:31 -0700538 EXPECT_NE(allowList.find(deviceInfo.get("security_level")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800539 allowList.end());
Max Bires757ed422022-09-07 16:20:31 -0700540 if (deviceInfo.get("security_level")->asTstr()->value() == "tee") {
Max Bires9c28a1e2022-02-03 19:14:06 -0800541 checkType(deviceInfo, cppbor::TSTR, "os_version");
542 }
Max Bires8b09c502022-01-30 20:03:16 -0800543 break;
544 case 1:
545 checkType(deviceInfo, cppbor::TSTR, "security_level");
546 allowList = getAllowedSecurityLevels();
Max Bires757ed422022-09-07 16:20:31 -0700547 EXPECT_NE(allowList.find(deviceInfo.get("security_level")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800548 allowList.end());
549 if (version->asUint()->value() == 1) {
550 checkType(deviceInfo, cppbor::TSTR, "att_id_state");
551 allowList = getAllowedAttIdStates();
Max Bires757ed422022-09-07 16:20:31 -0700552 EXPECT_NE(allowList.find(deviceInfo.get("att_id_state")->asTstr()->value()),
Max Bires8b09c502022-01-30 20:03:16 -0800553 allowList.end());
554 }
555 break;
556 default:
557 FAIL() << "Unrecognized version: " << version->asUint()->value();
558 }
559 }
560
Shawn Willden274bb552020-09-30 22:39:22 -0600561 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700562 size_t testEekLength_;
563 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000564 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600565 std::vector<MacedPublicKey> keysToSign_;
566 cppbor::Array cborKeysToSign_;
567};
568
569/**
570 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
571 * content.
572 */
Max Bires126869a2021-02-21 18:32:59 -0800573TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600574 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000575 for (size_t eekLength : {2, 3, 7}) {
576 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700577 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600578
David Drysdalecceca9f2021-03-12 15:49:47 +0000579 bytevec keysToSignMac;
580 DeviceInfo deviceInfo;
581 ProtectedData protectedData;
582 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700583 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000584 &protectedData, &keysToSignMac);
585 ASSERT_TRUE(status.isOk()) << status.getMessage();
586
David Drysdalef6fc5a62021-03-31 16:14:31 +0100587 checkProtectedData(deviceInfo, cppbor::Array(), keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000588 }
Shawn Willden274bb552020-09-30 22:39:22 -0600589}
590
591/**
Seth Moore42c11332021-07-02 15:38:17 -0700592 * Ensure that test mode outputs a unique BCC root key every time we request a
593 * certificate request. Else, it's possible that the test mode API could be used
594 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
595 * device public key multiple times.
596 */
597TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
598 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700599
600 bytevec keysToSignMac;
601 DeviceInfo deviceInfo;
602 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000603 generateTestEekChain(3);
Seth Moore42c11332021-07-02 15:38:17 -0700604 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700605 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
606 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700607 ASSERT_TRUE(status.isOk()) << status.getMessage();
608
609 std::vector<BccEntryData> firstBcc;
610 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
611 &firstBcc);
612
Seth Moore19acbe92021-06-23 15:15:52 -0700613 status = provisionable_->generateCertificateRequest(
614 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
615 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700616 ASSERT_TRUE(status.isOk()) << status.getMessage();
617
618 std::vector<BccEntryData> secondBcc;
619 checkProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData,
620 &secondBcc);
621
622 // Verify that none of the keys in the first BCC are repeated in the second one.
623 for (const auto& i : firstBcc) {
624 for (auto& j : secondBcc) {
625 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
626 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
627 }
628 }
629}
630
631/**
Seth Moore19acbe92021-06-23 15:15:52 -0700632 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
633 * is not run by default. Not all devices are GMS devices, and therefore they do not all
634 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600635 */
Seth Moore19acbe92021-06-23 15:15:52 -0700636TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600637 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000638
Seth Moore19acbe92021-06-23 15:15:52 -0700639 bytevec keysToSignMac;
640 DeviceInfo deviceInfo;
641 ProtectedData protectedData;
642 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000643 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
644 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700645 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600646}
647
648/**
649 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
650 */
Max Bires126869a2021-02-21 18:32:59 -0800651TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600652 bool testMode = true;
653 generateKeys(testMode, 4 /* numKeys */);
654
David Drysdalecceca9f2021-03-12 15:49:47 +0000655 for (size_t eekLength : {2, 3, 7}) {
656 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700657 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600658
David Drysdalecceca9f2021-03-12 15:49:47 +0000659 bytevec keysToSignMac;
660 DeviceInfo deviceInfo;
661 ProtectedData protectedData;
662 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700663 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000664 &keysToSignMac);
665 ASSERT_TRUE(status.isOk()) << status.getMessage();
666
David Drysdalef6fc5a62021-03-31 16:14:31 +0100667 checkProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac, protectedData);
David Drysdalecceca9f2021-03-12 15:49:47 +0000668 }
Shawn Willden274bb552020-09-30 22:39:22 -0600669}
670
671/**
Seth Moore19acbe92021-06-23 15:15:52 -0700672 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
673 * is not run by default. Not all devices are GMS devices, and therefore they do not all
674 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600675 */
Seth Moore19acbe92021-06-23 15:15:52 -0700676TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600677 bool testMode = false;
678 generateKeys(testMode, 4 /* numKeys */);
679
Seth Moore19acbe92021-06-23 15:15:52 -0700680 bytevec keysToSignMac;
681 DeviceInfo deviceInfo;
682 ProtectedData protectedData;
683 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000684 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
685 &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700686 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000687}
688
689/**
David Drysdalee99ed862021-03-15 16:43:06 +0000690 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
691 */
692TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
693 bool testMode = true;
694 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000695 auto result = corrupt_maced_key(keysToSign_[0]);
696 ASSERT_TRUE(result) << result.moveMessage();
697 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000698
699 bytevec keysToSignMac;
700 DeviceInfo deviceInfo;
701 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000702 generateTestEekChain(3);
David Drysdalee99ed862021-03-15 16:43:06 +0000703 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700704 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
705 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000706 ASSERT_FALSE(status.isOk()) << status.getMessage();
707 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
708}
709
710/**
711 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
712 */
713TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700714 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000715 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000716 auto result = corrupt_maced_key(keysToSign_[0]);
717 ASSERT_TRUE(result) << result.moveMessage();
718 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000719
720 bytevec keysToSignMac;
721 DeviceInfo deviceInfo;
722 ProtectedData protectedData;
723 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000724 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
725 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000726 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700727 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000728}
729
730/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000731 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
732 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000733 */
734TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
735 bool testMode = false;
736 generateKeys(testMode, 4 /* numKeys */);
737
subrahmanyamanfb213d62022-02-02 23:10:55 +0000738 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
Seth Moore19acbe92021-06-23 15:15:52 -0700739 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
740 ASSERT_NE(parsedChain, nullptr) << parseErr;
741 ASSERT_NE(parsedChain->asArray(), nullptr);
742
743 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
744 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000745 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000746
747 bytevec keysToSignMac;
748 DeviceInfo deviceInfo;
749 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700750 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
751 challenge_, &deviceInfo,
752 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000753 ASSERT_FALSE(status.isOk());
754 ASSERT_EQ(status.getServiceSpecificError(),
755 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
756 }
757}
758
759/**
760 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
761 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000762 */
763TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
764 bool testMode = false;
765 generateKeys(testMode, 4 /* numKeys */);
766
767 // Build an EEK chain that omits the first self-signed cert.
768 auto truncatedChain = cppbor::Array();
subrahmanyamanfb213d62022-02-02 23:10:55 +0000769 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
David Drysdalecceca9f2021-03-12 15:49:47 +0000770 ASSERT_TRUE(chain);
771 auto eekChain = chain->asArray();
772 ASSERT_NE(eekChain, nullptr);
773 for (size_t ii = 1; ii < eekChain->size(); ii++) {
774 truncatedChain.add(eekChain->get(ii)->clone());
775 }
776
Shawn Willden274bb552020-09-30 22:39:22 -0600777 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700778 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600779 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000780 auto status = provisionable_->generateCertificateRequest(
781 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
782 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600783 ASSERT_FALSE(status.isOk());
784 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
785}
786
787/**
788 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
789 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
790 */
Max Bires126869a2021-02-21 18:32:59 -0800791TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600792 generateKeys(false /* testMode */, 2 /* numKeys */);
793
794 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700795 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600796 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000797 generateTestEekChain(3);
Max Biresfdbb9042021-03-23 12:43:38 -0700798 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700799 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700800 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600801 ASSERT_FALSE(status.isOk());
802 ASSERT_EQ(status.getServiceSpecificError(),
803 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
804}
805
806/**
807 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
808 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
809 */
Max Bires126869a2021-02-21 18:32:59 -0800810TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600811 generateKeys(true /* testMode */, 2 /* numKeys */);
812
813 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700814 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600815 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000816 generateTestEekChain(3);
Shawn Willden274bb552020-09-30 22:39:22 -0600817 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700818 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000819 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600820 ASSERT_FALSE(status.isOk());
821 ASSERT_EQ(status.getServiceSpecificError(),
822 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
823}
824
825INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
826
827} // namespace aidl::android::hardware::security::keymint::test