blob: a1de93ee2a58632b33de01160aabe33544a2a306 [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;
Andrew Scullf2ae1932023-04-24 19:09:09 +000050
51constexpr int32_t VERSION_WITHOUT_EEK = 3;
Tri Vo0d6204e2022-09-29 16:15:34 -070052constexpr int32_t VERSION_WITHOUT_TEST_MODE = 3;
Andrew Scullf2ae1932023-04-24 19:09:09 +000053constexpr int32_t VERSION_WITH_CERTIFICATE_REQUEST_V2 = 3;
54constexpr int32_t VERSION_WITH_SUPPORTED_NUM_KEYS_IN_CSR = 3;
Seth Moorefc86bf42021-12-09 14:07:04 -080055
Tommy Chiufde3ad12023-03-17 05:58:28 +000056constexpr uint8_t MIN_CHALLENGE_SIZE = 0;
57constexpr uint8_t MAX_CHALLENGE_SIZE = 64;
Alice Wang895f4b32023-11-14 07:38:18 +000058const string RKP_VM_INSTANCE_NAME =
59 "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
Tommy Chiufde3ad12023-03-17 05:58:28 +000060
Shawn Willden274bb552020-09-30 22:39:22 -060061#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070062 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060063 INSTANTIATE_TEST_SUITE_P( \
64 PerInstance, name, \
65 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
66 ::android::PrintInstanceNameToString)
67
Seth Moorefc86bf42021-12-09 14:07:04 -080068using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060069using bytevec = std::vector<uint8_t>;
70using testing::MatchesRegex;
71using namespace remote_prov;
72using namespace keymaster;
73
74bytevec string_to_bytevec(const char* s) {
75 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
76 return bytevec(p, p + strlen(s));
77}
78
David Drysdalee99ed862021-03-15 16:43:06 +000079ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
80 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
81 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
82 return "COSE Mac0 parse failed";
83 }
84 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
85 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
86 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
87 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
88 if (!protParams || !unprotParams || !payload || !tag) {
89 return "Invalid COSE_Sign1: missing content";
90 }
91 auto corruptMac0 = cppbor::Array();
92 corruptMac0.add(protParams->clone());
93 corruptMac0.add(unprotParams->clone());
94 corruptMac0.add(payload->clone());
95 vector<uint8_t> tagData = tag->value();
96 tagData[0] ^= 0x08;
97 tagData[tagData.size() - 1] ^= 0x80;
98 corruptMac0.add(cppbor::Bstr(tagData));
99
100 return MacedPublicKey{corruptMac0.encode()};
101}
102
David Drysdalecceca9f2021-03-12 15:49:47 +0000103ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
104 if (coseSign1->size() != kCoseSign1EntryCount) {
105 return "Invalid COSE_Sign1, wrong entry count";
106 }
107 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
108 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
109 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
110 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
111 if (!protectedParams || !unprotectedParams || !payload || !signature) {
112 return "Invalid COSE_Sign1: missing content";
113 }
114
115 auto corruptSig = cppbor::Array();
116 corruptSig.add(protectedParams->clone());
117 corruptSig.add(unprotectedParams->clone());
118 corruptSig.add(payload->clone());
119 vector<uint8_t> sigData = signature->value();
120 sigData[0] ^= 0x08;
121 corruptSig.add(cppbor::Bstr(sigData));
122
123 return std::move(corruptSig);
124}
125
Seth Moore19acbe92021-06-23 15:15:52 -0700126ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
127 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000128 if (!chain || !chain->asArray()) {
129 return "EekChain parse failed";
130 }
131
132 cppbor::Array* eekChain = chain->asArray();
133 if (which >= eekChain->size()) {
134 return "selected sig out of range";
135 }
136 auto corruptChain = cppbor::Array();
137
138 for (int ii = 0; ii < eekChain->size(); ++ii) {
139 if (ii == which) {
140 auto sig = corrupt_sig(eekChain->get(which)->asArray());
141 if (!sig) {
142 return "Failed to build corrupted signature" + sig.moveMessage();
143 }
144 corruptChain.add(sig.moveValue());
145 } else {
146 corruptChain.add(eekChain->get(ii)->clone());
147 }
148 }
Seth Moore19acbe92021-06-23 15:15:52 -0700149 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000150}
151
David Drysdale4d3c2982021-03-31 18:21:40 +0100152string device_suffix(const string& name) {
153 size_t pos = name.find('/');
154 if (pos == string::npos) {
155 return name;
156 }
157 return name.substr(pos + 1);
158}
159
160bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
161 string rp_suffix = device_suffix(rp_name);
162
163 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
164 for (const string& km_name : km_names) {
165 // If the suffix of the KeyMint instance equals the suffix of the
166 // RemotelyProvisionedComponent instance, assume they match.
167 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
168 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
169 *keyMint = IKeyMintDevice::fromBinder(binder);
170 return true;
171 }
172 }
173 return false;
174}
175
Shawn Willden274bb552020-09-30 22:39:22 -0600176} // namespace
177
178class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
179 public:
180 virtual void SetUp() override {
181 if (AServiceManager_isDeclared(GetParam().c_str())) {
182 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
183 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
184 }
185 ASSERT_NE(provisionable_, nullptr);
Alice Wang895f4b32023-11-14 07:38:18 +0000186 auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo);
187 if (GetParam() == RKP_VM_INSTANCE_NAME &&
188 status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
189 GTEST_SKIP() << "The RKP VM is not supported on this system.";
190 }
191 ASSERT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600192 }
193
194 static vector<string> build_params() {
195 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
196 return params;
197 }
198
199 protected:
200 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000201 RpcHardwareInfo rpcHardwareInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600202};
203
Seth Moorefc86bf42021-12-09 14:07:04 -0800204/**
205 * Verify that every implementation reports a different unique id.
206 */
207TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
208 std::set<std::string> uniqueIds;
209 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
210 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
211 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
212 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
213 IRemotelyProvisionedComponent::fromBinder(binder);
214 ASSERT_NE(rpc, nullptr);
215
216 RpcHardwareInfo hwInfo;
Alice Wang895f4b32023-11-14 07:38:18 +0000217 auto status = rpc->getHardwareInfo(&hwInfo);
218 if (hal == RKP_VM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
219 GTEST_SKIP() << "The RKP VM is not supported on this system.";
220 }
221 ASSERT_TRUE(status.isOk());
Seth Moorefc86bf42021-12-09 14:07:04 -0800222
Tri Vodd12c482022-10-12 22:41:28 +0000223 if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800224 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
Andrew Scullf2ae1932023-04-24 19:09:09 +0000244 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_EEK) {
245 ASSERT_EQ(hwInfo.supportedEekCurve, RpcHardwareInfo::CURVE_NONE)
246 << "Invalid curve: " << hwInfo.supportedEekCurve;
247 return;
Hasini Gunasinghe666b2712023-01-05 21:35:51 +0000248 }
Andrew Scullf2ae1932023-04-24 19:09:09 +0000249
250 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
Seth Moorefc86bf42021-12-09 14:07:04 -0800251 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
252 << "Invalid curve: " << hwInfo.supportedEekCurve;
253}
254
255/**
256 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
257 */
258TEST_P(GetHardwareInfoTests, uniqueId) {
Tri Vodd12c482022-10-12 22:41:28 +0000259 if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800260 return;
261 }
262
263 RpcHardwareInfo hwInfo;
264 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
265 ASSERT_TRUE(hwInfo.uniqueId);
266 EXPECT_GE(hwInfo.uniqueId->size(), 1);
267 EXPECT_LE(hwInfo.uniqueId->size(), 32);
268}
269
Tri Vo9cab73c2022-10-28 13:40:24 -0700270/**
271 * Verify implementation supports at least MIN_SUPPORTED_NUM_KEYS_IN_CSR keys in a CSR.
272 */
273TEST_P(GetHardwareInfoTests, supportedNumKeysInCsr) {
Andrew Scullf2ae1932023-04-24 19:09:09 +0000274 if (rpcHardwareInfo.versionNumber < VERSION_WITH_SUPPORTED_NUM_KEYS_IN_CSR) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700275 return;
276 }
277
278 RpcHardwareInfo hwInfo;
279 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
280 ASSERT_GE(hwInfo.supportedNumKeysInCsr, RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR);
281}
282
Shawn Willden274bb552020-09-30 22:39:22 -0600283using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
284
285INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
286
287/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000288 * Generate and validate a production-mode key. MAC tag can't be verified, but
289 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600290 */
Max Bires126869a2021-02-21 18:32:59 -0800291TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600292 MacedPublicKey macedPubKey;
293 bytevec privateKeyBlob;
294 bool testMode = false;
295 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
296 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000297 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800298 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100299}
300
301/**
302 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
303 */
304TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
305 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
306 std::shared_ptr<IKeyMintDevice> keyMint;
307 if (!matching_keymint_device(GetParam(), &keyMint)) {
308 // No matching IKeyMintDevice.
309 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
310 return;
311 }
312 KeyMintHardwareInfo info;
313 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
314
315 MacedPublicKey macedPubKey;
316 bytevec privateKeyBlob;
317 bool testMode = false;
318 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
319 ASSERT_TRUE(status.isOk());
320 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800321 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100322
David Drysdalef0d516d2021-03-22 07:51:43 +0000323 AttestationKey attestKey;
324 attestKey.keyBlob = std::move(privateKeyBlob);
325 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600326
David Drysdalef0d516d2021-03-22 07:51:43 +0000327 // Generate an ECDSA key that is attested by the generated P256 keypair.
328 AuthorizationSet keyDesc = AuthorizationSetBuilder()
329 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100330 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000331 .AttestationChallenge("foo")
332 .AttestationApplicationId("bar")
333 .Digest(Digest::NONE)
334 .SetDefaultValidity();
335 KeyCreationResult creationResult;
336 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
337 ASSERT_TRUE(result.isOk());
338 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
339 vector<KeyCharacteristics> attested_key_characteristics =
340 std::move(creationResult.keyCharacteristics);
341 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
342 EXPECT_EQ(attested_key_cert_chain.size(), 1);
343
David Drysdale7dff4fc2021-12-10 10:10:52 +0000344 int32_t aidl_version = 0;
345 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000346 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
347 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000348 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000349 info.securityLevel,
350 attested_key_cert_chain[0].encodedCertificate));
351
352 // Attestation by itself is not valid (last entry is not self-signed).
353 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
354
355 // The signature over the attested key should correspond to the P256 public key.
356 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
357 ASSERT_TRUE(key_cert.get());
358 EVP_PKEY_Ptr signing_pubkey;
359 p256_pub_key(coseKeyData, &signing_pubkey);
360 ASSERT_TRUE(signing_pubkey.get());
361
362 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
363 << "Verification of attested certificate failed "
364 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600365}
366
367/**
368 * Generate and validate a test-mode key.
369 */
Max Bires126869a2021-02-21 18:32:59 -0800370TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600371 MacedPublicKey macedPubKey;
372 bytevec privateKeyBlob;
373 bool testMode = true;
374 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
Andrew Scullf2ae1932023-04-24 19:09:09 +0000375
376 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
377 ASSERT_FALSE(status.isOk());
378 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
379 return;
380 }
381
Shawn Willden274bb552020-09-30 22:39:22 -0600382 ASSERT_TRUE(status.isOk());
Tri Vob0b8acc2022-11-30 16:22:23 -0800383 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600384}
385
Tri Vo0d6204e2022-09-29 16:15:34 -0700386class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
Shawn Willden274bb552020-09-30 22:39:22 -0600387 protected:
Tri Vo0d6204e2022-09-29 16:15:34 -0700388 CertificateRequestTestBase()
389 : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
David Drysdalecceca9f2021-03-12 15:49:47 +0000390
Seth Moore19acbe92021-06-23 15:15:52 -0700391 void generateTestEekChain(size_t eekLength) {
subrahmanyamanfb213d62022-02-02 23:10:55 +0000392 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
David Drysdale08696a72022-03-10 10:43:25 +0000393 ASSERT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700394 if (chain) testEekChain_ = chain.moveValue();
395 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600396 }
397
398 void generateKeys(bool testMode, size_t numKeys) {
399 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
400 cborKeysToSign_ = cppbor::Array();
401
402 for (auto& key : keysToSign_) {
403 bytevec privateKeyBlob;
404 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
405 ASSERT_TRUE(status.isOk()) << status.getMessage();
406
David Drysdalec8400772021-03-11 12:35:11 +0000407 vector<uint8_t> payload_value;
Tri Vob0b8acc2022-11-30 16:22:23 -0800408 check_maced_pubkey(key, testMode, &payload_value);
David Drysdalec8400772021-03-11 12:35:11 +0000409 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600410 }
411 }
412
413 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700414 size_t testEekLength_;
415 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000416 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600417 std::vector<MacedPublicKey> keysToSign_;
418 cppbor::Array cborKeysToSign_;
419};
420
Tri Vo0d6204e2022-09-29 16:15:34 -0700421class CertificateRequestTest : public CertificateRequestTestBase {
422 protected:
423 void SetUp() override {
424 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000425 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700426
Andrew Scullf2ae1932023-04-24 19:09:09 +0000427 if (rpcHardwareInfo.versionNumber >= VERSION_WITH_CERTIFICATE_REQUEST_V2) {
Andrew Scull95b31312023-03-27 19:16:07 +0000428 GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
429 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
Tri Vo0d6204e2022-09-29 16:15:34 -0700430 }
431 }
432};
433
Shawn Willden274bb552020-09-30 22:39:22 -0600434/**
435 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
436 * content.
437 */
Max Bires126869a2021-02-21 18:32:59 -0800438TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600439 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000440 for (size_t eekLength : {2, 3, 7}) {
441 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700442 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600443
David Drysdalecceca9f2021-03-12 15:49:47 +0000444 bytevec keysToSignMac;
445 DeviceInfo deviceInfo;
446 ProtectedData protectedData;
447 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700448 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000449 &protectedData, &keysToSignMac);
450 ASSERT_TRUE(status.isOk()) << status.getMessage();
451
Seth Moore2fc6f832022-09-13 16:10:11 -0700452 auto result = verifyProductionProtectedData(
453 deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
454 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
455 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000456 }
Shawn Willden274bb552020-09-30 22:39:22 -0600457}
458
459/**
Seth Moore42c11332021-07-02 15:38:17 -0700460 * Ensure that test mode outputs a unique BCC root key every time we request a
461 * certificate request. Else, it's possible that the test mode API could be used
462 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
463 * device public key multiple times.
464 */
465TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
466 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700467
468 bytevec keysToSignMac;
469 DeviceInfo deviceInfo;
470 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000471 generateTestEekChain(3);
Seth Moore42c11332021-07-02 15:38:17 -0700472 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700473 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
474 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700475 ASSERT_TRUE(status.isOk()) << status.getMessage();
476
Seth Moore2fc6f832022-09-13 16:10:11 -0700477 auto firstBcc = verifyProductionProtectedData(
478 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
479 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
480 ASSERT_TRUE(firstBcc) << firstBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700481
Seth Moore19acbe92021-06-23 15:15:52 -0700482 status = provisionable_->generateCertificateRequest(
483 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
484 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700485 ASSERT_TRUE(status.isOk()) << status.getMessage();
486
Seth Moore2fc6f832022-09-13 16:10:11 -0700487 auto secondBcc = verifyProductionProtectedData(
488 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
489 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
490 ASSERT_TRUE(secondBcc) << secondBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700491
492 // Verify that none of the keys in the first BCC are repeated in the second one.
Seth Moore2fc6f832022-09-13 16:10:11 -0700493 for (const auto& i : *firstBcc) {
494 for (auto& j : *secondBcc) {
Seth Moore42c11332021-07-02 15:38:17 -0700495 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
496 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
497 }
498 }
499}
500
501/**
Seth Moore19acbe92021-06-23 15:15:52 -0700502 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
503 * is not run by default. Not all devices are GMS devices, and therefore they do not all
504 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600505 */
Seth Moore19acbe92021-06-23 15:15:52 -0700506TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600507 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000508
Seth Moore19acbe92021-06-23 15:15:52 -0700509 bytevec keysToSignMac;
510 DeviceInfo deviceInfo;
511 ProtectedData protectedData;
512 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000513 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
514 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700515 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600516}
517
518/**
519 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
520 */
Max Bires126869a2021-02-21 18:32:59 -0800521TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600522 bool testMode = true;
523 generateKeys(testMode, 4 /* numKeys */);
524
David Drysdalecceca9f2021-03-12 15:49:47 +0000525 for (size_t eekLength : {2, 3, 7}) {
526 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700527 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600528
David Drysdalecceca9f2021-03-12 15:49:47 +0000529 bytevec keysToSignMac;
530 DeviceInfo deviceInfo;
531 ProtectedData protectedData;
532 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700533 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000534 &keysToSignMac);
535 ASSERT_TRUE(status.isOk()) << status.getMessage();
536
Seth Moore2fc6f832022-09-13 16:10:11 -0700537 auto result = verifyProductionProtectedData(
538 deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
539 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
540 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000541 }
Shawn Willden274bb552020-09-30 22:39:22 -0600542}
543
544/**
Seth Moore19acbe92021-06-23 15:15:52 -0700545 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
546 * is not run by default. Not all devices are GMS devices, and therefore they do not all
547 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600548 */
Seth Moore19acbe92021-06-23 15:15:52 -0700549TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600550 bool testMode = false;
551 generateKeys(testMode, 4 /* numKeys */);
552
Seth Moore19acbe92021-06-23 15:15:52 -0700553 bytevec keysToSignMac;
554 DeviceInfo deviceInfo;
555 ProtectedData protectedData;
556 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000557 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
558 &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700559 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000560}
561
562/**
David Drysdalee99ed862021-03-15 16:43:06 +0000563 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
564 */
565TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
566 bool testMode = true;
567 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000568 auto result = corrupt_maced_key(keysToSign_[0]);
569 ASSERT_TRUE(result) << result.moveMessage();
570 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000571
572 bytevec keysToSignMac;
573 DeviceInfo deviceInfo;
574 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000575 generateTestEekChain(3);
David Drysdalee99ed862021-03-15 16:43:06 +0000576 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700577 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
578 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000579 ASSERT_FALSE(status.isOk()) << status.getMessage();
580 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
581}
582
583/**
584 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
585 */
586TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700587 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000588 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000589 auto result = corrupt_maced_key(keysToSign_[0]);
590 ASSERT_TRUE(result) << result.moveMessage();
591 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000592
593 bytevec keysToSignMac;
594 DeviceInfo deviceInfo;
595 ProtectedData protectedData;
596 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000597 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
598 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000599 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700600 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000601}
602
603/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000604 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
605 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000606 */
607TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
608 bool testMode = false;
609 generateKeys(testMode, 4 /* numKeys */);
610
subrahmanyamanfb213d62022-02-02 23:10:55 +0000611 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
Seth Moore19acbe92021-06-23 15:15:52 -0700612 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
613 ASSERT_NE(parsedChain, nullptr) << parseErr;
614 ASSERT_NE(parsedChain->asArray(), nullptr);
615
616 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
617 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000618 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000619
620 bytevec keysToSignMac;
621 DeviceInfo deviceInfo;
622 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700623 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
624 challenge_, &deviceInfo,
625 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000626 ASSERT_FALSE(status.isOk());
627 ASSERT_EQ(status.getServiceSpecificError(),
628 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
629 }
630}
631
632/**
633 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
634 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000635 */
636TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
637 bool testMode = false;
638 generateKeys(testMode, 4 /* numKeys */);
639
640 // Build an EEK chain that omits the first self-signed cert.
641 auto truncatedChain = cppbor::Array();
subrahmanyamanfb213d62022-02-02 23:10:55 +0000642 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
David Drysdalecceca9f2021-03-12 15:49:47 +0000643 ASSERT_TRUE(chain);
644 auto eekChain = chain->asArray();
645 ASSERT_NE(eekChain, nullptr);
646 for (size_t ii = 1; ii < eekChain->size(); ii++) {
647 truncatedChain.add(eekChain->get(ii)->clone());
648 }
649
Shawn Willden274bb552020-09-30 22:39:22 -0600650 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700651 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600652 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000653 auto status = provisionable_->generateCertificateRequest(
654 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
655 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600656 ASSERT_FALSE(status.isOk());
657 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
658}
659
660/**
661 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
662 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
663 */
Max Bires126869a2021-02-21 18:32:59 -0800664TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600665 generateKeys(false /* testMode */, 2 /* numKeys */);
666
667 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700668 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600669 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000670 generateTestEekChain(3);
Max Biresfdbb9042021-03-23 12:43:38 -0700671 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700672 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700673 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600674 ASSERT_FALSE(status.isOk());
675 ASSERT_EQ(status.getServiceSpecificError(),
676 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
677}
678
679/**
680 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
681 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
682 */
Max Bires126869a2021-02-21 18:32:59 -0800683TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600684 generateKeys(true /* testMode */, 2 /* numKeys */);
685
686 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700687 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600688 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000689 generateTestEekChain(3);
Shawn Willden274bb552020-09-30 22:39:22 -0600690 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700691 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000692 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600693 ASSERT_FALSE(status.isOk());
694 ASSERT_EQ(status.getServiceSpecificError(),
695 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
696}
697
698INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
699
Tri Vo0d6204e2022-09-29 16:15:34 -0700700class CertificateRequestV2Test : public CertificateRequestTestBase {
701 void SetUp() override {
702 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000703 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700704
Andrew Scullf2ae1932023-04-24 19:09:09 +0000705 if (rpcHardwareInfo.versionNumber < VERSION_WITH_CERTIFICATE_REQUEST_V2) {
Tri Vo0d6204e2022-09-29 16:15:34 -0700706 GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
707 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
708 }
709 }
710};
711
712/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000713 * Generate an empty certificate request with all possible length of challenge, and decrypt and
714 * verify the structure and content.
Tri Vo0d6204e2022-09-29 16:15:34 -0700715 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700716// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700717TEST_P(CertificateRequestV2Test, EmptyRequest) {
718 bytevec csr;
719
Tommy Chiufde3ad12023-03-17 05:58:28 +0000720 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
721 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
722 auto challenge = randomBytes(size);
723 auto status =
724 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
725 ASSERT_TRUE(status.isOk()) << status.getMessage();
Tri Vo0d6204e2022-09-29 16:15:34 -0700726
Tommy Chiufde3ad12023-03-17 05:58:28 +0000727 auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge);
728 ASSERT_TRUE(result) << result.message();
729 }
Tri Vo0d6204e2022-09-29 16:15:34 -0700730}
731
732/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000733 * Generate a non-empty certificate request with all possible length of challenge. Decrypt, parse
734 * and validate the contents.
Tri Vo0d6204e2022-09-29 16:15:34 -0700735 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700736// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700737TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
738 generateKeys(false /* testMode */, 1 /* numKeys */);
739
740 bytevec csr;
741
Tommy Chiufde3ad12023-03-17 05:58:28 +0000742 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
743 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
744 auto challenge = randomBytes(size);
745 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr);
746 ASSERT_TRUE(status.isOk()) << status.getMessage();
Tri Vo0d6204e2022-09-29 16:15:34 -0700747
Tommy Chiufde3ad12023-03-17 05:58:28 +0000748 auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge);
749 ASSERT_TRUE(result) << result.message();
750 }
751}
752
753/**
754 * Generate an empty certificate request with invalid size of challenge
755 */
756TEST_P(CertificateRequestV2Test, EmptyRequestWithInvalidChallengeFail) {
757 bytevec csr;
758
759 auto status = provisionable_->generateCertificateRequestV2(
760 /* keysToSign */ {}, randomBytes(MAX_CHALLENGE_SIZE + 1), &csr);
761 EXPECT_FALSE(status.isOk()) << status.getMessage();
762 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_FAILED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700763}
764
765/**
Andrew Scullfb49ad22022-11-09 21:02:48 +0000766 * Generate a non-empty certificate request. Make sure contents are reproducible but allow for the
767 * signature to be different since algorithms including ECDSA P-256 can include a random value.
Tri Vo0d6204e2022-09-29 16:15:34 -0700768 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700769// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700770TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
771 generateKeys(false /* testMode */, 1 /* numKeys */);
772
773 bytevec csr;
774
775 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
776 ASSERT_TRUE(status.isOk()) << status.getMessage();
777
Andrew Scullfb49ad22022-11-09 21:02:48 +0000778 auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
779 ASSERT_TRUE(firstCsr) << firstCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700780
781 status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
782 ASSERT_TRUE(status.isOk()) << status.getMessage();
783
Andrew Scullfb49ad22022-11-09 21:02:48 +0000784 auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
785 ASSERT_TRUE(secondCsr) << secondCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700786
Andrew Scullfb49ad22022-11-09 21:02:48 +0000787 ASSERT_EQ(**firstCsr, **secondCsr);
Tri Vo0d6204e2022-09-29 16:15:34 -0700788}
789
790/**
791 * Generate a non-empty certificate request with multiple keys.
792 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700793// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700794TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700795 generateKeys(false /* testMode */, rpcHardwareInfo.supportedNumKeysInCsr /* numKeys */);
Tri Vo0d6204e2022-09-29 16:15:34 -0700796
797 bytevec csr;
798
799 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
800 ASSERT_TRUE(status.isOk()) << status.getMessage();
801
802 auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
803 ASSERT_TRUE(result) << result.message();
804}
805
806/**
807 * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
808 */
809TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
810 generateKeys(false /* testMode */, 1 /* numKeys */);
811 auto result = corrupt_maced_key(keysToSign_[0]);
812 ASSERT_TRUE(result) << result.moveMessage();
813 MacedPublicKey keyWithCorruptMac = result.moveValue();
814
815 bytevec csr;
816 auto status =
817 provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
818 ASSERT_FALSE(status.isOk()) << status.getMessage();
819 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
820}
821
822/**
Andrew Scullf2ae1932023-04-24 19:09:09 +0000823 * Call generateCertificateRequest(). Make sure it's removed.
Tri Vo0d6204e2022-09-29 16:15:34 -0700824 */
Andrew Scullf2ae1932023-04-24 19:09:09 +0000825TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed_prodMode) {
826 bytevec keysToSignMac;
827 DeviceInfo deviceInfo;
828 ProtectedData protectedData;
829 auto status = provisionable_->generateCertificateRequest(
830 false /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
831 &protectedData, &keysToSignMac);
Tri Vo0d6204e2022-09-29 16:15:34 -0700832 ASSERT_FALSE(status.isOk()) << status.getMessage();
Andrew Scullf2ae1932023-04-24 19:09:09 +0000833 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700834}
835
Andrew Scull95b31312023-03-27 19:16:07 +0000836/**
Andrew Scullf2ae1932023-04-24 19:09:09 +0000837 * Call generateCertificateRequest() in test mode. Make sure it's removed.
Andrew Scull95b31312023-03-27 19:16:07 +0000838 */
Andrew Scullf2ae1932023-04-24 19:09:09 +0000839TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed_testMode) {
Andrew Scull95b31312023-03-27 19:16:07 +0000840 bytevec keysToSignMac;
841 DeviceInfo deviceInfo;
842 ProtectedData protectedData;
843 auto status = provisionable_->generateCertificateRequest(
844 true /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
845 &protectedData, &keysToSignMac);
846 ASSERT_FALSE(status.isOk()) << status.getMessage();
847 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
848}
849
Tri Voec50ee12023-02-14 16:29:53 -0800850void parse_root_of_trust(const vector<uint8_t>& attestation_cert,
851 vector<uint8_t>* verified_boot_key, VerifiedBoot* verified_boot_state,
852 bool* device_locked, vector<uint8_t>* verified_boot_hash) {
853 X509_Ptr cert(parse_cert_blob(attestation_cert));
854 ASSERT_TRUE(cert.get());
855
856 ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
857 ASSERT_TRUE(attest_rec);
858
859 auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, verified_boot_key,
860 verified_boot_state, device_locked, verified_boot_hash);
861 ASSERT_EQ(error, ErrorCode::OK);
862}
863
864/**
865 * Generate a CSR and verify DeviceInfo against IDs attested by KeyMint.
866 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700867// @VsrTest = 3.10-015
Tri Voec50ee12023-02-14 16:29:53 -0800868TEST_P(CertificateRequestV2Test, DeviceInfo) {
869 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
870 std::shared_ptr<IKeyMintDevice> keyMint;
871 if (!matching_keymint_device(GetParam(), &keyMint)) {
872 // No matching IKeyMintDevice.
873 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
874 return;
875 }
876 KeyMintHardwareInfo info;
877 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
878
879 // Get IDs attested by KeyMint.
880 MacedPublicKey macedPubKey;
881 bytevec privateKeyBlob;
882 auto irpcStatus =
883 provisionable_->generateEcdsaP256KeyPair(false, &macedPubKey, &privateKeyBlob);
884 ASSERT_TRUE(irpcStatus.isOk());
885
886 AttestationKey attestKey;
887 attestKey.keyBlob = std::move(privateKeyBlob);
888 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
889
890 // Generate an ECDSA key that is attested by the generated P256 keypair.
891 AuthorizationSet keyDesc = AuthorizationSetBuilder()
892 .Authorization(TAG_NO_AUTH_REQUIRED)
893 .EcdsaSigningKey(EcCurve::P_256)
894 .AttestationChallenge("foo")
895 .AttestationApplicationId("bar")
896 .Digest(Digest::NONE)
897 .SetDefaultValidity();
898 KeyCreationResult creationResult;
899 auto kmStatus = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
900 ASSERT_TRUE(kmStatus.isOk());
901
902 vector<KeyCharacteristics> key_characteristics = std::move(creationResult.keyCharacteristics);
903 vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain);
904 // We didn't provision the attestation key.
905 ASSERT_EQ(key_cert_chain.size(), 1);
906
907 // Parse attested patch levels.
908 auto auths = HwEnforcedAuthorizations(key_characteristics);
909
910 auto attestedSystemPatchLevel = auths.GetTagValue(TAG_OS_PATCHLEVEL);
911 auto attestedVendorPatchLevel = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
912 auto attestedBootPatchLevel = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
913
914 ASSERT_TRUE(attestedSystemPatchLevel.has_value());
915 ASSERT_TRUE(attestedVendorPatchLevel.has_value());
916 ASSERT_TRUE(attestedBootPatchLevel.has_value());
917
918 // Parse attested AVB values.
919 vector<uint8_t> key;
920 VerifiedBoot attestedVbState;
921 bool attestedBootloaderState;
922 vector<uint8_t> attestedVbmetaDigest;
923 parse_root_of_trust(key_cert_chain[0].encodedCertificate, &key, &attestedVbState,
924 &attestedBootloaderState, &attestedVbmetaDigest);
925
926 // Get IDs from DeviceInfo.
927 bytevec csr;
928 irpcStatus =
929 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
930 ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getMessage();
931
932 auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
933 ASSERT_TRUE(result) << result.message();
934
935 std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
936 ASSERT_TRUE(csrPayload);
937
938 auto deviceInfo = csrPayload->get(2)->asMap();
939 ASSERT_TRUE(deviceInfo);
940
941 auto vbState = deviceInfo->get("vb_state")->asTstr();
942 auto bootloaderState = deviceInfo->get("bootloader_state")->asTstr();
943 auto vbmetaDigest = deviceInfo->get("vbmeta_digest")->asBstr();
944 auto systemPatchLevel = deviceInfo->get("system_patch_level")->asUint();
945 auto vendorPatchLevel = deviceInfo->get("vendor_patch_level")->asUint();
946 auto bootPatchLevel = deviceInfo->get("boot_patch_level")->asUint();
947 auto securityLevel = deviceInfo->get("security_level")->asTstr();
948
949 ASSERT_TRUE(vbState);
950 ASSERT_TRUE(bootloaderState);
951 ASSERT_TRUE(vbmetaDigest);
952 ASSERT_TRUE(systemPatchLevel);
953 ASSERT_TRUE(vendorPatchLevel);
954 ASSERT_TRUE(bootPatchLevel);
955 ASSERT_TRUE(securityLevel);
956
957 auto kmDeviceName = device_suffix(GetParam());
958
959 // Compare DeviceInfo against IDs attested by KeyMint.
960 ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") ||
961 (securityLevel->value() == "strongbox" && kmDeviceName == "strongbox"));
962 ASSERT_TRUE((vbState->value() == "green" && attestedVbState == VerifiedBoot::VERIFIED) ||
963 (vbState->value() == "yellow" && attestedVbState == VerifiedBoot::SELF_SIGNED) ||
964 (vbState->value() == "orange" && attestedVbState == VerifiedBoot::UNVERIFIED));
965 ASSERT_TRUE((bootloaderState->value() == "locked" && attestedBootloaderState) ||
966 (bootloaderState->value() == "unlocked" && !attestedBootloaderState));
967 ASSERT_EQ(vbmetaDigest->value(), attestedVbmetaDigest);
968 ASSERT_EQ(systemPatchLevel->value(), attestedSystemPatchLevel.value());
969 ASSERT_EQ(vendorPatchLevel->value(), attestedVendorPatchLevel.value());
970 ASSERT_EQ(bootPatchLevel->value(), attestedBootPatchLevel.value());
971}
972
Tri Vo0d6204e2022-09-29 16:15:34 -0700973INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
974
Max Biresa9b3bb92022-11-21 23:02:09 -0800975using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
976
977INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
978
979TEST_P(VsrRequirementTest, VsrEnforcementTest) {
980 RpcHardwareInfo hwInfo;
981 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
982 int vsr_api_level = get_vsr_api_level();
983 if (vsr_api_level < 34) {
984 GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
985 << vsr_api_level;
986 }
987 EXPECT_GE(hwInfo.versionNumber, 3)
988 << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
989}
990
Shawn Willden274bb552020-09-30 22:39:22 -0600991} // namespace aidl::android::hardware::security::keymint::test