blob: bb0c790c1617cfb1571ccfed2772cce049b43f67 [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 Wangf112ec92024-10-08 07:30:28 +000058
Andrew Scull21461522024-03-25 15:08:08 +000059const string KEYMINT_STRONGBOX_INSTANCE_NAME =
60 "android.hardware.security.keymint.IKeyMintDevice/strongbox";
Tommy Chiufde3ad12023-03-17 05:58:28 +000061
Shawn Willden274bb552020-09-30 22:39:22 -060062#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070063 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060064 INSTANTIATE_TEST_SUITE_P( \
65 PerInstance, name, \
66 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
67 ::android::PrintInstanceNameToString)
68
Seth Moorefc86bf42021-12-09 14:07:04 -080069using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060070using bytevec = std::vector<uint8_t>;
71using testing::MatchesRegex;
72using namespace remote_prov;
73using namespace keymaster;
74
75bytevec string_to_bytevec(const char* s) {
76 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
77 return bytevec(p, p + strlen(s));
78}
79
David Drysdalee99ed862021-03-15 16:43:06 +000080ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
81 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
82 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
83 return "COSE Mac0 parse failed";
84 }
85 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
86 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
87 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
88 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
89 if (!protParams || !unprotParams || !payload || !tag) {
90 return "Invalid COSE_Sign1: missing content";
91 }
92 auto corruptMac0 = cppbor::Array();
93 corruptMac0.add(protParams->clone());
94 corruptMac0.add(unprotParams->clone());
95 corruptMac0.add(payload->clone());
96 vector<uint8_t> tagData = tag->value();
97 tagData[0] ^= 0x08;
98 tagData[tagData.size() - 1] ^= 0x80;
99 corruptMac0.add(cppbor::Bstr(tagData));
100
101 return MacedPublicKey{corruptMac0.encode()};
102}
103
David Drysdalecceca9f2021-03-12 15:49:47 +0000104ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
105 if (coseSign1->size() != kCoseSign1EntryCount) {
106 return "Invalid COSE_Sign1, wrong entry count";
107 }
108 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
109 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
110 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
111 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
112 if (!protectedParams || !unprotectedParams || !payload || !signature) {
113 return "Invalid COSE_Sign1: missing content";
114 }
115
116 auto corruptSig = cppbor::Array();
117 corruptSig.add(protectedParams->clone());
118 corruptSig.add(unprotectedParams->clone());
119 corruptSig.add(payload->clone());
120 vector<uint8_t> sigData = signature->value();
121 sigData[0] ^= 0x08;
122 corruptSig.add(cppbor::Bstr(sigData));
123
124 return std::move(corruptSig);
125}
126
Seth Moore19acbe92021-06-23 15:15:52 -0700127ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
128 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000129 if (!chain || !chain->asArray()) {
130 return "EekChain parse failed";
131 }
132
133 cppbor::Array* eekChain = chain->asArray();
134 if (which >= eekChain->size()) {
135 return "selected sig out of range";
136 }
137 auto corruptChain = cppbor::Array();
138
139 for (int ii = 0; ii < eekChain->size(); ++ii) {
140 if (ii == which) {
141 auto sig = corrupt_sig(eekChain->get(which)->asArray());
142 if (!sig) {
143 return "Failed to build corrupted signature" + sig.moveMessage();
144 }
145 corruptChain.add(sig.moveValue());
146 } else {
147 corruptChain.add(eekChain->get(ii)->clone());
148 }
149 }
Seth Moore19acbe92021-06-23 15:15:52 -0700150 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000151}
152
David Drysdale4d3c2982021-03-31 18:21:40 +0100153string device_suffix(const string& name) {
154 size_t pos = name.find('/');
155 if (pos == string::npos) {
156 return name;
157 }
158 return name.substr(pos + 1);
159}
160
161bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
162 string rp_suffix = device_suffix(rp_name);
163
164 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
165 for (const string& km_name : km_names) {
166 // If the suffix of the KeyMint instance equals the suffix of the
167 // RemotelyProvisionedComponent instance, assume they match.
168 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
169 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
170 *keyMint = IKeyMintDevice::fromBinder(binder);
171 return true;
172 }
173 }
174 return false;
175}
176
Shawn Willden274bb552020-09-30 22:39:22 -0600177} // namespace
178
179class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
180 public:
181 virtual void SetUp() override {
182 if (AServiceManager_isDeclared(GetParam().c_str())) {
183 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
184 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
185 }
186 ASSERT_NE(provisionable_, nullptr);
Alice Wang895f4b32023-11-14 07:38:18 +0000187 auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo);
Alice Wangf112ec92024-10-08 07:30:28 +0000188 isRkpVmInstance_ = GetParam() == RKPVM_INSTANCE_NAME;
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000189 if (isRkpVmInstance_) {
Alice Wang46ff2862024-05-14 07:07:05 +0000190 if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
191 GTEST_SKIP() << "The RKP VM is not supported on this system.";
192 }
193 int apiLevel = get_vsr_api_level();
194 if (apiLevel < __ANDROID_API_V__) {
195 GTEST_SKIP() << "The RKP VM is supported only on V+ devices. Vendor API level: "
196 << apiLevel;
197 }
Alice Wang895f4b32023-11-14 07:38:18 +0000198 }
199 ASSERT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600200 }
201
202 static vector<string> build_params() {
203 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
204 return params;
205 }
206
207 protected:
208 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000209 RpcHardwareInfo rpcHardwareInfo;
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000210 bool isRkpVmInstance_;
Shawn Willden274bb552020-09-30 22:39:22 -0600211};
212
Seth Moorefc86bf42021-12-09 14:07:04 -0800213/**
214 * Verify that every implementation reports a different unique id.
215 */
216TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
217 std::set<std::string> uniqueIds;
218 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
219 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
220 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
221 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
222 IRemotelyProvisionedComponent::fromBinder(binder);
223 ASSERT_NE(rpc, nullptr);
224
225 RpcHardwareInfo hwInfo;
Alice Wang895f4b32023-11-14 07:38:18 +0000226 auto status = rpc->getHardwareInfo(&hwInfo);
Alice Wangf112ec92024-10-08 07:30:28 +0000227 if (hal == RKPVM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
Alice Wang895f4b32023-11-14 07:38:18 +0000228 GTEST_SKIP() << "The RKP VM is not supported on this system.";
229 }
230 ASSERT_TRUE(status.isOk());
Seth Moorefc86bf42021-12-09 14:07:04 -0800231
Tri Vodd12c482022-10-12 22:41:28 +0000232 if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800233 ASSERT_TRUE(hwInfo.uniqueId);
234 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
235 EXPECT_TRUE(wasInserted);
236 } else {
237 ASSERT_FALSE(hwInfo.uniqueId);
238 }
239 }
240}
241
Andrew Scull21461522024-03-25 15:08:08 +0000242/**
243 * Verify that the default implementation supports DICE if there is a StrongBox KeyMint instance
244 * on the device.
245 */
246// @VsrTest = 3.10-015
247TEST(NonParameterizedTests, requireDiceOnDefaultInstanceIfStrongboxPresent) {
248 int vsr_api_level = get_vsr_api_level();
249 if (vsr_api_level < 35) {
250 GTEST_SKIP() << "Applies only to VSR API level 35 or newer, this device is: "
251 << vsr_api_level;
252 }
253
254 if (!AServiceManager_isDeclared(KEYMINT_STRONGBOX_INSTANCE_NAME.c_str())) {
255 GTEST_SKIP() << "Strongbox is not present on this device.";
256 }
257
258 ::ndk::SpAIBinder binder(AServiceManager_waitForService(DEFAULT_INSTANCE_NAME.c_str()));
259 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
260 IRemotelyProvisionedComponent::fromBinder(binder);
261 ASSERT_NE(rpc, nullptr);
262
263 bytevec challenge = randomBytes(64);
264 bytevec csr;
265 auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
266 EXPECT_TRUE(status.isOk()) << status.getDescription();
267
Alice Wangf112ec92024-10-08 07:30:28 +0000268 auto result = isCsrWithProperDiceChain(csr, DEFAULT_INSTANCE_NAME);
Andrew Scull21461522024-03-25 15:08:08 +0000269 ASSERT_TRUE(result) << result.message();
270 ASSERT_TRUE(*result);
271}
272
Seth Moorefc86bf42021-12-09 14:07:04 -0800273using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
274
275INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
276
277/**
278 * Verify that a valid curve is reported by the implementation.
279 */
280TEST_P(GetHardwareInfoTests, supportsValidCurve) {
281 RpcHardwareInfo hwInfo;
282 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
283
Andrew Scullf2ae1932023-04-24 19:09:09 +0000284 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_EEK) {
285 ASSERT_EQ(hwInfo.supportedEekCurve, RpcHardwareInfo::CURVE_NONE)
286 << "Invalid curve: " << hwInfo.supportedEekCurve;
287 return;
Hasini Gunasinghe666b2712023-01-05 21:35:51 +0000288 }
Andrew Scullf2ae1932023-04-24 19:09:09 +0000289
290 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
Seth Moorefc86bf42021-12-09 14:07:04 -0800291 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
292 << "Invalid curve: " << hwInfo.supportedEekCurve;
293}
294
295/**
296 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
297 */
298TEST_P(GetHardwareInfoTests, uniqueId) {
Tri Vodd12c482022-10-12 22:41:28 +0000299 if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800300 return;
301 }
302
303 RpcHardwareInfo hwInfo;
304 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
305 ASSERT_TRUE(hwInfo.uniqueId);
306 EXPECT_GE(hwInfo.uniqueId->size(), 1);
307 EXPECT_LE(hwInfo.uniqueId->size(), 32);
308}
309
Tri Vo9cab73c2022-10-28 13:40:24 -0700310/**
311 * Verify implementation supports at least MIN_SUPPORTED_NUM_KEYS_IN_CSR keys in a CSR.
312 */
313TEST_P(GetHardwareInfoTests, supportedNumKeysInCsr) {
Andrew Scullf2ae1932023-04-24 19:09:09 +0000314 if (rpcHardwareInfo.versionNumber < VERSION_WITH_SUPPORTED_NUM_KEYS_IN_CSR) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700315 return;
316 }
317
318 RpcHardwareInfo hwInfo;
319 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
320 ASSERT_GE(hwInfo.supportedNumKeysInCsr, RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR);
321}
322
Shawn Willden274bb552020-09-30 22:39:22 -0600323using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
324
325INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
326
327/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000328 * Generate and validate a production-mode key. MAC tag can't be verified, but
329 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600330 */
Max Bires126869a2021-02-21 18:32:59 -0800331TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600332 MacedPublicKey macedPubKey;
333 bytevec privateKeyBlob;
334 bool testMode = false;
335 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
336 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000337 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800338 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100339}
340
341/**
342 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
343 */
344TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
345 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
346 std::shared_ptr<IKeyMintDevice> keyMint;
347 if (!matching_keymint_device(GetParam(), &keyMint)) {
348 // No matching IKeyMintDevice.
349 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
350 return;
351 }
352 KeyMintHardwareInfo info;
353 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
354
355 MacedPublicKey macedPubKey;
356 bytevec privateKeyBlob;
357 bool testMode = false;
358 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
359 ASSERT_TRUE(status.isOk());
360 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800361 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100362
David Drysdalef0d516d2021-03-22 07:51:43 +0000363 AttestationKey attestKey;
364 attestKey.keyBlob = std::move(privateKeyBlob);
365 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600366
David Drysdalef0d516d2021-03-22 07:51:43 +0000367 // Generate an ECDSA key that is attested by the generated P256 keypair.
368 AuthorizationSet keyDesc = AuthorizationSetBuilder()
369 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100370 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000371 .AttestationChallenge("foo")
372 .AttestationApplicationId("bar")
373 .Digest(Digest::NONE)
374 .SetDefaultValidity();
375 KeyCreationResult creationResult;
376 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
377 ASSERT_TRUE(result.isOk());
378 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
379 vector<KeyCharacteristics> attested_key_characteristics =
380 std::move(creationResult.keyCharacteristics);
381 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
382 EXPECT_EQ(attested_key_cert_chain.size(), 1);
383
David Drysdale7dff4fc2021-12-10 10:10:52 +0000384 int32_t aidl_version = 0;
385 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000386 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
387 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000388 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000389 info.securityLevel,
390 attested_key_cert_chain[0].encodedCertificate));
391
392 // Attestation by itself is not valid (last entry is not self-signed).
393 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
394
395 // The signature over the attested key should correspond to the P256 public key.
396 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
397 ASSERT_TRUE(key_cert.get());
398 EVP_PKEY_Ptr signing_pubkey;
399 p256_pub_key(coseKeyData, &signing_pubkey);
400 ASSERT_TRUE(signing_pubkey.get());
401
402 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
403 << "Verification of attested certificate failed "
404 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600405}
406
407/**
408 * Generate and validate a test-mode key.
409 */
Max Bires126869a2021-02-21 18:32:59 -0800410TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600411 MacedPublicKey macedPubKey;
412 bytevec privateKeyBlob;
413 bool testMode = true;
414 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
Andrew Scullf2ae1932023-04-24 19:09:09 +0000415
416 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
417 ASSERT_FALSE(status.isOk());
418 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
419 return;
420 }
421
Shawn Willden274bb552020-09-30 22:39:22 -0600422 ASSERT_TRUE(status.isOk());
Tri Vob0b8acc2022-11-30 16:22:23 -0800423 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600424}
425
Tri Vo0d6204e2022-09-29 16:15:34 -0700426class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
Shawn Willden274bb552020-09-30 22:39:22 -0600427 protected:
Tri Vo0d6204e2022-09-29 16:15:34 -0700428 CertificateRequestTestBase()
429 : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
David Drysdalecceca9f2021-03-12 15:49:47 +0000430
Seth Moore19acbe92021-06-23 15:15:52 -0700431 void generateTestEekChain(size_t eekLength) {
subrahmanyamanfb213d62022-02-02 23:10:55 +0000432 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
David Drysdale08696a72022-03-10 10:43:25 +0000433 ASSERT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700434 if (chain) testEekChain_ = chain.moveValue();
435 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600436 }
437
438 void generateKeys(bool testMode, size_t numKeys) {
439 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
440 cborKeysToSign_ = cppbor::Array();
441
442 for (auto& key : keysToSign_) {
443 bytevec privateKeyBlob;
444 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
Frederick Mayle9891be02023-11-03 14:39:24 -0700445 ASSERT_TRUE(status.isOk()) << status.getDescription();
Shawn Willden274bb552020-09-30 22:39:22 -0600446
David Drysdalec8400772021-03-11 12:35:11 +0000447 vector<uint8_t> payload_value;
Tri Vob0b8acc2022-11-30 16:22:23 -0800448 check_maced_pubkey(key, testMode, &payload_value);
David Drysdalec8400772021-03-11 12:35:11 +0000449 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600450 }
451 }
452
453 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700454 size_t testEekLength_;
455 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000456 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600457 std::vector<MacedPublicKey> keysToSign_;
458 cppbor::Array cborKeysToSign_;
459};
460
Tri Vo0d6204e2022-09-29 16:15:34 -0700461class CertificateRequestTest : public CertificateRequestTestBase {
462 protected:
463 void SetUp() override {
464 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000465 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700466
Andrew Scullf2ae1932023-04-24 19:09:09 +0000467 if (rpcHardwareInfo.versionNumber >= VERSION_WITH_CERTIFICATE_REQUEST_V2) {
Andrew Scull95b31312023-03-27 19:16:07 +0000468 GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
469 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
Tri Vo0d6204e2022-09-29 16:15:34 -0700470 }
471 }
472};
473
Shawn Willden274bb552020-09-30 22:39:22 -0600474/**
475 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
476 * content.
477 */
Max Bires126869a2021-02-21 18:32:59 -0800478TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600479 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000480 for (size_t eekLength : {2, 3, 7}) {
481 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700482 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600483
David Drysdalecceca9f2021-03-12 15:49:47 +0000484 bytevec keysToSignMac;
485 DeviceInfo deviceInfo;
486 ProtectedData protectedData;
487 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700488 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000489 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700490 ASSERT_TRUE(status.isOk()) << status.getDescription();
David Drysdalecceca9f2021-03-12 15:49:47 +0000491
Sean Thomas2d2385b2024-11-07 23:56:03 +0000492 auto result = verifyProductionProtectedData(deviceInfo, cppbor::Array(), keysToSignMac,
493 protectedData, testEekChain_, eekId_,
494 rpcHardwareInfo, GetParam(), challenge_);
Seth Moore2fc6f832022-09-13 16:10:11 -0700495 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000496 }
Shawn Willden274bb552020-09-30 22:39:22 -0600497}
498
499/**
Seth Moore42c11332021-07-02 15:38:17 -0700500 * Ensure that test mode outputs a unique BCC root key every time we request a
501 * certificate request. Else, it's possible that the test mode API could be used
502 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
503 * device public key multiple times.
504 */
505TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
506 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700507
508 bytevec keysToSignMac;
509 DeviceInfo deviceInfo;
510 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000511 generateTestEekChain(3);
Seth Moore42c11332021-07-02 15:38:17 -0700512 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700513 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
514 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700515 ASSERT_TRUE(status.isOk()) << status.getDescription();
Seth Moore42c11332021-07-02 15:38:17 -0700516
Alice Wangf112ec92024-10-08 07:30:28 +0000517 auto firstBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(),
518 keysToSignMac, protectedData, testEekChain_,
Sean Thomas2d2385b2024-11-07 23:56:03 +0000519 eekId_, rpcHardwareInfo, GetParam(), challenge_);
Seth Moore2fc6f832022-09-13 16:10:11 -0700520 ASSERT_TRUE(firstBcc) << firstBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700521
Seth Moore19acbe92021-06-23 15:15:52 -0700522 status = provisionable_->generateCertificateRequest(
523 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
524 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700525 ASSERT_TRUE(status.isOk()) << status.getDescription();
Seth Moore42c11332021-07-02 15:38:17 -0700526
Alice Wangf112ec92024-10-08 07:30:28 +0000527 auto secondBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(),
528 keysToSignMac, protectedData, testEekChain_,
Sean Thomas2d2385b2024-11-07 23:56:03 +0000529 eekId_, rpcHardwareInfo, GetParam(), challenge_);
Seth Moore2fc6f832022-09-13 16:10:11 -0700530 ASSERT_TRUE(secondBcc) << secondBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700531
532 // Verify that none of the keys in the first BCC are repeated in the second one.
Seth Moore2fc6f832022-09-13 16:10:11 -0700533 for (const auto& i : *firstBcc) {
534 for (auto& j : *secondBcc) {
Seth Moore42c11332021-07-02 15:38:17 -0700535 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
536 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
537 }
538 }
539}
540
541/**
Seth Moore19acbe92021-06-23 15:15:52 -0700542 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
543 * is not run by default. Not all devices are GMS devices, and therefore they do not all
544 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600545 */
Seth Moore19acbe92021-06-23 15:15:52 -0700546TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600547 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000548
Seth Moore19acbe92021-06-23 15:15:52 -0700549 bytevec keysToSignMac;
550 DeviceInfo deviceInfo;
551 ProtectedData protectedData;
552 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000553 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
554 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700555 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600556}
557
558/**
559 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
560 */
Max Bires126869a2021-02-21 18:32:59 -0800561TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600562 bool testMode = true;
563 generateKeys(testMode, 4 /* numKeys */);
564
David Drysdalecceca9f2021-03-12 15:49:47 +0000565 for (size_t eekLength : {2, 3, 7}) {
566 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700567 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600568
David Drysdalecceca9f2021-03-12 15:49:47 +0000569 bytevec keysToSignMac;
570 DeviceInfo deviceInfo;
571 ProtectedData protectedData;
572 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700573 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000574 &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700575 ASSERT_TRUE(status.isOk()) << status.getDescription();
David Drysdalecceca9f2021-03-12 15:49:47 +0000576
Sean Thomas2d2385b2024-11-07 23:56:03 +0000577 auto result = verifyProductionProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac,
578 protectedData, testEekChain_, eekId_,
579 rpcHardwareInfo, GetParam(), challenge_);
Seth Moore2fc6f832022-09-13 16:10:11 -0700580 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000581 }
Shawn Willden274bb552020-09-30 22:39:22 -0600582}
583
584/**
Seth Moore19acbe92021-06-23 15:15:52 -0700585 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
586 * is not run by default. Not all devices are GMS devices, and therefore they do not all
587 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600588 */
Seth Moore19acbe92021-06-23 15:15:52 -0700589TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600590 bool testMode = false;
591 generateKeys(testMode, 4 /* numKeys */);
592
Seth Moore19acbe92021-06-23 15:15:52 -0700593 bytevec keysToSignMac;
594 DeviceInfo deviceInfo;
595 ProtectedData protectedData;
596 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000597 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
598 &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700599 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000600}
601
602/**
David Drysdalee99ed862021-03-15 16:43:06 +0000603 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
604 */
605TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
606 bool testMode = true;
607 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000608 auto result = corrupt_maced_key(keysToSign_[0]);
609 ASSERT_TRUE(result) << result.moveMessage();
610 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000611
612 bytevec keysToSignMac;
613 DeviceInfo deviceInfo;
614 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000615 generateTestEekChain(3);
David Drysdalee99ed862021-03-15 16:43:06 +0000616 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700617 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
618 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700619 ASSERT_FALSE(status.isOk()) << status.getDescription();
David Drysdalee99ed862021-03-15 16:43:06 +0000620 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
621}
622
623/**
624 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
625 */
626TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700627 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000628 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000629 auto result = corrupt_maced_key(keysToSign_[0]);
630 ASSERT_TRUE(result) << result.moveMessage();
631 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000632
633 bytevec keysToSignMac;
634 DeviceInfo deviceInfo;
635 ProtectedData protectedData;
636 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000637 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
638 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700639 ASSERT_FALSE(status.isOk()) << status.getDescription();
Seth Moore19acbe92021-06-23 15:15:52 -0700640 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000641}
642
643/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000644 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
645 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000646 */
647TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
648 bool testMode = false;
649 generateKeys(testMode, 4 /* numKeys */);
650
subrahmanyamanfb213d62022-02-02 23:10:55 +0000651 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
Seth Moore19acbe92021-06-23 15:15:52 -0700652 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
653 ASSERT_NE(parsedChain, nullptr) << parseErr;
654 ASSERT_NE(parsedChain->asArray(), nullptr);
655
656 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
657 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000658 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000659
660 bytevec keysToSignMac;
661 DeviceInfo deviceInfo;
662 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700663 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
664 challenge_, &deviceInfo,
665 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000666 ASSERT_FALSE(status.isOk());
667 ASSERT_EQ(status.getServiceSpecificError(),
668 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
669 }
670}
671
672/**
673 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
674 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000675 */
676TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
677 bool testMode = false;
678 generateKeys(testMode, 4 /* numKeys */);
679
680 // Build an EEK chain that omits the first self-signed cert.
681 auto truncatedChain = cppbor::Array();
subrahmanyamanfb213d62022-02-02 23:10:55 +0000682 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
David Drysdalecceca9f2021-03-12 15:49:47 +0000683 ASSERT_TRUE(chain);
684 auto eekChain = chain->asArray();
685 ASSERT_NE(eekChain, nullptr);
686 for (size_t ii = 1; ii < eekChain->size(); ii++) {
687 truncatedChain.add(eekChain->get(ii)->clone());
688 }
689
Shawn Willden274bb552020-09-30 22:39:22 -0600690 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700691 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600692 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000693 auto status = provisionable_->generateCertificateRequest(
694 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
695 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600696 ASSERT_FALSE(status.isOk());
697 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
698}
699
700/**
701 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
702 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
703 */
Max Bires126869a2021-02-21 18:32:59 -0800704TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600705 generateKeys(false /* testMode */, 2 /* numKeys */);
706
707 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700708 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600709 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000710 generateTestEekChain(3);
Max Biresfdbb9042021-03-23 12:43:38 -0700711 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700712 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700713 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600714 ASSERT_FALSE(status.isOk());
715 ASSERT_EQ(status.getServiceSpecificError(),
716 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
717}
718
719/**
720 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
721 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
722 */
Max Bires126869a2021-02-21 18:32:59 -0800723TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600724 generateKeys(true /* testMode */, 2 /* numKeys */);
725
726 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700727 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600728 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000729 generateTestEekChain(3);
Shawn Willden274bb552020-09-30 22:39:22 -0600730 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700731 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000732 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600733 ASSERT_FALSE(status.isOk());
734 ASSERT_EQ(status.getServiceSpecificError(),
735 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
736}
737
738INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
739
Tri Vo0d6204e2022-09-29 16:15:34 -0700740class CertificateRequestV2Test : public CertificateRequestTestBase {
741 void SetUp() override {
742 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000743 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700744
Andrew Scullf2ae1932023-04-24 19:09:09 +0000745 if (rpcHardwareInfo.versionNumber < VERSION_WITH_CERTIFICATE_REQUEST_V2) {
Tri Vo0d6204e2022-09-29 16:15:34 -0700746 GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
747 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
748 }
749 }
750};
751
752/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000753 * Generate an empty certificate request with all possible length of challenge, and decrypt and
754 * verify the structure and content.
Tri Vo0d6204e2022-09-29 16:15:34 -0700755 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700756// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700757TEST_P(CertificateRequestV2Test, EmptyRequest) {
758 bytevec csr;
759
Tommy Chiufde3ad12023-03-17 05:58:28 +0000760 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
761 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
762 auto challenge = randomBytes(size);
763 auto status =
764 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700765 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700766
Sean Thomas2d2385b2024-11-07 23:56:03 +0000767 auto result = verifyProductionCsr(cppbor::Array(), csr, rpcHardwareInfo, GetParam(),
Alice Wangf112ec92024-10-08 07:30:28 +0000768 challenge, isRkpVmInstance_);
Tommy Chiufde3ad12023-03-17 05:58:28 +0000769 ASSERT_TRUE(result) << result.message();
770 }
Tri Vo0d6204e2022-09-29 16:15:34 -0700771}
772
773/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000774 * Generate a non-empty certificate request with all possible length of challenge. Decrypt, parse
775 * and validate the contents.
Tri Vo0d6204e2022-09-29 16:15:34 -0700776 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700777// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700778TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
779 generateKeys(false /* testMode */, 1 /* numKeys */);
780
781 bytevec csr;
782
Tommy Chiufde3ad12023-03-17 05:58:28 +0000783 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
784 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
785 auto challenge = randomBytes(size);
786 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700787 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700788
Sean Thomas2d2385b2024-11-07 23:56:03 +0000789 auto result = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(),
Alice Wangf112ec92024-10-08 07:30:28 +0000790 challenge, isRkpVmInstance_);
Tommy Chiufde3ad12023-03-17 05:58:28 +0000791 ASSERT_TRUE(result) << result.message();
792 }
793}
794
795/**
796 * Generate an empty certificate request with invalid size of challenge
797 */
798TEST_P(CertificateRequestV2Test, EmptyRequestWithInvalidChallengeFail) {
799 bytevec csr;
800
801 auto status = provisionable_->generateCertificateRequestV2(
802 /* keysToSign */ {}, randomBytes(MAX_CHALLENGE_SIZE + 1), &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700803 EXPECT_FALSE(status.isOk()) << status.getDescription();
Tommy Chiufde3ad12023-03-17 05:58:28 +0000804 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_FAILED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700805}
806
807/**
Andrew Scullfb49ad22022-11-09 21:02:48 +0000808 * Generate a non-empty certificate request. Make sure contents are reproducible but allow for the
809 * signature to be different since algorithms including ECDSA P-256 can include a random value.
Tri Vo0d6204e2022-09-29 16:15:34 -0700810 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700811// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700812TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
813 generateKeys(false /* testMode */, 1 /* numKeys */);
814
815 bytevec csr;
816
817 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700818 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700819
Sean Thomas2d2385b2024-11-07 23:56:03 +0000820 auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(),
Alice Wangf112ec92024-10-08 07:30:28 +0000821 challenge_, isRkpVmInstance_);
Andrew Scullfb49ad22022-11-09 21:02:48 +0000822 ASSERT_TRUE(firstCsr) << firstCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700823
824 status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700825 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700826
Sean Thomas2d2385b2024-11-07 23:56:03 +0000827 auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(),
Alice Wangf112ec92024-10-08 07:30:28 +0000828 challenge_, isRkpVmInstance_);
Andrew Scullfb49ad22022-11-09 21:02:48 +0000829 ASSERT_TRUE(secondCsr) << secondCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700830
Andrew Scullfb49ad22022-11-09 21:02:48 +0000831 ASSERT_EQ(**firstCsr, **secondCsr);
Tri Vo0d6204e2022-09-29 16:15:34 -0700832}
833
834/**
835 * Generate a non-empty certificate request with multiple keys.
836 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700837// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700838TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700839 generateKeys(false /* testMode */, rpcHardwareInfo.supportedNumKeysInCsr /* numKeys */);
Tri Vo0d6204e2022-09-29 16:15:34 -0700840
841 bytevec csr;
842
843 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700844 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700845
Sean Thomas2d2385b2024-11-07 23:56:03 +0000846 auto result = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(), challenge_,
847 isRkpVmInstance_);
Tri Vo0d6204e2022-09-29 16:15:34 -0700848 ASSERT_TRUE(result) << result.message();
849}
850
851/**
852 * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
853 */
854TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
855 generateKeys(false /* testMode */, 1 /* numKeys */);
856 auto result = corrupt_maced_key(keysToSign_[0]);
857 ASSERT_TRUE(result) << result.moveMessage();
858 MacedPublicKey keyWithCorruptMac = result.moveValue();
859
860 bytevec csr;
861 auto status =
862 provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700863 ASSERT_FALSE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700864 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
865}
866
867/**
Andrew Scullf2ae1932023-04-24 19:09:09 +0000868 * Call generateCertificateRequest(). Make sure it's removed.
Tri Vo0d6204e2022-09-29 16:15:34 -0700869 */
Andrew Scullf2ae1932023-04-24 19:09:09 +0000870TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed_prodMode) {
871 bytevec keysToSignMac;
872 DeviceInfo deviceInfo;
873 ProtectedData protectedData;
874 auto status = provisionable_->generateCertificateRequest(
875 false /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
876 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700877 ASSERT_FALSE(status.isOk()) << status.getDescription();
Andrew Scullf2ae1932023-04-24 19:09:09 +0000878 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700879}
880
Andrew Scull95b31312023-03-27 19:16:07 +0000881/**
Andrew Scullf2ae1932023-04-24 19:09:09 +0000882 * Call generateCertificateRequest() in test mode. Make sure it's removed.
Andrew Scull95b31312023-03-27 19:16:07 +0000883 */
Andrew Scullf2ae1932023-04-24 19:09:09 +0000884TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed_testMode) {
Andrew Scull95b31312023-03-27 19:16:07 +0000885 bytevec keysToSignMac;
886 DeviceInfo deviceInfo;
887 ProtectedData protectedData;
888 auto status = provisionable_->generateCertificateRequest(
889 true /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
890 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700891 ASSERT_FALSE(status.isOk()) << status.getDescription();
Andrew Scull95b31312023-03-27 19:16:07 +0000892 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
893}
894
Tri Voec50ee12023-02-14 16:29:53 -0800895void parse_root_of_trust(const vector<uint8_t>& attestation_cert,
896 vector<uint8_t>* verified_boot_key, VerifiedBoot* verified_boot_state,
897 bool* device_locked, vector<uint8_t>* verified_boot_hash) {
898 X509_Ptr cert(parse_cert_blob(attestation_cert));
899 ASSERT_TRUE(cert.get());
900
901 ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
902 ASSERT_TRUE(attest_rec);
903
904 auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, verified_boot_key,
905 verified_boot_state, device_locked, verified_boot_hash);
906 ASSERT_EQ(error, ErrorCode::OK);
907}
908
909/**
910 * Generate a CSR and verify DeviceInfo against IDs attested by KeyMint.
911 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700912// @VsrTest = 3.10-015
Tri Voec50ee12023-02-14 16:29:53 -0800913TEST_P(CertificateRequestV2Test, DeviceInfo) {
914 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
915 std::shared_ptr<IKeyMintDevice> keyMint;
916 if (!matching_keymint_device(GetParam(), &keyMint)) {
917 // No matching IKeyMintDevice.
918 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
919 return;
920 }
921 KeyMintHardwareInfo info;
922 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
923
924 // Get IDs attested by KeyMint.
925 MacedPublicKey macedPubKey;
926 bytevec privateKeyBlob;
927 auto irpcStatus =
928 provisionable_->generateEcdsaP256KeyPair(false, &macedPubKey, &privateKeyBlob);
929 ASSERT_TRUE(irpcStatus.isOk());
930
931 AttestationKey attestKey;
932 attestKey.keyBlob = std::move(privateKeyBlob);
933 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
934
935 // Generate an ECDSA key that is attested by the generated P256 keypair.
936 AuthorizationSet keyDesc = AuthorizationSetBuilder()
937 .Authorization(TAG_NO_AUTH_REQUIRED)
938 .EcdsaSigningKey(EcCurve::P_256)
939 .AttestationChallenge("foo")
940 .AttestationApplicationId("bar")
941 .Digest(Digest::NONE)
942 .SetDefaultValidity();
943 KeyCreationResult creationResult;
944 auto kmStatus = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
945 ASSERT_TRUE(kmStatus.isOk());
946
947 vector<KeyCharacteristics> key_characteristics = std::move(creationResult.keyCharacteristics);
948 vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain);
949 // We didn't provision the attestation key.
950 ASSERT_EQ(key_cert_chain.size(), 1);
951
952 // Parse attested patch levels.
953 auto auths = HwEnforcedAuthorizations(key_characteristics);
954
955 auto attestedSystemPatchLevel = auths.GetTagValue(TAG_OS_PATCHLEVEL);
956 auto attestedVendorPatchLevel = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
957 auto attestedBootPatchLevel = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
958
959 ASSERT_TRUE(attestedSystemPatchLevel.has_value());
960 ASSERT_TRUE(attestedVendorPatchLevel.has_value());
961 ASSERT_TRUE(attestedBootPatchLevel.has_value());
962
963 // Parse attested AVB values.
964 vector<uint8_t> key;
965 VerifiedBoot attestedVbState;
966 bool attestedBootloaderState;
967 vector<uint8_t> attestedVbmetaDigest;
968 parse_root_of_trust(key_cert_chain[0].encodedCertificate, &key, &attestedVbState,
969 &attestedBootloaderState, &attestedVbmetaDigest);
970
971 // Get IDs from DeviceInfo.
972 bytevec csr;
973 irpcStatus =
974 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700975 ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getDescription();
Tri Voec50ee12023-02-14 16:29:53 -0800976
Alice Wangf112ec92024-10-08 07:30:28 +0000977 auto result =
Sean Thomas2d2385b2024-11-07 23:56:03 +0000978 verifyProductionCsr(cppbor::Array(), csr, rpcHardwareInfo, GetParam(), challenge_);
Tri Voec50ee12023-02-14 16:29:53 -0800979 ASSERT_TRUE(result) << result.message();
980
981 std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
982 ASSERT_TRUE(csrPayload);
983
984 auto deviceInfo = csrPayload->get(2)->asMap();
985 ASSERT_TRUE(deviceInfo);
986
987 auto vbState = deviceInfo->get("vb_state")->asTstr();
988 auto bootloaderState = deviceInfo->get("bootloader_state")->asTstr();
989 auto vbmetaDigest = deviceInfo->get("vbmeta_digest")->asBstr();
990 auto systemPatchLevel = deviceInfo->get("system_patch_level")->asUint();
991 auto vendorPatchLevel = deviceInfo->get("vendor_patch_level")->asUint();
992 auto bootPatchLevel = deviceInfo->get("boot_patch_level")->asUint();
993 auto securityLevel = deviceInfo->get("security_level")->asTstr();
994
995 ASSERT_TRUE(vbState);
996 ASSERT_TRUE(bootloaderState);
997 ASSERT_TRUE(vbmetaDigest);
998 ASSERT_TRUE(systemPatchLevel);
999 ASSERT_TRUE(vendorPatchLevel);
1000 ASSERT_TRUE(bootPatchLevel);
1001 ASSERT_TRUE(securityLevel);
1002
1003 auto kmDeviceName = device_suffix(GetParam());
1004
1005 // Compare DeviceInfo against IDs attested by KeyMint.
1006 ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") ||
1007 (securityLevel->value() == "strongbox" && kmDeviceName == "strongbox"));
1008 ASSERT_TRUE((vbState->value() == "green" && attestedVbState == VerifiedBoot::VERIFIED) ||
1009 (vbState->value() == "yellow" && attestedVbState == VerifiedBoot::SELF_SIGNED) ||
1010 (vbState->value() == "orange" && attestedVbState == VerifiedBoot::UNVERIFIED));
1011 ASSERT_TRUE((bootloaderState->value() == "locked" && attestedBootloaderState) ||
1012 (bootloaderState->value() == "unlocked" && !attestedBootloaderState));
1013 ASSERT_EQ(vbmetaDigest->value(), attestedVbmetaDigest);
1014 ASSERT_EQ(systemPatchLevel->value(), attestedSystemPatchLevel.value());
1015 ASSERT_EQ(vendorPatchLevel->value(), attestedVendorPatchLevel.value());
1016 ASSERT_EQ(bootPatchLevel->value(), attestedBootPatchLevel.value());
1017}
1018
Tri Vo0d6204e2022-09-29 16:15:34 -07001019INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
1020
Max Biresa9b3bb92022-11-21 23:02:09 -08001021using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
1022
1023INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
1024
1025TEST_P(VsrRequirementTest, VsrEnforcementTest) {
1026 RpcHardwareInfo hwInfo;
1027 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
1028 int vsr_api_level = get_vsr_api_level();
1029 if (vsr_api_level < 34) {
1030 GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
1031 << vsr_api_level;
1032 }
1033 EXPECT_GE(hwInfo.versionNumber, 3)
1034 << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
1035}
1036
Shawn Willden274bb552020-09-30 22:39:22 -06001037} // namespace aidl::android::hardware::security::keymint::test