• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #define LOG_TAG "keystore_client"
16 
17 #include "keystore/keystore_client_impl.h"
18 
19 #include <string>
20 #include <vector>
21 
22 #include <binder/IBinder.h>
23 #include <binder/IInterface.h>
24 #include <binder/IServiceManager.h>
25 #include <keystore/IKeystoreService.h>
26 #include <keystore/keystore.h>
27 #include <log/log.h>
28 #include <utils/String16.h>
29 #include <utils/String8.h>
30 
31 #include "keystore_client.pb.h"
32 #include <keystore/authorization_set.h>
33 #include <keystore/keystore_hidl_support.h>
34 
35 using android::ExportResult;
36 using keystore::KeyCharacteristics;
37 using android::OperationResult;
38 using android::String16;
39 using keystore::AuthorizationSet;
40 using keystore::AuthorizationSetBuilder;
41 
42 namespace {
43 
44 // Use the UID of the current process.
45 const int kDefaultUID = -1;
46 const char kEncryptSuffix[] = "_ENC";
47 const char kAuthenticateSuffix[] = "_AUTH";
48 constexpr uint32_t kAESKeySize = 256;      // bits
49 constexpr uint32_t kHMACKeySize = 256;     // bits
50 constexpr uint32_t kHMACOutputSize = 256;  // bits
51 
52 }  // namespace
53 
54 namespace keystore {
55 
KeystoreClientImpl()56 KeystoreClientImpl::KeystoreClientImpl() {
57     service_manager_ = android::defaultServiceManager();
58     keystore_binder_ = service_manager_->getService(String16("android.security.keystore"));
59     keystore_ = android::interface_cast<android::IKeystoreService>(keystore_binder_);
60 }
61 
encryptWithAuthentication(const std::string & key_name,const std::string & data,std::string * encrypted_data)62 bool KeystoreClientImpl::encryptWithAuthentication(const std::string& key_name,
63                                                    const std::string& data,
64                                                    std::string* encrypted_data) {
65     // The encryption algorithm is AES-256-CBC with PKCS #7 padding and a random
66     // IV. The authentication algorithm is HMAC-SHA256 and is computed over the
67     // cipher-text (i.e. Encrypt-then-MAC approach). This was chosen over AES-GCM
68     // because hardware support for GCM is not mandatory for all Brillo devices.
69     std::string encryption_key_name = key_name + kEncryptSuffix;
70     if (!createOrVerifyEncryptionKey(encryption_key_name)) {
71         return false;
72     }
73     std::string authentication_key_name = key_name + kAuthenticateSuffix;
74     if (!createOrVerifyAuthenticationKey(authentication_key_name)) {
75         return false;
76     }
77     AuthorizationSetBuilder encrypt_params;
78     encrypt_params.Padding(PaddingMode::PKCS7);
79     encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
80     AuthorizationSet output_params;
81     std::string raw_encrypted_data;
82     if (!oneShotOperation(KeyPurpose::ENCRYPT, encryption_key_name, encrypt_params, data,
83                           std::string(), /* signature_to_verify */
84                           &output_params, &raw_encrypted_data)) {
85         ALOGE("Encrypt: AES operation failed.");
86         return false;
87     }
88     auto init_vector_blob = output_params.GetTagValue(TAG_NONCE);
89     if (!init_vector_blob.isOk()){
90         ALOGE("Encrypt: Missing initialization vector.");
91         return false;
92     }
93     std::string init_vector = hidlVec2String(init_vector_blob.value());
94 
95     AuthorizationSetBuilder authenticate_params;
96     authenticate_params.Digest(Digest::SHA_2_256);
97     authenticate_params.Authorization(TAG_MAC_LENGTH, kHMACOutputSize);
98     std::string raw_authentication_data;
99     if (!oneShotOperation(KeyPurpose::SIGN, authentication_key_name, authenticate_params,
100                           init_vector + raw_encrypted_data, std::string(), /* signature_to_verify */
101                           &output_params, &raw_authentication_data)) {
102         ALOGE("Encrypt: HMAC operation failed.");
103         return false;
104     }
105     EncryptedData protobuf;
106     protobuf.set_init_vector(init_vector);
107     protobuf.set_authentication_data(raw_authentication_data);
108     protobuf.set_encrypted_data(raw_encrypted_data);
109     if (!protobuf.SerializeToString(encrypted_data)) {
110         ALOGE("Encrypt: Failed to serialize EncryptedData protobuf.");
111         return false;
112     }
113     return true;
114 }
115 
decryptWithAuthentication(const std::string & key_name,const std::string & encrypted_data,std::string * data)116 bool KeystoreClientImpl::decryptWithAuthentication(const std::string& key_name,
117                                                    const std::string& encrypted_data,
118                                                    std::string* data) {
119     EncryptedData protobuf;
120     if (!protobuf.ParseFromString(encrypted_data)) {
121         ALOGE("Decrypt: Failed to parse EncryptedData protobuf.");
122     }
123     // Verify authentication before attempting decryption.
124     std::string authentication_key_name = key_name + kAuthenticateSuffix;
125     AuthorizationSetBuilder authenticate_params;
126     authenticate_params.Digest(Digest::SHA_2_256);
127     AuthorizationSet output_params;
128     std::string output_data;
129     if (!oneShotOperation(KeyPurpose::VERIFY, authentication_key_name, authenticate_params,
130                           protobuf.init_vector() + protobuf.encrypted_data(),
131                           protobuf.authentication_data(), &output_params, &output_data)) {
132         ALOGE("Decrypt: HMAC operation failed.");
133         return false;
134     }
135     std::string encryption_key_name = key_name + kEncryptSuffix;
136     AuthorizationSetBuilder encrypt_params;
137     encrypt_params.Padding(PaddingMode::PKCS7);
138     encrypt_params.Authorization(TAG_BLOCK_MODE, BlockMode::CBC);
139     encrypt_params.Authorization(TAG_NONCE, protobuf.init_vector().data(),
140                                  protobuf.init_vector().size());
141     if (!oneShotOperation(KeyPurpose::DECRYPT, encryption_key_name, encrypt_params,
142                           protobuf.encrypted_data(), std::string(), /* signature_to_verify */
143                           &output_params, data)) {
144         ALOGE("Decrypt: AES operation failed.");
145         return false;
146     }
147     return true;
148 }
149 
oneShotOperation(KeyPurpose purpose,const std::string & key_name,const AuthorizationSet & input_parameters,const std::string & input_data,const std::string & signature_to_verify,AuthorizationSet * output_parameters,std::string * output_data)150 bool KeystoreClientImpl::oneShotOperation(KeyPurpose purpose, const std::string& key_name,
151                                           const AuthorizationSet& input_parameters,
152                                           const std::string& input_data,
153                                           const std::string& signature_to_verify,
154                                           AuthorizationSet* output_parameters,
155                                           std::string* output_data) {
156     uint64_t handle;
157     auto result =
158         beginOperation(purpose, key_name, input_parameters, output_parameters, &handle);
159     if (!result.isOk()) {
160         ALOGE("BeginOperation failed: %d", int32_t(result));
161         return false;
162     }
163     AuthorizationSet empty_params;
164     size_t num_input_bytes_consumed;
165     AuthorizationSet ignored_params;
166     result = updateOperation(handle, empty_params, input_data, &num_input_bytes_consumed,
167                              &ignored_params, output_data);
168     if (!result.isOk()) {
169         ALOGE("UpdateOperation failed: %d", int32_t(result));
170         return false;
171     }
172     result =
173         finishOperation(handle, empty_params, signature_to_verify, &ignored_params, output_data);
174     if (!result.isOk()) {
175         ALOGE("FinishOperation failed: %d", int32_t(result));
176         return false;
177     }
178     return true;
179 }
180 
addRandomNumberGeneratorEntropy(const std::string & entropy)181 KeyStoreNativeReturnCode KeystoreClientImpl::addRandomNumberGeneratorEntropy(const std::string& entropy) {
182     return keystore_->addRngEntropy(blob2hidlVec(entropy));
183 }
184 
generateKey(const std::string & key_name,const AuthorizationSet & key_parameters,AuthorizationSet * hardware_enforced_characteristics,AuthorizationSet * software_enforced_characteristics)185 KeyStoreNativeReturnCode KeystoreClientImpl::generateKey(const std::string& key_name,
186                                         const AuthorizationSet& key_parameters,
187                                         AuthorizationSet* hardware_enforced_characteristics,
188                                         AuthorizationSet* software_enforced_characteristics) {
189     String16 key_name16(key_name.data(), key_name.size());
190     KeyCharacteristics characteristics;
191     auto result =
192         keystore_->generateKey(key_name16, key_parameters.hidl_data(), hidl_vec<uint8_t>(),
193                                kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
194 
195     /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
196      * There are no references to Parcel memory after that, and ownership of the newly acquired
197      * memory is with the AuthorizationSet objects. */
198     *hardware_enforced_characteristics = characteristics.teeEnforced;
199     *software_enforced_characteristics = characteristics.softwareEnforced;
200     return result;
201 }
202 
203 KeyStoreNativeReturnCode
getKeyCharacteristics(const std::string & key_name,AuthorizationSet * hardware_enforced_characteristics,AuthorizationSet * software_enforced_characteristics)204 KeystoreClientImpl::getKeyCharacteristics(const std::string& key_name,
205                                           AuthorizationSet* hardware_enforced_characteristics,
206                                           AuthorizationSet* software_enforced_characteristics) {
207     String16 key_name16(key_name.data(), key_name.size());
208     KeyCharacteristics characteristics;
209     auto result = keystore_->getKeyCharacteristics(key_name16, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
210                                                       kDefaultUID, &characteristics);
211 
212     /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
213      * There are no references to Parcel memory after that, and ownership of the newly acquired
214      * memory is with the AuthorizationSet objects. */
215     *hardware_enforced_characteristics = characteristics.teeEnforced;
216     *software_enforced_characteristics = characteristics.softwareEnforced;
217     return result;
218 }
219 
importKey(const std::string & key_name,const AuthorizationSet & key_parameters,KeyFormat key_format,const std::string & key_data,AuthorizationSet * hardware_enforced_characteristics,AuthorizationSet * software_enforced_characteristics)220 KeyStoreNativeReturnCode KeystoreClientImpl::importKey(const std::string& key_name,
221                                       const AuthorizationSet& key_parameters,
222                                       KeyFormat key_format,
223                                       const std::string& key_data,
224                                       AuthorizationSet* hardware_enforced_characteristics,
225                                       AuthorizationSet* software_enforced_characteristics) {
226     String16 key_name16(key_name.data(), key_name.size());
227     auto hidlKeyData = blob2hidlVec(key_data);
228     KeyCharacteristics characteristics;
229     auto result = keystore_->importKey(key_name16, key_parameters.hidl_data(), key_format,
230             hidlKeyData, kDefaultUID, KEYSTORE_FLAG_NONE, &characteristics);
231 
232     /* assignment (hidl_vec<KeyParameter> -> AuthorizationSet) makes a deep copy.
233      * There are no references to Parcel memory after that, and ownership of the newly acquired
234      * memory is with the AuthorizationSet objects. */
235     *hardware_enforced_characteristics = characteristics.teeEnforced;
236     *software_enforced_characteristics = characteristics.softwareEnforced;
237     return result;
238 }
239 
exportKey(KeyFormat export_format,const std::string & key_name,std::string * export_data)240 KeyStoreNativeReturnCode KeystoreClientImpl::exportKey(KeyFormat export_format,
241                                       const std::string& key_name, std::string* export_data) {
242     String16 key_name16(key_name.data(), key_name.size());
243     ExportResult export_result;
244     keystore_->exportKey(key_name16, export_format, hidl_vec<uint8_t>(), hidl_vec<uint8_t>(),
245                          kDefaultUID, &export_result);
246     *export_data = hidlVec2String(export_result.exportData);
247     return export_result.resultCode;
248 }
249 
deleteKey(const std::string & key_name)250 KeyStoreNativeReturnCode KeystoreClientImpl::deleteKey(const std::string& key_name) {
251     String16 key_name16(key_name.data(), key_name.size());
252     return keystore_->del(key_name16, kDefaultUID);
253 }
254 
deleteAllKeys()255 KeyStoreNativeReturnCode KeystoreClientImpl::deleteAllKeys() {
256     return keystore_->clear_uid(kDefaultUID);
257 }
258 
beginOperation(KeyPurpose purpose,const std::string & key_name,const AuthorizationSet & input_parameters,AuthorizationSet * output_parameters,uint64_t * handle)259 KeyStoreNativeReturnCode KeystoreClientImpl::beginOperation(KeyPurpose purpose, const std::string& key_name,
260                                            const AuthorizationSet& input_parameters,
261                                            AuthorizationSet* output_parameters,
262                                            uint64_t* handle) {
263     android::sp<android::IBinder> token(new android::BBinder);
264     String16 key_name16(key_name.data(), key_name.size());
265     OperationResult result;
266     keystore_->begin(token, key_name16, purpose, true /*pruneable*/, input_parameters.hidl_data(),
267                      hidl_vec<uint8_t>(), kDefaultUID, &result);
268     if (result.resultCode.isOk()) {
269         *handle = getNextVirtualHandle();
270         active_operations_[*handle] = result.token;
271         if (result.outParams.size()) {
272             *output_parameters = result.outParams;
273         }
274     }
275     return result.resultCode;
276 }
277 
updateOperation(uint64_t handle,const AuthorizationSet & input_parameters,const std::string & input_data,size_t * num_input_bytes_consumed,AuthorizationSet * output_parameters,std::string * output_data)278 KeyStoreNativeReturnCode KeystoreClientImpl::updateOperation(uint64_t handle,
279                                             const AuthorizationSet& input_parameters,
280                                             const std::string& input_data,
281                                             size_t* num_input_bytes_consumed,
282                                             AuthorizationSet* output_parameters,
283                                             std::string* output_data) {
284     if (active_operations_.count(handle) == 0) {
285         return ErrorCode::INVALID_OPERATION_HANDLE;
286     }
287     OperationResult result;
288     auto hidlInputData = blob2hidlVec(input_data);
289     keystore_->update(active_operations_[handle], input_parameters.hidl_data(), hidlInputData,
290             &result);
291 
292     if (result.resultCode.isOk()) {
293         *num_input_bytes_consumed = result.inputConsumed;
294         if (result.outParams.size()) {
295             *output_parameters = result.outParams;
296         }
297         // TODO verify that append should not be assign
298         output_data->append(hidlVec2String(result.data));
299     }
300     return result.resultCode;
301 }
302 
finishOperation(uint64_t handle,const AuthorizationSet & input_parameters,const std::string & signature_to_verify,AuthorizationSet * output_parameters,std::string * output_data)303 KeyStoreNativeReturnCode KeystoreClientImpl::finishOperation(uint64_t handle,
304                                             const AuthorizationSet& input_parameters,
305                                             const std::string& signature_to_verify,
306                                             AuthorizationSet* output_parameters,
307                                             std::string* output_data) {
308     if (active_operations_.count(handle) == 0) {
309         return ErrorCode::INVALID_OPERATION_HANDLE;
310     }
311     OperationResult result;
312     auto hidlSignature = blob2hidlVec(signature_to_verify);
313     keystore_->finish(active_operations_[handle], input_parameters.hidl_data(),
314                       hidlSignature,
315                       hidl_vec<uint8_t>(), &result);
316 
317     if (result.resultCode.isOk()) {
318         if (result.outParams.size()) {
319             *output_parameters = result.outParams;
320         }
321         // TODO verify that append should not be assign
322         output_data->append(hidlVec2String(result.data));
323         active_operations_.erase(handle);
324     }
325     return result.resultCode;
326 }
327 
abortOperation(uint64_t handle)328 KeyStoreNativeReturnCode KeystoreClientImpl::abortOperation(uint64_t handle) {
329     if (active_operations_.count(handle) == 0) {
330         return ErrorCode::INVALID_OPERATION_HANDLE;
331     }
332     auto error_code = keystore_->abort(active_operations_[handle]);
333     if (error_code.isOk()) {
334         active_operations_.erase(handle);
335     }
336     return error_code;
337 }
338 
doesKeyExist(const std::string & key_name)339 bool KeystoreClientImpl::doesKeyExist(const std::string& key_name) {
340     String16 key_name16(key_name.data(), key_name.size());
341     auto error_code = keystore_->exist(key_name16, kDefaultUID);
342     return error_code.isOk();
343 }
344 
listKeys(const std::string & prefix,std::vector<std::string> * key_name_list)345 bool KeystoreClientImpl::listKeys(const std::string& prefix,
346                                   std::vector<std::string>* key_name_list) {
347     String16 prefix16(prefix.data(), prefix.size());
348     android::Vector<String16> matches;
349     auto error_code = keystore_->list(prefix16, kDefaultUID, &matches);
350     if (error_code.isOk()) {
351         for (const auto& match : matches) {
352             android::String8 key_name(match);
353             key_name_list->push_back(prefix + std::string(key_name.string(), key_name.size()));
354         }
355         return true;
356     }
357     return false;
358 }
359 
getNextVirtualHandle()360 uint64_t KeystoreClientImpl::getNextVirtualHandle() {
361     return next_virtual_handle_++;
362 }
363 
createOrVerifyEncryptionKey(const std::string & key_name)364 bool KeystoreClientImpl::createOrVerifyEncryptionKey(const std::string& key_name) {
365     bool key_exists = doesKeyExist(key_name);
366     if (key_exists) {
367         bool verified = false;
368         if (!verifyEncryptionKeyAttributes(key_name, &verified)) {
369             return false;
370         }
371         if (!verified) {
372             auto result = deleteKey(key_name);
373             if (!result.isOk()) {
374                 ALOGE("Failed to delete invalid encryption key: %d", int32_t(result));
375                 return false;
376             }
377             key_exists = false;
378         }
379     }
380     if (!key_exists) {
381         AuthorizationSetBuilder key_parameters;
382         key_parameters.AesEncryptionKey(kAESKeySize)
383             .Padding(PaddingMode::PKCS7)
384             .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
385             .Authorization(TAG_NO_AUTH_REQUIRED);
386         AuthorizationSet hardware_enforced_characteristics;
387         AuthorizationSet software_enforced_characteristics;
388         auto result =
389             generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
390                         &software_enforced_characteristics);
391         if (!result.isOk()) {
392             ALOGE("Failed to generate encryption key: %d", int32_t(result));
393             return false;
394         }
395         if (hardware_enforced_characteristics.size() == 0) {
396             ALOGW("WARNING: Encryption key is not hardware-backed.");
397         }
398     }
399     return true;
400 }
401 
createOrVerifyAuthenticationKey(const std::string & key_name)402 bool KeystoreClientImpl::createOrVerifyAuthenticationKey(const std::string& key_name) {
403     bool key_exists = doesKeyExist(key_name);
404     if (key_exists) {
405         bool verified = false;
406         if (!verifyAuthenticationKeyAttributes(key_name, &verified)) {
407             return false;
408         }
409         if (!verified) {
410             auto result = deleteKey(key_name);
411             if (!result.isOk()) {
412                 ALOGE("Failed to delete invalid authentication key: %d", int32_t(result));
413                 return false;
414             }
415             key_exists = false;
416         }
417     }
418     if (!key_exists) {
419         AuthorizationSetBuilder key_parameters;
420         key_parameters.HmacKey(kHMACKeySize)
421             .Digest(Digest::SHA_2_256)
422             .Authorization(TAG_MIN_MAC_LENGTH, kHMACOutputSize)
423             .Authorization(TAG_NO_AUTH_REQUIRED);
424         AuthorizationSet hardware_enforced_characteristics;
425         AuthorizationSet software_enforced_characteristics;
426         auto result =
427             generateKey(key_name, key_parameters, &hardware_enforced_characteristics,
428                         &software_enforced_characteristics);
429         if (!result.isOk()) {
430             ALOGE("Failed to generate authentication key: %d", int32_t(result));
431             return false;
432         }
433         if (hardware_enforced_characteristics.size() == 0) {
434             ALOGW("WARNING: Authentication key is not hardware-backed.");
435         }
436     }
437     return true;
438 }
439 
verifyEncryptionKeyAttributes(const std::string & key_name,bool * verified)440 bool KeystoreClientImpl::verifyEncryptionKeyAttributes(const std::string& key_name,
441                                                        bool* verified) {
442     AuthorizationSet hardware_enforced_characteristics;
443     AuthorizationSet software_enforced_characteristics;
444     auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
445                                            &software_enforced_characteristics);
446     if (!result.isOk()) {
447         ALOGE("Failed to query encryption key: %d", int32_t(result));
448         return false;
449     }
450     *verified = true;
451     auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
452             software_enforced_characteristics.GetTagValue(TAG_ALGORITHM));
453     if (!algorithm.isOk() || algorithm.value() != Algorithm::AES) {
454         ALOGW("Found encryption key with invalid algorithm.");
455         *verified = false;
456     }
457     auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE),
458             software_enforced_characteristics.GetTagValue(TAG_KEY_SIZE));
459     if (!key_size.isOk() || key_size.value() != kAESKeySize) {
460         ALOGW("Found encryption key with invalid size.");
461         *verified = false;
462     }
463     auto block_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE),
464             software_enforced_characteristics.GetTagValue(TAG_BLOCK_MODE));
465     if (!block_mode.isOk() || block_mode.value() != BlockMode::CBC) {
466         ALOGW("Found encryption key with invalid block mode.");
467         *verified = false;
468     }
469     auto padding_mode = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_PADDING),
470             software_enforced_characteristics.GetTagValue(TAG_PADDING));
471     if (!padding_mode.isOk() || padding_mode.value() != PaddingMode::PKCS7) {
472         ALOGW("Found encryption key with invalid padding mode.");
473         *verified = false;
474     }
475     if (hardware_enforced_characteristics.size() == 0) {
476         ALOGW("WARNING: Encryption key is not hardware-backed.");
477     }
478     return true;
479 }
480 
verifyAuthenticationKeyAttributes(const std::string & key_name,bool * verified)481 bool KeystoreClientImpl::verifyAuthenticationKeyAttributes(const std::string& key_name,
482                                                            bool* verified) {
483     AuthorizationSet hardware_enforced_characteristics;
484     AuthorizationSet software_enforced_characteristics;
485     auto result = getKeyCharacteristics(key_name, &hardware_enforced_characteristics,
486                                            &software_enforced_characteristics);
487     if (!result.isOk()) {
488         ALOGE("Failed to query authentication key: %d", int32_t(result));
489         return false;
490     }
491     *verified = true;
492     auto algorithm = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_ALGORITHM),
493             software_enforced_characteristics.GetTagValue(TAG_ALGORITHM));
494     if (!algorithm.isOk() || algorithm.value() != Algorithm::HMAC){
495         ALOGW("Found authentication key with invalid algorithm.");
496         *verified = false;
497     }
498     auto key_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_KEY_SIZE),
499             software_enforced_characteristics.GetTagValue(TAG_KEY_SIZE));
500     if (!key_size.isOk() || key_size.value() != kHMACKeySize) {
501         ALOGW("Found authentication key with invalid size.");
502         *verified = false;
503     }
504     auto mac_size = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH),
505             software_enforced_characteristics.GetTagValue(TAG_MIN_MAC_LENGTH));
506     if (!mac_size.isOk() || mac_size.value() != kHMACOutputSize) {
507         ALOGW("Found authentication key with invalid minimum mac size.");
508         *verified = false;
509     }
510     auto digest = NullOrOr(hardware_enforced_characteristics.GetTagValue(TAG_DIGEST),
511             software_enforced_characteristics.GetTagValue(TAG_DIGEST));
512     if (!digest.isOk() || digest.value() != Digest::SHA_2_256) {
513         ALOGW("Found authentication key with invalid digest list.");
514         *verified = false;
515     }
516     if (hardware_enforced_characteristics.size() == 0) {
517         ALOGW("WARNING: Authentication key is not hardware-backed.");
518     }
519     return true;
520 }
521 
522 }  // namespace keystore
523