blob: f68ff914d56835d76b792d5277543fdf918dcfa9 [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;
Andrew Scull21461522024-03-25 15:08:08 +000058const string DEFAULT_INSTANCE_NAME =
59 "android.hardware.security.keymint.IRemotelyProvisionedComponent/default";
Alice Wang895f4b32023-11-14 07:38:18 +000060const string RKP_VM_INSTANCE_NAME =
61 "android.hardware.security.keymint.IRemotelyProvisionedComponent/avf";
Andrew Scull21461522024-03-25 15:08:08 +000062const string KEYMINT_STRONGBOX_INSTANCE_NAME =
63 "android.hardware.security.keymint.IKeyMintDevice/strongbox";
Tommy Chiufde3ad12023-03-17 05:58:28 +000064
Shawn Willden274bb552020-09-30 22:39:22 -060065#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070066 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060067 INSTANTIATE_TEST_SUITE_P( \
68 PerInstance, name, \
69 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
70 ::android::PrintInstanceNameToString)
71
Seth Moorefc86bf42021-12-09 14:07:04 -080072using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060073using bytevec = std::vector<uint8_t>;
74using testing::MatchesRegex;
75using namespace remote_prov;
76using namespace keymaster;
77
78bytevec string_to_bytevec(const char* s) {
79 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
80 return bytevec(p, p + strlen(s));
81}
82
David Drysdalee99ed862021-03-15 16:43:06 +000083ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
84 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
85 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
86 return "COSE Mac0 parse failed";
87 }
88 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
89 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
90 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
91 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
92 if (!protParams || !unprotParams || !payload || !tag) {
93 return "Invalid COSE_Sign1: missing content";
94 }
95 auto corruptMac0 = cppbor::Array();
96 corruptMac0.add(protParams->clone());
97 corruptMac0.add(unprotParams->clone());
98 corruptMac0.add(payload->clone());
99 vector<uint8_t> tagData = tag->value();
100 tagData[0] ^= 0x08;
101 tagData[tagData.size() - 1] ^= 0x80;
102 corruptMac0.add(cppbor::Bstr(tagData));
103
104 return MacedPublicKey{corruptMac0.encode()};
105}
106
David Drysdalecceca9f2021-03-12 15:49:47 +0000107ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
108 if (coseSign1->size() != kCoseSign1EntryCount) {
109 return "Invalid COSE_Sign1, wrong entry count";
110 }
111 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
112 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
113 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
114 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
115 if (!protectedParams || !unprotectedParams || !payload || !signature) {
116 return "Invalid COSE_Sign1: missing content";
117 }
118
119 auto corruptSig = cppbor::Array();
120 corruptSig.add(protectedParams->clone());
121 corruptSig.add(unprotectedParams->clone());
122 corruptSig.add(payload->clone());
123 vector<uint8_t> sigData = signature->value();
124 sigData[0] ^= 0x08;
125 corruptSig.add(cppbor::Bstr(sigData));
126
127 return std::move(corruptSig);
128}
129
Seth Moore19acbe92021-06-23 15:15:52 -0700130ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
131 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000132 if (!chain || !chain->asArray()) {
133 return "EekChain parse failed";
134 }
135
136 cppbor::Array* eekChain = chain->asArray();
137 if (which >= eekChain->size()) {
138 return "selected sig out of range";
139 }
140 auto corruptChain = cppbor::Array();
141
142 for (int ii = 0; ii < eekChain->size(); ++ii) {
143 if (ii == which) {
144 auto sig = corrupt_sig(eekChain->get(which)->asArray());
145 if (!sig) {
146 return "Failed to build corrupted signature" + sig.moveMessage();
147 }
148 corruptChain.add(sig.moveValue());
149 } else {
150 corruptChain.add(eekChain->get(ii)->clone());
151 }
152 }
Seth Moore19acbe92021-06-23 15:15:52 -0700153 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000154}
155
David Drysdale4d3c2982021-03-31 18:21:40 +0100156string device_suffix(const string& name) {
157 size_t pos = name.find('/');
158 if (pos == string::npos) {
159 return name;
160 }
161 return name.substr(pos + 1);
162}
163
164bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
165 string rp_suffix = device_suffix(rp_name);
166
167 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
168 for (const string& km_name : km_names) {
169 // If the suffix of the KeyMint instance equals the suffix of the
170 // RemotelyProvisionedComponent instance, assume they match.
171 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
172 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
173 *keyMint = IKeyMintDevice::fromBinder(binder);
174 return true;
175 }
176 }
177 return false;
178}
179
Shawn Willden274bb552020-09-30 22:39:22 -0600180} // namespace
181
182class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
183 public:
184 virtual void SetUp() override {
185 if (AServiceManager_isDeclared(GetParam().c_str())) {
186 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
187 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
188 }
189 ASSERT_NE(provisionable_, nullptr);
Alice Wang895f4b32023-11-14 07:38:18 +0000190 auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo);
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000191 isRkpVmInstance_ = GetParam() == RKP_VM_INSTANCE_NAME;
192 if (isRkpVmInstance_) {
Alice Wang46ff2862024-05-14 07:07:05 +0000193 if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
194 GTEST_SKIP() << "The RKP VM is not supported on this system.";
195 }
196 int apiLevel = get_vsr_api_level();
197 if (apiLevel < __ANDROID_API_V__) {
198 GTEST_SKIP() << "The RKP VM is supported only on V+ devices. Vendor API level: "
199 << apiLevel;
200 }
Alice Wang895f4b32023-11-14 07:38:18 +0000201 }
202 ASSERT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600203 }
204
205 static vector<string> build_params() {
206 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
207 return params;
208 }
209
210 protected:
211 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000212 RpcHardwareInfo rpcHardwareInfo;
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000213 bool isRkpVmInstance_;
Shawn Willden274bb552020-09-30 22:39:22 -0600214};
215
Seth Moorefc86bf42021-12-09 14:07:04 -0800216/**
217 * Verify that every implementation reports a different unique id.
218 */
219TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
220 std::set<std::string> uniqueIds;
221 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
222 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
223 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
224 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
225 IRemotelyProvisionedComponent::fromBinder(binder);
226 ASSERT_NE(rpc, nullptr);
227
228 RpcHardwareInfo hwInfo;
Alice Wang895f4b32023-11-14 07:38:18 +0000229 auto status = rpc->getHardwareInfo(&hwInfo);
230 if (hal == RKP_VM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
231 GTEST_SKIP() << "The RKP VM is not supported on this system.";
232 }
233 ASSERT_TRUE(status.isOk());
Seth Moorefc86bf42021-12-09 14:07:04 -0800234
Tri Vodd12c482022-10-12 22:41:28 +0000235 if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800236 ASSERT_TRUE(hwInfo.uniqueId);
237 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
238 EXPECT_TRUE(wasInserted);
239 } else {
240 ASSERT_FALSE(hwInfo.uniqueId);
241 }
242 }
243}
244
Andrew Scull21461522024-03-25 15:08:08 +0000245/**
246 * Verify that the default implementation supports DICE if there is a StrongBox KeyMint instance
247 * on the device.
248 */
249// @VsrTest = 3.10-015
250TEST(NonParameterizedTests, requireDiceOnDefaultInstanceIfStrongboxPresent) {
251 int vsr_api_level = get_vsr_api_level();
252 if (vsr_api_level < 35) {
253 GTEST_SKIP() << "Applies only to VSR API level 35 or newer, this device is: "
254 << vsr_api_level;
255 }
256
257 if (!AServiceManager_isDeclared(KEYMINT_STRONGBOX_INSTANCE_NAME.c_str())) {
258 GTEST_SKIP() << "Strongbox is not present on this device.";
259 }
260
261 ::ndk::SpAIBinder binder(AServiceManager_waitForService(DEFAULT_INSTANCE_NAME.c_str()));
262 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
263 IRemotelyProvisionedComponent::fromBinder(binder);
264 ASSERT_NE(rpc, nullptr);
265
266 bytevec challenge = randomBytes(64);
267 bytevec csr;
268 auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
269 EXPECT_TRUE(status.isOk()) << status.getDescription();
270
271 auto result = isCsrWithProperDiceChain(csr);
272 ASSERT_TRUE(result) << result.message();
273 ASSERT_TRUE(*result);
274}
275
Seth Moorefc86bf42021-12-09 14:07:04 -0800276using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
277
278INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
279
280/**
281 * Verify that a valid curve is reported by the implementation.
282 */
283TEST_P(GetHardwareInfoTests, supportsValidCurve) {
284 RpcHardwareInfo hwInfo;
285 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
286
Andrew Scullf2ae1932023-04-24 19:09:09 +0000287 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_EEK) {
288 ASSERT_EQ(hwInfo.supportedEekCurve, RpcHardwareInfo::CURVE_NONE)
289 << "Invalid curve: " << hwInfo.supportedEekCurve;
290 return;
Hasini Gunasinghe666b2712023-01-05 21:35:51 +0000291 }
Andrew Scullf2ae1932023-04-24 19:09:09 +0000292
293 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
Seth Moorefc86bf42021-12-09 14:07:04 -0800294 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
295 << "Invalid curve: " << hwInfo.supportedEekCurve;
296}
297
298/**
299 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
300 */
301TEST_P(GetHardwareInfoTests, uniqueId) {
Tri Vodd12c482022-10-12 22:41:28 +0000302 if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800303 return;
304 }
305
306 RpcHardwareInfo hwInfo;
307 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
308 ASSERT_TRUE(hwInfo.uniqueId);
309 EXPECT_GE(hwInfo.uniqueId->size(), 1);
310 EXPECT_LE(hwInfo.uniqueId->size(), 32);
311}
312
Tri Vo9cab73c2022-10-28 13:40:24 -0700313/**
314 * Verify implementation supports at least MIN_SUPPORTED_NUM_KEYS_IN_CSR keys in a CSR.
315 */
316TEST_P(GetHardwareInfoTests, supportedNumKeysInCsr) {
Andrew Scullf2ae1932023-04-24 19:09:09 +0000317 if (rpcHardwareInfo.versionNumber < VERSION_WITH_SUPPORTED_NUM_KEYS_IN_CSR) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700318 return;
319 }
320
321 RpcHardwareInfo hwInfo;
322 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
323 ASSERT_GE(hwInfo.supportedNumKeysInCsr, RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR);
324}
325
Shawn Willden274bb552020-09-30 22:39:22 -0600326using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
327
328INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
329
330/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000331 * Generate and validate a production-mode key. MAC tag can't be verified, but
332 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600333 */
Max Bires126869a2021-02-21 18:32:59 -0800334TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600335 MacedPublicKey macedPubKey;
336 bytevec privateKeyBlob;
337 bool testMode = false;
338 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
339 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000340 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800341 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100342}
343
344/**
345 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
346 */
347TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
348 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
349 std::shared_ptr<IKeyMintDevice> keyMint;
350 if (!matching_keymint_device(GetParam(), &keyMint)) {
351 // No matching IKeyMintDevice.
352 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
353 return;
354 }
355 KeyMintHardwareInfo info;
356 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
357
358 MacedPublicKey macedPubKey;
359 bytevec privateKeyBlob;
360 bool testMode = false;
361 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
362 ASSERT_TRUE(status.isOk());
363 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800364 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100365
David Drysdalef0d516d2021-03-22 07:51:43 +0000366 AttestationKey attestKey;
367 attestKey.keyBlob = std::move(privateKeyBlob);
368 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600369
David Drysdalef0d516d2021-03-22 07:51:43 +0000370 // Generate an ECDSA key that is attested by the generated P256 keypair.
371 AuthorizationSet keyDesc = AuthorizationSetBuilder()
372 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100373 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000374 .AttestationChallenge("foo")
375 .AttestationApplicationId("bar")
376 .Digest(Digest::NONE)
377 .SetDefaultValidity();
378 KeyCreationResult creationResult;
379 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
380 ASSERT_TRUE(result.isOk());
381 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
382 vector<KeyCharacteristics> attested_key_characteristics =
383 std::move(creationResult.keyCharacteristics);
384 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
385 EXPECT_EQ(attested_key_cert_chain.size(), 1);
386
David Drysdale7dff4fc2021-12-10 10:10:52 +0000387 int32_t aidl_version = 0;
388 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000389 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
390 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000391 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000392 info.securityLevel,
393 attested_key_cert_chain[0].encodedCertificate));
394
395 // Attestation by itself is not valid (last entry is not self-signed).
396 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
397
398 // The signature over the attested key should correspond to the P256 public key.
399 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
400 ASSERT_TRUE(key_cert.get());
401 EVP_PKEY_Ptr signing_pubkey;
402 p256_pub_key(coseKeyData, &signing_pubkey);
403 ASSERT_TRUE(signing_pubkey.get());
404
405 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
406 << "Verification of attested certificate failed "
407 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600408}
409
410/**
411 * Generate and validate a test-mode key.
412 */
Max Bires126869a2021-02-21 18:32:59 -0800413TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600414 MacedPublicKey macedPubKey;
415 bytevec privateKeyBlob;
416 bool testMode = true;
417 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
Andrew Scullf2ae1932023-04-24 19:09:09 +0000418
419 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
420 ASSERT_FALSE(status.isOk());
421 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
422 return;
423 }
424
Shawn Willden274bb552020-09-30 22:39:22 -0600425 ASSERT_TRUE(status.isOk());
Tri Vob0b8acc2022-11-30 16:22:23 -0800426 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600427}
428
Tri Vo0d6204e2022-09-29 16:15:34 -0700429class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
Shawn Willden274bb552020-09-30 22:39:22 -0600430 protected:
Tri Vo0d6204e2022-09-29 16:15:34 -0700431 CertificateRequestTestBase()
432 : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
David Drysdalecceca9f2021-03-12 15:49:47 +0000433
Seth Moore19acbe92021-06-23 15:15:52 -0700434 void generateTestEekChain(size_t eekLength) {
subrahmanyamanfb213d62022-02-02 23:10:55 +0000435 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
David Drysdale08696a72022-03-10 10:43:25 +0000436 ASSERT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700437 if (chain) testEekChain_ = chain.moveValue();
438 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600439 }
440
441 void generateKeys(bool testMode, size_t numKeys) {
442 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
443 cborKeysToSign_ = cppbor::Array();
444
445 for (auto& key : keysToSign_) {
446 bytevec privateKeyBlob;
447 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
Frederick Mayle9891be02023-11-03 14:39:24 -0700448 ASSERT_TRUE(status.isOk()) << status.getDescription();
Shawn Willden274bb552020-09-30 22:39:22 -0600449
David Drysdalec8400772021-03-11 12:35:11 +0000450 vector<uint8_t> payload_value;
Tri Vob0b8acc2022-11-30 16:22:23 -0800451 check_maced_pubkey(key, testMode, &payload_value);
David Drysdalec8400772021-03-11 12:35:11 +0000452 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600453 }
454 }
455
456 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700457 size_t testEekLength_;
458 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000459 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600460 std::vector<MacedPublicKey> keysToSign_;
461 cppbor::Array cborKeysToSign_;
462};
463
Tri Vo0d6204e2022-09-29 16:15:34 -0700464class CertificateRequestTest : public CertificateRequestTestBase {
465 protected:
466 void SetUp() override {
467 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000468 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700469
Andrew Scullf2ae1932023-04-24 19:09:09 +0000470 if (rpcHardwareInfo.versionNumber >= VERSION_WITH_CERTIFICATE_REQUEST_V2) {
Andrew Scull95b31312023-03-27 19:16:07 +0000471 GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
472 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
Tri Vo0d6204e2022-09-29 16:15:34 -0700473 }
474 }
475};
476
Shawn Willden274bb552020-09-30 22:39:22 -0600477/**
478 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
479 * content.
480 */
Max Bires126869a2021-02-21 18:32:59 -0800481TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600482 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000483 for (size_t eekLength : {2, 3, 7}) {
484 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700485 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600486
David Drysdalecceca9f2021-03-12 15:49:47 +0000487 bytevec keysToSignMac;
488 DeviceInfo deviceInfo;
489 ProtectedData protectedData;
490 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700491 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000492 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700493 ASSERT_TRUE(status.isOk()) << status.getDescription();
David Drysdalecceca9f2021-03-12 15:49:47 +0000494
Seth Moore2fc6f832022-09-13 16:10:11 -0700495 auto result = verifyProductionProtectedData(
496 deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
497 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
498 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000499 }
Shawn Willden274bb552020-09-30 22:39:22 -0600500}
501
502/**
Seth Moore42c11332021-07-02 15:38:17 -0700503 * Ensure that test mode outputs a unique BCC root key every time we request a
504 * certificate request. Else, it's possible that the test mode API could be used
505 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
506 * device public key multiple times.
507 */
508TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
509 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700510
511 bytevec keysToSignMac;
512 DeviceInfo deviceInfo;
513 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000514 generateTestEekChain(3);
Seth Moore42c11332021-07-02 15:38:17 -0700515 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700516 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
517 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700518 ASSERT_TRUE(status.isOk()) << status.getDescription();
Seth Moore42c11332021-07-02 15:38:17 -0700519
Seth Moore2fc6f832022-09-13 16:10:11 -0700520 auto firstBcc = verifyProductionProtectedData(
521 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
522 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
523 ASSERT_TRUE(firstBcc) << firstBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700524
Seth Moore19acbe92021-06-23 15:15:52 -0700525 status = provisionable_->generateCertificateRequest(
526 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
527 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700528 ASSERT_TRUE(status.isOk()) << status.getDescription();
Seth Moore42c11332021-07-02 15:38:17 -0700529
Seth Moore2fc6f832022-09-13 16:10:11 -0700530 auto secondBcc = verifyProductionProtectedData(
531 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
532 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
533 ASSERT_TRUE(secondBcc) << secondBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700534
535 // Verify that none of the keys in the first BCC are repeated in the second one.
Seth Moore2fc6f832022-09-13 16:10:11 -0700536 for (const auto& i : *firstBcc) {
537 for (auto& j : *secondBcc) {
Seth Moore42c11332021-07-02 15:38:17 -0700538 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
539 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
540 }
541 }
542}
543
544/**
Seth Moore19acbe92021-06-23 15:15:52 -0700545 * Generate an 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_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600550 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000551
Seth Moore19acbe92021-06-23 15:15:52 -0700552 bytevec keysToSignMac;
553 DeviceInfo deviceInfo;
554 ProtectedData protectedData;
555 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000556 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
557 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700558 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600559}
560
561/**
562 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
563 */
Max Bires126869a2021-02-21 18:32:59 -0800564TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600565 bool testMode = true;
566 generateKeys(testMode, 4 /* numKeys */);
567
David Drysdalecceca9f2021-03-12 15:49:47 +0000568 for (size_t eekLength : {2, 3, 7}) {
569 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700570 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600571
David Drysdalecceca9f2021-03-12 15:49:47 +0000572 bytevec keysToSignMac;
573 DeviceInfo deviceInfo;
574 ProtectedData protectedData;
575 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700576 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000577 &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700578 ASSERT_TRUE(status.isOk()) << status.getDescription();
David Drysdalecceca9f2021-03-12 15:49:47 +0000579
Seth Moore2fc6f832022-09-13 16:10:11 -0700580 auto result = verifyProductionProtectedData(
581 deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
582 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
583 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000584 }
Shawn Willden274bb552020-09-30 22:39:22 -0600585}
586
587/**
Seth Moore19acbe92021-06-23 15:15:52 -0700588 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
589 * is not run by default. Not all devices are GMS devices, and therefore they do not all
590 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600591 */
Seth Moore19acbe92021-06-23 15:15:52 -0700592TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600593 bool testMode = false;
594 generateKeys(testMode, 4 /* numKeys */);
595
Seth Moore19acbe92021-06-23 15:15:52 -0700596 bytevec keysToSignMac;
597 DeviceInfo deviceInfo;
598 ProtectedData protectedData;
599 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000600 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
601 &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700602 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000603}
604
605/**
David Drysdalee99ed862021-03-15 16:43:06 +0000606 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
607 */
608TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
609 bool testMode = true;
610 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000611 auto result = corrupt_maced_key(keysToSign_[0]);
612 ASSERT_TRUE(result) << result.moveMessage();
613 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000614
615 bytevec keysToSignMac;
616 DeviceInfo deviceInfo;
617 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000618 generateTestEekChain(3);
David Drysdalee99ed862021-03-15 16:43:06 +0000619 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700620 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
621 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700622 ASSERT_FALSE(status.isOk()) << status.getDescription();
David Drysdalee99ed862021-03-15 16:43:06 +0000623 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
624}
625
626/**
627 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
628 */
629TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700630 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000631 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000632 auto result = corrupt_maced_key(keysToSign_[0]);
633 ASSERT_TRUE(result) << result.moveMessage();
634 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000635
636 bytevec keysToSignMac;
637 DeviceInfo deviceInfo;
638 ProtectedData protectedData;
639 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000640 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
641 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700642 ASSERT_FALSE(status.isOk()) << status.getDescription();
Seth Moore19acbe92021-06-23 15:15:52 -0700643 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000644}
645
646/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000647 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
648 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000649 */
650TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
651 bool testMode = false;
652 generateKeys(testMode, 4 /* numKeys */);
653
subrahmanyamanfb213d62022-02-02 23:10:55 +0000654 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
Seth Moore19acbe92021-06-23 15:15:52 -0700655 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
656 ASSERT_NE(parsedChain, nullptr) << parseErr;
657 ASSERT_NE(parsedChain->asArray(), nullptr);
658
659 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
660 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000661 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000662
663 bytevec keysToSignMac;
664 DeviceInfo deviceInfo;
665 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700666 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
667 challenge_, &deviceInfo,
668 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000669 ASSERT_FALSE(status.isOk());
670 ASSERT_EQ(status.getServiceSpecificError(),
671 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
672 }
673}
674
675/**
676 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
677 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000678 */
679TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
680 bool testMode = false;
681 generateKeys(testMode, 4 /* numKeys */);
682
683 // Build an EEK chain that omits the first self-signed cert.
684 auto truncatedChain = cppbor::Array();
subrahmanyamanfb213d62022-02-02 23:10:55 +0000685 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
David Drysdalecceca9f2021-03-12 15:49:47 +0000686 ASSERT_TRUE(chain);
687 auto eekChain = chain->asArray();
688 ASSERT_NE(eekChain, nullptr);
689 for (size_t ii = 1; ii < eekChain->size(); ii++) {
690 truncatedChain.add(eekChain->get(ii)->clone());
691 }
692
Shawn Willden274bb552020-09-30 22:39:22 -0600693 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700694 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600695 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000696 auto status = provisionable_->generateCertificateRequest(
697 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
698 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600699 ASSERT_FALSE(status.isOk());
700 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
701}
702
703/**
704 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
705 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
706 */
Max Bires126869a2021-02-21 18:32:59 -0800707TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600708 generateKeys(false /* testMode */, 2 /* numKeys */);
709
710 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700711 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600712 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000713 generateTestEekChain(3);
Max Biresfdbb9042021-03-23 12:43:38 -0700714 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700715 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700716 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600717 ASSERT_FALSE(status.isOk());
718 ASSERT_EQ(status.getServiceSpecificError(),
719 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
720}
721
722/**
723 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
724 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
725 */
Max Bires126869a2021-02-21 18:32:59 -0800726TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600727 generateKeys(true /* testMode */, 2 /* numKeys */);
728
729 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700730 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600731 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000732 generateTestEekChain(3);
Shawn Willden274bb552020-09-30 22:39:22 -0600733 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700734 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000735 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600736 ASSERT_FALSE(status.isOk());
737 ASSERT_EQ(status.getServiceSpecificError(),
738 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
739}
740
741INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
742
Tri Vo0d6204e2022-09-29 16:15:34 -0700743class CertificateRequestV2Test : public CertificateRequestTestBase {
744 void SetUp() override {
745 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000746 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700747
Andrew Scullf2ae1932023-04-24 19:09:09 +0000748 if (rpcHardwareInfo.versionNumber < VERSION_WITH_CERTIFICATE_REQUEST_V2) {
Tri Vo0d6204e2022-09-29 16:15:34 -0700749 GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
750 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
751 }
752 }
753};
754
755/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000756 * Generate an empty certificate request with all possible length of challenge, and decrypt and
757 * verify the structure and content.
Tri Vo0d6204e2022-09-29 16:15:34 -0700758 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700759// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700760TEST_P(CertificateRequestV2Test, EmptyRequest) {
761 bytevec csr;
762
Tommy Chiufde3ad12023-03-17 05:58:28 +0000763 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
764 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
765 auto challenge = randomBytes(size);
766 auto status =
767 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700768 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700769
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000770 auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge,
771 isRkpVmInstance_);
Tommy Chiufde3ad12023-03-17 05:58:28 +0000772 ASSERT_TRUE(result) << result.message();
773 }
Tri Vo0d6204e2022-09-29 16:15:34 -0700774}
775
776/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000777 * Generate a non-empty certificate request with all possible length of challenge. Decrypt, parse
778 * and validate the contents.
Tri Vo0d6204e2022-09-29 16:15:34 -0700779 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700780// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700781TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
782 generateKeys(false /* testMode */, 1 /* numKeys */);
783
784 bytevec csr;
785
Tommy Chiufde3ad12023-03-17 05:58:28 +0000786 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
787 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
788 auto challenge = randomBytes(size);
789 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700790 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700791
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000792 auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge,
793 isRkpVmInstance_);
Tommy Chiufde3ad12023-03-17 05:58:28 +0000794 ASSERT_TRUE(result) << result.message();
795 }
796}
797
798/**
799 * Generate an empty certificate request with invalid size of challenge
800 */
801TEST_P(CertificateRequestV2Test, EmptyRequestWithInvalidChallengeFail) {
802 bytevec csr;
803
804 auto status = provisionable_->generateCertificateRequestV2(
805 /* keysToSign */ {}, randomBytes(MAX_CHALLENGE_SIZE + 1), &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700806 EXPECT_FALSE(status.isOk()) << status.getDescription();
Tommy Chiufde3ad12023-03-17 05:58:28 +0000807 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_FAILED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700808}
809
810/**
Andrew Scullfb49ad22022-11-09 21:02:48 +0000811 * Generate a non-empty certificate request. Make sure contents are reproducible but allow for the
812 * signature to be different since algorithms including ECDSA P-256 can include a random value.
Tri Vo0d6204e2022-09-29 16:15:34 -0700813 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700814// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700815TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
816 generateKeys(false /* testMode */, 1 /* numKeys */);
817
818 bytevec csr;
819
820 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700821 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700822
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000823 auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_,
824 isRkpVmInstance_);
Andrew Scullfb49ad22022-11-09 21:02:48 +0000825 ASSERT_TRUE(firstCsr) << firstCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700826
827 status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700828 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700829
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000830 auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_,
831 isRkpVmInstance_);
Andrew Scullfb49ad22022-11-09 21:02:48 +0000832 ASSERT_TRUE(secondCsr) << secondCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700833
Andrew Scullfb49ad22022-11-09 21:02:48 +0000834 ASSERT_EQ(**firstCsr, **secondCsr);
Tri Vo0d6204e2022-09-29 16:15:34 -0700835}
836
837/**
838 * Generate a non-empty certificate request with multiple keys.
839 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700840// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700841TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700842 generateKeys(false /* testMode */, rpcHardwareInfo.supportedNumKeysInCsr /* numKeys */);
Tri Vo0d6204e2022-09-29 16:15:34 -0700843
844 bytevec csr;
845
846 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700847 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700848
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000849 auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_,
850 isRkpVmInstance_);
Tri Vo0d6204e2022-09-29 16:15:34 -0700851 ASSERT_TRUE(result) << result.message();
852}
853
854/**
855 * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
856 */
857TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
858 generateKeys(false /* testMode */, 1 /* numKeys */);
859 auto result = corrupt_maced_key(keysToSign_[0]);
860 ASSERT_TRUE(result) << result.moveMessage();
861 MacedPublicKey keyWithCorruptMac = result.moveValue();
862
863 bytevec csr;
864 auto status =
865 provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700866 ASSERT_FALSE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700867 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
868}
869
870/**
Andrew Scullf2ae1932023-04-24 19:09:09 +0000871 * Call generateCertificateRequest(). Make sure it's removed.
Tri Vo0d6204e2022-09-29 16:15:34 -0700872 */
Andrew Scullf2ae1932023-04-24 19:09:09 +0000873TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed_prodMode) {
874 bytevec keysToSignMac;
875 DeviceInfo deviceInfo;
876 ProtectedData protectedData;
877 auto status = provisionable_->generateCertificateRequest(
878 false /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
879 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700880 ASSERT_FALSE(status.isOk()) << status.getDescription();
Andrew Scullf2ae1932023-04-24 19:09:09 +0000881 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700882}
883
Andrew Scull95b31312023-03-27 19:16:07 +0000884/**
Andrew Scullf2ae1932023-04-24 19:09:09 +0000885 * Call generateCertificateRequest() in test mode. Make sure it's removed.
Andrew Scull95b31312023-03-27 19:16:07 +0000886 */
Andrew Scullf2ae1932023-04-24 19:09:09 +0000887TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed_testMode) {
Andrew Scull95b31312023-03-27 19:16:07 +0000888 bytevec keysToSignMac;
889 DeviceInfo deviceInfo;
890 ProtectedData protectedData;
891 auto status = provisionable_->generateCertificateRequest(
892 true /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
893 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700894 ASSERT_FALSE(status.isOk()) << status.getDescription();
Andrew Scull95b31312023-03-27 19:16:07 +0000895 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
896}
897
Tri Voec50ee12023-02-14 16:29:53 -0800898void parse_root_of_trust(const vector<uint8_t>& attestation_cert,
899 vector<uint8_t>* verified_boot_key, VerifiedBoot* verified_boot_state,
900 bool* device_locked, vector<uint8_t>* verified_boot_hash) {
901 X509_Ptr cert(parse_cert_blob(attestation_cert));
902 ASSERT_TRUE(cert.get());
903
904 ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
905 ASSERT_TRUE(attest_rec);
906
907 auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, verified_boot_key,
908 verified_boot_state, device_locked, verified_boot_hash);
909 ASSERT_EQ(error, ErrorCode::OK);
910}
911
912/**
913 * Generate a CSR and verify DeviceInfo against IDs attested by KeyMint.
914 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700915// @VsrTest = 3.10-015
Tri Voec50ee12023-02-14 16:29:53 -0800916TEST_P(CertificateRequestV2Test, DeviceInfo) {
917 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
918 std::shared_ptr<IKeyMintDevice> keyMint;
919 if (!matching_keymint_device(GetParam(), &keyMint)) {
920 // No matching IKeyMintDevice.
921 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
922 return;
923 }
924 KeyMintHardwareInfo info;
925 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
926
927 // Get IDs attested by KeyMint.
928 MacedPublicKey macedPubKey;
929 bytevec privateKeyBlob;
930 auto irpcStatus =
931 provisionable_->generateEcdsaP256KeyPair(false, &macedPubKey, &privateKeyBlob);
932 ASSERT_TRUE(irpcStatus.isOk());
933
934 AttestationKey attestKey;
935 attestKey.keyBlob = std::move(privateKeyBlob);
936 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
937
938 // Generate an ECDSA key that is attested by the generated P256 keypair.
939 AuthorizationSet keyDesc = AuthorizationSetBuilder()
940 .Authorization(TAG_NO_AUTH_REQUIRED)
941 .EcdsaSigningKey(EcCurve::P_256)
942 .AttestationChallenge("foo")
943 .AttestationApplicationId("bar")
944 .Digest(Digest::NONE)
945 .SetDefaultValidity();
946 KeyCreationResult creationResult;
947 auto kmStatus = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
948 ASSERT_TRUE(kmStatus.isOk());
949
950 vector<KeyCharacteristics> key_characteristics = std::move(creationResult.keyCharacteristics);
951 vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain);
952 // We didn't provision the attestation key.
953 ASSERT_EQ(key_cert_chain.size(), 1);
954
955 // Parse attested patch levels.
956 auto auths = HwEnforcedAuthorizations(key_characteristics);
957
958 auto attestedSystemPatchLevel = auths.GetTagValue(TAG_OS_PATCHLEVEL);
959 auto attestedVendorPatchLevel = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
960 auto attestedBootPatchLevel = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
961
962 ASSERT_TRUE(attestedSystemPatchLevel.has_value());
963 ASSERT_TRUE(attestedVendorPatchLevel.has_value());
964 ASSERT_TRUE(attestedBootPatchLevel.has_value());
965
966 // Parse attested AVB values.
967 vector<uint8_t> key;
968 VerifiedBoot attestedVbState;
969 bool attestedBootloaderState;
970 vector<uint8_t> attestedVbmetaDigest;
971 parse_root_of_trust(key_cert_chain[0].encodedCertificate, &key, &attestedVbState,
972 &attestedBootloaderState, &attestedVbmetaDigest);
973
974 // Get IDs from DeviceInfo.
975 bytevec csr;
976 irpcStatus =
977 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700978 ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getDescription();
Tri Voec50ee12023-02-14 16:29:53 -0800979
980 auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
981 ASSERT_TRUE(result) << result.message();
982
983 std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
984 ASSERT_TRUE(csrPayload);
985
986 auto deviceInfo = csrPayload->get(2)->asMap();
987 ASSERT_TRUE(deviceInfo);
988
989 auto vbState = deviceInfo->get("vb_state")->asTstr();
990 auto bootloaderState = deviceInfo->get("bootloader_state")->asTstr();
991 auto vbmetaDigest = deviceInfo->get("vbmeta_digest")->asBstr();
992 auto systemPatchLevel = deviceInfo->get("system_patch_level")->asUint();
993 auto vendorPatchLevel = deviceInfo->get("vendor_patch_level")->asUint();
994 auto bootPatchLevel = deviceInfo->get("boot_patch_level")->asUint();
995 auto securityLevel = deviceInfo->get("security_level")->asTstr();
996
997 ASSERT_TRUE(vbState);
998 ASSERT_TRUE(bootloaderState);
999 ASSERT_TRUE(vbmetaDigest);
1000 ASSERT_TRUE(systemPatchLevel);
1001 ASSERT_TRUE(vendorPatchLevel);
1002 ASSERT_TRUE(bootPatchLevel);
1003 ASSERT_TRUE(securityLevel);
1004
1005 auto kmDeviceName = device_suffix(GetParam());
1006
1007 // Compare DeviceInfo against IDs attested by KeyMint.
1008 ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") ||
1009 (securityLevel->value() == "strongbox" && kmDeviceName == "strongbox"));
1010 ASSERT_TRUE((vbState->value() == "green" && attestedVbState == VerifiedBoot::VERIFIED) ||
1011 (vbState->value() == "yellow" && attestedVbState == VerifiedBoot::SELF_SIGNED) ||
1012 (vbState->value() == "orange" && attestedVbState == VerifiedBoot::UNVERIFIED));
1013 ASSERT_TRUE((bootloaderState->value() == "locked" && attestedBootloaderState) ||
1014 (bootloaderState->value() == "unlocked" && !attestedBootloaderState));
1015 ASSERT_EQ(vbmetaDigest->value(), attestedVbmetaDigest);
1016 ASSERT_EQ(systemPatchLevel->value(), attestedSystemPatchLevel.value());
1017 ASSERT_EQ(vendorPatchLevel->value(), attestedVendorPatchLevel.value());
1018 ASSERT_EQ(bootPatchLevel->value(), attestedBootPatchLevel.value());
1019}
1020
Tri Vo0d6204e2022-09-29 16:15:34 -07001021INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
1022
Max Biresa9b3bb92022-11-21 23:02:09 -08001023using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
1024
1025INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
1026
1027TEST_P(VsrRequirementTest, VsrEnforcementTest) {
1028 RpcHardwareInfo hwInfo;
1029 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
1030 int vsr_api_level = get_vsr_api_level();
1031 if (vsr_api_level < 34) {
1032 GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
1033 << vsr_api_level;
1034 }
1035 EXPECT_GE(hwInfo.versionNumber, 3)
1036 << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
1037}
1038
Shawn Willden274bb552020-09-30 22:39:22 -06001039} // namespace aidl::android::hardware::security::keymint::test