blob: 5467679ca1d3e9267727fe86f293eb4ea00f4a1f [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>
Sean Thomasafbab602024-11-07 23:14:05 +000038#include <string_view>
Seth Moore42c11332021-07-02 15:38:17 -070039#include <vector>
Shawn Willden274bb552020-09-30 22:39:22 -060040
David Drysdalef0d516d2021-03-22 07:51:43 +000041#include "KeyMintAidlTestBase.h"
42
Shawn Willden274bb552020-09-30 22:39:22 -060043namespace aidl::android::hardware::security::keymint::test {
44
45using ::std::string;
46using ::std::vector;
47
48namespace {
49
Seth Moorefc86bf42021-12-09 14:07:04 -080050constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
Andrew Scullf2ae1932023-04-24 19:09:09 +000051
52constexpr int32_t VERSION_WITHOUT_EEK = 3;
Tri Vo0d6204e2022-09-29 16:15:34 -070053constexpr int32_t VERSION_WITHOUT_TEST_MODE = 3;
Andrew Scullf2ae1932023-04-24 19:09:09 +000054constexpr int32_t VERSION_WITH_CERTIFICATE_REQUEST_V2 = 3;
55constexpr int32_t VERSION_WITH_SUPPORTED_NUM_KEYS_IN_CSR = 3;
Seth Moorefc86bf42021-12-09 14:07:04 -080056
Tommy Chiufde3ad12023-03-17 05:58:28 +000057constexpr uint8_t MIN_CHALLENGE_SIZE = 0;
58constexpr uint8_t MAX_CHALLENGE_SIZE = 64;
Alice Wangf112ec92024-10-08 07:30:28 +000059
Andrew Scull21461522024-03-25 15:08:08 +000060const string KEYMINT_STRONGBOX_INSTANCE_NAME =
61 "android.hardware.security.keymint.IKeyMintDevice/strongbox";
Tommy Chiufde3ad12023-03-17 05:58:28 +000062
Shawn Willden274bb552020-09-30 22:39:22 -060063#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070064 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060065 INSTANTIATE_TEST_SUITE_P( \
66 PerInstance, name, \
67 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
68 ::android::PrintInstanceNameToString)
69
Seth Moorefc86bf42021-12-09 14:07:04 -080070using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060071using bytevec = std::vector<uint8_t>;
72using testing::MatchesRegex;
73using namespace remote_prov;
74using namespace keymaster;
75
76bytevec string_to_bytevec(const char* s) {
77 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
78 return bytevec(p, p + strlen(s));
79}
80
David Drysdalee99ed862021-03-15 16:43:06 +000081ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
82 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
83 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
84 return "COSE Mac0 parse failed";
85 }
86 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
87 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
88 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
89 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
90 if (!protParams || !unprotParams || !payload || !tag) {
91 return "Invalid COSE_Sign1: missing content";
92 }
93 auto corruptMac0 = cppbor::Array();
94 corruptMac0.add(protParams->clone());
95 corruptMac0.add(unprotParams->clone());
96 corruptMac0.add(payload->clone());
97 vector<uint8_t> tagData = tag->value();
98 tagData[0] ^= 0x08;
99 tagData[tagData.size() - 1] ^= 0x80;
100 corruptMac0.add(cppbor::Bstr(tagData));
101
102 return MacedPublicKey{corruptMac0.encode()};
103}
104
David Drysdalecceca9f2021-03-12 15:49:47 +0000105ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
106 if (coseSign1->size() != kCoseSign1EntryCount) {
107 return "Invalid COSE_Sign1, wrong entry count";
108 }
109 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
110 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
111 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
112 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
113 if (!protectedParams || !unprotectedParams || !payload || !signature) {
114 return "Invalid COSE_Sign1: missing content";
115 }
116
117 auto corruptSig = cppbor::Array();
118 corruptSig.add(protectedParams->clone());
119 corruptSig.add(unprotectedParams->clone());
120 corruptSig.add(payload->clone());
121 vector<uint8_t> sigData = signature->value();
122 sigData[0] ^= 0x08;
123 corruptSig.add(cppbor::Bstr(sigData));
124
125 return std::move(corruptSig);
126}
127
Seth Moore19acbe92021-06-23 15:15:52 -0700128ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
129 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000130 if (!chain || !chain->asArray()) {
131 return "EekChain parse failed";
132 }
133
134 cppbor::Array* eekChain = chain->asArray();
135 if (which >= eekChain->size()) {
136 return "selected sig out of range";
137 }
138 auto corruptChain = cppbor::Array();
139
140 for (int ii = 0; ii < eekChain->size(); ++ii) {
141 if (ii == which) {
142 auto sig = corrupt_sig(eekChain->get(which)->asArray());
143 if (!sig) {
144 return "Failed to build corrupted signature" + sig.moveMessage();
145 }
146 corruptChain.add(sig.moveValue());
147 } else {
148 corruptChain.add(eekChain->get(ii)->clone());
149 }
150 }
Seth Moore19acbe92021-06-23 15:15:52 -0700151 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000152}
153
David Drysdale4d3c2982021-03-31 18:21:40 +0100154bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
Sean Thomasafbab602024-11-07 23:14:05 +0000155 auto rp_suffix = deviceSuffix(rp_name);
David Drysdale4d3c2982021-03-31 18:21:40 +0100156
157 vector<string> km_names = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
158 for (const string& km_name : km_names) {
159 // If the suffix of the KeyMint instance equals the suffix of the
160 // RemotelyProvisionedComponent instance, assume they match.
Sean Thomasafbab602024-11-07 23:14:05 +0000161 if (deviceSuffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
David Drysdale4d3c2982021-03-31 18:21:40 +0100162 ::ndk::SpAIBinder binder(AServiceManager_waitForService(km_name.c_str()));
163 *keyMint = IKeyMintDevice::fromBinder(binder);
164 return true;
165 }
166 }
167 return false;
168}
169
Shawn Willden274bb552020-09-30 22:39:22 -0600170} // namespace
171
172class VtsRemotelyProvisionedComponentTests : public testing::TestWithParam<std::string> {
173 public:
174 virtual void SetUp() override {
175 if (AServiceManager_isDeclared(GetParam().c_str())) {
176 ::ndk::SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
177 provisionable_ = IRemotelyProvisionedComponent::fromBinder(binder);
178 }
179 ASSERT_NE(provisionable_, nullptr);
Alice Wang895f4b32023-11-14 07:38:18 +0000180 auto status = provisionable_->getHardwareInfo(&rpcHardwareInfo);
Alice Wangf112ec92024-10-08 07:30:28 +0000181 isRkpVmInstance_ = GetParam() == RKPVM_INSTANCE_NAME;
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000182 if (isRkpVmInstance_) {
Alice Wang46ff2862024-05-14 07:07:05 +0000183 if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
184 GTEST_SKIP() << "The RKP VM is not supported on this system.";
185 }
186 int apiLevel = get_vsr_api_level();
187 if (apiLevel < __ANDROID_API_V__) {
188 GTEST_SKIP() << "The RKP VM is supported only on V+ devices. Vendor API level: "
189 << apiLevel;
190 }
Alice Wang895f4b32023-11-14 07:38:18 +0000191 }
192 ASSERT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600193 }
194
195 static vector<string> build_params() {
196 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
197 return params;
198 }
199
200 protected:
201 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000202 RpcHardwareInfo rpcHardwareInfo;
Karuna Wadheraca6d8cc2024-07-18 14:08:36 +0000203 bool isRkpVmInstance_;
Shawn Willden274bb552020-09-30 22:39:22 -0600204};
205
Seth Moorefc86bf42021-12-09 14:07:04 -0800206/**
207 * Verify that every implementation reports a different unique id.
208 */
209TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
210 std::set<std::string> uniqueIds;
211 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
212 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
213 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
214 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
215 IRemotelyProvisionedComponent::fromBinder(binder);
216 ASSERT_NE(rpc, nullptr);
217
218 RpcHardwareInfo hwInfo;
Alice Wang895f4b32023-11-14 07:38:18 +0000219 auto status = rpc->getHardwareInfo(&hwInfo);
Alice Wangf112ec92024-10-08 07:30:28 +0000220 if (hal == RKPVM_INSTANCE_NAME && status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
Alice Wang895f4b32023-11-14 07:38:18 +0000221 GTEST_SKIP() << "The RKP VM is not supported on this system.";
222 }
223 ASSERT_TRUE(status.isOk());
Seth Moorefc86bf42021-12-09 14:07:04 -0800224
Tri Vodd12c482022-10-12 22:41:28 +0000225 if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800226 ASSERT_TRUE(hwInfo.uniqueId);
227 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
228 EXPECT_TRUE(wasInserted);
229 } else {
230 ASSERT_FALSE(hwInfo.uniqueId);
231 }
232 }
233}
234
Andrew Scull21461522024-03-25 15:08:08 +0000235/**
236 * Verify that the default implementation supports DICE if there is a StrongBox KeyMint instance
237 * on the device.
238 */
239// @VsrTest = 3.10-015
240TEST(NonParameterizedTests, requireDiceOnDefaultInstanceIfStrongboxPresent) {
241 int vsr_api_level = get_vsr_api_level();
242 if (vsr_api_level < 35) {
243 GTEST_SKIP() << "Applies only to VSR API level 35 or newer, this device is: "
244 << vsr_api_level;
245 }
246
247 if (!AServiceManager_isDeclared(KEYMINT_STRONGBOX_INSTANCE_NAME.c_str())) {
248 GTEST_SKIP() << "Strongbox is not present on this device.";
249 }
250
251 ::ndk::SpAIBinder binder(AServiceManager_waitForService(DEFAULT_INSTANCE_NAME.c_str()));
252 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
253 IRemotelyProvisionedComponent::fromBinder(binder);
254 ASSERT_NE(rpc, nullptr);
255
256 bytevec challenge = randomBytes(64);
257 bytevec csr;
258 auto status = rpc->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
259 EXPECT_TRUE(status.isOk()) << status.getDescription();
260
Alice Wangf112ec92024-10-08 07:30:28 +0000261 auto result = isCsrWithProperDiceChain(csr, DEFAULT_INSTANCE_NAME);
Andrew Scull21461522024-03-25 15:08:08 +0000262 ASSERT_TRUE(result) << result.message();
263 ASSERT_TRUE(*result);
264}
265
Seth Moorefc86bf42021-12-09 14:07:04 -0800266using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
267
268INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
269
270/**
271 * Verify that a valid curve is reported by the implementation.
272 */
273TEST_P(GetHardwareInfoTests, supportsValidCurve) {
274 RpcHardwareInfo hwInfo;
275 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
276
Andrew Scullf2ae1932023-04-24 19:09:09 +0000277 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_EEK) {
278 ASSERT_EQ(hwInfo.supportedEekCurve, RpcHardwareInfo::CURVE_NONE)
279 << "Invalid curve: " << hwInfo.supportedEekCurve;
280 return;
Hasini Gunasinghe666b2712023-01-05 21:35:51 +0000281 }
Andrew Scullf2ae1932023-04-24 19:09:09 +0000282
283 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
Seth Moorefc86bf42021-12-09 14:07:04 -0800284 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
285 << "Invalid curve: " << hwInfo.supportedEekCurve;
286}
287
288/**
289 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
290 */
291TEST_P(GetHardwareInfoTests, uniqueId) {
Tri Vodd12c482022-10-12 22:41:28 +0000292 if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800293 return;
294 }
295
296 RpcHardwareInfo hwInfo;
297 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
298 ASSERT_TRUE(hwInfo.uniqueId);
299 EXPECT_GE(hwInfo.uniqueId->size(), 1);
300 EXPECT_LE(hwInfo.uniqueId->size(), 32);
301}
302
Tri Vo9cab73c2022-10-28 13:40:24 -0700303/**
304 * Verify implementation supports at least MIN_SUPPORTED_NUM_KEYS_IN_CSR keys in a CSR.
305 */
306TEST_P(GetHardwareInfoTests, supportedNumKeysInCsr) {
Andrew Scullf2ae1932023-04-24 19:09:09 +0000307 if (rpcHardwareInfo.versionNumber < VERSION_WITH_SUPPORTED_NUM_KEYS_IN_CSR) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700308 return;
309 }
310
311 RpcHardwareInfo hwInfo;
312 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
313 ASSERT_GE(hwInfo.supportedNumKeysInCsr, RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR);
314}
315
Shawn Willden274bb552020-09-30 22:39:22 -0600316using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
317
318INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
319
320/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000321 * Generate and validate a production-mode key. MAC tag can't be verified, but
322 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600323 */
Max Bires126869a2021-02-21 18:32:59 -0800324TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600325 MacedPublicKey macedPubKey;
326 bytevec privateKeyBlob;
327 bool testMode = false;
328 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
329 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000330 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800331 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100332}
333
334/**
335 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
336 */
337TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
338 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
339 std::shared_ptr<IKeyMintDevice> keyMint;
340 if (!matching_keymint_device(GetParam(), &keyMint)) {
341 // No matching IKeyMintDevice.
342 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
343 return;
344 }
345 KeyMintHardwareInfo info;
346 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
347
348 MacedPublicKey macedPubKey;
349 bytevec privateKeyBlob;
350 bool testMode = false;
351 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
352 ASSERT_TRUE(status.isOk());
353 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800354 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100355
David Drysdalef0d516d2021-03-22 07:51:43 +0000356 AttestationKey attestKey;
357 attestKey.keyBlob = std::move(privateKeyBlob);
358 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600359
David Drysdalef0d516d2021-03-22 07:51:43 +0000360 // Generate an ECDSA key that is attested by the generated P256 keypair.
361 AuthorizationSet keyDesc = AuthorizationSetBuilder()
362 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100363 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000364 .AttestationChallenge("foo")
365 .AttestationApplicationId("bar")
366 .Digest(Digest::NONE)
367 .SetDefaultValidity();
368 KeyCreationResult creationResult;
369 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
370 ASSERT_TRUE(result.isOk());
371 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
372 vector<KeyCharacteristics> attested_key_characteristics =
373 std::move(creationResult.keyCharacteristics);
374 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
375 EXPECT_EQ(attested_key_cert_chain.size(), 1);
376
David Drysdale7dff4fc2021-12-10 10:10:52 +0000377 int32_t aidl_version = 0;
378 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000379 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
380 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000381 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000382 info.securityLevel,
383 attested_key_cert_chain[0].encodedCertificate));
384
385 // Attestation by itself is not valid (last entry is not self-signed).
386 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
387
388 // The signature over the attested key should correspond to the P256 public key.
389 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
390 ASSERT_TRUE(key_cert.get());
391 EVP_PKEY_Ptr signing_pubkey;
392 p256_pub_key(coseKeyData, &signing_pubkey);
393 ASSERT_TRUE(signing_pubkey.get());
394
395 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
396 << "Verification of attested certificate failed "
397 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600398}
399
400/**
401 * Generate and validate a test-mode key.
402 */
Max Bires126869a2021-02-21 18:32:59 -0800403TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600404 MacedPublicKey macedPubKey;
405 bytevec privateKeyBlob;
406 bool testMode = true;
407 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
Andrew Scullf2ae1932023-04-24 19:09:09 +0000408
409 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
410 ASSERT_FALSE(status.isOk());
411 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
412 return;
413 }
414
Shawn Willden274bb552020-09-30 22:39:22 -0600415 ASSERT_TRUE(status.isOk());
Tri Vob0b8acc2022-11-30 16:22:23 -0800416 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600417}
418
Tri Vo0d6204e2022-09-29 16:15:34 -0700419class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
Shawn Willden274bb552020-09-30 22:39:22 -0600420 protected:
Tri Vo0d6204e2022-09-29 16:15:34 -0700421 CertificateRequestTestBase()
422 : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
David Drysdalecceca9f2021-03-12 15:49:47 +0000423
Seth Moore19acbe92021-06-23 15:15:52 -0700424 void generateTestEekChain(size_t eekLength) {
subrahmanyamanfb213d62022-02-02 23:10:55 +0000425 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
David Drysdale08696a72022-03-10 10:43:25 +0000426 ASSERT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700427 if (chain) testEekChain_ = chain.moveValue();
428 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600429 }
430
431 void generateKeys(bool testMode, size_t numKeys) {
432 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
433 cborKeysToSign_ = cppbor::Array();
434
435 for (auto& key : keysToSign_) {
436 bytevec privateKeyBlob;
437 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
Frederick Mayle9891be02023-11-03 14:39:24 -0700438 ASSERT_TRUE(status.isOk()) << status.getDescription();
Shawn Willden274bb552020-09-30 22:39:22 -0600439
David Drysdalec8400772021-03-11 12:35:11 +0000440 vector<uint8_t> payload_value;
Tri Vob0b8acc2022-11-30 16:22:23 -0800441 check_maced_pubkey(key, testMode, &payload_value);
David Drysdalec8400772021-03-11 12:35:11 +0000442 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600443 }
444 }
445
446 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700447 size_t testEekLength_;
448 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000449 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600450 std::vector<MacedPublicKey> keysToSign_;
451 cppbor::Array cborKeysToSign_;
452};
453
Tri Vo0d6204e2022-09-29 16:15:34 -0700454class CertificateRequestTest : public CertificateRequestTestBase {
455 protected:
456 void SetUp() override {
457 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000458 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700459
Andrew Scullf2ae1932023-04-24 19:09:09 +0000460 if (rpcHardwareInfo.versionNumber >= VERSION_WITH_CERTIFICATE_REQUEST_V2) {
Andrew Scull95b31312023-03-27 19:16:07 +0000461 GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
462 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
Tri Vo0d6204e2022-09-29 16:15:34 -0700463 }
464 }
465};
466
Shawn Willden274bb552020-09-30 22:39:22 -0600467/**
468 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
469 * content.
470 */
Max Bires126869a2021-02-21 18:32:59 -0800471TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600472 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000473 for (size_t eekLength : {2, 3, 7}) {
474 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700475 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600476
David Drysdalecceca9f2021-03-12 15:49:47 +0000477 bytevec keysToSignMac;
478 DeviceInfo deviceInfo;
479 ProtectedData protectedData;
480 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700481 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000482 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700483 ASSERT_TRUE(status.isOk()) << status.getDescription();
David Drysdalecceca9f2021-03-12 15:49:47 +0000484
Sean Thomas2d2385b2024-11-07 23:56:03 +0000485 auto result = verifyProductionProtectedData(deviceInfo, cppbor::Array(), keysToSignMac,
486 protectedData, testEekChain_, eekId_,
487 rpcHardwareInfo, GetParam(), challenge_);
Seth Moore2fc6f832022-09-13 16:10:11 -0700488 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000489 }
Shawn Willden274bb552020-09-30 22:39:22 -0600490}
491
492/**
Seth Moore42c11332021-07-02 15:38:17 -0700493 * Ensure that test mode outputs a unique BCC root key every time we request a
494 * certificate request. Else, it's possible that the test mode API could be used
495 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
496 * device public key multiple times.
497 */
498TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
499 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700500
501 bytevec keysToSignMac;
502 DeviceInfo deviceInfo;
503 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000504 generateTestEekChain(3);
Seth Moore42c11332021-07-02 15:38:17 -0700505 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700506 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
507 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700508 ASSERT_TRUE(status.isOk()) << status.getDescription();
Seth Moore42c11332021-07-02 15:38:17 -0700509
Alice Wangf112ec92024-10-08 07:30:28 +0000510 auto firstBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(),
511 keysToSignMac, protectedData, testEekChain_,
Sean Thomas2d2385b2024-11-07 23:56:03 +0000512 eekId_, rpcHardwareInfo, GetParam(), challenge_);
Seth Moore2fc6f832022-09-13 16:10:11 -0700513 ASSERT_TRUE(firstBcc) << firstBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700514
Seth Moore19acbe92021-06-23 15:15:52 -0700515 status = provisionable_->generateCertificateRequest(
516 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
Alice Wangf112ec92024-10-08 07:30:28 +0000520 auto secondBcc = verifyProductionProtectedData(deviceInfo, /*keysToSign=*/cppbor::Array(),
521 keysToSignMac, protectedData, testEekChain_,
Sean Thomas2d2385b2024-11-07 23:56:03 +0000522 eekId_, rpcHardwareInfo, GetParam(), challenge_);
Seth Moore2fc6f832022-09-13 16:10:11 -0700523 ASSERT_TRUE(secondBcc) << secondBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700524
525 // Verify that none of the keys in the first BCC are repeated in the second one.
Seth Moore2fc6f832022-09-13 16:10:11 -0700526 for (const auto& i : *firstBcc) {
527 for (auto& j : *secondBcc) {
Seth Moore42c11332021-07-02 15:38:17 -0700528 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
529 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
530 }
531 }
532}
533
534/**
Seth Moore19acbe92021-06-23 15:15:52 -0700535 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
536 * is not run by default. Not all devices are GMS devices, and therefore they do not all
537 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600538 */
Seth Moore19acbe92021-06-23 15:15:52 -0700539TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600540 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000541
Seth Moore19acbe92021-06-23 15:15:52 -0700542 bytevec keysToSignMac;
543 DeviceInfo deviceInfo;
544 ProtectedData protectedData;
545 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000546 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
547 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700548 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600549}
550
551/**
552 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
553 */
Max Bires126869a2021-02-21 18:32:59 -0800554TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600555 bool testMode = true;
556 generateKeys(testMode, 4 /* numKeys */);
557
David Drysdalecceca9f2021-03-12 15:49:47 +0000558 for (size_t eekLength : {2, 3, 7}) {
559 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700560 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600561
David Drysdalecceca9f2021-03-12 15:49:47 +0000562 bytevec keysToSignMac;
563 DeviceInfo deviceInfo;
564 ProtectedData protectedData;
565 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700566 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000567 &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700568 ASSERT_TRUE(status.isOk()) << status.getDescription();
David Drysdalecceca9f2021-03-12 15:49:47 +0000569
Sean Thomas2d2385b2024-11-07 23:56:03 +0000570 auto result = verifyProductionProtectedData(deviceInfo, cborKeysToSign_, keysToSignMac,
571 protectedData, testEekChain_, eekId_,
572 rpcHardwareInfo, GetParam(), challenge_);
Seth Moore2fc6f832022-09-13 16:10:11 -0700573 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000574 }
Shawn Willden274bb552020-09-30 22:39:22 -0600575}
576
577/**
Seth Moore19acbe92021-06-23 15:15:52 -0700578 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
579 * is not run by default. Not all devices are GMS devices, and therefore they do not all
580 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600581 */
Seth Moore19acbe92021-06-23 15:15:52 -0700582TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600583 bool testMode = false;
584 generateKeys(testMode, 4 /* numKeys */);
585
Seth Moore19acbe92021-06-23 15:15:52 -0700586 bytevec keysToSignMac;
587 DeviceInfo deviceInfo;
588 ProtectedData protectedData;
589 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000590 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
591 &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700592 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000593}
594
595/**
David Drysdalee99ed862021-03-15 16:43:06 +0000596 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
597 */
598TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
599 bool testMode = true;
600 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000601 auto result = corrupt_maced_key(keysToSign_[0]);
602 ASSERT_TRUE(result) << result.moveMessage();
603 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000604
605 bytevec keysToSignMac;
606 DeviceInfo deviceInfo;
607 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000608 generateTestEekChain(3);
David Drysdalee99ed862021-03-15 16:43:06 +0000609 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700610 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
611 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700612 ASSERT_FALSE(status.isOk()) << status.getDescription();
David Drysdalee99ed862021-03-15 16:43:06 +0000613 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
614}
615
616/**
617 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
618 */
619TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700620 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000621 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000622 auto result = corrupt_maced_key(keysToSign_[0]);
623 ASSERT_TRUE(result) << result.moveMessage();
624 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000625
626 bytevec keysToSignMac;
627 DeviceInfo deviceInfo;
628 ProtectedData protectedData;
629 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000630 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
631 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700632 ASSERT_FALSE(status.isOk()) << status.getDescription();
Seth Moore19acbe92021-06-23 15:15:52 -0700633 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000634}
635
636/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000637 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
638 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000639 */
640TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
641 bool testMode = false;
642 generateKeys(testMode, 4 /* numKeys */);
643
subrahmanyamanfb213d62022-02-02 23:10:55 +0000644 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
Seth Moore19acbe92021-06-23 15:15:52 -0700645 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
646 ASSERT_NE(parsedChain, nullptr) << parseErr;
647 ASSERT_NE(parsedChain->asArray(), nullptr);
648
649 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
650 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000651 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000652
653 bytevec keysToSignMac;
654 DeviceInfo deviceInfo;
655 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700656 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
657 challenge_, &deviceInfo,
658 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000659 ASSERT_FALSE(status.isOk());
660 ASSERT_EQ(status.getServiceSpecificError(),
661 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
662 }
663}
664
665/**
666 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
667 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000668 */
669TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
670 bool testMode = false;
671 generateKeys(testMode, 4 /* numKeys */);
672
673 // Build an EEK chain that omits the first self-signed cert.
674 auto truncatedChain = cppbor::Array();
subrahmanyamanfb213d62022-02-02 23:10:55 +0000675 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
David Drysdalecceca9f2021-03-12 15:49:47 +0000676 ASSERT_TRUE(chain);
677 auto eekChain = chain->asArray();
678 ASSERT_NE(eekChain, nullptr);
679 for (size_t ii = 1; ii < eekChain->size(); ii++) {
680 truncatedChain.add(eekChain->get(ii)->clone());
681 }
682
Shawn Willden274bb552020-09-30 22:39:22 -0600683 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700684 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600685 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000686 auto status = provisionable_->generateCertificateRequest(
687 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
688 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600689 ASSERT_FALSE(status.isOk());
690 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
691}
692
693/**
694 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
695 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
696 */
Max Bires126869a2021-02-21 18:32:59 -0800697TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600698 generateKeys(false /* testMode */, 2 /* numKeys */);
699
700 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700701 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600702 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000703 generateTestEekChain(3);
Max Biresfdbb9042021-03-23 12:43:38 -0700704 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700705 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700706 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600707 ASSERT_FALSE(status.isOk());
708 ASSERT_EQ(status.getServiceSpecificError(),
709 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
710}
711
712/**
713 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
714 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
715 */
Max Bires126869a2021-02-21 18:32:59 -0800716TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600717 generateKeys(true /* testMode */, 2 /* numKeys */);
718
719 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700720 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600721 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000722 generateTestEekChain(3);
Shawn Willden274bb552020-09-30 22:39:22 -0600723 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700724 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000725 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600726 ASSERT_FALSE(status.isOk());
727 ASSERT_EQ(status.getServiceSpecificError(),
728 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
729}
730
731INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
732
Tri Vo0d6204e2022-09-29 16:15:34 -0700733class CertificateRequestV2Test : public CertificateRequestTestBase {
734 void SetUp() override {
735 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000736 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700737
Andrew Scullf2ae1932023-04-24 19:09:09 +0000738 if (rpcHardwareInfo.versionNumber < VERSION_WITH_CERTIFICATE_REQUEST_V2) {
Tri Vo0d6204e2022-09-29 16:15:34 -0700739 GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
740 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
741 }
742 }
743};
744
745/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000746 * Generate an empty certificate request with all possible length of challenge, and decrypt and
747 * verify the structure and content.
Tri Vo0d6204e2022-09-29 16:15:34 -0700748 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700749// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700750TEST_P(CertificateRequestV2Test, EmptyRequest) {
751 bytevec csr;
752
Tommy Chiufde3ad12023-03-17 05:58:28 +0000753 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
754 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
755 auto challenge = randomBytes(size);
756 auto status =
757 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700758 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700759
Sean Thomas2d2385b2024-11-07 23:56:03 +0000760 auto result = verifyProductionCsr(cppbor::Array(), csr, rpcHardwareInfo, GetParam(),
Alice Wangf112ec92024-10-08 07:30:28 +0000761 challenge, isRkpVmInstance_);
Tommy Chiufde3ad12023-03-17 05:58:28 +0000762 ASSERT_TRUE(result) << result.message();
763 }
Tri Vo0d6204e2022-09-29 16:15:34 -0700764}
765
766/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000767 * Generate a non-empty certificate request with all possible length of challenge. Decrypt, parse
768 * and validate the contents.
Tri Vo0d6204e2022-09-29 16:15:34 -0700769 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700770// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700771TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
772 generateKeys(false /* testMode */, 1 /* numKeys */);
773
774 bytevec csr;
775
Tommy Chiufde3ad12023-03-17 05:58:28 +0000776 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
777 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
778 auto challenge = randomBytes(size);
779 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700780 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700781
Sean Thomas2d2385b2024-11-07 23:56:03 +0000782 auto result = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(),
Alice Wangf112ec92024-10-08 07:30:28 +0000783 challenge, isRkpVmInstance_);
Tommy Chiufde3ad12023-03-17 05:58:28 +0000784 ASSERT_TRUE(result) << result.message();
785 }
786}
787
788/**
789 * Generate an empty certificate request with invalid size of challenge
790 */
791TEST_P(CertificateRequestV2Test, EmptyRequestWithInvalidChallengeFail) {
792 bytevec csr;
793
794 auto status = provisionable_->generateCertificateRequestV2(
795 /* keysToSign */ {}, randomBytes(MAX_CHALLENGE_SIZE + 1), &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700796 EXPECT_FALSE(status.isOk()) << status.getDescription();
Tommy Chiufde3ad12023-03-17 05:58:28 +0000797 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_FAILED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700798}
799
800/**
Andrew Scullfb49ad22022-11-09 21:02:48 +0000801 * Generate a non-empty certificate request. Make sure contents are reproducible but allow for the
802 * signature to be different since algorithms including ECDSA P-256 can include a random value.
Tri Vo0d6204e2022-09-29 16:15:34 -0700803 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700804// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700805TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
806 generateKeys(false /* testMode */, 1 /* numKeys */);
807
808 bytevec csr;
809
810 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700811 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700812
Sean Thomas2d2385b2024-11-07 23:56:03 +0000813 auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(),
Alice Wangf112ec92024-10-08 07:30:28 +0000814 challenge_, isRkpVmInstance_);
Andrew Scullfb49ad22022-11-09 21:02:48 +0000815 ASSERT_TRUE(firstCsr) << firstCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700816
817 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 secondCsr = 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(secondCsr) << secondCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700823
Andrew Scullfb49ad22022-11-09 21:02:48 +0000824 ASSERT_EQ(**firstCsr, **secondCsr);
Tri Vo0d6204e2022-09-29 16:15:34 -0700825}
826
827/**
828 * Generate a non-empty certificate request with multiple keys.
829 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700830// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700831TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700832 generateKeys(false /* testMode */, rpcHardwareInfo.supportedNumKeysInCsr /* numKeys */);
Tri Vo0d6204e2022-09-29 16:15:34 -0700833
834 bytevec csr;
835
836 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700837 ASSERT_TRUE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700838
Sean Thomas2d2385b2024-11-07 23:56:03 +0000839 auto result = verifyProductionCsr(cborKeysToSign_, csr, rpcHardwareInfo, GetParam(), challenge_,
840 isRkpVmInstance_);
Tri Vo0d6204e2022-09-29 16:15:34 -0700841 ASSERT_TRUE(result) << result.message();
842}
843
844/**
845 * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
846 */
847TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
848 generateKeys(false /* testMode */, 1 /* numKeys */);
849 auto result = corrupt_maced_key(keysToSign_[0]);
850 ASSERT_TRUE(result) << result.moveMessage();
851 MacedPublicKey keyWithCorruptMac = result.moveValue();
852
853 bytevec csr;
854 auto status =
855 provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700856 ASSERT_FALSE(status.isOk()) << status.getDescription();
Tri Vo0d6204e2022-09-29 16:15:34 -0700857 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
858}
859
860/**
Andrew Scullf2ae1932023-04-24 19:09:09 +0000861 * Call generateCertificateRequest(). Make sure it's removed.
Tri Vo0d6204e2022-09-29 16:15:34 -0700862 */
Andrew Scullf2ae1932023-04-24 19:09:09 +0000863TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed_prodMode) {
864 bytevec keysToSignMac;
865 DeviceInfo deviceInfo;
866 ProtectedData protectedData;
867 auto status = provisionable_->generateCertificateRequest(
868 false /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
869 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700870 ASSERT_FALSE(status.isOk()) << status.getDescription();
Andrew Scullf2ae1932023-04-24 19:09:09 +0000871 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700872}
873
Andrew Scull95b31312023-03-27 19:16:07 +0000874/**
Andrew Scullf2ae1932023-04-24 19:09:09 +0000875 * Call generateCertificateRequest() in test mode. Make sure it's removed.
Andrew Scull95b31312023-03-27 19:16:07 +0000876 */
Andrew Scullf2ae1932023-04-24 19:09:09 +0000877TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed_testMode) {
Andrew Scull95b31312023-03-27 19:16:07 +0000878 bytevec keysToSignMac;
879 DeviceInfo deviceInfo;
880 ProtectedData protectedData;
881 auto status = provisionable_->generateCertificateRequest(
882 true /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
883 &protectedData, &keysToSignMac);
Frederick Mayle9891be02023-11-03 14:39:24 -0700884 ASSERT_FALSE(status.isOk()) << status.getDescription();
Andrew Scull95b31312023-03-27 19:16:07 +0000885 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
886}
887
Tri Voec50ee12023-02-14 16:29:53 -0800888void parse_root_of_trust(const vector<uint8_t>& attestation_cert,
889 vector<uint8_t>* verified_boot_key, VerifiedBoot* verified_boot_state,
890 bool* device_locked, vector<uint8_t>* verified_boot_hash) {
891 X509_Ptr cert(parse_cert_blob(attestation_cert));
892 ASSERT_TRUE(cert.get());
893
894 ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
895 ASSERT_TRUE(attest_rec);
896
897 auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, verified_boot_key,
898 verified_boot_state, device_locked, verified_boot_hash);
899 ASSERT_EQ(error, ErrorCode::OK);
900}
901
902/**
903 * Generate a CSR and verify DeviceInfo against IDs attested by KeyMint.
904 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700905// @VsrTest = 3.10-015
Tri Voec50ee12023-02-14 16:29:53 -0800906TEST_P(CertificateRequestV2Test, DeviceInfo) {
907 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
908 std::shared_ptr<IKeyMintDevice> keyMint;
909 if (!matching_keymint_device(GetParam(), &keyMint)) {
910 // No matching IKeyMintDevice.
911 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
912 return;
913 }
914 KeyMintHardwareInfo info;
915 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
916
917 // Get IDs attested by KeyMint.
918 MacedPublicKey macedPubKey;
919 bytevec privateKeyBlob;
920 auto irpcStatus =
921 provisionable_->generateEcdsaP256KeyPair(false, &macedPubKey, &privateKeyBlob);
922 ASSERT_TRUE(irpcStatus.isOk());
923
924 AttestationKey attestKey;
925 attestKey.keyBlob = std::move(privateKeyBlob);
926 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
927
928 // Generate an ECDSA key that is attested by the generated P256 keypair.
929 AuthorizationSet keyDesc = AuthorizationSetBuilder()
930 .Authorization(TAG_NO_AUTH_REQUIRED)
931 .EcdsaSigningKey(EcCurve::P_256)
932 .AttestationChallenge("foo")
933 .AttestationApplicationId("bar")
934 .Digest(Digest::NONE)
935 .SetDefaultValidity();
936 KeyCreationResult creationResult;
937 auto kmStatus = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
938 ASSERT_TRUE(kmStatus.isOk());
939
940 vector<KeyCharacteristics> key_characteristics = std::move(creationResult.keyCharacteristics);
941 vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain);
942 // We didn't provision the attestation key.
943 ASSERT_EQ(key_cert_chain.size(), 1);
944
945 // Parse attested patch levels.
946 auto auths = HwEnforcedAuthorizations(key_characteristics);
947
948 auto attestedSystemPatchLevel = auths.GetTagValue(TAG_OS_PATCHLEVEL);
949 auto attestedVendorPatchLevel = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
950 auto attestedBootPatchLevel = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
951
952 ASSERT_TRUE(attestedSystemPatchLevel.has_value());
953 ASSERT_TRUE(attestedVendorPatchLevel.has_value());
954 ASSERT_TRUE(attestedBootPatchLevel.has_value());
955
956 // Parse attested AVB values.
957 vector<uint8_t> key;
958 VerifiedBoot attestedVbState;
959 bool attestedBootloaderState;
960 vector<uint8_t> attestedVbmetaDigest;
961 parse_root_of_trust(key_cert_chain[0].encodedCertificate, &key, &attestedVbState,
962 &attestedBootloaderState, &attestedVbmetaDigest);
963
964 // Get IDs from DeviceInfo.
965 bytevec csr;
966 irpcStatus =
967 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
Frederick Mayle9891be02023-11-03 14:39:24 -0700968 ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getDescription();
Tri Voec50ee12023-02-14 16:29:53 -0800969
Alice Wangf112ec92024-10-08 07:30:28 +0000970 auto result =
Sean Thomas2d2385b2024-11-07 23:56:03 +0000971 verifyProductionCsr(cppbor::Array(), csr, rpcHardwareInfo, GetParam(), challenge_);
Tri Voec50ee12023-02-14 16:29:53 -0800972 ASSERT_TRUE(result) << result.message();
973
974 std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
975 ASSERT_TRUE(csrPayload);
976
977 auto deviceInfo = csrPayload->get(2)->asMap();
978 ASSERT_TRUE(deviceInfo);
979
980 auto vbState = deviceInfo->get("vb_state")->asTstr();
981 auto bootloaderState = deviceInfo->get("bootloader_state")->asTstr();
982 auto vbmetaDigest = deviceInfo->get("vbmeta_digest")->asBstr();
983 auto systemPatchLevel = deviceInfo->get("system_patch_level")->asUint();
984 auto vendorPatchLevel = deviceInfo->get("vendor_patch_level")->asUint();
985 auto bootPatchLevel = deviceInfo->get("boot_patch_level")->asUint();
986 auto securityLevel = deviceInfo->get("security_level")->asTstr();
987
988 ASSERT_TRUE(vbState);
989 ASSERT_TRUE(bootloaderState);
990 ASSERT_TRUE(vbmetaDigest);
991 ASSERT_TRUE(systemPatchLevel);
992 ASSERT_TRUE(vendorPatchLevel);
993 ASSERT_TRUE(bootPatchLevel);
994 ASSERT_TRUE(securityLevel);
995
Sean Thomasafbab602024-11-07 23:14:05 +0000996 auto kmDeviceName = deviceSuffix(GetParam());
Tri Voec50ee12023-02-14 16:29:53 -0800997
998 // Compare DeviceInfo against IDs attested by KeyMint.
999 ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") ||
1000 (securityLevel->value() == "strongbox" && kmDeviceName == "strongbox"));
1001 ASSERT_TRUE((vbState->value() == "green" && attestedVbState == VerifiedBoot::VERIFIED) ||
1002 (vbState->value() == "yellow" && attestedVbState == VerifiedBoot::SELF_SIGNED) ||
1003 (vbState->value() == "orange" && attestedVbState == VerifiedBoot::UNVERIFIED));
1004 ASSERT_TRUE((bootloaderState->value() == "locked" && attestedBootloaderState) ||
1005 (bootloaderState->value() == "unlocked" && !attestedBootloaderState));
1006 ASSERT_EQ(vbmetaDigest->value(), attestedVbmetaDigest);
1007 ASSERT_EQ(systemPatchLevel->value(), attestedSystemPatchLevel.value());
1008 ASSERT_EQ(vendorPatchLevel->value(), attestedVendorPatchLevel.value());
1009 ASSERT_EQ(bootPatchLevel->value(), attestedBootPatchLevel.value());
1010}
1011
Tri Vo0d6204e2022-09-29 16:15:34 -07001012INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
1013
Max Biresa9b3bb92022-11-21 23:02:09 -08001014using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
1015
1016INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
1017
1018TEST_P(VsrRequirementTest, VsrEnforcementTest) {
1019 RpcHardwareInfo hwInfo;
1020 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
1021 int vsr_api_level = get_vsr_api_level();
1022 if (vsr_api_level < 34) {
1023 GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
1024 << vsr_api_level;
1025 }
1026 EXPECT_GE(hwInfo.versionNumber, 3)
1027 << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
1028}
1029
Shawn Willden274bb552020-09-30 22:39:22 -06001030} // namespace aidl::android::hardware::security::keymint::test