xref: /aosp_15_r20/system/security/ondevice-signing/KeystoreHmacKey.cpp (revision e1997b9af69e3155ead6e072d106a0077849ffba)
1 /*
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 #include <string>
18 
19 #include <android-base/file.h>
20 #include <android-base/logging.h>
21 #include <binder/IServiceManager.h>
22 
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 
27 #include "CertUtils.h"
28 #include "KeyConstants.h"
29 #include "KeystoreHmacKey.h"
30 
31 using android::sp;
32 using android::String16;
33 
34 using android::hardware::security::keymint::Algorithm;
35 using android::hardware::security::keymint::Digest;
36 using android::hardware::security::keymint::KeyParameter;
37 using android::hardware::security::keymint::KeyParameterValue;
38 using android::hardware::security::keymint::KeyPurpose;
39 using android::hardware::security::keymint::Tag;
40 
41 using android::system::keystore2::CreateOperationResponse;
42 using android::system::keystore2::Domain;
43 using android::system::keystore2::KeyDescriptor;
44 using android::system::keystore2::KeyEntryResponse;
45 using android::system::keystore2::KeyMetadata;
46 
47 using android::base::Error;
48 using android::base::Result;
49 
50 using android::base::unique_fd;
51 
getHmacKeyDescriptor(const android::String16 & keyAlias,int64_t keyNspace)52 static KeyDescriptor getHmacKeyDescriptor(const android::String16& keyAlias, int64_t keyNspace) {
53     // AIDL parcelable objects don't have constructor
54     static KeyDescriptor descriptor;
55     static std::once_flag flag;
56     std::call_once(flag, [&]() {
57         descriptor.domain = Domain::SELINUX;
58         descriptor.alias = keyAlias + android::String16("-hmac");
59         descriptor.nspace = keyNspace;
60     });
61 
62     return descriptor;
63 }
64 
createKey()65 Result<void> KeystoreHmacKey::createKey() {
66     std::vector<KeyParameter> params;
67 
68     KeyParameter algo;
69     algo.tag = Tag::ALGORITHM;
70     algo.value = KeyParameterValue::make<KeyParameterValue::algorithm>(Algorithm::HMAC);
71     params.push_back(algo);
72 
73     KeyParameter key_size;
74     key_size.tag = Tag::KEY_SIZE;
75     key_size.value = KeyParameterValue::make<KeyParameterValue::integer>(kHmacKeySize);
76     params.push_back(key_size);
77 
78     KeyParameter min_mac_length;
79     min_mac_length.tag = Tag::MIN_MAC_LENGTH;
80     min_mac_length.value = KeyParameterValue::make<KeyParameterValue::integer>(256);
81     params.push_back(min_mac_length);
82 
83     KeyParameter digest;
84     digest.tag = Tag::DIGEST;
85     digest.value = KeyParameterValue::make<KeyParameterValue::digest>(Digest::SHA_2_256);
86     params.push_back(digest);
87 
88     KeyParameter purposeSign;
89     purposeSign.tag = Tag::PURPOSE;
90     purposeSign.value = KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::SIGN);
91     params.push_back(purposeSign);
92 
93     KeyParameter purposeVerify;
94     purposeVerify.tag = Tag::PURPOSE;
95     purposeVerify.value =
96         KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::VERIFY);
97     params.push_back(purposeVerify);
98 
99     KeyParameter auth;
100     auth.tag = Tag::NO_AUTH_REQUIRED;
101     auth.value = KeyParameterValue::make<KeyParameterValue::boolValue>(true);
102     params.push_back(auth);
103 
104     KeyParameter boot_level;
105     boot_level.tag = Tag::MAX_BOOT_LEVEL;
106     boot_level.value = KeyParameterValue::make<KeyParameterValue::integer>(mKeyBootLevel);
107     params.push_back(boot_level);
108 
109     KeyMetadata metadata;
110     auto status = mSecurityLevel->generateKey(mDescriptor, {}, params, 0, {}, &metadata);
111     if (!status.isOk()) {
112         return Error() << "Failed to create new HMAC key: " << status;
113     }
114 
115     return {};
116 }
117 
initialize(sp<IKeystoreService> service,sp<IKeystoreSecurityLevel> securityLevel)118 Result<void> KeystoreHmacKey::initialize(sp<IKeystoreService> service,
119                                          sp<IKeystoreSecurityLevel> securityLevel) {
120     mService = std::move(service);
121     mSecurityLevel = std::move(securityLevel);
122 
123     // See if we can fetch an existing key
124     KeyEntryResponse keyEntryResponse;
125     LOG(INFO) << "Trying to retrieve existing HMAC key...";
126     auto status = mService->getKeyEntry(mDescriptor, &keyEntryResponse);
127     bool keyValid = false;
128 
129     if (status.isOk()) {
130         // Make sure this is an early boot key
131         for (const auto& auth : keyEntryResponse.metadata.authorizations) {
132             if (auth.keyParameter.tag == Tag::MAX_BOOT_LEVEL) {
133                 if (auth.keyParameter.value.get<KeyParameterValue::integer>() == mKeyBootLevel) {
134                     keyValid = true;
135                     break;
136                 }
137             }
138         }
139         if (!keyValid) {
140             LOG(WARNING) << "Found invalid HMAC key without MAX_BOOT_LEVEL tag";
141         }
142     }
143 
144     if (!keyValid) {
145         LOG(INFO) << "Existing HMAC key not found or invalid, creating new key";
146         return createKey();
147     } else {
148         return {};
149     }
150 }
151 
KeystoreHmacKey(const android::String16 & keyAlias,int64_t keyNspace,int keyBootLevel)152 KeystoreHmacKey::KeystoreHmacKey(const android::String16& keyAlias, int64_t keyNspace,
153                                  int keyBootLevel)
154     : mDescriptor(getHmacKeyDescriptor(keyAlias, keyNspace)), mKeyBootLevel(keyBootLevel) {}
155 
getVerifyOpParameters()156 static std::vector<KeyParameter> getVerifyOpParameters() {
157     std::vector<KeyParameter> opParameters;
158 
159     KeyParameter algo;
160     algo.tag = Tag::ALGORITHM;
161     algo.value = KeyParameterValue::make<KeyParameterValue::algorithm>(Algorithm::HMAC);
162     opParameters.push_back(algo);
163 
164     KeyParameter digest;
165     digest.tag = Tag::DIGEST;
166     digest.value = KeyParameterValue::make<KeyParameterValue::digest>(Digest::SHA_2_256);
167     opParameters.push_back(digest);
168 
169     KeyParameter purpose;
170     purpose.tag = Tag::PURPOSE;
171     purpose.value = KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::VERIFY);
172     opParameters.push_back(purpose);
173 
174     return opParameters;
175 }
176 
getSignOpParameters()177 static std::vector<KeyParameter> getSignOpParameters() {
178     std::vector<KeyParameter> opParameters;
179 
180     KeyParameter algo;
181     algo.tag = Tag::ALGORITHM;
182     algo.value = KeyParameterValue::make<KeyParameterValue::algorithm>(Algorithm::HMAC);
183     opParameters.push_back(algo);
184 
185     KeyParameter mac_length;
186     mac_length.tag = Tag::MAC_LENGTH;
187     mac_length.value = KeyParameterValue::make<KeyParameterValue::integer>(256);
188     opParameters.push_back(mac_length);
189 
190     KeyParameter digest;
191     digest.tag = Tag::DIGEST;
192     digest.value = KeyParameterValue::make<KeyParameterValue::digest>(Digest::SHA_2_256);
193     opParameters.push_back(digest);
194 
195     KeyParameter purpose;
196     purpose.tag = Tag::PURPOSE;
197     purpose.value = KeyParameterValue::make<KeyParameterValue::keyPurpose>(KeyPurpose::SIGN);
198     opParameters.push_back(purpose);
199 
200     return opParameters;
201 }
202 
sign(const std::string & message) const203 Result<std::string> KeystoreHmacKey::sign(const std::string& message) const {
204     CreateOperationResponse opResponse;
205     static auto params = getSignOpParameters();
206 
207     auto status = mSecurityLevel->createOperation(mDescriptor, params, false, &opResponse);
208     if (!status.isOk()) {
209         return Error() << "Failed to create keystore signing operation: " << status;
210     }
211     auto operation = opResponse.iOperation;
212 
213     std::optional<std::vector<uint8_t>> out;
214     status = operation->update({message.begin(), message.end()}, &out);
215     if (!status.isOk()) {
216         return Error() << "Failed to call keystore update operation.";
217     }
218 
219     std::optional<std::vector<uint8_t>> signature;
220     status = operation->finish({}, {}, &signature);
221     if (!status.isOk()) {
222         return Error() << "Failed to call keystore finish operation.";
223     }
224 
225     if (!signature.has_value()) {
226         return Error() << "Didn't receive a signature from keystore finish operation.";
227     }
228 
229     return std::string{signature.value().begin(), signature.value().end()};
230 }
231 
verify(const std::string & message,const std::string & signature) const232 Result<void> KeystoreHmacKey::verify(const std::string& message,
233                                      const std::string& signature) const {
234     CreateOperationResponse opResponse;
235     static auto params = getVerifyOpParameters();
236 
237     auto status = mSecurityLevel->createOperation(mDescriptor, params, false, &opResponse);
238     if (!status.isOk()) {
239         return Error() << "Failed to create keystore verification operation: " << status;
240     }
241     auto operation = opResponse.iOperation;
242 
243     std::optional<std::vector<uint8_t>> out;
244     status = operation->update({message.begin(), message.end()}, &out);
245     if (!status.isOk()) {
246         return Error() << "Failed to call keystore update operation.";
247     }
248 
249     std::optional<std::vector<uint8_t>> out_signature;
250     std::vector<uint8_t> in_signature{signature.begin(), signature.end()};
251     status = operation->finish({}, in_signature, &out_signature);
252     if (!status.isOk()) {
253         return Error() << "Failed to call keystore finish operation.";
254     }
255 
256     return {};
257 }
258 
deleteKey() const259 Result<void> KeystoreHmacKey::deleteKey() const {
260     auto status = mService->deleteKey(mDescriptor);
261     if (!status.isOk()) {
262         return Error() << "Failed to delete HMAC key: " << status;
263     }
264 
265     return {};
266 }
267