blob: 89ab2c2672132bb33feeba79f5a600b55645940d [file] [log] [blame]
Shawn Willden274bb552020-09-30 22:39:22 -06001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Seth Mooref1f62152022-09-13 12:00:30 -070017#include <memory>
Seth Moore2fc6f832022-09-13 16:10:11 -070018#include <string>
Shawn Willden274bb552020-09-30 22:39:22 -060019#define LOG_TAG "VtsRemotelyProvisionableComponentTests"
20
Seth Moore8f810b12022-12-12 16:51:01 -080021#include <aidl/android/hardware/security/keymint/BnRemotelyProvisionedComponent.h>
Shawn Willden274bb552020-09-30 22:39:22 -060022#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
23#include <aidl/android/hardware/security/keymint/SecurityLevel.h>
24#include <android/binder_manager.h>
Seth Moorefc86bf42021-12-09 14:07:04 -080025#include <binder/IServiceManager.h>
Tri Voec50ee12023-02-14 16:29:53 -080026#include <cppbor.h>
Shawn Willden274bb552020-09-30 22:39:22 -060027#include <cppbor_parse.h>
Shawn Willden274bb552020-09-30 22:39:22 -060028#include <gmock/gmock.h>
Max Bires9704ff62021-04-07 11:12:01 -070029#include <keymaster/cppcose/cppcose.h>
Shawn Willden274bb552020-09-30 22:39:22 -060030#include <keymaster/keymaster_configuration.h>
David Drysdalef0d516d2021-03-22 07:51:43 +000031#include <keymint_support/authorization_set.h>
32#include <openssl/ec.h>
33#include <openssl/ec_key.h>
34#include <openssl/x509.h>
Shawn Willden274bb552020-09-30 22:39:22 -060035#include <remote_prov/remote_prov_utils.h>
Max Bires757ed422022-09-07 16:20:31 -070036#include <optional>
Seth Moorefc86bf42021-12-09 14:07:04 -080037#include <set>
Seth Moore42c11332021-07-02 15:38:17 -070038#include <vector>
Shawn Willden274bb552020-09-30 22:39:22 -060039
David Drysdalef0d516d2021-03-22 07:51:43 +000040#include "KeyMintAidlTestBase.h"
41
Shawn Willden274bb552020-09-30 22:39:22 -060042namespace aidl::android::hardware::security::keymint::test {
43
44using ::std::string;
45using ::std::vector;
46
47namespace {
48
Seth Moorefc86bf42021-12-09 14:07:04 -080049constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
Tri Vo0d6204e2022-09-29 16:15:34 -070050constexpr int32_t VERSION_WITHOUT_TEST_MODE = 3;
Seth Moorefc86bf42021-12-09 14:07:04 -080051
Tommy Chiufde3ad12023-03-17 05:58:28 +000052constexpr uint8_t MIN_CHALLENGE_SIZE = 0;
53constexpr uint8_t MAX_CHALLENGE_SIZE = 64;
54
Shawn Willden274bb552020-09-30 22:39:22 -060055#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
Seth Moore6305e232021-07-27 14:20:17 -070056 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
Shawn Willden274bb552020-09-30 22:39:22 -060057 INSTANTIATE_TEST_SUITE_P( \
58 PerInstance, name, \
59 testing::ValuesIn(VtsRemotelyProvisionedComponentTests::build_params()), \
60 ::android::PrintInstanceNameToString)
61
Seth Moorefc86bf42021-12-09 14:07:04 -080062using ::android::sp;
Shawn Willden274bb552020-09-30 22:39:22 -060063using bytevec = std::vector<uint8_t>;
64using testing::MatchesRegex;
65using namespace remote_prov;
66using namespace keymaster;
67
68bytevec string_to_bytevec(const char* s) {
69 const uint8_t* p = reinterpret_cast<const uint8_t*>(s);
70 return bytevec(p, p + strlen(s));
71}
72
David Drysdalee99ed862021-03-15 16:43:06 +000073ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
74 auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
75 if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
76 return "COSE Mac0 parse failed";
77 }
78 auto protParams = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
79 auto unprotParams = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
80 auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
81 auto tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
82 if (!protParams || !unprotParams || !payload || !tag) {
83 return "Invalid COSE_Sign1: missing content";
84 }
85 auto corruptMac0 = cppbor::Array();
86 corruptMac0.add(protParams->clone());
87 corruptMac0.add(unprotParams->clone());
88 corruptMac0.add(payload->clone());
89 vector<uint8_t> tagData = tag->value();
90 tagData[0] ^= 0x08;
91 tagData[tagData.size() - 1] ^= 0x80;
92 corruptMac0.add(cppbor::Bstr(tagData));
93
94 return MacedPublicKey{corruptMac0.encode()};
95}
96
David Drysdalecceca9f2021-03-12 15:49:47 +000097ErrMsgOr<cppbor::Array> corrupt_sig(const cppbor::Array* coseSign1) {
98 if (coseSign1->size() != kCoseSign1EntryCount) {
99 return "Invalid COSE_Sign1, wrong entry count";
100 }
101 const cppbor::Bstr* protectedParams = coseSign1->get(kCoseSign1ProtectedParams)->asBstr();
102 const cppbor::Map* unprotectedParams = coseSign1->get(kCoseSign1UnprotectedParams)->asMap();
103 const cppbor::Bstr* payload = coseSign1->get(kCoseSign1Payload)->asBstr();
104 const cppbor::Bstr* signature = coseSign1->get(kCoseSign1Signature)->asBstr();
105 if (!protectedParams || !unprotectedParams || !payload || !signature) {
106 return "Invalid COSE_Sign1: missing content";
107 }
108
109 auto corruptSig = cppbor::Array();
110 corruptSig.add(protectedParams->clone());
111 corruptSig.add(unprotectedParams->clone());
112 corruptSig.add(payload->clone());
113 vector<uint8_t> sigData = signature->value();
114 sigData[0] ^= 0x08;
115 corruptSig.add(cppbor::Bstr(sigData));
116
117 return std::move(corruptSig);
118}
119
Seth Moore19acbe92021-06-23 15:15:52 -0700120ErrMsgOr<bytevec> corrupt_sig_chain(const bytevec& encodedEekChain, int which) {
121 auto [chain, _, parseErr] = cppbor::parse(encodedEekChain);
David Drysdalecceca9f2021-03-12 15:49:47 +0000122 if (!chain || !chain->asArray()) {
123 return "EekChain parse failed";
124 }
125
126 cppbor::Array* eekChain = chain->asArray();
127 if (which >= eekChain->size()) {
128 return "selected sig out of range";
129 }
130 auto corruptChain = cppbor::Array();
131
132 for (int ii = 0; ii < eekChain->size(); ++ii) {
133 if (ii == which) {
134 auto sig = corrupt_sig(eekChain->get(which)->asArray());
135 if (!sig) {
136 return "Failed to build corrupted signature" + sig.moveMessage();
137 }
138 corruptChain.add(sig.moveValue());
139 } else {
140 corruptChain.add(eekChain->get(ii)->clone());
141 }
142 }
Seth Moore19acbe92021-06-23 15:15:52 -0700143 return corruptChain.encode();
David Drysdalecceca9f2021-03-12 15:49:47 +0000144}
145
David Drysdale4d3c2982021-03-31 18:21:40 +0100146string device_suffix(const string& name) {
147 size_t pos = name.find('/');
148 if (pos == string::npos) {
149 return name;
150 }
151 return name.substr(pos + 1);
152}
153
154bool matching_keymint_device(const string& rp_name, std::shared_ptr<IKeyMintDevice>* keyMint) {
155 string rp_suffix = device_suffix(rp_name);
156
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.
161 if (device_suffix(km_name) == rp_suffix && AServiceManager_isDeclared(km_name.c_str())) {
162 ::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);
subrahmanyamanfb213d62022-02-02 23:10:55 +0000180 ASSERT_TRUE(provisionable_->getHardwareInfo(&rpcHardwareInfo).isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600181 }
182
183 static vector<string> build_params() {
184 auto params = ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
185 return params;
186 }
187
188 protected:
189 std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000190 RpcHardwareInfo rpcHardwareInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600191};
192
Seth Moorefc86bf42021-12-09 14:07:04 -0800193/**
194 * Verify that every implementation reports a different unique id.
195 */
196TEST(NonParameterizedTests, eachRpcHasAUniqueId) {
197 std::set<std::string> uniqueIds;
198 for (auto hal : ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor)) {
199 ASSERT_TRUE(AServiceManager_isDeclared(hal.c_str()));
200 ::ndk::SpAIBinder binder(AServiceManager_waitForService(hal.c_str()));
201 std::shared_ptr<IRemotelyProvisionedComponent> rpc =
202 IRemotelyProvisionedComponent::fromBinder(binder);
203 ASSERT_NE(rpc, nullptr);
204
205 RpcHardwareInfo hwInfo;
206 ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
207
Tri Vodd12c482022-10-12 22:41:28 +0000208 if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800209 ASSERT_TRUE(hwInfo.uniqueId);
210 auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
211 EXPECT_TRUE(wasInserted);
212 } else {
213 ASSERT_FALSE(hwInfo.uniqueId);
214 }
215 }
216}
217
218using GetHardwareInfoTests = VtsRemotelyProvisionedComponentTests;
219
220INSTANTIATE_REM_PROV_AIDL_TEST(GetHardwareInfoTests);
221
222/**
223 * Verify that a valid curve is reported by the implementation.
224 */
225TEST_P(GetHardwareInfoTests, supportsValidCurve) {
226 RpcHardwareInfo hwInfo;
227 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
228
229 const std::set<int> validCurves = {RpcHardwareInfo::CURVE_P256, RpcHardwareInfo::CURVE_25519};
Hasini Gunasinghe666b2712023-01-05 21:35:51 +0000230 // First check for the implementations that supports only IRPC V3+.
231 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
232 bytevec keysToSignMac;
233 DeviceInfo deviceInfo;
234 ProtectedData protectedData;
235 auto status = provisionable_->generateCertificateRequest(false, {}, {}, {}, &deviceInfo,
236 &protectedData, &keysToSignMac);
237 if (!status.isOk() &&
238 (status.getServiceSpecificError() == BnRemotelyProvisionedComponent::STATUS_REMOVED)) {
239 ASSERT_EQ(hwInfo.supportedEekCurve, RpcHardwareInfo::CURVE_NONE)
240 << "Invalid curve: " << hwInfo.supportedEekCurve;
241 return;
242 }
243 }
Seth Moorefc86bf42021-12-09 14:07:04 -0800244 ASSERT_EQ(validCurves.count(hwInfo.supportedEekCurve), 1)
245 << "Invalid curve: " << hwInfo.supportedEekCurve;
246}
247
248/**
249 * Verify that the unique id is within the length limits as described in RpcHardwareInfo.aidl.
250 */
251TEST_P(GetHardwareInfoTests, uniqueId) {
Tri Vodd12c482022-10-12 22:41:28 +0000252 if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
Seth Moorefc86bf42021-12-09 14:07:04 -0800253 return;
254 }
255
256 RpcHardwareInfo hwInfo;
257 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
258 ASSERT_TRUE(hwInfo.uniqueId);
259 EXPECT_GE(hwInfo.uniqueId->size(), 1);
260 EXPECT_LE(hwInfo.uniqueId->size(), 32);
261}
262
Tri Vo9cab73c2022-10-28 13:40:24 -0700263/**
264 * Verify implementation supports at least MIN_SUPPORTED_NUM_KEYS_IN_CSR keys in a CSR.
265 */
266TEST_P(GetHardwareInfoTests, supportedNumKeysInCsr) {
267 if (rpcHardwareInfo.versionNumber < VERSION_WITHOUT_TEST_MODE) {
268 return;
269 }
270
271 RpcHardwareInfo hwInfo;
272 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
273 ASSERT_GE(hwInfo.supportedNumKeysInCsr, RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR);
274}
275
Shawn Willden274bb552020-09-30 22:39:22 -0600276using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
277
278INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
279
280/**
David Drysdalef0d516d2021-03-22 07:51:43 +0000281 * Generate and validate a production-mode key. MAC tag can't be verified, but
282 * the private key blob should be usable in KeyMint operations.
Shawn Willden274bb552020-09-30 22:39:22 -0600283 */
Max Bires126869a2021-02-21 18:32:59 -0800284TEST_P(GenerateKeyTests, generateEcdsaP256Key_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600285 MacedPublicKey macedPubKey;
286 bytevec privateKeyBlob;
287 bool testMode = false;
288 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
289 ASSERT_TRUE(status.isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000290 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800291 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100292}
293
294/**
295 * Generate and validate a production-mode key, then use it as a KeyMint attestation key.
296 */
297TEST_P(GenerateKeyTests, generateAndUseEcdsaP256Key_prodMode) {
298 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
299 std::shared_ptr<IKeyMintDevice> keyMint;
300 if (!matching_keymint_device(GetParam(), &keyMint)) {
301 // No matching IKeyMintDevice.
302 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
303 return;
304 }
305 KeyMintHardwareInfo info;
306 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
307
308 MacedPublicKey macedPubKey;
309 bytevec privateKeyBlob;
310 bool testMode = false;
311 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
312 ASSERT_TRUE(status.isOk());
313 vector<uint8_t> coseKeyData;
Tri Vob0b8acc2022-11-30 16:22:23 -0800314 check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
David Drysdale4d3c2982021-03-31 18:21:40 +0100315
David Drysdalef0d516d2021-03-22 07:51:43 +0000316 AttestationKey attestKey;
317 attestKey.keyBlob = std::move(privateKeyBlob);
318 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
Shawn Willden274bb552020-09-30 22:39:22 -0600319
David Drysdalef0d516d2021-03-22 07:51:43 +0000320 // Generate an ECDSA key that is attested by the generated P256 keypair.
321 AuthorizationSet keyDesc = AuthorizationSetBuilder()
322 .Authorization(TAG_NO_AUTH_REQUIRED)
David Drysdale915ce252021-10-14 15:17:36 +0100323 .EcdsaSigningKey(EcCurve::P_256)
David Drysdalef0d516d2021-03-22 07:51:43 +0000324 .AttestationChallenge("foo")
325 .AttestationApplicationId("bar")
326 .Digest(Digest::NONE)
327 .SetDefaultValidity();
328 KeyCreationResult creationResult;
329 auto result = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
330 ASSERT_TRUE(result.isOk());
331 vector<uint8_t> attested_key_blob = std::move(creationResult.keyBlob);
332 vector<KeyCharacteristics> attested_key_characteristics =
333 std::move(creationResult.keyCharacteristics);
334 vector<Certificate> attested_key_cert_chain = std::move(creationResult.certificateChain);
335 EXPECT_EQ(attested_key_cert_chain.size(), 1);
336
David Drysdale7dff4fc2021-12-10 10:10:52 +0000337 int32_t aidl_version = 0;
338 ASSERT_TRUE(keyMint->getInterfaceVersion(&aidl_version).isOk());
David Drysdalef0d516d2021-03-22 07:51:43 +0000339 AuthorizationSet hw_enforced = HwEnforcedAuthorizations(attested_key_characteristics);
340 AuthorizationSet sw_enforced = SwEnforcedAuthorizations(attested_key_characteristics);
David Drysdale7dff4fc2021-12-10 10:10:52 +0000341 EXPECT_TRUE(verify_attestation_record(aidl_version, "foo", "bar", sw_enforced, hw_enforced,
David Drysdalef0d516d2021-03-22 07:51:43 +0000342 info.securityLevel,
343 attested_key_cert_chain[0].encodedCertificate));
344
345 // Attestation by itself is not valid (last entry is not self-signed).
346 EXPECT_FALSE(ChainSignaturesAreValid(attested_key_cert_chain));
347
348 // The signature over the attested key should correspond to the P256 public key.
349 X509_Ptr key_cert(parse_cert_blob(attested_key_cert_chain[0].encodedCertificate));
350 ASSERT_TRUE(key_cert.get());
351 EVP_PKEY_Ptr signing_pubkey;
352 p256_pub_key(coseKeyData, &signing_pubkey);
353 ASSERT_TRUE(signing_pubkey.get());
354
355 ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
356 << "Verification of attested certificate failed "
357 << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
Shawn Willden274bb552020-09-30 22:39:22 -0600358}
359
360/**
361 * Generate and validate a test-mode key.
362 */
Max Bires126869a2021-02-21 18:32:59 -0800363TEST_P(GenerateKeyTests, generateEcdsaP256Key_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600364 MacedPublicKey macedPubKey;
365 bytevec privateKeyBlob;
366 bool testMode = true;
367 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
368 ASSERT_TRUE(status.isOk());
Tri Vob0b8acc2022-11-30 16:22:23 -0800369 check_maced_pubkey(macedPubKey, testMode, nullptr);
Shawn Willden274bb552020-09-30 22:39:22 -0600370}
371
Tri Vo0d6204e2022-09-29 16:15:34 -0700372class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
Shawn Willden274bb552020-09-30 22:39:22 -0600373 protected:
Tri Vo0d6204e2022-09-29 16:15:34 -0700374 CertificateRequestTestBase()
375 : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
David Drysdalecceca9f2021-03-12 15:49:47 +0000376
Seth Moore19acbe92021-06-23 15:15:52 -0700377 void generateTestEekChain(size_t eekLength) {
subrahmanyamanfb213d62022-02-02 23:10:55 +0000378 auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
David Drysdale08696a72022-03-10 10:43:25 +0000379 ASSERT_TRUE(chain) << chain.message();
Seth Moore19acbe92021-06-23 15:15:52 -0700380 if (chain) testEekChain_ = chain.moveValue();
381 testEekLength_ = eekLength;
Shawn Willden274bb552020-09-30 22:39:22 -0600382 }
383
384 void generateKeys(bool testMode, size_t numKeys) {
385 keysToSign_ = std::vector<MacedPublicKey>(numKeys);
386 cborKeysToSign_ = cppbor::Array();
387
388 for (auto& key : keysToSign_) {
389 bytevec privateKeyBlob;
390 auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &key, &privateKeyBlob);
391 ASSERT_TRUE(status.isOk()) << status.getMessage();
392
David Drysdalec8400772021-03-11 12:35:11 +0000393 vector<uint8_t> payload_value;
Tri Vob0b8acc2022-11-30 16:22:23 -0800394 check_maced_pubkey(key, testMode, &payload_value);
David Drysdalec8400772021-03-11 12:35:11 +0000395 cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
Shawn Willden274bb552020-09-30 22:39:22 -0600396 }
397 }
398
399 bytevec eekId_;
Seth Moore19acbe92021-06-23 15:15:52 -0700400 size_t testEekLength_;
401 EekChain testEekChain_;
David Drysdalec8400772021-03-11 12:35:11 +0000402 bytevec challenge_;
Shawn Willden274bb552020-09-30 22:39:22 -0600403 std::vector<MacedPublicKey> keysToSign_;
404 cppbor::Array cborKeysToSign_;
405};
406
Tri Vo0d6204e2022-09-29 16:15:34 -0700407class CertificateRequestTest : public CertificateRequestTestBase {
408 protected:
409 void SetUp() override {
410 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000411 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700412
413 if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
Andrew Scull95b31312023-03-27 19:16:07 +0000414 GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
415 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
Tri Vo0d6204e2022-09-29 16:15:34 -0700416 }
417 }
418};
419
Shawn Willden274bb552020-09-30 22:39:22 -0600420/**
421 * Generate an empty certificate request in test mode, and decrypt and verify the structure and
422 * content.
423 */
Max Bires126869a2021-02-21 18:32:59 -0800424TEST_P(CertificateRequestTest, EmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600425 bool testMode = true;
David Drysdalecceca9f2021-03-12 15:49:47 +0000426 for (size_t eekLength : {2, 3, 7}) {
427 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700428 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600429
David Drysdalecceca9f2021-03-12 15:49:47 +0000430 bytevec keysToSignMac;
431 DeviceInfo deviceInfo;
432 ProtectedData protectedData;
433 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700434 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalecceca9f2021-03-12 15:49:47 +0000435 &protectedData, &keysToSignMac);
436 ASSERT_TRUE(status.isOk()) << status.getMessage();
437
Seth Moore2fc6f832022-09-13 16:10:11 -0700438 auto result = verifyProductionProtectedData(
439 deviceInfo, cppbor::Array(), keysToSignMac, protectedData, testEekChain_, eekId_,
440 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
441 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000442 }
Shawn Willden274bb552020-09-30 22:39:22 -0600443}
444
445/**
Seth Moore42c11332021-07-02 15:38:17 -0700446 * Ensure that test mode outputs a unique BCC root key every time we request a
447 * certificate request. Else, it's possible that the test mode API could be used
448 * to fingerprint devices. Only the GEEK should be allowed to decrypt the same
449 * device public key multiple times.
450 */
451TEST_P(CertificateRequestTest, NewKeyPerCallInTestMode) {
452 constexpr bool testMode = true;
Seth Moore42c11332021-07-02 15:38:17 -0700453
454 bytevec keysToSignMac;
455 DeviceInfo deviceInfo;
456 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000457 generateTestEekChain(3);
Seth Moore42c11332021-07-02 15:38:17 -0700458 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700459 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
460 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700461 ASSERT_TRUE(status.isOk()) << status.getMessage();
462
Seth Moore2fc6f832022-09-13 16:10:11 -0700463 auto firstBcc = verifyProductionProtectedData(
464 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
465 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
466 ASSERT_TRUE(firstBcc) << firstBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700467
Seth Moore19acbe92021-06-23 15:15:52 -0700468 status = provisionable_->generateCertificateRequest(
469 testMode, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
470 &protectedData, &keysToSignMac);
Seth Moore42c11332021-07-02 15:38:17 -0700471 ASSERT_TRUE(status.isOk()) << status.getMessage();
472
Seth Moore2fc6f832022-09-13 16:10:11 -0700473 auto secondBcc = verifyProductionProtectedData(
474 deviceInfo, /*keysToSign=*/cppbor::Array(), keysToSignMac, protectedData, testEekChain_,
475 eekId_, rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
476 ASSERT_TRUE(secondBcc) << secondBcc.message();
Seth Moore42c11332021-07-02 15:38:17 -0700477
478 // Verify that none of the keys in the first BCC are repeated in the second one.
Seth Moore2fc6f832022-09-13 16:10:11 -0700479 for (const auto& i : *firstBcc) {
480 for (auto& j : *secondBcc) {
Seth Moore42c11332021-07-02 15:38:17 -0700481 ASSERT_THAT(i.pubKey, testing::Not(testing::ElementsAreArray(j.pubKey)))
482 << "Found a repeated pubkey in two generateCertificateRequest test mode calls";
483 }
484 }
485}
486
487/**
Seth Moore19acbe92021-06-23 15:15:52 -0700488 * Generate an empty certificate request in prod mode. This test must be run explicitly, and
489 * is not run by default. Not all devices are GMS devices, and therefore they do not all
490 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600491 */
Seth Moore19acbe92021-06-23 15:15:52 -0700492TEST_P(CertificateRequestTest, DISABLED_EmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600493 bool testMode = false;
David Drysdalecceca9f2021-03-12 15:49:47 +0000494
Seth Moore19acbe92021-06-23 15:15:52 -0700495 bytevec keysToSignMac;
496 DeviceInfo deviceInfo;
497 ProtectedData protectedData;
498 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000499 testMode, {} /* keysToSign */, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
500 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700501 EXPECT_TRUE(status.isOk());
Shawn Willden274bb552020-09-30 22:39:22 -0600502}
503
504/**
505 * Generate a non-empty certificate request in test mode. Decrypt, parse and validate the contents.
506 */
Max Bires126869a2021-02-21 18:32:59 -0800507TEST_P(CertificateRequestTest, NonEmptyRequest_testMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600508 bool testMode = true;
509 generateKeys(testMode, 4 /* numKeys */);
510
David Drysdalecceca9f2021-03-12 15:49:47 +0000511 for (size_t eekLength : {2, 3, 7}) {
512 SCOPED_TRACE(testing::Message() << "EEK of length " << eekLength);
Seth Moore19acbe92021-06-23 15:15:52 -0700513 generateTestEekChain(eekLength);
Shawn Willden274bb552020-09-30 22:39:22 -0600514
David Drysdalecceca9f2021-03-12 15:49:47 +0000515 bytevec keysToSignMac;
516 DeviceInfo deviceInfo;
517 ProtectedData protectedData;
518 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700519 testMode, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo, &protectedData,
David Drysdalecceca9f2021-03-12 15:49:47 +0000520 &keysToSignMac);
521 ASSERT_TRUE(status.isOk()) << status.getMessage();
522
Seth Moore2fc6f832022-09-13 16:10:11 -0700523 auto result = verifyProductionProtectedData(
524 deviceInfo, cborKeysToSign_, keysToSignMac, protectedData, testEekChain_, eekId_,
525 rpcHardwareInfo.supportedEekCurve, provisionable_.get(), challenge_);
526 ASSERT_TRUE(result) << result.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000527 }
Shawn Willden274bb552020-09-30 22:39:22 -0600528}
529
530/**
Seth Moore19acbe92021-06-23 15:15:52 -0700531 * Generate a non-empty certificate request in prod mode. This test must be run explicitly, and
532 * is not run by default. Not all devices are GMS devices, and therefore they do not all
533 * trust the Google EEK root.
Shawn Willden274bb552020-09-30 22:39:22 -0600534 */
Seth Moore19acbe92021-06-23 15:15:52 -0700535TEST_P(CertificateRequestTest, DISABLED_NonEmptyRequest_prodMode) {
Shawn Willden274bb552020-09-30 22:39:22 -0600536 bool testMode = false;
537 generateKeys(testMode, 4 /* numKeys */);
538
Seth Moore19acbe92021-06-23 15:15:52 -0700539 bytevec keysToSignMac;
540 DeviceInfo deviceInfo;
541 ProtectedData protectedData;
542 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000543 testMode, keysToSign_, getProdEekChain(rpcHardwareInfo.supportedEekCurve), challenge_,
544 &deviceInfo, &protectedData, &keysToSignMac);
Seth Moore19acbe92021-06-23 15:15:52 -0700545 EXPECT_TRUE(status.isOk());
David Drysdalecceca9f2021-03-12 15:49:47 +0000546}
547
548/**
David Drysdalee99ed862021-03-15 16:43:06 +0000549 * Generate a non-empty certificate request in test mode, but with the MAC corrupted on the keypair.
550 */
551TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_testMode) {
552 bool testMode = true;
553 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000554 auto result = corrupt_maced_key(keysToSign_[0]);
555 ASSERT_TRUE(result) << result.moveMessage();
556 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000557
558 bytevec keysToSignMac;
559 DeviceInfo deviceInfo;
560 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000561 generateTestEekChain(3);
David Drysdalee99ed862021-03-15 16:43:06 +0000562 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700563 testMode, {keyWithCorruptMac}, testEekChain_.chain, challenge_, &deviceInfo,
564 &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000565 ASSERT_FALSE(status.isOk()) << status.getMessage();
566 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
567}
568
569/**
570 * Generate a non-empty certificate request in prod mode, but with the MAC corrupted on the keypair.
571 */
572TEST_P(CertificateRequestTest, NonEmptyRequestCorruptMac_prodMode) {
Seth Moore19acbe92021-06-23 15:15:52 -0700573 bool testMode = false;
David Drysdalee99ed862021-03-15 16:43:06 +0000574 generateKeys(testMode, 1 /* numKeys */);
David Drysdale08696a72022-03-10 10:43:25 +0000575 auto result = corrupt_maced_key(keysToSign_[0]);
576 ASSERT_TRUE(result) << result.moveMessage();
577 MacedPublicKey keyWithCorruptMac = result.moveValue();
David Drysdalee99ed862021-03-15 16:43:06 +0000578
579 bytevec keysToSignMac;
580 DeviceInfo deviceInfo;
581 ProtectedData protectedData;
582 auto status = provisionable_->generateCertificateRequest(
subrahmanyamanfb213d62022-02-02 23:10:55 +0000583 testMode, {keyWithCorruptMac}, getProdEekChain(rpcHardwareInfo.supportedEekCurve),
584 challenge_, &deviceInfo, &protectedData, &keysToSignMac);
David Drysdalee99ed862021-03-15 16:43:06 +0000585 ASSERT_FALSE(status.isOk()) << status.getMessage();
Seth Moore19acbe92021-06-23 15:15:52 -0700586 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
David Drysdalee99ed862021-03-15 16:43:06 +0000587}
588
589/**
David Drysdalecceca9f2021-03-12 15:49:47 +0000590 * Generate a non-empty certificate request in prod mode that has a corrupt EEK chain.
591 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000592 */
593TEST_P(CertificateRequestTest, NonEmptyCorruptEekRequest_prodMode) {
594 bool testMode = false;
595 generateKeys(testMode, 4 /* numKeys */);
596
subrahmanyamanfb213d62022-02-02 23:10:55 +0000597 auto prodEekChain = getProdEekChain(rpcHardwareInfo.supportedEekCurve);
Seth Moore19acbe92021-06-23 15:15:52 -0700598 auto [parsedChain, _, parseErr] = cppbor::parse(prodEekChain);
599 ASSERT_NE(parsedChain, nullptr) << parseErr;
600 ASSERT_NE(parsedChain->asArray(), nullptr);
601
602 for (int ii = 0; ii < parsedChain->asArray()->size(); ++ii) {
603 auto chain = corrupt_sig_chain(prodEekChain, ii);
David Drysdalecceca9f2021-03-12 15:49:47 +0000604 ASSERT_TRUE(chain) << chain.message();
David Drysdalecceca9f2021-03-12 15:49:47 +0000605
606 bytevec keysToSignMac;
607 DeviceInfo deviceInfo;
608 ProtectedData protectedData;
Seth Moore19acbe92021-06-23 15:15:52 -0700609 auto status = provisionable_->generateCertificateRequest(testMode, keysToSign_, *chain,
610 challenge_, &deviceInfo,
611 &protectedData, &keysToSignMac);
David Drysdalecceca9f2021-03-12 15:49:47 +0000612 ASSERT_FALSE(status.isOk());
613 ASSERT_EQ(status.getServiceSpecificError(),
614 BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
615 }
616}
617
618/**
619 * Generate a non-empty certificate request in prod mode that has an incomplete EEK chain.
620 * Confirm that the request is rejected.
David Drysdalecceca9f2021-03-12 15:49:47 +0000621 */
622TEST_P(CertificateRequestTest, NonEmptyIncompleteEekRequest_prodMode) {
623 bool testMode = false;
624 generateKeys(testMode, 4 /* numKeys */);
625
626 // Build an EEK chain that omits the first self-signed cert.
627 auto truncatedChain = cppbor::Array();
subrahmanyamanfb213d62022-02-02 23:10:55 +0000628 auto [chain, _, parseErr] = cppbor::parse(getProdEekChain(rpcHardwareInfo.supportedEekCurve));
David Drysdalecceca9f2021-03-12 15:49:47 +0000629 ASSERT_TRUE(chain);
630 auto eekChain = chain->asArray();
631 ASSERT_NE(eekChain, nullptr);
632 for (size_t ii = 1; ii < eekChain->size(); ii++) {
633 truncatedChain.add(eekChain->get(ii)->clone());
634 }
635
Shawn Willden274bb552020-09-30 22:39:22 -0600636 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700637 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600638 ProtectedData protectedData;
David Drysdalecceca9f2021-03-12 15:49:47 +0000639 auto status = provisionable_->generateCertificateRequest(
640 testMode, keysToSign_, truncatedChain.encode(), challenge_, &deviceInfo, &protectedData,
641 &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600642 ASSERT_FALSE(status.isOk());
643 ASSERT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_EEK);
644}
645
646/**
647 * Generate a non-empty certificate request in test mode, with prod keys. Must fail with
648 * STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
649 */
Max Bires126869a2021-02-21 18:32:59 -0800650TEST_P(CertificateRequestTest, NonEmptyRequest_prodKeyInTestCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600651 generateKeys(false /* testMode */, 2 /* numKeys */);
652
653 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700654 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600655 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000656 generateTestEekChain(3);
Max Biresfdbb9042021-03-23 12:43:38 -0700657 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700658 true /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
Max Biresfdbb9042021-03-23 12:43:38 -0700659 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600660 ASSERT_FALSE(status.isOk());
661 ASSERT_EQ(status.getServiceSpecificError(),
662 BnRemotelyProvisionedComponent::STATUS_PRODUCTION_KEY_IN_TEST_REQUEST);
663}
664
665/**
666 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
667 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
668 */
Max Bires126869a2021-02-21 18:32:59 -0800669TEST_P(CertificateRequestTest, NonEmptyRequest_testKeyInProdCert) {
Shawn Willden274bb552020-09-30 22:39:22 -0600670 generateKeys(true /* testMode */, 2 /* numKeys */);
671
672 bytevec keysToSignMac;
Max Biresfdbb9042021-03-23 12:43:38 -0700673 DeviceInfo deviceInfo;
Shawn Willden274bb552020-09-30 22:39:22 -0600674 ProtectedData protectedData;
subrahmanyamanfb213d62022-02-02 23:10:55 +0000675 generateTestEekChain(3);
Shawn Willden274bb552020-09-30 22:39:22 -0600676 auto status = provisionable_->generateCertificateRequest(
Seth Moore19acbe92021-06-23 15:15:52 -0700677 false /* testMode */, keysToSign_, testEekChain_.chain, challenge_, &deviceInfo,
David Drysdalec8400772021-03-11 12:35:11 +0000678 &protectedData, &keysToSignMac);
Shawn Willden274bb552020-09-30 22:39:22 -0600679 ASSERT_FALSE(status.isOk());
680 ASSERT_EQ(status.getServiceSpecificError(),
681 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
682}
683
684INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
685
Tri Vo0d6204e2022-09-29 16:15:34 -0700686class CertificateRequestV2Test : public CertificateRequestTestBase {
687 void SetUp() override {
688 CertificateRequestTestBase::SetUp();
Andrew Scull1bcb6022022-12-27 10:43:27 +0000689 ASSERT_FALSE(HasFatalFailure());
Tri Vo0d6204e2022-09-29 16:15:34 -0700690
691 if (rpcHardwareInfo.versionNumber < VERSION_WITHOUT_TEST_MODE) {
692 GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
693 << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
694 }
695 }
696};
697
698/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000699 * Generate an empty certificate request with all possible length of challenge, and decrypt and
700 * verify the structure and content.
Tri Vo0d6204e2022-09-29 16:15:34 -0700701 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700702// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700703TEST_P(CertificateRequestV2Test, EmptyRequest) {
704 bytevec csr;
705
Tommy Chiufde3ad12023-03-17 05:58:28 +0000706 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
707 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
708 auto challenge = randomBytes(size);
709 auto status =
710 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge, &csr);
711 ASSERT_TRUE(status.isOk()) << status.getMessage();
Tri Vo0d6204e2022-09-29 16:15:34 -0700712
Tommy Chiufde3ad12023-03-17 05:58:28 +0000713 auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge);
714 ASSERT_TRUE(result) << result.message();
715 }
Tri Vo0d6204e2022-09-29 16:15:34 -0700716}
717
718/**
Tommy Chiufde3ad12023-03-17 05:58:28 +0000719 * Generate a non-empty certificate request with all possible length of challenge. Decrypt, parse
720 * and validate the contents.
Tri Vo0d6204e2022-09-29 16:15:34 -0700721 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700722// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700723TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
724 generateKeys(false /* testMode */, 1 /* numKeys */);
725
726 bytevec csr;
727
Tommy Chiufde3ad12023-03-17 05:58:28 +0000728 for (auto size = MIN_CHALLENGE_SIZE; size <= MAX_CHALLENGE_SIZE; size++) {
729 SCOPED_TRACE(testing::Message() << "challenge[" << size << "]");
730 auto challenge = randomBytes(size);
731 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge, &csr);
732 ASSERT_TRUE(status.isOk()) << status.getMessage();
Tri Vo0d6204e2022-09-29 16:15:34 -0700733
Tommy Chiufde3ad12023-03-17 05:58:28 +0000734 auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge);
735 ASSERT_TRUE(result) << result.message();
736 }
737}
738
739/**
740 * Generate an empty certificate request with invalid size of challenge
741 */
742TEST_P(CertificateRequestV2Test, EmptyRequestWithInvalidChallengeFail) {
743 bytevec csr;
744
745 auto status = provisionable_->generateCertificateRequestV2(
746 /* keysToSign */ {}, randomBytes(MAX_CHALLENGE_SIZE + 1), &csr);
747 EXPECT_FALSE(status.isOk()) << status.getMessage();
748 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_FAILED);
Tri Vo0d6204e2022-09-29 16:15:34 -0700749}
750
751/**
Andrew Scullfb49ad22022-11-09 21:02:48 +0000752 * Generate a non-empty certificate request. Make sure contents are reproducible but allow for the
753 * signature to be different since algorithms including ECDSA P-256 can include a random value.
Tri Vo0d6204e2022-09-29 16:15:34 -0700754 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700755// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700756TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
757 generateKeys(false /* testMode */, 1 /* numKeys */);
758
759 bytevec csr;
760
761 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
762 ASSERT_TRUE(status.isOk()) << status.getMessage();
763
Andrew Scullfb49ad22022-11-09 21:02:48 +0000764 auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
765 ASSERT_TRUE(firstCsr) << firstCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700766
767 status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
768 ASSERT_TRUE(status.isOk()) << status.getMessage();
769
Andrew Scullfb49ad22022-11-09 21:02:48 +0000770 auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
771 ASSERT_TRUE(secondCsr) << secondCsr.message();
Tri Vo0d6204e2022-09-29 16:15:34 -0700772
Andrew Scullfb49ad22022-11-09 21:02:48 +0000773 ASSERT_EQ(**firstCsr, **secondCsr);
Tri Vo0d6204e2022-09-29 16:15:34 -0700774}
775
776/**
777 * Generate a non-empty certificate request with multiple keys.
778 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700779// @VsrTest = 3.10-015
Tri Vo0d6204e2022-09-29 16:15:34 -0700780TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
Tri Vo9cab73c2022-10-28 13:40:24 -0700781 generateKeys(false /* testMode */, rpcHardwareInfo.supportedNumKeysInCsr /* numKeys */);
Tri Vo0d6204e2022-09-29 16:15:34 -0700782
783 bytevec csr;
784
785 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
786 ASSERT_TRUE(status.isOk()) << status.getMessage();
787
788 auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
789 ASSERT_TRUE(result) << result.message();
790}
791
792/**
793 * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
794 */
795TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
796 generateKeys(false /* testMode */, 1 /* numKeys */);
797 auto result = corrupt_maced_key(keysToSign_[0]);
798 ASSERT_TRUE(result) << result.moveMessage();
799 MacedPublicKey keyWithCorruptMac = result.moveValue();
800
801 bytevec csr;
802 auto status =
803 provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
804 ASSERT_FALSE(status.isOk()) << status.getMessage();
805 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
806}
807
808/**
Tri Vob0b8acc2022-11-30 16:22:23 -0800809 * Generate a non-empty certificate request in prod mode, with test keys. Must fail with
810 * STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
Tri Vo0d6204e2022-09-29 16:15:34 -0700811 */
812TEST_P(CertificateRequestV2Test, NonEmptyRequest_testKeyInProdCert) {
813 generateKeys(true /* testMode */, 1 /* numKeys */);
814
815 bytevec csr;
816 auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
Tri Vo0d6204e2022-09-29 16:15:34 -0700817 ASSERT_FALSE(status.isOk()) << status.getMessage();
Tri Vob0b8acc2022-11-30 16:22:23 -0800818 ASSERT_EQ(status.getServiceSpecificError(),
819 BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST);
Tri Vo0d6204e2022-09-29 16:15:34 -0700820}
821
Andrew Scull95b31312023-03-27 19:16:07 +0000822/**
823 * Call generateCertificateRequest(). Make sure it's removed.
824 */
825TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed) {
826 bytevec keysToSignMac;
827 DeviceInfo deviceInfo;
828 ProtectedData protectedData;
829 auto status = provisionable_->generateCertificateRequest(
830 true /* testMode */, {} /* keysToSign */, {} /* EEK chain */, challenge_, &deviceInfo,
831 &protectedData, &keysToSignMac);
832 ASSERT_FALSE(status.isOk()) << status.getMessage();
833 EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
834}
835
Tri Voec50ee12023-02-14 16:29:53 -0800836void parse_root_of_trust(const vector<uint8_t>& attestation_cert,
837 vector<uint8_t>* verified_boot_key, VerifiedBoot* verified_boot_state,
838 bool* device_locked, vector<uint8_t>* verified_boot_hash) {
839 X509_Ptr cert(parse_cert_blob(attestation_cert));
840 ASSERT_TRUE(cert.get());
841
842 ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
843 ASSERT_TRUE(attest_rec);
844
845 auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, verified_boot_key,
846 verified_boot_state, device_locked, verified_boot_hash);
847 ASSERT_EQ(error, ErrorCode::OK);
848}
849
850/**
851 * Generate a CSR and verify DeviceInfo against IDs attested by KeyMint.
852 */
Seth Mooreac1639f2023-04-27 11:14:11 -0700853// @VsrTest = 3.10-015
Tri Voec50ee12023-02-14 16:29:53 -0800854TEST_P(CertificateRequestV2Test, DeviceInfo) {
855 // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent.
856 std::shared_ptr<IKeyMintDevice> keyMint;
857 if (!matching_keymint_device(GetParam(), &keyMint)) {
858 // No matching IKeyMintDevice.
859 GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found";
860 return;
861 }
862 KeyMintHardwareInfo info;
863 ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk());
864
865 // Get IDs attested by KeyMint.
866 MacedPublicKey macedPubKey;
867 bytevec privateKeyBlob;
868 auto irpcStatus =
869 provisionable_->generateEcdsaP256KeyPair(false, &macedPubKey, &privateKeyBlob);
870 ASSERT_TRUE(irpcStatus.isOk());
871
872 AttestationKey attestKey;
873 attestKey.keyBlob = std::move(privateKeyBlob);
874 attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key");
875
876 // Generate an ECDSA key that is attested by the generated P256 keypair.
877 AuthorizationSet keyDesc = AuthorizationSetBuilder()
878 .Authorization(TAG_NO_AUTH_REQUIRED)
879 .EcdsaSigningKey(EcCurve::P_256)
880 .AttestationChallenge("foo")
881 .AttestationApplicationId("bar")
882 .Digest(Digest::NONE)
883 .SetDefaultValidity();
884 KeyCreationResult creationResult;
885 auto kmStatus = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult);
886 ASSERT_TRUE(kmStatus.isOk());
887
888 vector<KeyCharacteristics> key_characteristics = std::move(creationResult.keyCharacteristics);
889 vector<Certificate> key_cert_chain = std::move(creationResult.certificateChain);
890 // We didn't provision the attestation key.
891 ASSERT_EQ(key_cert_chain.size(), 1);
892
893 // Parse attested patch levels.
894 auto auths = HwEnforcedAuthorizations(key_characteristics);
895
896 auto attestedSystemPatchLevel = auths.GetTagValue(TAG_OS_PATCHLEVEL);
897 auto attestedVendorPatchLevel = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL);
898 auto attestedBootPatchLevel = auths.GetTagValue(TAG_BOOT_PATCHLEVEL);
899
900 ASSERT_TRUE(attestedSystemPatchLevel.has_value());
901 ASSERT_TRUE(attestedVendorPatchLevel.has_value());
902 ASSERT_TRUE(attestedBootPatchLevel.has_value());
903
904 // Parse attested AVB values.
905 vector<uint8_t> key;
906 VerifiedBoot attestedVbState;
907 bool attestedBootloaderState;
908 vector<uint8_t> attestedVbmetaDigest;
909 parse_root_of_trust(key_cert_chain[0].encodedCertificate, &key, &attestedVbState,
910 &attestedBootloaderState, &attestedVbmetaDigest);
911
912 // Get IDs from DeviceInfo.
913 bytevec csr;
914 irpcStatus =
915 provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
916 ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getMessage();
917
918 auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
919 ASSERT_TRUE(result) << result.message();
920
921 std::unique_ptr<cppbor::Array> csrPayload = std::move(*result);
922 ASSERT_TRUE(csrPayload);
923
924 auto deviceInfo = csrPayload->get(2)->asMap();
925 ASSERT_TRUE(deviceInfo);
926
927 auto vbState = deviceInfo->get("vb_state")->asTstr();
928 auto bootloaderState = deviceInfo->get("bootloader_state")->asTstr();
929 auto vbmetaDigest = deviceInfo->get("vbmeta_digest")->asBstr();
930 auto systemPatchLevel = deviceInfo->get("system_patch_level")->asUint();
931 auto vendorPatchLevel = deviceInfo->get("vendor_patch_level")->asUint();
932 auto bootPatchLevel = deviceInfo->get("boot_patch_level")->asUint();
933 auto securityLevel = deviceInfo->get("security_level")->asTstr();
934
935 ASSERT_TRUE(vbState);
936 ASSERT_TRUE(bootloaderState);
937 ASSERT_TRUE(vbmetaDigest);
938 ASSERT_TRUE(systemPatchLevel);
939 ASSERT_TRUE(vendorPatchLevel);
940 ASSERT_TRUE(bootPatchLevel);
941 ASSERT_TRUE(securityLevel);
942
943 auto kmDeviceName = device_suffix(GetParam());
944
945 // Compare DeviceInfo against IDs attested by KeyMint.
946 ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") ||
947 (securityLevel->value() == "strongbox" && kmDeviceName == "strongbox"));
948 ASSERT_TRUE((vbState->value() == "green" && attestedVbState == VerifiedBoot::VERIFIED) ||
949 (vbState->value() == "yellow" && attestedVbState == VerifiedBoot::SELF_SIGNED) ||
950 (vbState->value() == "orange" && attestedVbState == VerifiedBoot::UNVERIFIED));
951 ASSERT_TRUE((bootloaderState->value() == "locked" && attestedBootloaderState) ||
952 (bootloaderState->value() == "unlocked" && !attestedBootloaderState));
953 ASSERT_EQ(vbmetaDigest->value(), attestedVbmetaDigest);
954 ASSERT_EQ(systemPatchLevel->value(), attestedSystemPatchLevel.value());
955 ASSERT_EQ(vendorPatchLevel->value(), attestedVendorPatchLevel.value());
956 ASSERT_EQ(bootPatchLevel->value(), attestedBootPatchLevel.value());
957}
958
Tri Vo0d6204e2022-09-29 16:15:34 -0700959INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
960
Max Biresa9b3bb92022-11-21 23:02:09 -0800961using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;
962
963INSTANTIATE_REM_PROV_AIDL_TEST(VsrRequirementTest);
964
965TEST_P(VsrRequirementTest, VsrEnforcementTest) {
966 RpcHardwareInfo hwInfo;
967 ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
968 int vsr_api_level = get_vsr_api_level();
969 if (vsr_api_level < 34) {
970 GTEST_SKIP() << "Applies only to VSR API level 34 or newer, this device is: "
971 << vsr_api_level;
972 }
973 EXPECT_GE(hwInfo.versionNumber, 3)
974 << "VSR 14+ requires IRemotelyProvisionedComponent v3 or newer.";
975}
976
Shawn Willden274bb552020-09-30 22:39:22 -0600977} // namespace aidl::android::hardware::security::keymint::test