xref: /aosp_15_r20/hardware/interfaces/identity/aidl/vts/Util.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
1*4d7e907cSAndroid Build Coastguard Worker /*
2*4d7e907cSAndroid Build Coastguard Worker  * Copyright 2019, The Android Open Source Project
3*4d7e907cSAndroid Build Coastguard Worker  *
4*4d7e907cSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d7e907cSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*4d7e907cSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*4d7e907cSAndroid Build Coastguard Worker  *
8*4d7e907cSAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
9*4d7e907cSAndroid Build Coastguard Worker  *
10*4d7e907cSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*4d7e907cSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d7e907cSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d7e907cSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*4d7e907cSAndroid Build Coastguard Worker  * limitations under the License.
15*4d7e907cSAndroid Build Coastguard Worker  */
16*4d7e907cSAndroid Build Coastguard Worker 
17*4d7e907cSAndroid Build Coastguard Worker #define LOG_TAG "Util"
18*4d7e907cSAndroid Build Coastguard Worker 
19*4d7e907cSAndroid Build Coastguard Worker #include "Util.h"
20*4d7e907cSAndroid Build Coastguard Worker 
21*4d7e907cSAndroid Build Coastguard Worker #include <android-base/logging.h>
22*4d7e907cSAndroid Build Coastguard Worker 
23*4d7e907cSAndroid Build Coastguard Worker #include <KeyMintAidlTestBase.h>
24*4d7e907cSAndroid Build Coastguard Worker #include <aidl/Gtest.h>
25*4d7e907cSAndroid Build Coastguard Worker #include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
26*4d7e907cSAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
27*4d7e907cSAndroid Build Coastguard Worker #include <keymaster/km_openssl/openssl_utils.h>
28*4d7e907cSAndroid Build Coastguard Worker #include <keymasterV4_1/attestation_record.h>
29*4d7e907cSAndroid Build Coastguard Worker #include <keymint_support/openssl_utils.h>
30*4d7e907cSAndroid Build Coastguard Worker #include <openssl/evp.h>
31*4d7e907cSAndroid Build Coastguard Worker 
32*4d7e907cSAndroid Build Coastguard Worker #include <charconv>
33*4d7e907cSAndroid Build Coastguard Worker #include <map>
34*4d7e907cSAndroid Build Coastguard Worker 
35*4d7e907cSAndroid Build Coastguard Worker namespace android::hardware::identity::test_utils {
36*4d7e907cSAndroid Build Coastguard Worker 
37*4d7e907cSAndroid Build Coastguard Worker using std::endl;
38*4d7e907cSAndroid Build Coastguard Worker using std::map;
39*4d7e907cSAndroid Build Coastguard Worker using std::optional;
40*4d7e907cSAndroid Build Coastguard Worker using std::string;
41*4d7e907cSAndroid Build Coastguard Worker using std::vector;
42*4d7e907cSAndroid Build Coastguard Worker 
43*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::security::keymint::test::check_maced_pubkey;
44*4d7e907cSAndroid Build Coastguard Worker using ::aidl::android::hardware::security::keymint::test::p256_pub_key;
45*4d7e907cSAndroid Build Coastguard Worker using ::android::sp;
46*4d7e907cSAndroid Build Coastguard Worker using ::android::String16;
47*4d7e907cSAndroid Build Coastguard Worker using ::android::base::StringPrintf;
48*4d7e907cSAndroid Build Coastguard Worker using ::android::binder::Status;
49*4d7e907cSAndroid Build Coastguard Worker using ::android::hardware::security::keymint::MacedPublicKey;
50*4d7e907cSAndroid Build Coastguard Worker using ::keymaster::X509_Ptr;
51*4d7e907cSAndroid Build Coastguard Worker 
setupWritableCredential(sp<IWritableIdentityCredential> & writableCredential,sp<IIdentityCredentialStore> & credentialStore,bool testCredential)52*4d7e907cSAndroid Build Coastguard Worker bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
53*4d7e907cSAndroid Build Coastguard Worker                              sp<IIdentityCredentialStore>& credentialStore, bool testCredential) {
54*4d7e907cSAndroid Build Coastguard Worker     if (credentialStore == nullptr) {
55*4d7e907cSAndroid Build Coastguard Worker         return false;
56*4d7e907cSAndroid Build Coastguard Worker     }
57*4d7e907cSAndroid Build Coastguard Worker 
58*4d7e907cSAndroid Build Coastguard Worker     string docType = "org.iso.18013-5.2019.mdl";
59*4d7e907cSAndroid Build Coastguard Worker     Status result = credentialStore->createCredential(docType, testCredential, &writableCredential);
60*4d7e907cSAndroid Build Coastguard Worker 
61*4d7e907cSAndroid Build Coastguard Worker     if (result.isOk() && writableCredential != nullptr) {
62*4d7e907cSAndroid Build Coastguard Worker         return true;
63*4d7e907cSAndroid Build Coastguard Worker     } else {
64*4d7e907cSAndroid Build Coastguard Worker         return false;
65*4d7e907cSAndroid Build Coastguard Worker     }
66*4d7e907cSAndroid Build Coastguard Worker }
67*4d7e907cSAndroid Build Coastguard Worker 
createFakeRemotelyProvisionedCertificateChain(const MacedPublicKey & macedPublicKey)68*4d7e907cSAndroid Build Coastguard Worker optional<vector<vector<uint8_t>>> createFakeRemotelyProvisionedCertificateChain(
69*4d7e907cSAndroid Build Coastguard Worker         const MacedPublicKey& macedPublicKey) {
70*4d7e907cSAndroid Build Coastguard Worker     // The helper library uses the NDK symbols, so play a little trickery here to convert
71*4d7e907cSAndroid Build Coastguard Worker     // the data into the proper type so we can reuse the helper function to get the pubkey.
72*4d7e907cSAndroid Build Coastguard Worker     ::aidl::android::hardware::security::keymint::MacedPublicKey ndkMacedPublicKey;
73*4d7e907cSAndroid Build Coastguard Worker     ndkMacedPublicKey.macedKey = macedPublicKey.macedKey;
74*4d7e907cSAndroid Build Coastguard Worker 
75*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> publicKeyBits;
76*4d7e907cSAndroid Build Coastguard Worker     check_maced_pubkey(ndkMacedPublicKey, /*testMode=*/false, &publicKeyBits);
77*4d7e907cSAndroid Build Coastguard Worker 
78*4d7e907cSAndroid Build Coastguard Worker     ::aidl::android::hardware::security::keymint::EVP_PKEY_Ptr publicKey;
79*4d7e907cSAndroid Build Coastguard Worker     p256_pub_key(publicKeyBits, &publicKey);
80*4d7e907cSAndroid Build Coastguard Worker 
81*4d7e907cSAndroid Build Coastguard Worker     // Generate an arbitrary root key for our chain
82*4d7e907cSAndroid Build Coastguard Worker     bssl::UniquePtr<EC_KEY> ecRootKey(EC_KEY_new());
83*4d7e907cSAndroid Build Coastguard Worker     bssl::UniquePtr<EVP_PKEY> rootKey(EVP_PKEY_new());
84*4d7e907cSAndroid Build Coastguard Worker     if (ecRootKey.get() == nullptr || rootKey.get() == nullptr) {
85*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Memory allocation failed";
86*4d7e907cSAndroid Build Coastguard Worker         return {};
87*4d7e907cSAndroid Build Coastguard Worker     }
88*4d7e907cSAndroid Build Coastguard Worker 
89*4d7e907cSAndroid Build Coastguard Worker     bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
90*4d7e907cSAndroid Build Coastguard Worker     if (group.get() == nullptr) {
91*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Error creating EC group by curve name";
92*4d7e907cSAndroid Build Coastguard Worker         return {};
93*4d7e907cSAndroid Build Coastguard Worker     }
94*4d7e907cSAndroid Build Coastguard Worker 
95*4d7e907cSAndroid Build Coastguard Worker     if (EC_KEY_set_group(ecRootKey.get(), group.get()) != 1 ||
96*4d7e907cSAndroid Build Coastguard Worker         EC_KEY_generate_key(ecRootKey.get()) != 1 || EC_KEY_check_key(ecRootKey.get()) < 0) {
97*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Error generating key";
98*4d7e907cSAndroid Build Coastguard Worker         return {};
99*4d7e907cSAndroid Build Coastguard Worker     }
100*4d7e907cSAndroid Build Coastguard Worker 
101*4d7e907cSAndroid Build Coastguard Worker     if (EVP_PKEY_set1_EC_KEY(rootKey.get(), ecRootKey.get()) != 1) {
102*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Error getting private key";
103*4d7e907cSAndroid Build Coastguard Worker         return {};
104*4d7e907cSAndroid Build Coastguard Worker     }
105*4d7e907cSAndroid Build Coastguard Worker 
106*4d7e907cSAndroid Build Coastguard Worker     // The VTS test does not fully validate the chain, so we're ok without the proper CA extensions.
107*4d7e907cSAndroid Build Coastguard Worker     map<string, vector<uint8_t>> extensions;
108*4d7e907cSAndroid Build Coastguard Worker 
109*4d7e907cSAndroid Build Coastguard Worker     // Now make a self-signed cert
110*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> root = support::ecPublicKeyGenerateCertificate(
111*4d7e907cSAndroid Build Coastguard Worker             rootKey.get(), rootKey.get(),
112*4d7e907cSAndroid Build Coastguard Worker             /*serialDecimal=*/"31415",
113*4d7e907cSAndroid Build Coastguard Worker             /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
114*4d7e907cSAndroid Build Coastguard Worker             /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
115*4d7e907cSAndroid Build Coastguard Worker             /*validityNotBefore=*/time(nullptr),
116*4d7e907cSAndroid Build Coastguard Worker             /*validityNotAfter=*/time(nullptr) + 365 * 24 * 3600, extensions);
117*4d7e907cSAndroid Build Coastguard Worker     if (!root) {
118*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Error generating root cert";
119*4d7e907cSAndroid Build Coastguard Worker         return std::nullopt;
120*4d7e907cSAndroid Build Coastguard Worker     }
121*4d7e907cSAndroid Build Coastguard Worker 
122*4d7e907cSAndroid Build Coastguard Worker     // Now sign a CA cert so that we have a chain that's good enough to satisfy
123*4d7e907cSAndroid Build Coastguard Worker     // the VTS tests.
124*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> intermediate = support::ecPublicKeyGenerateCertificate(
125*4d7e907cSAndroid Build Coastguard Worker             publicKey.get(), rootKey.get(),
126*4d7e907cSAndroid Build Coastguard Worker             /*serialDecimal=*/"42",
127*4d7e907cSAndroid Build Coastguard Worker             /*subject=*/"Android IdentityCredential VTS Test Root Certificate",
128*4d7e907cSAndroid Build Coastguard Worker             /*subject=*/"Android IdentityCredential VTS Test Attestation Certificate",
129*4d7e907cSAndroid Build Coastguard Worker             /*validityNotBefore=*/time(nullptr),
130*4d7e907cSAndroid Build Coastguard Worker             /*validityNotAfter=*/time(nullptr) + 365 * 24 * 3600, extensions);
131*4d7e907cSAndroid Build Coastguard Worker     if (!intermediate) {
132*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Error generating intermediate cert";
133*4d7e907cSAndroid Build Coastguard Worker         return std::nullopt;
134*4d7e907cSAndroid Build Coastguard Worker     }
135*4d7e907cSAndroid Build Coastguard Worker 
136*4d7e907cSAndroid Build Coastguard Worker     return vector<vector<uint8_t>>{std::move(*intermediate), std::move(*root)};
137*4d7e907cSAndroid Build Coastguard Worker }
138*4d7e907cSAndroid Build Coastguard Worker 
generateReaderCertificate(string serialDecimal)139*4d7e907cSAndroid Build Coastguard Worker optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal) {
140*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> privKey;
141*4d7e907cSAndroid Build Coastguard Worker     return generateReaderCertificate(serialDecimal, &privKey);
142*4d7e907cSAndroid Build Coastguard Worker }
143*4d7e907cSAndroid Build Coastguard Worker 
generateReaderCertificate(string serialDecimal,vector<uint8_t> * outReaderPrivateKey)144*4d7e907cSAndroid Build Coastguard Worker optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
145*4d7e907cSAndroid Build Coastguard Worker                                                     vector<uint8_t>* outReaderPrivateKey) {
146*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
147*4d7e907cSAndroid Build Coastguard Worker     if (!readerKeyPKCS8) {
148*4d7e907cSAndroid Build Coastguard Worker         return {};
149*4d7e907cSAndroid Build Coastguard Worker     }
150*4d7e907cSAndroid Build Coastguard Worker 
151*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> readerPublicKey =
152*4d7e907cSAndroid Build Coastguard Worker             support::ecKeyPairGetPublicKey(readerKeyPKCS8.value());
153*4d7e907cSAndroid Build Coastguard Worker     optional<vector<uint8_t>> readerKey = support::ecKeyPairGetPrivateKey(readerKeyPKCS8.value());
154*4d7e907cSAndroid Build Coastguard Worker     if (!readerPublicKey || !readerKey) {
155*4d7e907cSAndroid Build Coastguard Worker         return {};
156*4d7e907cSAndroid Build Coastguard Worker     }
157*4d7e907cSAndroid Build Coastguard Worker 
158*4d7e907cSAndroid Build Coastguard Worker     if (outReaderPrivateKey == nullptr) {
159*4d7e907cSAndroid Build Coastguard Worker         return {};
160*4d7e907cSAndroid Build Coastguard Worker     }
161*4d7e907cSAndroid Build Coastguard Worker 
162*4d7e907cSAndroid Build Coastguard Worker     *outReaderPrivateKey = readerKey.value();
163*4d7e907cSAndroid Build Coastguard Worker 
164*4d7e907cSAndroid Build Coastguard Worker     string issuer = "Android Open Source Project";
165*4d7e907cSAndroid Build Coastguard Worker     string subject = "Android IdentityCredential VTS Test";
166*4d7e907cSAndroid Build Coastguard Worker     time_t validityNotBefore = time(nullptr);
167*4d7e907cSAndroid Build Coastguard Worker     time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
168*4d7e907cSAndroid Build Coastguard Worker 
169*4d7e907cSAndroid Build Coastguard Worker     return support::ecPublicKeyGenerateCertificate(readerPublicKey.value(), readerKey.value(),
170*4d7e907cSAndroid Build Coastguard Worker                                                    serialDecimal, issuer, subject,
171*4d7e907cSAndroid Build Coastguard Worker                                                    validityNotBefore, validityNotAfter, {});
172*4d7e907cSAndroid Build Coastguard Worker }
173*4d7e907cSAndroid Build Coastguard Worker 
addAccessControlProfiles(sp<IWritableIdentityCredential> & writableCredential,const vector<TestProfile> & testProfiles)174*4d7e907cSAndroid Build Coastguard Worker optional<vector<SecureAccessControlProfile>> addAccessControlProfiles(
175*4d7e907cSAndroid Build Coastguard Worker         sp<IWritableIdentityCredential>& writableCredential,
176*4d7e907cSAndroid Build Coastguard Worker         const vector<TestProfile>& testProfiles) {
177*4d7e907cSAndroid Build Coastguard Worker     Status result;
178*4d7e907cSAndroid Build Coastguard Worker 
179*4d7e907cSAndroid Build Coastguard Worker     vector<SecureAccessControlProfile> secureProfiles;
180*4d7e907cSAndroid Build Coastguard Worker 
181*4d7e907cSAndroid Build Coastguard Worker     for (const auto& testProfile : testProfiles) {
182*4d7e907cSAndroid Build Coastguard Worker         SecureAccessControlProfile profile;
183*4d7e907cSAndroid Build Coastguard Worker         Certificate cert;
184*4d7e907cSAndroid Build Coastguard Worker         cert.encodedCertificate = testProfile.readerCertificate;
185*4d7e907cSAndroid Build Coastguard Worker         int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
186*4d7e907cSAndroid Build Coastguard Worker         result = writableCredential->addAccessControlProfile(
187*4d7e907cSAndroid Build Coastguard Worker                 testProfile.id, cert, testProfile.userAuthenticationRequired,
188*4d7e907cSAndroid Build Coastguard Worker                 testProfile.timeoutMillis, secureUserId, &profile);
189*4d7e907cSAndroid Build Coastguard Worker 
190*4d7e907cSAndroid Build Coastguard Worker         // Don't use assert so all errors can be outputed.  Then return
191*4d7e907cSAndroid Build Coastguard Worker         // instead of exit even on errors so caller can decide.
192*4d7e907cSAndroid Build Coastguard Worker         EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
193*4d7e907cSAndroid Build Coastguard Worker                                    << "test profile id = " << testProfile.id << endl;
194*4d7e907cSAndroid Build Coastguard Worker         EXPECT_EQ(testProfile.id, profile.id);
195*4d7e907cSAndroid Build Coastguard Worker         EXPECT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
196*4d7e907cSAndroid Build Coastguard Worker         EXPECT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
197*4d7e907cSAndroid Build Coastguard Worker         EXPECT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
198*4d7e907cSAndroid Build Coastguard Worker         EXPECT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
199*4d7e907cSAndroid Build Coastguard Worker 
200*4d7e907cSAndroid Build Coastguard Worker         if (!result.isOk() || testProfile.id != profile.id ||
201*4d7e907cSAndroid Build Coastguard Worker             testProfile.readerCertificate != profile.readerCertificate.encodedCertificate ||
202*4d7e907cSAndroid Build Coastguard Worker             testProfile.userAuthenticationRequired != profile.userAuthenticationRequired ||
203*4d7e907cSAndroid Build Coastguard Worker             testProfile.timeoutMillis != profile.timeoutMillis ||
204*4d7e907cSAndroid Build Coastguard Worker             support::kAesGcmTagSize + support::kAesGcmIvSize != profile.mac.size()) {
205*4d7e907cSAndroid Build Coastguard Worker             return {};
206*4d7e907cSAndroid Build Coastguard Worker         }
207*4d7e907cSAndroid Build Coastguard Worker 
208*4d7e907cSAndroid Build Coastguard Worker         secureProfiles.push_back(profile);
209*4d7e907cSAndroid Build Coastguard Worker     }
210*4d7e907cSAndroid Build Coastguard Worker 
211*4d7e907cSAndroid Build Coastguard Worker     return secureProfiles;
212*4d7e907cSAndroid Build Coastguard Worker }
213*4d7e907cSAndroid Build Coastguard Worker 
214*4d7e907cSAndroid Build Coastguard Worker // Most test expects this function to pass. So we will print out additional
215*4d7e907cSAndroid Build Coastguard Worker // value if failed so more debug data can be provided.
addEntry(sp<IWritableIdentityCredential> & writableCredential,const TestEntryData & entry,int dataChunkSize,map<const TestEntryData *,vector<vector<uint8_t>>> & encryptedBlobs,bool expectSuccess)216*4d7e907cSAndroid Build Coastguard Worker bool addEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
217*4d7e907cSAndroid Build Coastguard Worker               int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
218*4d7e907cSAndroid Build Coastguard Worker               bool expectSuccess) {
219*4d7e907cSAndroid Build Coastguard Worker     Status result;
220*4d7e907cSAndroid Build Coastguard Worker     vector<vector<uint8_t>> chunks = support::chunkVector(entry.valueCbor, dataChunkSize);
221*4d7e907cSAndroid Build Coastguard Worker 
222*4d7e907cSAndroid Build Coastguard Worker     result = writableCredential->beginAddEntry(entry.profileIds, entry.nameSpace, entry.name,
223*4d7e907cSAndroid Build Coastguard Worker                                                entry.valueCbor.size());
224*4d7e907cSAndroid Build Coastguard Worker 
225*4d7e907cSAndroid Build Coastguard Worker     if (expectSuccess) {
226*4d7e907cSAndroid Build Coastguard Worker         EXPECT_TRUE(result.isOk())
227*4d7e907cSAndroid Build Coastguard Worker                 << result.exceptionCode() << "; " << result.exceptionMessage() << endl
228*4d7e907cSAndroid Build Coastguard Worker                 << "entry name = " << entry.name << ", name space=" << entry.nameSpace << endl;
229*4d7e907cSAndroid Build Coastguard Worker     }
230*4d7e907cSAndroid Build Coastguard Worker 
231*4d7e907cSAndroid Build Coastguard Worker     if (!result.isOk()) {
232*4d7e907cSAndroid Build Coastguard Worker         return false;
233*4d7e907cSAndroid Build Coastguard Worker     }
234*4d7e907cSAndroid Build Coastguard Worker 
235*4d7e907cSAndroid Build Coastguard Worker     vector<vector<uint8_t>> encryptedChunks;
236*4d7e907cSAndroid Build Coastguard Worker     for (const auto& chunk : chunks) {
237*4d7e907cSAndroid Build Coastguard Worker         vector<uint8_t> encryptedContent;
238*4d7e907cSAndroid Build Coastguard Worker         result = writableCredential->addEntryValue(chunk, &encryptedContent);
239*4d7e907cSAndroid Build Coastguard Worker         if (expectSuccess) {
240*4d7e907cSAndroid Build Coastguard Worker             EXPECT_TRUE(result.isOk())
241*4d7e907cSAndroid Build Coastguard Worker                     << result.exceptionCode() << "; " << result.exceptionMessage() << endl
242*4d7e907cSAndroid Build Coastguard Worker                     << "entry name = " << entry.name << ", name space = " << entry.nameSpace
243*4d7e907cSAndroid Build Coastguard Worker                     << endl;
244*4d7e907cSAndroid Build Coastguard Worker 
245*4d7e907cSAndroid Build Coastguard Worker             EXPECT_GT(encryptedContent.size(), 0u) << "entry name = " << entry.name
246*4d7e907cSAndroid Build Coastguard Worker                                                    << ", name space = " << entry.nameSpace << endl;
247*4d7e907cSAndroid Build Coastguard Worker         }
248*4d7e907cSAndroid Build Coastguard Worker 
249*4d7e907cSAndroid Build Coastguard Worker         if (!result.isOk() || encryptedContent.size() <= 0u) {
250*4d7e907cSAndroid Build Coastguard Worker             return false;
251*4d7e907cSAndroid Build Coastguard Worker         }
252*4d7e907cSAndroid Build Coastguard Worker 
253*4d7e907cSAndroid Build Coastguard Worker         encryptedChunks.push_back(encryptedContent);
254*4d7e907cSAndroid Build Coastguard Worker     }
255*4d7e907cSAndroid Build Coastguard Worker 
256*4d7e907cSAndroid Build Coastguard Worker     encryptedBlobs[&entry] = encryptedChunks;
257*4d7e907cSAndroid Build Coastguard Worker     return true;
258*4d7e907cSAndroid Build Coastguard Worker }
259*4d7e907cSAndroid Build Coastguard Worker 
setImageData(vector<uint8_t> & image)260*4d7e907cSAndroid Build Coastguard Worker void setImageData(vector<uint8_t>& image) {
261*4d7e907cSAndroid Build Coastguard Worker     image.resize(256 * 1024 - 10);
262*4d7e907cSAndroid Build Coastguard Worker     for (size_t n = 0; n < image.size(); n++) {
263*4d7e907cSAndroid Build Coastguard Worker         image[n] = (uint8_t)n;
264*4d7e907cSAndroid Build Coastguard Worker     }
265*4d7e907cSAndroid Build Coastguard Worker }
266*4d7e907cSAndroid Build Coastguard Worker 
x509NameToRfc2253String(X509_NAME * name)267*4d7e907cSAndroid Build Coastguard Worker string x509NameToRfc2253String(X509_NAME* name) {
268*4d7e907cSAndroid Build Coastguard Worker     char* buf;
269*4d7e907cSAndroid Build Coastguard Worker     size_t bufSize;
270*4d7e907cSAndroid Build Coastguard Worker     BIO* bio;
271*4d7e907cSAndroid Build Coastguard Worker 
272*4d7e907cSAndroid Build Coastguard Worker     bio = BIO_new(BIO_s_mem());
273*4d7e907cSAndroid Build Coastguard Worker     X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
274*4d7e907cSAndroid Build Coastguard Worker     bufSize = BIO_get_mem_data(bio, &buf);
275*4d7e907cSAndroid Build Coastguard Worker     string ret = string(buf, bufSize);
276*4d7e907cSAndroid Build Coastguard Worker     BIO_free(bio);
277*4d7e907cSAndroid Build Coastguard Worker 
278*4d7e907cSAndroid Build Coastguard Worker     return ret;
279*4d7e907cSAndroid Build Coastguard Worker }
280*4d7e907cSAndroid Build Coastguard Worker 
parseDigits(const char ** s,int numDigits)281*4d7e907cSAndroid Build Coastguard Worker int parseDigits(const char** s, int numDigits) {
282*4d7e907cSAndroid Build Coastguard Worker     int result;
283*4d7e907cSAndroid Build Coastguard Worker     auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
284*4d7e907cSAndroid Build Coastguard Worker     if (ec != std::errc()) {
285*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Error parsing " << numDigits << " digits "
286*4d7e907cSAndroid Build Coastguard Worker                    << " from " << s;
287*4d7e907cSAndroid Build Coastguard Worker         return 0;
288*4d7e907cSAndroid Build Coastguard Worker     }
289*4d7e907cSAndroid Build Coastguard Worker     *s += numDigits;
290*4d7e907cSAndroid Build Coastguard Worker     return result;
291*4d7e907cSAndroid Build Coastguard Worker }
292*4d7e907cSAndroid Build Coastguard Worker 
parseAsn1Time(const ASN1_TIME * asn1Time,time_t * outTime)293*4d7e907cSAndroid Build Coastguard Worker bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
294*4d7e907cSAndroid Build Coastguard Worker     struct tm tm;
295*4d7e907cSAndroid Build Coastguard Worker 
296*4d7e907cSAndroid Build Coastguard Worker     memset(&tm, '\0', sizeof(tm));
297*4d7e907cSAndroid Build Coastguard Worker     const char* timeStr = (const char*)asn1Time->data;
298*4d7e907cSAndroid Build Coastguard Worker     const char* s = timeStr;
299*4d7e907cSAndroid Build Coastguard Worker     if (asn1Time->type == V_ASN1_UTCTIME) {
300*4d7e907cSAndroid Build Coastguard Worker         tm.tm_year = parseDigits(&s, 2);
301*4d7e907cSAndroid Build Coastguard Worker         if (tm.tm_year < 70) {
302*4d7e907cSAndroid Build Coastguard Worker             tm.tm_year += 100;
303*4d7e907cSAndroid Build Coastguard Worker         }
304*4d7e907cSAndroid Build Coastguard Worker     } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
305*4d7e907cSAndroid Build Coastguard Worker         tm.tm_year = parseDigits(&s, 4) - 1900;
306*4d7e907cSAndroid Build Coastguard Worker         tm.tm_year -= 1900;
307*4d7e907cSAndroid Build Coastguard Worker     } else {
308*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
309*4d7e907cSAndroid Build Coastguard Worker         return false;
310*4d7e907cSAndroid Build Coastguard Worker     }
311*4d7e907cSAndroid Build Coastguard Worker     tm.tm_mon = parseDigits(&s, 2) - 1;
312*4d7e907cSAndroid Build Coastguard Worker     tm.tm_mday = parseDigits(&s, 2);
313*4d7e907cSAndroid Build Coastguard Worker     tm.tm_hour = parseDigits(&s, 2);
314*4d7e907cSAndroid Build Coastguard Worker     tm.tm_min = parseDigits(&s, 2);
315*4d7e907cSAndroid Build Coastguard Worker     tm.tm_sec = parseDigits(&s, 2);
316*4d7e907cSAndroid Build Coastguard Worker     // This may need to be updated if someone create certificates using +/- instead of Z.
317*4d7e907cSAndroid Build Coastguard Worker     //
318*4d7e907cSAndroid Build Coastguard Worker     if (*s != 'Z') {
319*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
320*4d7e907cSAndroid Build Coastguard Worker         return false;
321*4d7e907cSAndroid Build Coastguard Worker     }
322*4d7e907cSAndroid Build Coastguard Worker 
323*4d7e907cSAndroid Build Coastguard Worker     time_t t = timegm(&tm);
324*4d7e907cSAndroid Build Coastguard Worker     if (t == -1) {
325*4d7e907cSAndroid Build Coastguard Worker         LOG(ERROR) << "Error converting broken-down time to time_t";
326*4d7e907cSAndroid Build Coastguard Worker         return false;
327*4d7e907cSAndroid Build Coastguard Worker     }
328*4d7e907cSAndroid Build Coastguard Worker     *outTime = t;
329*4d7e907cSAndroid Build Coastguard Worker     return true;
330*4d7e907cSAndroid Build Coastguard Worker }
331*4d7e907cSAndroid Build Coastguard Worker 
validateAttestationCertificate(const vector<Certificate> & credentialKeyCertChain,const vector<uint8_t> & expectedChallenge,const vector<uint8_t> & expectedAppId,bool isTestCredential)332*4d7e907cSAndroid Build Coastguard Worker void validateAttestationCertificate(const vector<Certificate>& credentialKeyCertChain,
333*4d7e907cSAndroid Build Coastguard Worker                                     const vector<uint8_t>& expectedChallenge,
334*4d7e907cSAndroid Build Coastguard Worker                                     const vector<uint8_t>& expectedAppId, bool isTestCredential) {
335*4d7e907cSAndroid Build Coastguard Worker     ASSERT_GE(credentialKeyCertChain.size(), 2);
336*4d7e907cSAndroid Build Coastguard Worker 
337*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> certBytes = credentialKeyCertChain[0].encodedCertificate;
338*4d7e907cSAndroid Build Coastguard Worker     const uint8_t* certData = certBytes.data();
339*4d7e907cSAndroid Build Coastguard Worker     X509_Ptr cert = X509_Ptr(d2i_X509(nullptr, &certData, certBytes.size()));
340*4d7e907cSAndroid Build Coastguard Worker 
341*4d7e907cSAndroid Build Coastguard Worker     vector<uint8_t> batchCertBytes = credentialKeyCertChain[1].encodedCertificate;
342*4d7e907cSAndroid Build Coastguard Worker     const uint8_t* batchCertData = batchCertBytes.data();
343*4d7e907cSAndroid Build Coastguard Worker     X509_Ptr batchCert = X509_Ptr(d2i_X509(nullptr, &batchCertData, batchCertBytes.size()));
344*4d7e907cSAndroid Build Coastguard Worker 
345*4d7e907cSAndroid Build Coastguard Worker     // First get some values from the batch certificate which is checked
346*4d7e907cSAndroid Build Coastguard Worker     // against the top-level certificate (subject, notAfter)
347*4d7e907cSAndroid Build Coastguard Worker     //
348*4d7e907cSAndroid Build Coastguard Worker 
349*4d7e907cSAndroid Build Coastguard Worker     X509_NAME* batchSubject = X509_get_subject_name(batchCert.get());
350*4d7e907cSAndroid Build Coastguard Worker     ASSERT_NE(nullptr, batchSubject);
351*4d7e907cSAndroid Build Coastguard Worker     time_t batchNotAfter;
352*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(batchCert.get()), &batchNotAfter));
353*4d7e907cSAndroid Build Coastguard Worker 
354*4d7e907cSAndroid Build Coastguard Worker     // Check all the requirements from IWritableIdentityCredential::getAttestationCertificate()...
355*4d7e907cSAndroid Build Coastguard Worker     //
356*4d7e907cSAndroid Build Coastguard Worker 
357*4d7e907cSAndroid Build Coastguard Worker     //  - version: INTEGER 2 (means v3 certificate).
358*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(2, X509_get_version(cert.get()));
359*4d7e907cSAndroid Build Coastguard Worker 
360*4d7e907cSAndroid Build Coastguard Worker     //  - serialNumber: INTEGER 1 (fixed value: same on all certs).
361*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(1, ASN1_INTEGER_get(X509_get_serialNumber(cert.get())));
362*4d7e907cSAndroid Build Coastguard Worker 
363*4d7e907cSAndroid Build Coastguard Worker     //  - signature: must be set to ECDSA.
364*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(NID_ecdsa_with_SHA256, X509_get_signature_nid(cert.get()));
365*4d7e907cSAndroid Build Coastguard Worker 
366*4d7e907cSAndroid Build Coastguard Worker     //  - subject: CN shall be set to "Android Identity Credential Key". (fixed value:
367*4d7e907cSAndroid Build Coastguard Worker     //    same on all certs)
368*4d7e907cSAndroid Build Coastguard Worker     X509_NAME* subject = X509_get_subject_name(cert.get());
369*4d7e907cSAndroid Build Coastguard Worker     ASSERT_NE(nullptr, subject);
370*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ("CN=Android Identity Credential Key", x509NameToRfc2253String(subject));
371*4d7e907cSAndroid Build Coastguard Worker 
372*4d7e907cSAndroid Build Coastguard Worker     //  - issuer: Same as the subject field of the batch attestation key.
373*4d7e907cSAndroid Build Coastguard Worker     X509_NAME* issuer = X509_get_issuer_name(cert.get());
374*4d7e907cSAndroid Build Coastguard Worker     ASSERT_NE(nullptr, issuer);
375*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(x509NameToRfc2253String(batchSubject), x509NameToRfc2253String(issuer));
376*4d7e907cSAndroid Build Coastguard Worker 
377*4d7e907cSAndroid Build Coastguard Worker     //  - validity: Should be from current time and expire at the same time as the
378*4d7e907cSAndroid Build Coastguard Worker     //    attestation batch certificate used.
379*4d7e907cSAndroid Build Coastguard Worker     //
380*4d7e907cSAndroid Build Coastguard Worker     //  Allow for 10 seconds drift to account for the time drift between Secure HW
381*4d7e907cSAndroid Build Coastguard Worker     //  and this environment plus the difference between when the certificate was
382*4d7e907cSAndroid Build Coastguard Worker     //  created and until now
383*4d7e907cSAndroid Build Coastguard Worker     //
384*4d7e907cSAndroid Build Coastguard Worker     time_t notBefore;
385*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), &notBefore));
386*4d7e907cSAndroid Build Coastguard Worker     uint64_t now = time(nullptr);
387*4d7e907cSAndroid Build Coastguard Worker     int64_t diffSecs = now - notBefore;
388*4d7e907cSAndroid Build Coastguard Worker     int64_t allowDriftSecs = 10;
389*4d7e907cSAndroid Build Coastguard Worker     EXPECT_LE(-allowDriftSecs, diffSecs);
390*4d7e907cSAndroid Build Coastguard Worker     EXPECT_GE(allowDriftSecs, diffSecs);
391*4d7e907cSAndroid Build Coastguard Worker 
392*4d7e907cSAndroid Build Coastguard Worker     time_t notAfter;
393*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), &notAfter));
394*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(notAfter, batchNotAfter);
395*4d7e907cSAndroid Build Coastguard Worker 
396*4d7e907cSAndroid Build Coastguard Worker     auto [err, attRec] = keymaster::V4_1::parse_attestation_record(certBytes);
397*4d7e907cSAndroid Build Coastguard Worker     ASSERT_EQ(keymaster::V4_1::ErrorCode::OK, err);
398*4d7e907cSAndroid Build Coastguard Worker 
399*4d7e907cSAndroid Build Coastguard Worker     //  - subjectPublicKeyInfo: must contain attested public key.
400*4d7e907cSAndroid Build Coastguard Worker 
401*4d7e907cSAndroid Build Coastguard Worker     //  - The attestationVersion field in the attestation extension must be at least 3.
402*4d7e907cSAndroid Build Coastguard Worker     EXPECT_GE(attRec.attestation_version, 3);
403*4d7e907cSAndroid Build Coastguard Worker 
404*4d7e907cSAndroid Build Coastguard Worker     //  - The attestationSecurityLevel field must be set to either Software (0),
405*4d7e907cSAndroid Build Coastguard Worker     //    TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
406*4d7e907cSAndroid Build Coastguard Worker     //    implemented.
407*4d7e907cSAndroid Build Coastguard Worker     EXPECT_GE(attRec.attestation_security_level,
408*4d7e907cSAndroid Build Coastguard Worker               keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
409*4d7e907cSAndroid Build Coastguard Worker 
410*4d7e907cSAndroid Build Coastguard Worker     //  - The keymasterVersion field in the attestation extension must be set to the.
411*4d7e907cSAndroid Build Coastguard Worker     //    same value as used for Android Keystore keys.
412*4d7e907cSAndroid Build Coastguard Worker     //
413*4d7e907cSAndroid Build Coastguard Worker     // Nothing to check here...
414*4d7e907cSAndroid Build Coastguard Worker 
415*4d7e907cSAndroid Build Coastguard Worker     //  - The keymasterSecurityLevel field in the attestation extension must be set to
416*4d7e907cSAndroid Build Coastguard Worker     //    either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
417*4d7e907cSAndroid Build Coastguard Worker     //    the Trusted Application backing the HAL implementation is implemented.
418*4d7e907cSAndroid Build Coastguard Worker     EXPECT_GE(attRec.keymaster_security_level, keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
419*4d7e907cSAndroid Build Coastguard Worker 
420*4d7e907cSAndroid Build Coastguard Worker     //  - The attestationChallenge field must be set to the passed-in challenge.
421*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(expectedChallenge.size(), attRec.attestation_challenge.size());
422*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(memcmp(expectedChallenge.data(), attRec.attestation_challenge.data(),
423*4d7e907cSAndroid Build Coastguard Worker                        attRec.attestation_challenge.size()) == 0);
424*4d7e907cSAndroid Build Coastguard Worker 
425*4d7e907cSAndroid Build Coastguard Worker     //  - The uniqueId field must be empty.
426*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(attRec.unique_id.size(), 0);
427*4d7e907cSAndroid Build Coastguard Worker 
428*4d7e907cSAndroid Build Coastguard Worker     //  - The softwareEnforced field in the attestation extension must include
429*4d7e907cSAndroid Build Coastguard Worker     //    Tag::ATTESTATION_APPLICATION_ID which must be set to the bytes of the passed-in
430*4d7e907cSAndroid Build Coastguard Worker     //    attestationApplicationId.
431*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.software_enforced.Contains(keymaster::V4_0::TAG_ATTESTATION_APPLICATION_ID,
432*4d7e907cSAndroid Build Coastguard Worker                                                   expectedAppId));
433*4d7e907cSAndroid Build Coastguard Worker 
434*4d7e907cSAndroid Build Coastguard Worker     //  - The teeEnforced field in the attestation extension must include
435*4d7e907cSAndroid Build Coastguard Worker     //
436*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity
437*4d7e907cSAndroid Build Coastguard Worker     //      Credential key (which can only sign/MAC very specific messages) and not an Android
438*4d7e907cSAndroid Build Coastguard Worker     //      Keystore key (which can be used to sign/MAC anything). This must not be set
439*4d7e907cSAndroid Build Coastguard Worker     //      for test credentials.
440*4d7e907cSAndroid Build Coastguard Worker     bool hasIcKeyTag =
441*4d7e907cSAndroid Build Coastguard Worker             attRec.hardware_enforced.Contains(static_cast<android::hardware::keymaster::V4_0::Tag>(
442*4d7e907cSAndroid Build Coastguard Worker                     keymaster::V4_1::Tag::IDENTITY_CREDENTIAL_KEY));
443*4d7e907cSAndroid Build Coastguard Worker     if (isTestCredential) {
444*4d7e907cSAndroid Build Coastguard Worker         EXPECT_FALSE(hasIcKeyTag);
445*4d7e907cSAndroid Build Coastguard Worker     } else {
446*4d7e907cSAndroid Build Coastguard Worker         EXPECT_TRUE(hasIcKeyTag);
447*4d7e907cSAndroid Build Coastguard Worker     }
448*4d7e907cSAndroid Build Coastguard Worker 
449*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::PURPOSE must be set to SIGN
450*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_PURPOSE,
451*4d7e907cSAndroid Build Coastguard Worker                                                   keymaster::V4_0::KeyPurpose::SIGN));
452*4d7e907cSAndroid Build Coastguard Worker 
453*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::KEY_SIZE must be set to the appropriate key size, in bits (e.g. 256)
454*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_KEY_SIZE, 256));
455*4d7e907cSAndroid Build Coastguard Worker 
456*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::ALGORITHM must be set to EC
457*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_ALGORITHM,
458*4d7e907cSAndroid Build Coastguard Worker                                                   keymaster::V4_0::Algorithm::EC));
459*4d7e907cSAndroid Build Coastguard Worker 
460*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::NO_AUTH_REQUIRED must be set
461*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_NO_AUTH_REQUIRED));
462*4d7e907cSAndroid Build Coastguard Worker 
463*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::DIGEST must be include SHA_2_256
464*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_DIGEST,
465*4d7e907cSAndroid Build Coastguard Worker                                                   keymaster::V4_0::Digest::SHA_2_256));
466*4d7e907cSAndroid Build Coastguard Worker 
467*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::EC_CURVE must be set to P_256
468*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_EC_CURVE,
469*4d7e907cSAndroid Build Coastguard Worker                                                   keymaster::V4_0::EcCurve::P_256));
470*4d7e907cSAndroid Build Coastguard Worker 
471*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::ROOT_OF_TRUST must be set
472*4d7e907cSAndroid Build Coastguard Worker     //
473*4d7e907cSAndroid Build Coastguard Worker     EXPECT_GE(attRec.root_of_trust.security_level,
474*4d7e907cSAndroid Build Coastguard Worker               keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
475*4d7e907cSAndroid Build Coastguard Worker 
476*4d7e907cSAndroid Build Coastguard Worker     //    - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set
477*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_VERSION));
478*4d7e907cSAndroid Build Coastguard Worker     EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_PATCHLEVEL));
479*4d7e907cSAndroid Build Coastguard Worker 
480*4d7e907cSAndroid Build Coastguard Worker     // TODO: we could retrieve osVersion and osPatchLevel from Android itself and compare it
481*4d7e907cSAndroid Build Coastguard Worker     // with what was reported in the certificate.
482*4d7e907cSAndroid Build Coastguard Worker }
483*4d7e907cSAndroid Build Coastguard Worker 
verifyAuthKeyCertificate(const vector<uint8_t> & authKeyCertChain)484*4d7e907cSAndroid Build Coastguard Worker void verifyAuthKeyCertificate(const vector<uint8_t>& authKeyCertChain) {
485*4d7e907cSAndroid Build Coastguard Worker     const uint8_t* data = authKeyCertChain.data();
486*4d7e907cSAndroid Build Coastguard Worker     auto cert = X509_Ptr(d2i_X509(nullptr, &data, authKeyCertChain.size()));
487*4d7e907cSAndroid Build Coastguard Worker 
488*4d7e907cSAndroid Build Coastguard Worker     //  - version: INTEGER 2 (means v3 certificate).
489*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(X509_get_version(cert.get()), 2);
490*4d7e907cSAndroid Build Coastguard Worker 
491*4d7e907cSAndroid Build Coastguard Worker     //  - serialNumber: INTEGER 1 (fixed value: same on all certs).
492*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(ASN1_INTEGER_get(X509_get_serialNumber(cert.get())), 1);
493*4d7e907cSAndroid Build Coastguard Worker 
494*4d7e907cSAndroid Build Coastguard Worker     //  - signature: must be set to ECDSA.
495*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(X509_get_signature_nid(cert.get()), NID_ecdsa_with_SHA256);
496*4d7e907cSAndroid Build Coastguard Worker 
497*4d7e907cSAndroid Build Coastguard Worker     //  - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed
498*4d7e907cSAndroid Build Coastguard Worker     //    value: same on all certs)
499*4d7e907cSAndroid Build Coastguard Worker     X509_NAME* subject = X509_get_subject_name(cert.get());
500*4d7e907cSAndroid Build Coastguard Worker     ASSERT_NE(subject, nullptr);
501*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(x509NameToRfc2253String(subject),
502*4d7e907cSAndroid Build Coastguard Worker               "CN=Android Identity Credential Authentication Key");
503*4d7e907cSAndroid Build Coastguard Worker 
504*4d7e907cSAndroid Build Coastguard Worker     //  - issuer: CN shall be set to "Android Identity Credential Key". (fixed value:
505*4d7e907cSAndroid Build Coastguard Worker     //    same on all certs)
506*4d7e907cSAndroid Build Coastguard Worker     X509_NAME* issuer = X509_get_issuer_name(cert.get());
507*4d7e907cSAndroid Build Coastguard Worker     ASSERT_NE(issuer, nullptr);
508*4d7e907cSAndroid Build Coastguard Worker     EXPECT_EQ(x509NameToRfc2253String(issuer), "CN=Android Identity Credential Key");
509*4d7e907cSAndroid Build Coastguard Worker 
510*4d7e907cSAndroid Build Coastguard Worker     //  - subjectPublicKeyInfo: must contain attested public key.
511*4d7e907cSAndroid Build Coastguard Worker 
512*4d7e907cSAndroid Build Coastguard Worker     //  - validity: should be from current time and one year in the future (365 days).
513*4d7e907cSAndroid Build Coastguard Worker     time_t notBefore, notAfter;
514*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), &notAfter));
515*4d7e907cSAndroid Build Coastguard Worker     ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), &notBefore));
516*4d7e907cSAndroid Build Coastguard Worker 
517*4d7e907cSAndroid Build Coastguard Worker     //  Allow for 10 seconds drift to account for the time drift between Secure HW
518*4d7e907cSAndroid Build Coastguard Worker     //  and this environment plus the difference between when the certificate was
519*4d7e907cSAndroid Build Coastguard Worker     //  created and until now
520*4d7e907cSAndroid Build Coastguard Worker     //
521*4d7e907cSAndroid Build Coastguard Worker     uint64_t now = time(nullptr);
522*4d7e907cSAndroid Build Coastguard Worker     int64_t diffSecs = now - notBefore;
523*4d7e907cSAndroid Build Coastguard Worker     int64_t allowDriftSecs = 10;
524*4d7e907cSAndroid Build Coastguard Worker     EXPECT_LE(-allowDriftSecs, diffSecs);
525*4d7e907cSAndroid Build Coastguard Worker     EXPECT_GE(allowDriftSecs, diffSecs);
526*4d7e907cSAndroid Build Coastguard Worker 
527*4d7e907cSAndroid Build Coastguard Worker     // The AIDL spec used to call for "one year in the future (365
528*4d7e907cSAndroid Build Coastguard Worker     // days)" but was updated to say "current time and 31536000
529*4d7e907cSAndroid Build Coastguard Worker     // seconds in the future (approximately 365 days)" to clarify that
530*4d7e907cSAndroid Build Coastguard Worker     // this was the original intention.
531*4d7e907cSAndroid Build Coastguard Worker     //
532*4d7e907cSAndroid Build Coastguard Worker     // However a number of implementations interpreted this as a
533*4d7e907cSAndroid Build Coastguard Worker     // "literal year" which started causing problems in March 2023
534*4d7e907cSAndroid Build Coastguard Worker     // because 2024 is a leap year. Since the extra day doesn't really
535*4d7e907cSAndroid Build Coastguard Worker     // matter (the validity period is specified in the MSO anyway and
536*4d7e907cSAndroid Build Coastguard Worker     // that's what RPs use), we allow both interpretations.
537*4d7e907cSAndroid Build Coastguard Worker     //
538*4d7e907cSAndroid Build Coastguard Worker     // For simplicity, we just require that that notAfter is after
539*4d7e907cSAndroid Build Coastguard Worker     // 31536000 and which also covers the case if there's a leap-day
540*4d7e907cSAndroid Build Coastguard Worker     // and possible leap-seconds.
541*4d7e907cSAndroid Build Coastguard Worker     //
542*4d7e907cSAndroid Build Coastguard Worker     constexpr uint64_t kSecsIn365Days = 365 * 24 * 60 * 60;
543*4d7e907cSAndroid Build Coastguard Worker     EXPECT_LE(notBefore + kSecsIn365Days, notAfter);
544*4d7e907cSAndroid Build Coastguard Worker }
545*4d7e907cSAndroid Build Coastguard Worker 
buildRequestNamespaces(const vector<TestEntryData> entries)546*4d7e907cSAndroid Build Coastguard Worker vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
547*4d7e907cSAndroid Build Coastguard Worker     vector<RequestNamespace> ret;
548*4d7e907cSAndroid Build Coastguard Worker     RequestNamespace curNs;
549*4d7e907cSAndroid Build Coastguard Worker     for (const TestEntryData& testEntry : entries) {
550*4d7e907cSAndroid Build Coastguard Worker         if (testEntry.nameSpace != curNs.namespaceName) {
551*4d7e907cSAndroid Build Coastguard Worker             if (curNs.namespaceName.size() > 0) {
552*4d7e907cSAndroid Build Coastguard Worker                 ret.push_back(curNs);
553*4d7e907cSAndroid Build Coastguard Worker             }
554*4d7e907cSAndroid Build Coastguard Worker             curNs.namespaceName = testEntry.nameSpace;
555*4d7e907cSAndroid Build Coastguard Worker             curNs.items.clear();
556*4d7e907cSAndroid Build Coastguard Worker         }
557*4d7e907cSAndroid Build Coastguard Worker 
558*4d7e907cSAndroid Build Coastguard Worker         RequestDataItem item;
559*4d7e907cSAndroid Build Coastguard Worker         item.name = testEntry.name;
560*4d7e907cSAndroid Build Coastguard Worker         item.size = testEntry.valueCbor.size();
561*4d7e907cSAndroid Build Coastguard Worker         item.accessControlProfileIds = testEntry.profileIds;
562*4d7e907cSAndroid Build Coastguard Worker         curNs.items.push_back(item);
563*4d7e907cSAndroid Build Coastguard Worker     }
564*4d7e907cSAndroid Build Coastguard Worker     if (curNs.namespaceName.size() > 0) {
565*4d7e907cSAndroid Build Coastguard Worker         ret.push_back(curNs);
566*4d7e907cSAndroid Build Coastguard Worker     }
567*4d7e907cSAndroid Build Coastguard Worker     return ret;
568*4d7e907cSAndroid Build Coastguard Worker }
569*4d7e907cSAndroid Build Coastguard Worker 
570*4d7e907cSAndroid Build Coastguard Worker }  // namespace android::hardware::identity::test_utils
571