You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
3.1 KiB
94 lines
3.1 KiB
/* |
|
* Copyright 2014 The Android Open Source Project |
|
* |
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
* you may not use this file except in compliance with the License. |
|
* You may obtain a copy of the License at |
|
* |
|
* http://www.apache.org/licenses/LICENSE-2.0 |
|
* |
|
* Unless required by applicable law or agreed to in writing, software |
|
* distributed under the License is distributed on an "AS IS" BASIS, |
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
* See the License for the specific language governing permissions and |
|
* limitations under the License. |
|
*/ |
|
|
|
#include "aes_key.h" |
|
|
|
#include <assert.h> |
|
|
|
#include <keymaster/new> |
|
|
|
#include <openssl/err.h> |
|
#include <openssl/rand.h> |
|
|
|
#include "aes_operation.h" |
|
|
|
namespace keymaster { |
|
|
|
AesEncryptionOperationFactory encrypt_factory; |
|
AesDecryptionOperationFactory decrypt_factory; |
|
|
|
OperationFactory* AesKeyFactory::GetOperationFactory(keymaster_purpose_t purpose) const { |
|
switch (purpose) { |
|
case KM_PURPOSE_ENCRYPT: |
|
return &encrypt_factory; |
|
case KM_PURPOSE_DECRYPT: |
|
return &decrypt_factory; |
|
default: |
|
return nullptr; |
|
} |
|
} |
|
|
|
keymaster_error_t AesKeyFactory::LoadKey(const KeymasterKeyBlob& key_material, |
|
const AuthorizationSet& /* additional_params */, |
|
const AuthorizationSet& hw_enforced, |
|
const AuthorizationSet& sw_enforced, |
|
UniquePtr<Key>* key) const { |
|
if (!key) |
|
return KM_ERROR_OUTPUT_PARAMETER_NULL; |
|
|
|
uint32_t min_mac_length = 0; |
|
if (hw_enforced.Contains(TAG_BLOCK_MODE, KM_MODE_GCM) || |
|
sw_enforced.Contains(TAG_BLOCK_MODE, KM_MODE_GCM)) { |
|
|
|
if (!hw_enforced.GetTagValue(TAG_MIN_MAC_LENGTH, &min_mac_length) && |
|
!sw_enforced.GetTagValue(TAG_MIN_MAC_LENGTH, &min_mac_length)) { |
|
|
|
LOG_E("AES-GCM key must have KM_TAG_MIN_MAC_LENGTH", 0); |
|
return KM_ERROR_INVALID_KEY_BLOB; |
|
} |
|
} |
|
|
|
keymaster_error_t error = KM_ERROR_OK; |
|
key->reset(new (std::nothrow) AesKey(key_material, hw_enforced, sw_enforced, &error)); |
|
if (!key->get()) |
|
error = KM_ERROR_MEMORY_ALLOCATION_FAILED; |
|
return error; |
|
} |
|
|
|
keymaster_error_t AesKeyFactory::validate_algorithm_specific_new_key_params( |
|
const AuthorizationSet& key_description) const { |
|
if (key_description.Contains(TAG_BLOCK_MODE, KM_MODE_GCM)) { |
|
uint32_t min_tag_length; |
|
if (!key_description.GetTagValue(TAG_MIN_MAC_LENGTH, &min_tag_length)) |
|
return KM_ERROR_MISSING_MIN_MAC_LENGTH; |
|
|
|
if (min_tag_length % 8 != 0) |
|
return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH; |
|
|
|
if (min_tag_length < kMinGcmTagLength || min_tag_length > kMaxGcmTagLength) |
|
return KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH; |
|
} else { |
|
// Not GCM |
|
if (key_description.find(TAG_MIN_MAC_LENGTH) != -1) { |
|
LOG_W("KM_TAG_MIN_MAC_LENGTH found for non AES-GCM key", 0); |
|
return KM_ERROR_INVALID_TAG; |
|
} |
|
} |
|
|
|
return KM_ERROR_OK; |
|
} |
|
|
|
} // namespace keymaster
|
|
|