blob: 9f68bfa847f2eca1f2898c30fd90a01d2e937cd1 [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
Seth Moore8f810b12022-12-12 16:51:01 -080021#include <aidl/android/hardware/security/keymint/BnRemotelyProvisionedComponent.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>
Tri Voec50ee12023-02-14 16:29:53 -080026#include <cppbor.h>
Shawn Willden274bb552020-09-30 22:39:22 -060027#include <cppbor_parse.h>
Shawn Willden274bb552020-09-30 22:39:22 -060028#include <gmock/gmock.h>
Max Bires9704ff62021-04-07 11:12:01 -070029#include <keymaster/cppcose/cppcose.h>
Shawn Willden274bb552020-09-30 22:39:22 -060030#include <keymaster/keymaster_configuration.h>
David Drysdalef0d516d2021-03-22 07:51:43 +000031#include <keymint_support/authorization_set.h>
32#include <openssl/ec.h>
33#include <openssl/ec_key.h>
34#include <openssl/x509.h>
Shawn Willden274bb552020-09-30 22:39:22 -060035#include <remote_prov/remote_prov_utils.h>
Max Bires757ed422022-09-07 16:20:31 -070036#include <optional>
Seth Moorefc86bf42021-12-09 14:07:04 -080037#include <set>
Seth Moore42c11332021-07-02 15:38:17 -070038#include <vector>
Shawn Willden274bb552020-09-30 22:39:22 -060039
David Drysdalef0d516d2021-03-22 07:51:43 +000040#include "KeyMintAidlTestBase.h"
41
Shawn Willden274bb552020-09-30 22:39:22 -060042namespace aidl::android::hardware::security::keymint::test {
43
44using ::std::string;
45using ::std::vector;
46
47namespace {
48
Seth Moorefc86bf42021-12-09 14:07:04 -080049constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
Tri Vo0d6204e2022-09-29 16:15:34 -070050constexpr int32_t VERSION_WITHOUT_TEST_MODE = 3;
Seth Moorefc86bf42021-12-09 14:07:04 -080051
Shawn Willden274bb552020-09-30 22:39:22 -060052#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070053 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060054 INSTANTIATE_TEST_SUITE_P( \
55 PerInstance, name, \
56 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
57 ::android::PrintInstanceNameToString)
58
Seth Moorefc86bf42021-12-09 14:07:04 -080059using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060060using bytevec = std::vector<uint8_t>;
61using testing::MatchesRegex;
62using namespace remote_prov;
63using namespace keymaster;
64
65bytevec string_to_bytevec(const char* s) {
66 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
67 return bytevec(p, p + strlen(s));
68}
69
David Drysdalee99ed862021-03-15 16:43:06 +000070ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
71 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
72 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
73 return "COSE Mac0 parse failed";
74 }
75 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
76 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
77 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
78 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
79 if (!protParams || !unprotParams || !payload || !tag) {
80 return "Invalid COSE_Sign1: missing content";
81 }
82 auto corruptMac0 = cppbor::Array();
83 corruptMac0.add(protParams->clone());
84 corruptMac0.add(unprotParams->clone());
85 corruptMac0.add(payload->clone());
86 vector<uint8_t> tagData = tag->value();
87 tagData[0] ^= 0x08;
88 tagData[tagData.size() - 1] ^= 0x80;
89 corruptMac0.add(cppbor::Bstr(tagData));
90
91 return MacedPublicKey{corruptMac0.encode()};
92}
93
David Drysdalecceca9f2021-03-12 15:49:47 +000094ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
95 if (coseSign1->size() != kCoseSign1EntryCount) {
96 return "Invalid COSE_Sign1, wrong entry count";
97 }
98 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
99 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
100 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
101 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
102 if (!protectedParams || !unprotectedParams || !payload || !signature) {
103 return "Invalid COSE_Sign1: missing content";
104 }
105
106 auto corruptSig = cppbor::Array();
107 corruptSig.add(protectedParams->clone());
108 corruptSig.add(unprotectedParams->clone());
109 corruptSig.add(payload->clone());
110 vector<uint8_t> sigData = signature->value();
111 sigData[0] ^= 0x08;
112 corruptSig.add(cppbor::Bstr(sigData));
113
114 return std::move(corruptSig);
115}
116
Seth Moore19acbe92021-06-23 15:15:52 -0700117ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
118 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000119 if (!chain || !chain->asArray()) {
120 return "EekChain parse failed";
121 }
122
123 cppbor::Array* eekChain = chain->asArray();
124 if (which >= eekChain->size()) {
125 return "selected sig out of range";
126 }
127 auto corruptChain = cppbor::Array();
128
129 for (int ii = 0; ii < eekChain->size(); ++ii) {
130 if (ii == which) {
131 auto sig = corrupt_sig(eekChain->get(which)->asArray());
132 if (!sig) {
133 return "Failed to build corrupted signature" + sig.moveMessage();
134 }
135 corruptChain.add(sig.moveValue());
136 } else {
137 corruptChain.add(eekChain->get(ii)->clone());
138 }
139 }
Seth Moore19acbe92021-06-23 15:15:52 -0700140 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000141}
142
David Drysdale4d3c2982021-03-31 18:21:40 +0100143string device_suffix(const string& name) {
144 size_t pos = name.find('/');
145 if (pos == string::npos) {
146 return name;
147 }
148 return name.substr(pos + 1);
149}
150
151bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
152 string rp_suffix = device_suffix(rp_name);
153
154 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
155 for (const string& km_name : km_names) {
156 // If the suffix of the KeyMint instance equals the suffix of the
157 // RemotelyProvisionedComponent instance, assume they match.
158 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
159 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
160 *keyMint = IKeyMintDevice::fromBinder(binder);
161 return true;
162 }
163 }
164 return false;
165}
166
Shawn Willden274bb552020-09-30 22:39:22 -0600167} // namespace
168
169class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
170 public:
171 virtual void SetUp() override {
172 if (AServiceManager_isDeclared(GetParam().c_str())) {
173 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
174 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
175 }
176 ASSERT_NE(provisionable_, nullptr);
subrahmanyamanfb213d62022-02-02 23:10:55 +0000177 ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600178 }
179
180 static vector<string> build_params() {
181 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
182 return params;
183 }
184
185 protected:
186 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000187 RpcHardwareInfo rpcHardwareInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600188};
189
Seth Moorefc86bf42021-12-09 14:07:04 -0800190/**
191 * Verify that every implementation reports a different unique id.
192 */
193TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
194 std::set<std::string> uniqueIds;
195 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
196 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
197 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
198 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
199 IRemotelyProvisionedComponent::fromBinder(binder);
200 ASSERT_NE(rpc, nullptr);
201
202 RpcHardwareInfo hwInfo;
203 ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
204
Tri Vodd12c482022-10-12 22:41:28 +0000205 if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800206 ASSERT_TRUE(hwInfo.uniqueId);
207 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
208 EXPECT_TRUE(wasInserted);
209 } else {
210 ASSERT_FALSE(hwInfo.uniqueId);
211 }
212 }
213}
214
215using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
216
217INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
218
219/**
220 * Verify that a valid curve is reported by the implementation.
221 */
222TEST_P(GetHardwareInfoTests, supportsValidCurve) {
223 RpcHardwareInfo hwInfo;
224 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
225
226 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
Hasini Gunasinghe666b2712023-01-05 21:35:51 +0000227 // First check for the implementations that supports only IRPC V3+.
228 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
229 bytevec keysToSignMac;
230 DeviceInfo deviceInfo;
231 ProtectedData protectedData;
232 auto status = provisionable_->generateCertificateRequest(false, {}, {}, {}, &deviceInfo,
233 &protectedData, &keysToSignMac);
234 if (!status.isOk() &&
235 (status.getServiceSpecificError() == BnRemotelyProvisionedComponent::STATUS_REMOVED)) {
236 ASSERT_EQ(hwInfo.supportedEekCurve, RpcHardwareInfo::CURVE_NONE)
237 << "Invalid curve: " << hwInfo.supportedEekCurve;
238 return;
239 }
240 }
Seth Moorefc86bf42021-12-09 14:07:04 -0800241 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
242 << "Invalid curve: " << hwInfo.supportedEekCurve;
243}
244
245/**
246 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
247 */
248TEST_P(GetHardwareInfoTests, uniqueId) {
Tri Vodd12c482022-10-12 22:41:28 +0000249 if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800250 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
Tri Vo9cab73c2022-10-28 13:40:24 -0700260/**
261 * Verify implementation supports at least MIN_SUPPORTED_NUM_KEYS_IN_CSR keys in a CSR.
262 */
263TEST_P(GetHardwareInfoTests, supportedNumKeysInCsr) {
264 if (rpcHardwareInfo.versionNumber < VERSION_WITHOUT_TEST_MODE) {
265 return;
266 }
267
268 RpcHardwareInfo hwInfo;
269 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
270 ASSERT_GE(hwInfo.supportedNumKeysInCsr, RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR);
271}
272
Shawn Willden274bb552020-09-30 22:39:22 -0600273using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
274
275INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
276
277/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000278 * Generate and validate a production-mode key. MAC tag can't be verified, but
279 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600280 */
Max Bires126869a2021-02-21 18:32:59 -0800281TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600282 MacedPublicKey macedPubKey;
283 bytevec privateKeyBlob;
284 bool testMode = false;
285 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
286 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000287 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800288 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100289}
290
291/**
292 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
293 */
294TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
295 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
296 std::shared_ptr<IKeyMintDevice> keyMint;
297 if (!matching_keymint_device(GetParam(), &keyMint)) {
298 // No matching IKeyMintDevice.
299 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
300 return;
301 }
302 KeyMintHardwareInfo info;
303 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
304
305 MacedPublicKey macedPubKey;
306 bytevec privateKeyBlob;
307 bool testMode = false;
308 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
309 ASSERT_TRUE(status.isOk());
310 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800311 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100312
David Drysdalef0d516d2021-03-22 07:51:43 +0000313 AttestationKey attestKey;
314 attestKey.keyBlob = std::move(privateKeyBlob);
315 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600316
David Drysdalef0d516d2021-03-22 07:51:43 +0000317 // Generate an ECDSA key that is attested by the generated P256 keypair.
318 AuthorizationSet keyDesc = AuthorizationSetBuilder()
319 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100320 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000321 .AttestationChallenge("foo")
322 .AttestationApplicationId("bar")
323 .Digest(Digest::NONE)
324 .SetDefaultValidity();
325 KeyCreationResult creationResult;
326 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
327 ASSERT_TRUE(result.isOk());
328 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
329 vector<KeyCharacteristics> attested_key_characteristics =
330 std::move(creationResult.keyCharacteristics);
331 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
332 EXPECT_EQ(attested_key_cert_chain.size(), 1);
333
David Drysdale7dff4fc2021-12-10 10:10:52 +0000334 int32_t aidl_version = 0;
335 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000336 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
337 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000338 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000339 info.securityLevel,
340 attested_key_cert_chain[0].encodedCertificate));
341
342 // Attestation by itself is not valid (last entry is not self-signed).
343 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
344
345 // The signature over the attested key should correspond to the P256 public key.
346 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
347 ASSERT_TRUE(key_cert.get());
348 EVP_PKEY_Ptr signing_pubkey;
349 p256_pub_key(coseKeyData, &signing_pubkey);
350 ASSERT_TRUE(signing_pubkey.get());
351
352 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
353 << "Verification of attested certificate failed "
354 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600355}
356
357/**
358 * Generate and validate a test-mode key.
359 */
Max Bires126869a2021-02-21 18:32:59 -0800360TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600361 MacedPublicKey macedPubKey;
362 bytevec privateKeyBlob;
363 bool testMode = true;
364 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
365 ASSERT_TRUE(status.isOk());
Tri Vob0b8acc2022-11-30 16:22:23 -0800366 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600367}
368
Tri Vo0d6204e2022-09-29 16:15:34 -0700369class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
Shawn Willden274bb552020-09-30 22:39:22 -0600370 protected:
Tri Vo0d6204e2022-09-29 16:15:34 -0700371 CertificateRequestTestBase()
372 : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
David Drysdalecceca9f2021-03-12 15:49:47 +0000373
Seth Moore19acbe92021-06-23 15:15:52 -0700374 void generateTestEekChain(size_t eekLength) {
subrahmanyamanfb213d62022-02-02 23:10:55 +0000375 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
David Drysdale08696a72022-03-10 10:43:25 +0000376 ASSERT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700377 if (chain) testEekChain_ = chain.moveValue();
378 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600379 }
380
381 void generateKeys(bool testMode, size_t numKeys) {
382 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
383 cborKeysToSign_ = cppbor::Array();
384
385 for (auto& key : keysToSign_) {
386 bytevec privateKeyBlob;
387 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
388 ASSERT_TRUE(status.isOk()) << status.getMessage();
389
David Drysdalec8400772021-03-11 12:35:11 +0000390 vector<uint8_t> payload_value;
Tri Vob0b8acc2022-11-30 16:22:23 -0800391 check_maced_pubkey(key, testMode, &payload_value);
David Drysdalec8400772021-03-11 12:35:11 +0000392 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600393 }
394 }
395
396 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700397 size_t testEekLength_;
398 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000399 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600400 std::vector<MacedPublicKey> keysToSign_;
401 cppbor::Array cborKeysToSign_;
402};
403
Tri Vo0d6204e2022-09-29 16:15:34 -0700404class CertificateRequestTest : public CertificateRequestTestBase {
405 protected:
406 void SetUp() override {
407 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000408 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700409
410 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
Andrew Scull95b31312023-03-27 19:16:07 +0000411 GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
412 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
Tri Vo0d6204e2022-09-29 16:15:34 -0700413 }
414 }
415};
416
Shawn Willden274bb552020-09-30 22:39:22 -0600417/**
418 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
419 * content.
420 */
Max Bires126869a2021-02-21 18:32:59 -0800421TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600422 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000423 for (size_t eekLength : {2, 3, 7}) {
424 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700425 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600426
David Drysdalecceca9f2021-03-12 15:49:47 +0000427 bytevec keysToSignMac;
428 DeviceInfo deviceInfo;
429 ProtectedData protectedData;
430 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700431 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000432 &protectedData, &keysToSignMac);
433 ASSERT_TRUE(status.isOk()) << status.getMessage();
434
Seth Moore2fc6f832022-09-13 16:10:11 -0700435 auto result = verifyProductionProtectedData(
436 deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
437 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
438 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000439 }
Shawn Willden274bb552020-09-30 22:39:22 -0600440}
441
442/**
Seth Moore42c11332021-07-02 15:38:17 -0700443 * Ensure that test mode outputs a unique BCC root key every time we request a
444 * certificate request. Else, it's possible that the test mode API could be used
445 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
446 * device public key multiple times.
447 */
448TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
449 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700450
451 bytevec keysToSignMac;
452 DeviceInfo deviceInfo;
453 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000454 generateTestEekChain(3);
Seth Moore42c11332021-07-02 15:38:17 -0700455 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700456 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
457 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700458 ASSERT_TRUE(status.isOk()) << status.getMessage();
459
Seth Moore2fc6f832022-09-13 16:10:11 -0700460 auto firstBcc = verifyProductionProtectedData(
461 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
462 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
463 ASSERT_TRUE(firstBcc) << firstBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700464
Seth Moore19acbe92021-06-23 15:15:52 -0700465 status = provisionable_->generateCertificateRequest(
466 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
467 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700468 ASSERT_TRUE(status.isOk()) << status.getMessage();
469
Seth Moore2fc6f832022-09-13 16:10:11 -0700470 auto secondBcc = verifyProductionProtectedData(
471 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
472 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
473 ASSERT_TRUE(secondBcc) << secondBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700474
475 // Verify that none of the keys in the first BCC are repeated in the second one.
Seth Moore2fc6f832022-09-13 16:10:11 -0700476 for (const auto& i : *firstBcc) {
477 for (auto& j : *secondBcc) {
Seth Moore42c11332021-07-02 15:38:17 -0700478 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
479 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
480 }
481 }
482}
483
484/**
Seth Moore19acbe92021-06-23 15:15:52 -0700485 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
486 * is not run by default. Not all devices are GMS devices, and therefore they do not all
487 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600488 */
Seth Moore19acbe92021-06-23 15:15:52 -0700489TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600490 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000491
Seth Moore19acbe92021-06-23 15:15:52 -0700492 bytevec keysToSignMac;
493 DeviceInfo deviceInfo;
494 ProtectedData protectedData;
495 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000496 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
497 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700498 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600499}
500
501/**
502 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
503 */
Max Bires126869a2021-02-21 18:32:59 -0800504TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600505 bool testMode = true;
506 generateKeys(testMode, 4 /* numKeys */);
507
David Drysdalecceca9f2021-03-12 15:49:47 +0000508 for (size_t eekLength : {2, 3, 7}) {
509 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700510 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600511
David Drysdalecceca9f2021-03-12 15:49:47 +0000512 bytevec keysToSignMac;
513 DeviceInfo deviceInfo;
514 ProtectedData protectedData;
515 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700516 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000517 &keysToSignMac);
518 ASSERT_TRUE(status.isOk()) << status.getMessage();
519
Seth Moore2fc6f832022-09-13 16:10:11 -0700520 auto result = verifyProductionProtectedData(
521 deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
522 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
523 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000524 }
Shawn Willden274bb552020-09-30 22:39:22 -0600525}
526
527/**
Seth Moore19acbe92021-06-23 15:15:52 -0700528 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
529 * is not run by default. Not all devices are GMS devices, and therefore they do not all
530 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600531 */
Seth Moore19acbe92021-06-23 15:15:52 -0700532TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600533 bool testMode = false;
534 generateKeys(testMode, 4 /* numKeys */);
535
Seth Moore19acbe92021-06-23 15:15:52 -0700536 bytevec keysToSignMac;
537 DeviceInfo deviceInfo;
538 ProtectedData protectedData;
539 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000540 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
541 &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700542 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000543}
544
545/**
David Drysdalee99ed862021-03-15 16:43:06 +0000546 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
547 */
548TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
549 bool testMode = true;
550 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000551 auto result = corrupt_maced_key(keysToSign_[0]);
552 ASSERT_TRUE(result) << result.moveMessage();
553 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000554
555 bytevec keysToSignMac;
556 DeviceInfo deviceInfo;
557 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000558 generateTestEekChain(3);
David Drysdalee99ed862021-03-15 16:43:06 +0000559 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700560 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
561 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000562 ASSERT_FALSE(status.isOk()) << status.getMessage();
563 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
564}
565
566/**
567 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
568 */
569TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700570 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000571 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000572 auto result = corrupt_maced_key(keysToSign_[0]);
573 ASSERT_TRUE(result) << result.moveMessage();
574 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000575
576 bytevec keysToSignMac;
577 DeviceInfo deviceInfo;
578 ProtectedData protectedData;
579 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000580 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
581 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000582 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700583 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000584}
585
586/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000587 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
588 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000589 */
590TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
591 bool testMode = false;
592 generateKeys(testMode, 4 /* numKeys */);
593
subrahmanyamanfb213d62022-02-02 23:10:55 +0000594 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
Seth Moore19acbe92021-06-23 15:15:52 -0700595 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
596 ASSERT_NE(parsedChain, nullptr) << parseErr;
597 ASSERT_NE(parsedChain->asArray(), nullptr);
598
599 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
600 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000601 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000602
603 bytevec keysToSignMac;
604 DeviceInfo deviceInfo;
605 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700606 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
607 challenge_, &deviceInfo,
608 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000609 ASSERT_FALSE(status.isOk());
610 ASSERT_EQ(status.getServiceSpecificError(),
611 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
612 }
613}
614
615/**
616 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
617 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000618 */
619TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
620 bool testMode = false;
621 generateKeys(testMode, 4 /* numKeys */);
622
623 // Build an EEK chain that omits the first self-signed cert.
624 auto truncatedChain = cppbor::Array();
subrahmanyamanfb213d62022-02-02 23:10:55 +0000625 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
David Drysdalecceca9f2021-03-12 15:49:47 +0000626 ASSERT_TRUE(chain);
627 auto eekChain = chain->asArray();
628 ASSERT_NE(eekChain, nullptr);
629 for (size_t ii = 1; ii < eekChain->size(); ii++) {
630 truncatedChain.add(eekChain->get(ii)->clone());
631 }
632
Shawn Willden274bb552020-09-30 22:39:22 -0600633 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700634 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600635 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000636 auto status = provisionable_->generateCertificateRequest(
637 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
638 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600639 ASSERT_FALSE(status.isOk());
640 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
641}
642
643/**
644 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
645 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
646 */
Max Bires126869a2021-02-21 18:32:59 -0800647TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600648 generateKeys(false /* testMode */, 2 /* numKeys */);
649
650 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700651 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600652 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000653 generateTestEekChain(3);
Max Biresfdbb9042021-03-23 12:43:38 -0700654 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700655 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700656 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600657 ASSERT_FALSE(status.isOk());
658 ASSERT_EQ(status.getServiceSpecificError(),
659 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
660}
661
662/**
663 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
664 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
665 */
Max Bires126869a2021-02-21 18:32:59 -0800666TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600667 generateKeys(true /* testMode */, 2 /* numKeys */);
668
669 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700670 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600671 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000672 generateTestEekChain(3);
Shawn Willden274bb552020-09-30 22:39:22 -0600673 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700674 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000675 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600676 ASSERT_FALSE(status.isOk());
677 ASSERT_EQ(status.getServiceSpecificError(),
678 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
679}
680
681INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
682
Tri Vo0d6204e2022-09-29 16:15:34 -0700683class CertificateRequestV2Test : public CertificateRequestTestBase {
684 void SetUp() override {
685 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000686 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700687
688 if (rpcHardwareInfo.versionNumber < VERSION_WITHOUT_TEST_MODE) {
689 GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
690 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
691 }
692 }
693};
694
695/**
696 * Generate an empty certificate request, and decrypt and verify the structure and content.
697 */
698TEST_P(CertificateRequestV2Test, EmptyRequest) {
699 bytevec csr;
700
701 auto status =
702 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
703 ASSERT_TRUE(status.isOk()) << status.getMessage();
704
705 auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
706 ASSERT_TRUE(result) << result.message();
707}
708
709/**
710 * Generate a non-empty certificate request. Decrypt, parse and validate the contents.
711 */
712TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
713 generateKeys(false /* testMode */, 1 /* numKeys */);
714
715 bytevec csr;
716
717 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
718 ASSERT_TRUE(status.isOk()) << status.getMessage();
719
720 auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
721 ASSERT_TRUE(result) << result.message();
722}
723
724/**
Andrew Scullfb49ad22022-11-09 21:02:48 +0000725 * Generate a non-empty certificate request. Make sure contents are reproducible but allow for the
726 * signature to be different since algorithms including ECDSA P-256 can include a random value.
Tri Vo0d6204e2022-09-29 16:15:34 -0700727 */
728TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
729 generateKeys(false /* testMode */, 1 /* numKeys */);
730
731 bytevec csr;
732
733 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
734 ASSERT_TRUE(status.isOk()) << status.getMessage();
735
Andrew Scullfb49ad22022-11-09 21:02:48 +0000736 auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
737 ASSERT_TRUE(firstCsr) << firstCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700738
739 status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
740 ASSERT_TRUE(status.isOk()) << status.getMessage();
741
Andrew Scullfb49ad22022-11-09 21:02:48 +0000742 auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
743 ASSERT_TRUE(secondCsr) << secondCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700744
Andrew Scullfb49ad22022-11-09 21:02:48 +0000745 ASSERT_EQ(**firstCsr, **secondCsr);
Tri Vo0d6204e2022-09-29 16:15:34 -0700746}
747
748/**
749 * Generate a non-empty certificate request with multiple keys.
750 */
751TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700752 generateKeys(false /* testMode */, rpcHardwareInfo.supportedNumKeysInCsr /* numKeys */);
Tri Vo0d6204e2022-09-29 16:15:34 -0700753
754 bytevec csr;
755
756 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
757 ASSERT_TRUE(status.isOk()) << status.getMessage();
758
759 auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
760 ASSERT_TRUE(result) << result.message();
761}
762
763/**
764 * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
765 */
766TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
767 generateKeys(false /* testMode */, 1 /* numKeys */);
768 auto result = corrupt_maced_key(keysToSign_[0]);
769 ASSERT_TRUE(result) << result.moveMessage();
770 MacedPublicKey keyWithCorruptMac = result.moveValue();
771
772 bytevec csr;
773 auto status =
774 provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
775 ASSERT_FALSE(status.isOk()) << status.getMessage();
776 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
777}
778
779/**
Tri Vob0b8acc2022-11-30 16:22:23 -0800780 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
781 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
Tri Vo0d6204e2022-09-29 16:15:34 -0700782 */
783TEST_P(CertificateRequestV2Test, NonEmptyRequest_testKeyInProdCert) {
784 generateKeys(true /* testMode */, 1 /* numKeys */);
785
786 bytevec csr;
787 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Tri Vo0d6204e2022-09-29 16:15:34 -0700788 ASSERT_FALSE(status.isOk()) << status.getMessage();
Tri Vob0b8acc2022-11-30 16:22:23 -0800789 ASSERT_EQ(status.getServiceSpecificError(),
790 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
Tri Vo0d6204e2022-09-29 16:15:34 -0700791}
792
Andrew Scull95b31312023-03-27 19:16:07 +0000793/**
794 * Call generateCertificateRequest(). Make sure it's removed.
795 */
796TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed) {
797 bytevec keysToSignMac;
798 DeviceInfo deviceInfo;
799 ProtectedData protectedData;
800 auto status = provisionable_->generateCertificateRequest(
801 true /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
802 &protectedData, &keysToSignMac);
803 ASSERT_FALSE(status.isOk()) << status.getMessage();
804 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
805}
806
Tri Voec50ee12023-02-14 16:29:53 -0800807void parse_root_of_trust(const vector<uint8_t>& attestation_cert,
808 vector<uint8_t>* verified_boot_key, VerifiedBoot* verified_boot_state,
809 bool* device_locked, vector<uint8_t>* verified_boot_hash) {
810 X509_Ptr cert(parse_cert_blob(attestation_cert));
811 ASSERT_TRUE(cert.get());
812
813 ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
814 ASSERT_TRUE(attest_rec);
815
816 auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, verified_boot_key,
817 verified_boot_state, device_locked, verified_boot_hash);
818 ASSERT_EQ(error, ErrorCode::OK);
819}
820
821/**
822 * Generate a CSR and verify DeviceInfo against IDs attested by KeyMint.
823 */
824TEST_P(CertificateRequestV2Test, DeviceInfo) {
825 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
826 std::shared_ptr<IKeyMintDevice> keyMint;
827 if (!matching_keymint_device(GetParam(), &keyMint)) {
828 // No matching IKeyMintDevice.
829 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
830 return;
831 }
832 KeyMintHardwareInfo info;
833 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
834
835 // Get IDs attested by KeyMint.
836 MacedPublicKey macedPubKey;
837 bytevec privateKeyBlob;
838 auto irpcStatus =
839 provisionable_->generateEcdsaP256KeyPair(false, &macedPubKey, &privateKeyBlob);
840 ASSERT_TRUE(irpcStatus.isOk());
841
842 AttestationKey attestKey;
843 attestKey.keyBlob = std::move(privateKeyBlob);
844 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
845
846 // Generate an ECDSA key that is attested by the generated P256 keypair.
847 AuthorizationSet keyDesc = AuthorizationSetBuilder()
848 .Authorization(TAG_NO_AUTH_REQUIRED)
849 .EcdsaSigningKey(EcCurve::P_256)
850 .AttestationChallenge("foo")
851 .AttestationApplicationId("bar")
852 .Digest(Digest::NONE)
853 .SetDefaultValidity();
854 KeyCreationResult creationResult;
855 auto kmStatus = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
856 ASSERT_TRUE(kmStatus.isOk());
857
858 vector<KeyCharacteristics> key_characteristics = std::move(creationResult.keyCharacteristics);
859 vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain);
860 // We didn't provision the attestation key.
861 ASSERT_EQ(key_cert_chain.size(), 1);
862
863 // Parse attested patch levels.
864 auto auths = HwEnforcedAuthorizations(key_characteristics);
865
866 auto attestedSystemPatchLevel = auths.GetTagValue(TAG_OS_PATCHLEVEL);
867 auto attestedVendorPatchLevel = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
868 auto attestedBootPatchLevel = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
869
870 ASSERT_TRUE(attestedSystemPatchLevel.has_value());
871 ASSERT_TRUE(attestedVendorPatchLevel.has_value());
872 ASSERT_TRUE(attestedBootPatchLevel.has_value());
873
874 // Parse attested AVB values.
875 vector<uint8_t> key;
876 VerifiedBoot attestedVbState;
877 bool attestedBootloaderState;
878 vector<uint8_t> attestedVbmetaDigest;
879 parse_root_of_trust(key_cert_chain[0].encodedCertificate, &key, &attestedVbState,
880 &attestedBootloaderState, &attestedVbmetaDigest);
881
882 // Get IDs from DeviceInfo.
883 bytevec csr;
884 irpcStatus =
885 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
886 ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getMessage();
887
888 auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
889 ASSERT_TRUE(result) << result.message();
890
891 std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
892 ASSERT_TRUE(csrPayload);
893
894 auto deviceInfo = csrPayload->get(2)->asMap();
895 ASSERT_TRUE(deviceInfo);
896
897 auto vbState = deviceInfo->get("vb_state")->asTstr();
898 auto bootloaderState = deviceInfo->get("bootloader_state")->asTstr();
899 auto vbmetaDigest = deviceInfo->get("vbmeta_digest")->asBstr();
900 auto systemPatchLevel = deviceInfo->get("system_patch_level")->asUint();
901 auto vendorPatchLevel = deviceInfo->get("vendor_patch_level")->asUint();
902 auto bootPatchLevel = deviceInfo->get("boot_patch_level")->asUint();
903 auto securityLevel = deviceInfo->get("security_level")->asTstr();
904
905 ASSERT_TRUE(vbState);
906 ASSERT_TRUE(bootloaderState);
907 ASSERT_TRUE(vbmetaDigest);
908 ASSERT_TRUE(systemPatchLevel);
909 ASSERT_TRUE(vendorPatchLevel);
910 ASSERT_TRUE(bootPatchLevel);
911 ASSERT_TRUE(securityLevel);
912
913 auto kmDeviceName = device_suffix(GetParam());
914
915 // Compare DeviceInfo against IDs attested by KeyMint.
916 ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") ||
917 (securityLevel->value() == "strongbox" && kmDeviceName == "strongbox"));
918 ASSERT_TRUE((vbState->value() == "green" && attestedVbState == VerifiedBoot::VERIFIED) ||
919 (vbState->value() == "yellow" && attestedVbState == VerifiedBoot::SELF_SIGNED) ||
920 (vbState->value() == "orange" && attestedVbState == VerifiedBoot::UNVERIFIED));
921 ASSERT_TRUE((bootloaderState->value() == "locked" && attestedBootloaderState) ||
922 (bootloaderState->value() == "unlocked" && !attestedBootloaderState));
923 ASSERT_EQ(vbmetaDigest->value(), attestedVbmetaDigest);
924 ASSERT_EQ(systemPatchLevel->value(), attestedSystemPatchLevel.value());
925 ASSERT_EQ(vendorPatchLevel->value(), attestedVendorPatchLevel.value());
926 ASSERT_EQ(bootPatchLevel->value(), attestedBootPatchLevel.value());
927}
928
Tri Vo0d6204e2022-09-29 16:15:34 -0700929INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
930
Max Biresa9b3bb92022-11-21 23:02:09 -0800931using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
932
933INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
934
935TEST_P(VsrRequirementTest, VsrEnforcementTest) {
936 RpcHardwareInfo hwInfo;
937 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
938 int vsr_api_level = get_vsr_api_level();
939 if (vsr_api_level < 34) {
940 GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
941 << vsr_api_level;
942 }
943 EXPECT_GE(hwInfo.versionNumber, 3)
944 << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
945}
946
Shawn Willden274bb552020-09-30 22:39:22 -0600947} // namespace aidl::android::hardware::security::keymint::test