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