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 #include "VtsIdentityTestUtils.h"
18 
19 #include <aidl/Gtest.h>
20 #include <map>
21 
22 #include "VtsAttestationParserSupport.h"
23 
24 namespace android::hardware::identity::test_utils {
25 
26 using std::endl;
27 using std::map;
28 using std::optional;
29 using std::string;
30 using std::vector;
31 
32 using ::android::sp;
33 using ::android::String16;
34 using ::android::binder::Status;
35 
setupWritableCredential(sp<IWritableIdentityCredential> & writableCredential,sp<IIdentityCredentialStore> & credentialStore)36 bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
37                              sp<IIdentityCredentialStore>& credentialStore) {
38     if (credentialStore == nullptr) {
39         return false;
40     }
41 
42     string docType = "org.iso.18013-5.2019.mdl";
43     bool testCredential = true;
44     Status result = credentialStore->createCredential(docType, testCredential, &writableCredential);
45 
46     if (result.isOk() && writableCredential != nullptr) {
47         return true;
48     } else {
49         return false;
50     }
51 }
52 
generateReaderCertificate(string serialDecimal)53 optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal) {
54     vector<uint8_t> privKey;
55     return generateReaderCertificate(serialDecimal, &privKey);
56 }
57 
generateReaderCertificate(string serialDecimal,vector<uint8_t> * outReaderPrivateKey)58 optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
59                                                     vector<uint8_t>* outReaderPrivateKey) {
60     optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
61     if (!readerKeyPKCS8) {
62         return {};
63     }
64 
65     optional<vector<uint8_t>> readerPublicKey =
66             support::ecKeyPairGetPublicKey(readerKeyPKCS8.value());
67     optional<vector<uint8_t>> readerKey = support::ecKeyPairGetPrivateKey(readerKeyPKCS8.value());
68     if (!readerPublicKey || !readerKey) {
69         return {};
70     }
71 
72     if (outReaderPrivateKey == nullptr) {
73         return {};
74     }
75 
76     *outReaderPrivateKey = readerKey.value();
77 
78     string issuer = "Android Open Source Project";
79     string subject = "Android IdentityCredential VTS Test";
80     time_t validityNotBefore = time(nullptr);
81     time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
82 
83     return support::ecPublicKeyGenerateCertificate(readerPublicKey.value(), readerKey.value(),
84                                                    serialDecimal, issuer, subject,
85                                                    validityNotBefore, validityNotAfter);
86 }
87 
addAccessControlProfiles(sp<IWritableIdentityCredential> & writableCredential,const vector<TestProfile> & testProfiles)88 optional<vector<SecureAccessControlProfile>> addAccessControlProfiles(
89         sp<IWritableIdentityCredential>& writableCredential,
90         const vector<TestProfile>& testProfiles) {
91     Status result;
92 
93     vector<SecureAccessControlProfile> secureProfiles;
94 
95     for (const auto& testProfile : testProfiles) {
96         SecureAccessControlProfile profile;
97         Certificate cert;
98         cert.encodedCertificate = testProfile.readerCertificate;
99         int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
100         result = writableCredential->addAccessControlProfile(
101                 testProfile.id, cert, testProfile.userAuthenticationRequired,
102                 testProfile.timeoutMillis, secureUserId, &profile);
103 
104         // Don't use assert so all errors can be outputed.  Then return
105         // instead of exit even on errors so caller can decide.
106         EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
107                                    << "test profile id = " << testProfile.id << endl;
108         EXPECT_EQ(testProfile.id, profile.id);
109         EXPECT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
110         EXPECT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
111         EXPECT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
112         EXPECT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
113 
114         if (!result.isOk() || testProfile.id != profile.id ||
115             testProfile.readerCertificate != profile.readerCertificate.encodedCertificate ||
116             testProfile.userAuthenticationRequired != profile.userAuthenticationRequired ||
117             testProfile.timeoutMillis != profile.timeoutMillis ||
118             support::kAesGcmTagSize + support::kAesGcmIvSize != profile.mac.size()) {
119             return {};
120         }
121 
122         secureProfiles.push_back(profile);
123     }
124 
125     return secureProfiles;
126 }
127 
128 // Most test expects this function to pass. So we will print out additional
129 // 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)130 bool addEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
131               int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
132               bool expectSuccess) {
133     Status result;
134     vector<vector<uint8_t>> chunks = support::chunkVector(entry.valueCbor, dataChunkSize);
135 
136     result = writableCredential->beginAddEntry(entry.profileIds, entry.nameSpace, entry.name,
137                                                entry.valueCbor.size());
138 
139     if (expectSuccess) {
140         EXPECT_TRUE(result.isOk())
141                 << result.exceptionCode() << "; " << result.exceptionMessage() << endl
142                 << "entry name = " << entry.name << ", name space=" << entry.nameSpace << endl;
143     }
144 
145     if (!result.isOk()) {
146         return false;
147     }
148 
149     vector<vector<uint8_t>> encryptedChunks;
150     for (const auto& chunk : chunks) {
151         vector<uint8_t> encryptedContent;
152         result = writableCredential->addEntryValue(chunk, &encryptedContent);
153         if (expectSuccess) {
154             EXPECT_TRUE(result.isOk())
155                     << result.exceptionCode() << "; " << result.exceptionMessage() << endl
156                     << "entry name = " << entry.name << ", name space = " << entry.nameSpace
157                     << endl;
158 
159             EXPECT_GT(encryptedContent.size(), 0u) << "entry name = " << entry.name
160                                                    << ", name space = " << entry.nameSpace << endl;
161         }
162 
163         if (!result.isOk() || encryptedContent.size() <= 0u) {
164             return false;
165         }
166 
167         encryptedChunks.push_back(encryptedContent);
168     }
169 
170     encryptedBlobs[&entry] = encryptedChunks;
171     return true;
172 }
173 
setImageData(vector<uint8_t> & image)174 void setImageData(vector<uint8_t>& image) {
175     image.resize(256 * 1024 - 10);
176     for (size_t n = 0; n < image.size(); n++) {
177         image[n] = (uint8_t)n;
178     }
179 }
180 
validateAttestationCertificate(const vector<Certificate> & inputCertificates,const vector<uint8_t> & expectedChallenge,const vector<uint8_t> & expectedAppId,const HardwareInformation & hwInfo)181 bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
182                                     const vector<uint8_t>& expectedChallenge,
183                                     const vector<uint8_t>& expectedAppId,
184                                     const HardwareInformation& hwInfo) {
185     AttestationCertificateParser certParser_(inputCertificates);
186     bool ret = certParser_.parse();
187     EXPECT_TRUE(ret);
188     if (!ret) {
189         return false;
190     }
191 
192     // As per the IC HAL, the version of the Identity
193     // Credential HAL is 1.0 - and this is encoded as major*10 + minor. This field is used by
194     // Keymaster which is known to report integers less than or equal to 4 (for KM up to 4.0)
195     // and integers greater or equal than 41 (for KM starting with 4.1).
196     //
197     // Since we won't get to version 4.0 of the IC HAL for a while, let's also check that a KM
198     // version isn't errornously returned.
199     EXPECT_LE(10, certParser_.getKeymasterVersion());
200     EXPECT_GT(40, certParser_.getKeymasterVersion());
201     EXPECT_LE(3, certParser_.getAttestationVersion());
202 
203     // Verify the app id matches to whatever we set it to be.
204     optional<vector<uint8_t>> appId =
205             certParser_.getSwEnforcedBlob(::keymaster::TAG_ATTESTATION_APPLICATION_ID);
206     if (appId) {
207         EXPECT_EQ(expectedAppId.size(), appId.value().size());
208         EXPECT_EQ(0, memcmp(expectedAppId.data(), appId.value().data(), expectedAppId.size()));
209     } else {
210         // app id not found
211         EXPECT_EQ(0, expectedAppId.size());
212     }
213 
214     EXPECT_TRUE(certParser_.getHwEnforcedBool(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
215     EXPECT_FALSE(certParser_.getHwEnforcedBool(::keymaster::TAG_INCLUDE_UNIQUE_ID));
216 
217     // Verify the challenge always matches in size and data of what is passed
218     // in.
219     vector<uint8_t> attChallenge = certParser_.getAttestationChallenge();
220     EXPECT_EQ(expectedChallenge.size(), attChallenge.size());
221     EXPECT_EQ(0, memcmp(expectedChallenge.data(), attChallenge.data(), expectedChallenge.size()));
222 
223     // Ensure the attestation conveys that it's implemented in secure hardware (with carve-out
224     // for the reference implementation which cannot be implemented in secure hardware).
225     if (hwInfo.credentialStoreName == "Identity Credential Reference Implementation" &&
226         hwInfo.credentialStoreAuthorName == "Google") {
227         EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getKeymasterSecurityLevel());
228         EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getAttestationSecurityLevel());
229 
230     } else {
231         // Actual devices should use TrustedEnvironment or StrongBox.
232         EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getKeymasterSecurityLevel());
233         EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getAttestationSecurityLevel());
234     }
235     return true;
236 }
237 
buildRequestNamespaces(const vector<TestEntryData> entries)238 vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
239     vector<RequestNamespace> ret;
240     RequestNamespace curNs;
241     for (const TestEntryData& testEntry : entries) {
242         if (testEntry.nameSpace != curNs.namespaceName) {
243             if (curNs.namespaceName.size() > 0) {
244                 ret.push_back(curNs);
245             }
246             curNs.namespaceName = testEntry.nameSpace;
247             curNs.items.clear();
248         }
249 
250         RequestDataItem item;
251         item.name = testEntry.name;
252         item.size = testEntry.valueCbor.size();
253         item.accessControlProfileIds = testEntry.profileIds;
254         curNs.items.push_back(item);
255     }
256     if (curNs.namespaceName.size() > 0) {
257         ret.push_back(curNs);
258     }
259     return ret;
260 }
261 
262 }  // namespace android::hardware::identity::test_utils
263