blob: 48e47dc735659f12cc439cfd4696f69ace669c2a [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
17#include "VtsIdentityTestUtils.h"
18
19#include <aidl/Gtest.h>
20#include <map>
21
22namespace android::hardware::identity::test_utils {
23
24using std::endl;
25using std::map;
26using std::optional;
27using std::string;
28using std::vector;
29
30using ::android::sp;
31using ::android::String16;
32using ::android::binder::Status;
33
34bool SetupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
35 sp<IIdentityCredentialStore>& credentialStore) {
36 if (credentialStore == nullptr) {
37 return false;
38 }
39
40 string docType = "org.iso.18013-5.2019.mdl";
41 bool testCredential = true;
42 Status result = credentialStore->createCredential(docType, testCredential, &writableCredential);
43
44 if (result.isOk() && writableCredential != nullptr) {
45 return true;
46 } else {
47 return false;
48 }
49}
50
51optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal) {
52 vector<uint8_t> privKey;
53 return GenerateReaderCertificate(serialDecimal, privKey);
54}
55
56optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal,
57 vector<uint8_t>& readerPrivateKey) {
58 optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
59 if (!readerKeyPKCS8) {
60 return {};
61 }
62
63 optional<vector<uint8_t>> readerPublicKey =
64 support::ecKeyPairGetPublicKey(readerKeyPKCS8.value());
65 optional<vector<uint8_t>> readerKey = support::ecKeyPairGetPrivateKey(readerKeyPKCS8.value());
66 if (!readerPublicKey || !readerKey) {
67 return {};
68 }
69
70 readerPrivateKey = readerKey.value();
71
72 string issuer = "Android Open Source Project";
73 string subject = "Android IdentityCredential VTS Test";
74 time_t validityNotBefore = time(nullptr);
75 time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
76
77 return support::ecPublicKeyGenerateCertificate(readerPublicKey.value(), readerKey.value(),
78 serialDecimal, issuer, subject,
79 validityNotBefore, validityNotAfter);
80}
81
82optional<vector<SecureAccessControlProfile>> AddAccessControlProfiles(
83 sp<IWritableIdentityCredential>& writableCredential,
84 const vector<TestProfile>& testProfiles) {
85 Status result;
86
87 vector<SecureAccessControlProfile> secureProfiles;
88
89 for (const auto& testProfile : testProfiles) {
90 SecureAccessControlProfile profile;
91 Certificate cert;
92 cert.encodedCertificate = testProfile.readerCertificate;
93 result = writableCredential->addAccessControlProfile(
94 testProfile.id, cert, testProfile.userAuthenticationRequired,
95 testProfile.timeoutMillis, 0, &profile);
96
97 // Don't use assert so all errors can be outputed. Then return
98 // instead of exit even on errors so caller can decide.
99 EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
100 << "test profile id = " << testProfile.id << endl;
101 EXPECT_EQ(testProfile.id, profile.id);
102 EXPECT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
103 EXPECT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
104 EXPECT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
105 EXPECT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
106
107 if (!result.isOk() || testProfile.id != profile.id ||
108 testProfile.readerCertificate != profile.readerCertificate.encodedCertificate ||
109 testProfile.userAuthenticationRequired != profile.userAuthenticationRequired ||
110 testProfile.timeoutMillis != profile.timeoutMillis ||
111 support::kAesGcmTagSize + support::kAesGcmIvSize != profile.mac.size()) {
112 return {};
113 }
114
115 secureProfiles.push_back(profile);
116 }
117
118 return secureProfiles;
119}
120
121// Most test expects this function to pass. So we will print out additional
122// value if failed so more debug data can be provided.
123bool AddEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
124 int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
125 bool expectSuccess) {
126 Status result;
127 vector<vector<uint8_t>> chunks = support::chunkVector(entry.valueCbor, dataChunkSize);
128
129 result = writableCredential->beginAddEntry(entry.profileIds, entry.nameSpace, entry.name,
130 entry.valueCbor.size());
131
132 if (expectSuccess) {
133 EXPECT_TRUE(result.isOk())
134 << result.exceptionCode() << "; " << result.exceptionMessage() << endl
135 << "entry name = " << entry.name << ", name space=" << entry.nameSpace << endl;
136 }
137
138 if (!result.isOk()) {
139 return false;
140 }
141
142 vector<vector<uint8_t>> encryptedChunks;
143 for (const auto& chunk : chunks) {
144 vector<uint8_t> encryptedContent;
145 result = writableCredential->addEntryValue(chunk, &encryptedContent);
146 if (expectSuccess) {
147 EXPECT_TRUE(result.isOk())
148 << result.exceptionCode() << "; " << result.exceptionMessage() << endl
149 << "entry name = " << entry.name << ", name space = " << entry.nameSpace
150 << endl;
151
152 EXPECT_GT(encryptedContent.size(), 0u) << "entry name = " << entry.name
153 << ", name space = " << entry.nameSpace << endl;
154 }
155
156 if (!result.isOk() || encryptedContent.size() <= 0u) {
157 return false;
158 }
159
160 encryptedChunks.push_back(encryptedContent);
161 }
162
163 encryptedBlobs[&entry] = encryptedChunks;
164 return true;
165}
166
167bool ValidateAttestationCertificate(vector<Certificate>& inputCertificates) {
168 return (inputCertificates.size() >= 2);
169 // TODO: add parsing of the certificate and make sure it is genuine.
170}
171
172void SetImageData(vector<uint8_t>& image) {
173 image.resize(256 * 1024 - 10);
174 for (size_t n = 0; n < image.size(); n++) {
175 image[n] = (uint8_t)n;
176 }
177}
178
David Zeuthen28edb102020-04-28 18:54:55 -0400179vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
180 vector<RequestNamespace> ret;
181 RequestNamespace curNs;
182 for (const TestEntryData& testEntry : entries) {
183 if (testEntry.nameSpace != curNs.namespaceName) {
184 if (curNs.namespaceName.size() > 0) {
185 ret.push_back(curNs);
186 }
187 curNs.namespaceName = testEntry.nameSpace;
188 curNs.items.clear();
189 }
190
191 RequestDataItem item;
192 item.name = testEntry.name;
193 item.size = testEntry.valueCbor.size();
194 item.accessControlProfileIds = testEntry.profileIds;
195 curNs.items.push_back(item);
196 }
197 if (curNs.namespaceName.size() > 0) {
198 ret.push_back(curNs);
199 }
200 return ret;
201}
202
Selene Huang92b61d62020-03-04 02:24:16 -0800203} // namespace android::hardware::identity::test_utils