blob: 3b106514b4a35a3eb82a396d18098ca4661637a1 [file] [log] [blame]
Selene Huang92b61d62020-03-04 02:24:16 -08001/*
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
David Zeuthen34abaae2020-10-26 20:26:36 -040017#define LOG_TAG "VtsIdentityTestUtils"
18
Selene Huang92b61d62020-03-04 02:24:16 -080019#include "VtsIdentityTestUtils.h"
20
21#include <aidl/Gtest.h>
David Zeuthen34abaae2020-10-26 20:26:36 -040022#include <android-base/logging.h>
23#include <keymaster/km_openssl/openssl_utils.h>
24#include <keymasterV4_1/attestation_record.h>
25#include <charconv>
Selene Huang92b61d62020-03-04 02:24:16 -080026#include <map>
27
28namespace android::hardware::identity::test_utils {
29
30using std::endl;
31using std::map;
32using std::optional;
33using std::string;
34using std::vector;
35
36using ::android::sp;
37using ::android::String16;
38using ::android::binder::Status;
David Zeuthen34abaae2020-10-26 20:26:36 -040039using ::keymaster::X509_Ptr;
Selene Huang92b61d62020-03-04 02:24:16 -080040
Selene Huangcab019a2020-03-11 04:37:48 -070041bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
David Zeuthen34abaae2020-10-26 20:26:36 -040042 sp<IIdentityCredentialStore>& credentialStore, bool testCredential) {
Selene Huang92b61d62020-03-04 02:24:16 -080043 if (credentialStore == nullptr) {
44 return false;
45 }
46
47 string docType = "org.iso.18013-5.2019.mdl";
Selene Huang92b61d62020-03-04 02:24:16 -080048 Status result = credentialStore->createCredential(docType, testCredential, &writableCredential);
49
50 if (result.isOk() && writableCredential != nullptr) {
51 return true;
52 } else {
53 return false;
54 }
55}
56
Selene Huangcab019a2020-03-11 04:37:48 -070057optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal) {
Selene Huang92b61d62020-03-04 02:24:16 -080058 vector<uint8_t> privKey;
Selene Huangcab019a2020-03-11 04:37:48 -070059 return generateReaderCertificate(serialDecimal, &privKey);
Selene Huang92b61d62020-03-04 02:24:16 -080060}
61
Selene Huangcab019a2020-03-11 04:37:48 -070062optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
63 vector<uint8_t>* outReaderPrivateKey) {
Selene Huang92b61d62020-03-04 02:24:16 -080064 optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
65 if (!readerKeyPKCS8) {
66 return {};
67 }
68
69 optional<vector<uint8_t>> readerPublicKey =
70 support::ecKeyPairGetPublicKey(readerKeyPKCS8.value());
71 optional<vector<uint8_t>> readerKey = support::ecKeyPairGetPrivateKey(readerKeyPKCS8.value());
72 if (!readerPublicKey || !readerKey) {
73 return {};
74 }
75
Selene Huangcab019a2020-03-11 04:37:48 -070076 if (outReaderPrivateKey == nullptr) {
77 return {};
78 }
79
80 *outReaderPrivateKey = readerKey.value();
Selene Huang92b61d62020-03-04 02:24:16 -080081
82 string issuer = "Android Open Source Project";
83 string subject = "Android IdentityCredential VTS Test";
84 time_t validityNotBefore = time(nullptr);
85 time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
86
87 return support::ecPublicKeyGenerateCertificate(readerPublicKey.value(), readerKey.value(),
88 serialDecimal, issuer, subject,
89 validityNotBefore, validityNotAfter);
90}
91
Selene Huangcab019a2020-03-11 04:37:48 -070092optional<vector<SecureAccessControlProfile>> addAccessControlProfiles(
Selene Huang92b61d62020-03-04 02:24:16 -080093 sp<IWritableIdentityCredential>& writableCredential,
94 const vector<TestProfile>& testProfiles) {
95 Status result;
96
97 vector<SecureAccessControlProfile> secureProfiles;
98
99 for (const auto& testProfile : testProfiles) {
100 SecureAccessControlProfile profile;
101 Certificate cert;
102 cert.encodedCertificate = testProfile.readerCertificate;
David Zeuthenef739512020-06-03 13:24:52 -0400103 int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
Selene Huang92b61d62020-03-04 02:24:16 -0800104 result = writableCredential->addAccessControlProfile(
105 testProfile.id, cert, testProfile.userAuthenticationRequired,
David Zeuthenef739512020-06-03 13:24:52 -0400106 testProfile.timeoutMillis, secureUserId, &profile);
Selene Huang92b61d62020-03-04 02:24:16 -0800107
108 // Don't use assert so all errors can be outputed. Then return
109 // instead of exit even on errors so caller can decide.
110 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
111 << "test profile id = " << testProfile.id << endl;
112 EXPECT_EQ(testProfile.id, profile.id);
113 EXPECT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
114 EXPECT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
115 EXPECT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
116 EXPECT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
117
118 if (!result.isOk() || testProfile.id != profile.id ||
119 testProfile.readerCertificate != profile.readerCertificate.encodedCertificate ||
120 testProfile.userAuthenticationRequired != profile.userAuthenticationRequired ||
121 testProfile.timeoutMillis != profile.timeoutMillis ||
122 support::kAesGcmTagSize + support::kAesGcmIvSize != profile.mac.size()) {
123 return {};
124 }
125
126 secureProfiles.push_back(profile);
127 }
128
129 return secureProfiles;
130}
131
132// Most test expects this function to pass. So we will print out additional
133// value if failed so more debug data can be provided.
Selene Huangcab019a2020-03-11 04:37:48 -0700134bool addEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
Selene Huang92b61d62020-03-04 02:24:16 -0800135 int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
136 bool expectSuccess) {
137 Status result;
138 vector<vector<uint8_t>> chunks = support::chunkVector(entry.valueCbor, dataChunkSize);
139
140 result = writableCredential->beginAddEntry(entry.profileIds, entry.nameSpace, entry.name,
141 entry.valueCbor.size());
142
143 if (expectSuccess) {
144 EXPECT_TRUE(result.isOk())
145 << result.exceptionCode() << "; " << result.exceptionMessage() << endl
146 << "entry name = " << entry.name << ", name space=" << entry.nameSpace << endl;
147 }
148
149 if (!result.isOk()) {
150 return false;
151 }
152
153 vector<vector<uint8_t>> encryptedChunks;
154 for (const auto& chunk : chunks) {
155 vector<uint8_t> encryptedContent;
156 result = writableCredential->addEntryValue(chunk, &encryptedContent);
157 if (expectSuccess) {
158 EXPECT_TRUE(result.isOk())
159 << result.exceptionCode() << "; " << result.exceptionMessage() << endl
160 << "entry name = " << entry.name << ", name space = " << entry.nameSpace
161 << endl;
162
163 EXPECT_GT(encryptedContent.size(), 0u) << "entry name = " << entry.name
164 << ", name space = " << entry.nameSpace << endl;
165 }
166
167 if (!result.isOk() || encryptedContent.size() <= 0u) {
168 return false;
169 }
170
171 encryptedChunks.push_back(encryptedContent);
172 }
173
174 encryptedBlobs[&entry] = encryptedChunks;
175 return true;
176}
177
Selene Huangcab019a2020-03-11 04:37:48 -0700178void setImageData(vector<uint8_t>& image) {
Selene Huang92b61d62020-03-04 02:24:16 -0800179 image.resize(256 * 1024 - 10);
180 for (size_t n = 0; n < image.size(); n++) {
181 image[n] = (uint8_t)n;
182 }
183}
184
David Zeuthen34abaae2020-10-26 20:26:36 -0400185string x509NameToRfc2253String(X509_NAME* name) {
186 char* buf;
187 size_t bufSize;
188 BIO* bio;
189
190 bio = BIO_new(BIO_s_mem());
191 X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253);
192 bufSize = BIO_get_mem_data(bio, &buf);
193 string ret = string(buf, bufSize);
194 BIO_free(bio);
195
196 return ret;
197}
198
199int parseDigits(const char** s, int numDigits) {
200 int result;
201 auto [_, ec] = std::from_chars(*s, *s + numDigits, result);
202 if (ec != std::errc()) {
203 LOG(ERROR) << "Error parsing " << numDigits << " digits "
204 << " from " << s;
205 return 0;
206 }
207 *s += numDigits;
208 return result;
209}
210
211bool parseAsn1Time(const ASN1_TIME* asn1Time, time_t* outTime) {
212 struct tm tm;
213
214 memset(&tm, '\0', sizeof(tm));
215 const char* timeStr = (const char*)asn1Time->data;
216 const char* s = timeStr;
217 if (asn1Time->type == V_ASN1_UTCTIME) {
218 tm.tm_year = parseDigits(&s, 2);
219 if (tm.tm_year < 70) {
220 tm.tm_year += 100;
221 }
222 } else if (asn1Time->type == V_ASN1_GENERALIZEDTIME) {
223 tm.tm_year = parseDigits(&s, 4) - 1900;
224 tm.tm_year -= 1900;
225 } else {
226 LOG(ERROR) << "Unsupported ASN1_TIME type " << asn1Time->type;
227 return false;
228 }
229 tm.tm_mon = parseDigits(&s, 2) - 1;
230 tm.tm_mday = parseDigits(&s, 2);
231 tm.tm_hour = parseDigits(&s, 2);
232 tm.tm_min = parseDigits(&s, 2);
233 tm.tm_sec = parseDigits(&s, 2);
234 // This may need to be updated if someone create certificates using +/- instead of Z.
235 //
236 if (*s != 'Z') {
237 LOG(ERROR) << "Expected Z in string '" << timeStr << "' at offset " << (s - timeStr);
Selene Huangcab019a2020-03-11 04:37:48 -0700238 return false;
239 }
240
David Zeuthen34abaae2020-10-26 20:26:36 -0400241 time_t t = timegm(&tm);
242 if (t == -1) {
243 LOG(ERROR) << "Error converting broken-down time to time_t";
244 return false;
Selene Huangcab019a2020-03-11 04:37:48 -0700245 }
David Zeuthen34abaae2020-10-26 20:26:36 -0400246 *outTime = t;
Selene Huangcab019a2020-03-11 04:37:48 -0700247 return true;
248}
249
David Zeuthen34abaae2020-10-26 20:26:36 -0400250void validateAttestationCertificate(const vector<Certificate>& credentialKeyCertChain,
251 const vector<uint8_t>& expectedChallenge,
252 const vector<uint8_t>& expectedAppId, bool isTestCredential) {
253 ASSERT_GE(credentialKeyCertChain.size(), 2);
254
255 vector<uint8_t> certBytes = credentialKeyCertChain[0].encodedCertificate;
256 const uint8_t* certData = certBytes.data();
257 X509_Ptr cert = X509_Ptr(d2i_X509(nullptr, &certData, certBytes.size()));
258
259 vector<uint8_t> batchCertBytes = credentialKeyCertChain[1].encodedCertificate;
260 const uint8_t* batchCertData = batchCertBytes.data();
261 X509_Ptr batchCert = X509_Ptr(d2i_X509(nullptr, &batchCertData, batchCertBytes.size()));
262
263 // First get some values from the batch certificate which is checked
264 // against the top-level certificate (subject, notAfter)
265 //
266
267 X509_NAME* batchSubject = X509_get_subject_name(batchCert.get());
268 ASSERT_NE(nullptr, batchSubject);
269 time_t batchNotAfter;
270 ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(batchCert.get()), &batchNotAfter));
271
272 // Check all the requirements from IWritableIdentityCredential::getAttestationCertificate()...
273 //
274
275 // - version: INTEGER 2 (means v3 certificate).
276 EXPECT_EQ(2, X509_get_version(cert.get()));
277
278 // - serialNumber: INTEGER 1 (fixed value: same on all certs).
279 EXPECT_EQ(1, ASN1_INTEGER_get(X509_get_serialNumber(cert.get())));
280
281 // - signature: must be set to ECDSA.
282 EXPECT_EQ(NID_ecdsa_with_SHA256, X509_get_signature_nid(cert.get()));
283
284 // - subject: CN shall be set to "Android Identity Credential Key". (fixed value:
285 // same on all certs)
286 X509_NAME* subject = X509_get_subject_name(cert.get());
287 ASSERT_NE(nullptr, subject);
288 EXPECT_EQ("CN=Android Identity Credential Key", x509NameToRfc2253String(subject));
289
290 // - issuer: Same as the subject field of the batch attestation key.
291 X509_NAME* issuer = X509_get_issuer_name(cert.get());
292 ASSERT_NE(nullptr, issuer);
293 EXPECT_EQ(x509NameToRfc2253String(batchSubject), x509NameToRfc2253String(issuer));
294
295 // - validity: Should be from current time and expire at the same time as the
296 // attestation batch certificate used.
297 //
298 // Allow for 10 seconds drift to account for the time drift between Secure HW
299 // and this environment plus the difference between when the certificate was
300 // created and until now
301 //
302 time_t notBefore;
303 ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), &notBefore));
304 uint64_t now = time(nullptr);
305 int64_t diffSecs = now - notBefore;
306 int64_t allowDriftSecs = 10;
307 EXPECT_LE(-allowDriftSecs, diffSecs);
308 EXPECT_GE(allowDriftSecs, diffSecs);
309
310 time_t notAfter;
311 ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), &notAfter));
312 EXPECT_EQ(notAfter, batchNotAfter);
313
314 auto [err, attRec] = keymaster::V4_1::parse_attestation_record(certBytes);
315 ASSERT_EQ(keymaster::V4_1::ErrorCode::OK, err);
316
317 // - subjectPublicKeyInfo: must contain attested public key.
318
319 // - The attestationVersion field in the attestation extension must be at least 3.
320 EXPECT_GE(attRec.attestation_version, 3);
321
322 // - The attestationSecurityLevel field must be set to either Software (0),
323 // TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
324 // implemented.
325 EXPECT_GE(attRec.attestation_security_level,
326 keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
327
328 // - The keymasterVersion field in the attestation extension must be set to the.
329 // same value as used for Android Keystore keys.
330 //
331 // Nothing to check here...
332
333 // - The keymasterSecurityLevel field in the attestation extension must be set to
334 // either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
335 // the Trusted Application backing the HAL implementation is implemented.
336 EXPECT_GE(attRec.keymaster_security_level, keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
337
338 // - The attestationChallenge field must be set to the passed-in challenge.
339 EXPECT_EQ(expectedChallenge.size(), attRec.attestation_challenge.size());
340 EXPECT_TRUE(memcmp(expectedChallenge.data(), attRec.attestation_challenge.data(),
341 attRec.attestation_challenge.size()) == 0);
342
343 // - The uniqueId field must be empty.
344 EXPECT_EQ(attRec.unique_id.size(), 0);
345
346 // - The softwareEnforced field in the attestation extension must include
347 // Tag::ATTESTATION_APPLICATION_ID which must be set to the bytes of the passed-in
348 // attestationApplicationId.
349 EXPECT_TRUE(attRec.software_enforced.Contains(keymaster::V4_0::TAG_ATTESTATION_APPLICATION_ID,
350 expectedAppId));
351
352 // - The teeEnforced field in the attestation extension must include
353 //
354 // - Tag::IDENTITY_CREDENTIAL_KEY which indicates that the key is an Identity
355 // Credential key (which can only sign/MAC very specific messages) and not an Android
356 // Keystore key (which can be used to sign/MAC anything). This must not be set
357 // for test credentials.
358 bool hasIcKeyTag =
359 attRec.hardware_enforced.Contains(static_cast<android::hardware::keymaster::V4_0::Tag>(
360 keymaster::V4_1::Tag::IDENTITY_CREDENTIAL_KEY));
361 if (isTestCredential) {
362 EXPECT_FALSE(hasIcKeyTag);
363 } else {
364 EXPECT_TRUE(hasIcKeyTag);
365 }
366
367 // - Tag::PURPOSE must be set to SIGN
368 EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_PURPOSE,
369 keymaster::V4_0::KeyPurpose::SIGN));
370
371 // - Tag::KEY_SIZE must be set to the appropriate key size, in bits (e.g. 256)
372 EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_KEY_SIZE, 256));
373
374 // - Tag::ALGORITHM must be set to EC
375 EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_ALGORITHM,
376 keymaster::V4_0::Algorithm::EC));
377
378 // - Tag::NO_AUTH_REQUIRED must be set
379 EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_NO_AUTH_REQUIRED));
380
381 // - Tag::DIGEST must be include SHA_2_256
382 EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_DIGEST,
383 keymaster::V4_0::Digest::SHA_2_256));
384
385 // - Tag::EC_CURVE must be set to P_256
386 EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_EC_CURVE,
387 keymaster::V4_0::EcCurve::P_256));
388
389 // - Tag::ROOT_OF_TRUST must be set
390 //
391 EXPECT_GE(attRec.root_of_trust.security_level,
392 keymaster::V4_0::SecurityLevel::TRUSTED_ENVIRONMENT);
393
394 // - Tag::OS_VERSION and Tag::OS_PATCHLEVEL must be set
395 EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_VERSION));
396 EXPECT_TRUE(attRec.hardware_enforced.Contains(keymaster::V4_0::TAG_OS_PATCHLEVEL));
397
398 // TODO: we could retrieve osVersion and osPatchLevel from Android itself and compare it
399 // with what was reported in the certificate.
400}
401
402void verifyAuthKeyCertificate(const vector<uint8_t>& authKeyCertChain) {
403 const uint8_t* data = authKeyCertChain.data();
404 auto cert = X509_Ptr(d2i_X509(nullptr, &data, authKeyCertChain.size()));
405
406 // - version: INTEGER 2 (means v3 certificate).
407 EXPECT_EQ(X509_get_version(cert.get()), 2);
408
409 // - serialNumber: INTEGER 1 (fixed value: same on all certs).
410 EXPECT_EQ(ASN1_INTEGER_get(X509_get_serialNumber(cert.get())), 1);
411
412 // - signature: must be set to ECDSA.
413 EXPECT_EQ(X509_get_signature_nid(cert.get()), NID_ecdsa_with_SHA256);
414
415 // - subject: CN shall be set to "Android Identity Credential Authentication Key". (fixed
416 // value: same on all certs)
417 X509_NAME* subject = X509_get_subject_name(cert.get());
418 ASSERT_NE(subject, nullptr);
419 EXPECT_EQ(x509NameToRfc2253String(subject),
420 "CN=Android Identity Credential Authentication Key");
421
422 // - issuer: CN shall be set to "Android Identity Credential Key". (fixed value:
423 // same on all certs)
424 X509_NAME* issuer = X509_get_issuer_name(cert.get());
425 ASSERT_NE(issuer, nullptr);
426 EXPECT_EQ(x509NameToRfc2253String(issuer), "CN=Android Identity Credential Key");
427
428 // - subjectPublicKeyInfo: must contain attested public key.
429
430 // - validity: should be from current time and one year in the future (365 days).
431 time_t notBefore, notAfter;
432 ASSERT_TRUE(parseAsn1Time(X509_get0_notAfter(cert.get()), &notAfter));
433 ASSERT_TRUE(parseAsn1Time(X509_get0_notBefore(cert.get()), &notBefore));
434
435 // Allow for 10 seconds drift to account for the time drift between Secure HW
436 // and this environment plus the difference between when the certificate was
437 // created and until now
438 //
439 uint64_t now = time(nullptr);
440 int64_t diffSecs = now - notBefore;
441 int64_t allowDriftSecs = 10;
442 EXPECT_LE(-allowDriftSecs, diffSecs);
443 EXPECT_GE(allowDriftSecs, diffSecs);
444 constexpr uint64_t kSecsInOneYear = 365 * 24 * 60 * 60;
445 EXPECT_EQ(notBefore + kSecsInOneYear, notAfter);
446}
447
David Zeuthen28edb102020-04-28 18:54:55 -0400448vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
449 vector<RequestNamespace> ret;
450 RequestNamespace curNs;
451 for (const TestEntryData& testEntry : entries) {
452 if (testEntry.nameSpace != curNs.namespaceName) {
453 if (curNs.namespaceName.size() > 0) {
454 ret.push_back(curNs);
455 }
456 curNs.namespaceName = testEntry.nameSpace;
457 curNs.items.clear();
458 }
459
460 RequestDataItem item;
461 item.name = testEntry.name;
462 item.size = testEntry.valueCbor.size();
463 item.accessControlProfileIds = testEntry.profileIds;
464 curNs.items.push_back(item);
465 }
466 if (curNs.namespaceName.size() > 0) {
467 ret.push_back(curNs);
468 }
469 return ret;
470}
471
Selene Huang92b61d62020-03-04 02:24:16 -0800472} // namespace android::hardware::identity::test_utils