1 /*
2 * Copyright 2020, 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 <gtest/gtest.h>
18
19 #include "km_compat.h"
20 #include <keymint_support/keymint_tags.h>
21
22 #include <aidl/android/hardware/security/keymint/ErrorCode.h>
23 #include <aidl/android/hardware/security/keymint/IKeyMintOperation.h>
24
25 using ::aidl::android::hardware::security::keymint::Algorithm;
26 using ::aidl::android::hardware::security::keymint::BlockMode;
27 using ::aidl::android::hardware::security::keymint::Certificate;
28 using ::aidl::android::hardware::security::keymint::Digest;
29 using ::aidl::android::hardware::security::keymint::EcCurve;
30 using ::aidl::android::hardware::security::keymint::ErrorCode;
31 using ::aidl::android::hardware::security::keymint::IKeyMintOperation;
32 using ::aidl::android::hardware::security::keymint::KeyCharacteristics;
33 using ::aidl::android::hardware::security::keymint::KeyPurpose;
34 using ::aidl::android::hardware::security::keymint::PaddingMode;
35 using ::aidl::android::hardware::security::keymint::SecurityLevel;
36
37 namespace KMV1 = ::aidl::android::hardware::security::keymint;
38
generateAESKey(std::shared_ptr<KeyMintDevice> device)39 static std::vector<uint8_t> generateAESKey(std::shared_ptr<KeyMintDevice> device) {
40 auto keyParams = std::vector<KeyParameter>({
41 KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::AES),
42 KMV1::makeKeyParameter(KMV1::TAG_KEY_SIZE, 128),
43 KMV1::makeKeyParameter(KMV1::TAG_BLOCK_MODE, BlockMode::CBC),
44 KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::NONE),
45 KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
46 KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::ENCRYPT),
47 KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::DECRYPT),
48 });
49 KeyCreationResult creationResult;
50 auto status = device->generateKey(keyParams, std::nullopt /* attest_key */, &creationResult);
51 if (!status.isOk()) {
52 return {};
53 }
54 return creationResult.keyBlob;
55 }
56
generateECSingingKey(std::shared_ptr<KeyMintDevice> device)57 static bool generateECSingingKey(std::shared_ptr<KeyMintDevice> device) {
58 uint64_t now_ms = (uint64_t)time(nullptr) * 1000;
59
60 auto keyParams = std::vector<KeyParameter>({
61 KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::EC),
62 KMV1::makeKeyParameter(KMV1::TAG_EC_CURVE, EcCurve::P_256),
63 KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
64 KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::SHA_2_256),
65 KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
66 KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::VERIFY),
67 KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_BEFORE, now_ms - 60 * 60 * 1000),
68 KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_AFTER, now_ms + 60 * 60 * 1000),
69 });
70 KeyCreationResult creationResult;
71 auto status = device->generateKey(keyParams, std::nullopt /* attest_key */, &creationResult);
72 EXPECT_TRUE(status.isOk()) << status.getDescription();
73 return status.isOk();
74 }
75
begin(std::shared_ptr<KeyMintDevice> device,bool valid)76 static std::variant<BeginResult, ScopedAStatus> begin(std::shared_ptr<KeyMintDevice> device,
77 bool valid) {
78 auto blob = generateAESKey(device);
79 std::vector<KeyParameter> kps;
80 if (valid) {
81 kps.push_back(KMV1::makeKeyParameter(KMV1::TAG_BLOCK_MODE, BlockMode::CBC));
82 kps.push_back(KMV1::makeKeyParameter(KMV1::TAG_PADDING, PaddingMode::NONE));
83 }
84 BeginResult beginResult;
85 auto status = device->begin(KeyPurpose::ENCRYPT, blob, kps, HardwareAuthToken(), &beginResult);
86 if (!status.isOk()) {
87 return status;
88 }
89 return beginResult;
90 }
91
92 static std::shared_ptr<KMV1::IKeyMintOperation>
generateAndBeginECDHKeyOperation(std::shared_ptr<KeyMintDevice> device)93 generateAndBeginECDHKeyOperation(std::shared_ptr<KeyMintDevice> device) {
94 uint64_t now_ms = (uint64_t)time(nullptr) * 1000;
95
96 auto keyParams = std::vector<KeyParameter>({
97 KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::EC),
98 KMV1::makeKeyParameter(KMV1::TAG_EC_CURVE, EcCurve::P_256),
99 KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
100 KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::NONE),
101 KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::AGREE_KEY),
102 KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_BEFORE, now_ms - 60 * 60 * 1000),
103 KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_AFTER, now_ms + 60 * 60 * 1000),
104 });
105 KeyCreationResult creationResult;
106 auto status = device->generateKey(keyParams, std::nullopt /* attest_key */, &creationResult);
107 EXPECT_TRUE(status.isOk()) << status.getDescription();
108 if (!status.isOk()) {
109 return {};
110 }
111 std::vector<KeyParameter> kps;
112 BeginResult beginResult;
113 auto bstatus = device->begin(KeyPurpose::AGREE_KEY, creationResult.keyBlob, kps,
114 HardwareAuthToken(), &beginResult);
115 EXPECT_TRUE(status.isOk()) << status.getDescription();
116 if (status.isOk()) {
117 return beginResult.operation;
118 }
119 return {};
120 }
121
122 static const int NUM_SLOTS = 2;
123
TEST(SlotTest,TestSlots)124 TEST(SlotTest, TestSlots) {
125 static std::shared_ptr<KeyMintDevice> device =
126 KeyMintDevice::getWrappedKeymasterDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
127 ASSERT_NE(device.get(), nullptr);
128
129 device->setNumFreeSlots(NUM_SLOTS);
130
131 // A begin() that returns a failure should not use a slot.
132 auto result = begin(device, false);
133 ASSERT_TRUE(std::holds_alternative<ScopedAStatus>(result));
134
135 // Software emulated operations must not leak virtual slots.
136 ASSERT_TRUE(!!generateAndBeginECDHKeyOperation(device));
137
138 // Software emulated operations must not impact virtual slots accounting.
139 // As opposed to the previous call, the software operation is kept alive.
140 auto software_op = generateAndBeginECDHKeyOperation(device);
141 ASSERT_TRUE(!!software_op);
142
143 // Fill up all the slots.
144 std::vector<std::shared_ptr<IKeyMintOperation>> operations;
145 for (int i = 0; i < NUM_SLOTS; i++) {
146 auto result = begin(device, true);
147 ASSERT_TRUE(std::holds_alternative<BeginResult>(result));
148 operations.push_back(std::get<BeginResult>(result).operation);
149 }
150
151 // We should not be able to create a new operation.
152 result = begin(device, true);
153 ASSERT_TRUE(std::holds_alternative<ScopedAStatus>(result));
154 ASSERT_EQ(std::get<ScopedAStatus>(result).getServiceSpecificError(),
155 static_cast<int32_t>(ErrorCode::TOO_MANY_OPERATIONS));
156
157 // At this point all slots are in use. We should still be able to generate keys which
158 // require an operation slot during generation.
159 ASSERT_TRUE(generateECSingingKey(device));
160
161 // Software emulated operations should work despite having all virtual operation slots
162 // depleted.
163 ASSERT_TRUE(generateAndBeginECDHKeyOperation(device));
164
165 // TODO: I'm not sure how to generate a failing update call to test that.
166
167 // Calling finish should free up a slot.
168 auto last = operations.back();
169 operations.pop_back();
170 std::vector<uint8_t> byteVec;
171 auto status = last->finish(std::nullopt /* input */, std::nullopt /* signature */,
172 std::nullopt /* authToken */, std::nullopt /* timestampToken */,
173 std::nullopt /* confirmationToken */, &byteVec);
174 ASSERT_TRUE(status.isOk());
175 result = begin(device, true);
176 ASSERT_TRUE(std::holds_alternative<BeginResult>(result));
177 operations.push_back(std::get<BeginResult>(result).operation);
178
179 // Calling finish and abort on an already-finished operation should not free up another slot.
180 status = last->finish(std::nullopt /* input */, std::nullopt /* signature */,
181 std::nullopt /* authToken */, std::nullopt /* timestampToken */,
182 std::nullopt /* confirmationToken */, &byteVec);
183 ASSERT_TRUE(!status.isOk());
184 status = last->abort();
185 ASSERT_TRUE(!status.isOk());
186 result = begin(device, true);
187 ASSERT_TRUE(std::holds_alternative<ScopedAStatus>(result));
188 ASSERT_EQ(std::get<ScopedAStatus>(result).getServiceSpecificError(),
189 static_cast<int32_t>(ErrorCode::TOO_MANY_OPERATIONS));
190
191 // Calling abort should free up a slot.
192 last = operations.back();
193 operations.pop_back();
194 status = last->abort();
195 ASSERT_TRUE(status.isOk());
196 result = begin(device, true);
197 ASSERT_TRUE(std::holds_alternative<BeginResult>(result));
198 operations.push_back(std::get<BeginResult>(result).operation);
199
200 // Calling finish and abort on an already-aborted operation should not free up another slot.
201 status = last->finish(std::nullopt /* input */, std::nullopt /* signature */,
202 std::nullopt /* authToken */, std::nullopt /* timestampToken */,
203 std::nullopt /* confirmationToken */, &byteVec);
204 ASSERT_TRUE(!status.isOk());
205 status = last->abort();
206 ASSERT_TRUE(!status.isOk());
207 result = begin(device, true);
208 ASSERT_TRUE(std::holds_alternative<ScopedAStatus>(result));
209 ASSERT_EQ(std::get<ScopedAStatus>(result).getServiceSpecificError(),
210 static_cast<int32_t>(ErrorCode::TOO_MANY_OPERATIONS));
211
212 // Generating a certificate with signWith uses a slot but falls back to not using one.
213 auto kps = std::vector<KeyParameter>({
214 KMV1::makeKeyParameter(KMV1::TAG_ALGORITHM, Algorithm::RSA),
215 KMV1::makeKeyParameter(KMV1::TAG_KEY_SIZE, 2048),
216 KMV1::makeKeyParameter(KMV1::TAG_RSA_PUBLIC_EXPONENT, 65537),
217 KMV1::makeKeyParameter(KMV1::TAG_DIGEST, Digest::SHA_2_256),
218 KMV1::makeKeyParameter(KMV1::TAG_PURPOSE, KeyPurpose::SIGN),
219 KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_BEFORE, 0),
220 KMV1::makeKeyParameter(KMV1::TAG_CERTIFICATE_NOT_AFTER, 253402300799000),
221 KMV1::makeKeyParameter(KMV1::TAG_NO_AUTH_REQUIRED, true),
222 });
223 KeyCreationResult creationResult;
224 status = device->generateKey(kps, std::nullopt /* attest_key */, &creationResult);
225 ASSERT_TRUE(status.isOk());
226 // But generating a certificate with signCert does not use a slot.
227 kps.pop_back();
228 status = device->generateKey(kps, std::nullopt /* attest_key */, &creationResult);
229 ASSERT_TRUE(status.isOk());
230
231 // Destructing operations should free up their slots.
232 operations.clear();
233 result = begin(device, true);
234 ASSERT_TRUE(std::holds_alternative<BeginResult>(result));
235 }
236