blob: 83ee188ad6431f7e630f4f24e5e3f43caabcc727 [file] [log] [blame]
Shawn Willden0cc617c2022-02-11 12:51:53 -07001/*
2 * Copyright (C) 2021 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 "keymint_2_se_provisioning_test"
18
19#include <map>
20#include <memory>
21#include <vector>
22
23#include <android-base/logging.h>
24#include <android/binder_manager.h>
25
26#include <cppbor_parse.h>
27#include <keymaster/cppcose/cppcose.h>
28#include <keymint_support/key_param_output.h>
29
30#include "KeyMintAidlTestBase.h"
31
32namespace aidl::android::hardware::security::keymint::test {
33
34using std::array;
35using std::map;
36using std::shared_ptr;
37using std::vector;
38
39class SecureElementProvisioningTest : public testing::Test {
40 protected:
David Drysdale795f7582022-03-01 13:52:15 +000041 static void SetUpTestSuite() {
Shawn Willden0cc617c2022-02-11 12:51:53 -070042 auto params = ::android::getAidlHalInstanceNames(IKeyMintDevice::descriptor);
43 for (auto& param : params) {
44 ASSERT_TRUE(AServiceManager_isDeclared(param.c_str()))
45 << "IKeyMintDevice instance " << param << " found but not declared.";
46 ::ndk::SpAIBinder binder(AServiceManager_waitForService(param.c_str()));
47 auto keymint = IKeyMintDevice::fromBinder(binder);
48 ASSERT_NE(keymint, nullptr) << "Failed to get IKeyMintDevice instance " << param;
49
50 KeyMintHardwareInfo info;
51 ASSERT_TRUE(keymint->getHardwareInfo(&info).isOk());
52 ASSERT_EQ(keymints_.count(info.securityLevel), 0)
53 << "There must be exactly one IKeyMintDevice with security level "
54 << info.securityLevel;
55
56 keymints_[info.securityLevel] = std::move(keymint);
57 }
58 }
59
60 static map<SecurityLevel, shared_ptr<IKeyMintDevice>> keymints_;
61};
62
63map<SecurityLevel, shared_ptr<IKeyMintDevice>> SecureElementProvisioningTest::keymints_;
64
65TEST_F(SecureElementProvisioningTest, ValidConfigurations) {
66 // TEE is required
67 ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
68 // StrongBox is optional
69 ASSERT_LE(keymints_.count(SecurityLevel::STRONGBOX), 1);
70}
71
72TEST_F(SecureElementProvisioningTest, TeeOnly) {
73 ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
74 auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
75 ASSERT_NE(tee, nullptr);
76
77 array<uint8_t, 16> challenge1 = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
78 array<uint8_t, 16> challenge2 = {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
79
80 vector<uint8_t> rootOfTrust1;
81 Status result = tee->getRootOfTrust(challenge1, &rootOfTrust1);
82
83 // TODO: Remove the next line to require TEEs to succeed.
84 if (!result.isOk()) return;
85
86 ASSERT_TRUE(result.isOk());
87
88 // TODO: Parse and validate rootOfTrust1 here
89
90 vector<uint8_t> rootOfTrust2;
91 result = tee->getRootOfTrust(challenge2, &rootOfTrust2);
92 ASSERT_TRUE(result.isOk());
93
94 // TODO: Parse and validate rootOfTrust2 here
95
96 ASSERT_NE(rootOfTrust1, rootOfTrust2);
97
98 vector<uint8_t> rootOfTrust3;
99 result = tee->getRootOfTrust(challenge1, &rootOfTrust3);
100 ASSERT_TRUE(result.isOk());
101
102 ASSERT_EQ(rootOfTrust1, rootOfTrust3);
103
104 // TODO: Parse and validate rootOfTrust3 here
105}
106
107TEST_F(SecureElementProvisioningTest, TeeDoesNotImplementStrongBoxMethods) {
108 ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
109 auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
110 ASSERT_NE(tee, nullptr);
111
112 array<uint8_t, 16> challenge;
113 Status result = tee->getRootOfTrustChallenge(&challenge);
114 ASSERT_FALSE(result.isOk());
115 ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
116 ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
117
118 result = tee->sendRootOfTrust({});
119 ASSERT_FALSE(result.isOk());
120 ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
121 ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
122}
123
124TEST_F(SecureElementProvisioningTest, StrongBoxDoesNotImplementTeeMethods) {
125 if (keymints_.count(SecurityLevel::STRONGBOX) == 0) return;
126
127 auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
128 ASSERT_NE(sb, nullptr);
129
130 vector<uint8_t> rootOfTrust;
131 Status result = sb->getRootOfTrust({}, &rootOfTrust);
132 ASSERT_FALSE(result.isOk());
133 ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
134 ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()), ErrorCode::UNIMPLEMENTED);
135}
136
137TEST_F(SecureElementProvisioningTest, UnimplementedTest) {
138 if (keymints_.count(SecurityLevel::STRONGBOX) == 0) return; // Need a StrongBox to provision.
139
140 ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
141 auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
142 ASSERT_NE(tee, nullptr);
143
144 ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
145 auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
146 ASSERT_NE(sb, nullptr);
147
148 array<uint8_t, 16> challenge;
149 Status result = sb->getRootOfTrustChallenge(&challenge);
150 if (!result.isOk()) {
151 // Strongbox does not have to implement this feature if it has uses an alternative mechanism
152 // to provision the root of trust. In that case it MUST return UNIMPLEMENTED, both from
153 // getRootOfTrustChallenge() and from sendRootOfTrust().
154 ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
155 ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
156 ErrorCode::UNIMPLEMENTED);
157
158 result = sb->sendRootOfTrust({});
159 ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
160 ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
161 ErrorCode::UNIMPLEMENTED);
162
163 SUCCEED() << "This Strongbox implementation does not use late root of trust delivery.";
164 return;
165 }
166}
167
168TEST_F(SecureElementProvisioningTest, ChallengeQualityTest) {
169 if (keymints_.count(SecurityLevel::STRONGBOX) == 0) return; // Need a StrongBox to provision.
170
171 ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
172 auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
173 ASSERT_NE(sb, nullptr);
174
175 array<uint8_t, 16> challenge1;
176 Status result = sb->getRootOfTrustChallenge(&challenge1);
177 if (!result.isOk()) return;
178
179 array<uint8_t, 16> challenge2;
180 result = sb->getRootOfTrustChallenge(&challenge2);
181 ASSERT_TRUE(result.isOk());
182 ASSERT_NE(challenge1, challenge2);
183
184 // TODO: When we add entropy testing in other relevant places in these tests, add it here, too,
185 // to verify that challenges appear to have adequate entropy.
186}
187
188TEST_F(SecureElementProvisioningTest, ProvisioningTest) {
189 if (keymints_.count(SecurityLevel::STRONGBOX) == 0) return; // Need a StrongBox to provision.
190
191 ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
192 auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
193 ASSERT_NE(tee, nullptr);
194
195 ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
196 auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
197 ASSERT_NE(sb, nullptr);
198
199 array<uint8_t, 16> challenge;
200 Status result = sb->getRootOfTrustChallenge(&challenge);
201 if (!result.isOk()) return;
202
203 vector<uint8_t> rootOfTrust;
204 result = tee->getRootOfTrust(challenge, &rootOfTrust);
205 ASSERT_TRUE(result.isOk());
206
207 // TODO: Verify COSE_Mac0 structure and content here.
208
209 result = sb->sendRootOfTrust(rootOfTrust);
210 ASSERT_TRUE(result.isOk());
211
212 // Sending again must fail, because a new challenge is required.
213 result = sb->sendRootOfTrust(rootOfTrust);
214 ASSERT_FALSE(result.isOk());
215}
216
217TEST_F(SecureElementProvisioningTest, InvalidProvisioningTest) {
218 if (keymints_.count(SecurityLevel::STRONGBOX) == 0) return; // Need a StrongBox to provision.
219
220 ASSERT_EQ(keymints_.count(SecurityLevel::TRUSTED_ENVIRONMENT), 1);
221 auto tee = keymints_.find(SecurityLevel::TRUSTED_ENVIRONMENT)->second;
222 ASSERT_NE(tee, nullptr);
223
224 ASSERT_EQ(keymints_.count(SecurityLevel::STRONGBOX), 1);
225 auto sb = keymints_.find(SecurityLevel::STRONGBOX)->second;
226 ASSERT_NE(sb, nullptr);
227
228 array<uint8_t, 16> challenge;
229 Status result = sb->getRootOfTrustChallenge(&challenge);
230 if (!result.isOk()) return;
231
232 result = sb->sendRootOfTrust({});
233 ASSERT_FALSE(result.isOk());
234 ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
235 ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
236 ErrorCode::VERIFICATION_FAILED);
237
238 vector<uint8_t> rootOfTrust;
239 result = tee->getRootOfTrust(challenge, &rootOfTrust);
240 ASSERT_TRUE(result.isOk());
241
242 vector<uint8_t> corruptedRootOfTrust = rootOfTrust;
243 corruptedRootOfTrust[corruptedRootOfTrust.size() / 2]++;
244 result = sb->sendRootOfTrust(corruptedRootOfTrust);
245 ASSERT_FALSE(result.isOk());
246 ASSERT_EQ(result.getExceptionCode(), EX_SERVICE_SPECIFIC);
247 ASSERT_EQ(static_cast<ErrorCode>(result.getServiceSpecificError()),
248 ErrorCode::VERIFICATION_FAILED);
249
250 // Now try the correct RoT
251 result = sb->sendRootOfTrust(rootOfTrust);
252 ASSERT_TRUE(result.isOk());
253}
254
255} // namespace aidl::android::hardware::security::keymint::test