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