1 /* 2 * Copyright 2014 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 "operation.h" 18 19 #include <keymaster/authorization_set.h> 20 #include <keymaster/keymaster_context.h> 21 22 #include "key.h" 23 24 namespace keymaster { 25 26 bool OperationFactory::supported(keymaster_padding_t padding) const { 27 size_t padding_count; 28 const keymaster_padding_t* supported_paddings = SupportedPaddingModes(&padding_count); 29 for (size_t i = 0; i < padding_count; ++i) 30 if (padding == supported_paddings[i]) 31 return true; 32 return false; 33 } 34 35 bool OperationFactory::supported(keymaster_block_mode_t block_mode) const { 36 size_t block_mode_count; 37 const keymaster_block_mode_t* supported_block_modes = SupportedBlockModes(&block_mode_count); 38 for (size_t i = 0; i < block_mode_count; ++i) 39 if (block_mode == supported_block_modes[i]) 40 return true; 41 return false; 42 } 43 44 bool OperationFactory::supported(keymaster_digest_t digest) const { 45 size_t digest_count; 46 const keymaster_digest_t* supported_digests = SupportedDigests(&digest_count); 47 for (size_t i = 0; i < digest_count; ++i) 48 if (digest == supported_digests[i]) 49 return true; 50 return false; 51 } 52 53 inline bool is_public_key_algorithm(keymaster_algorithm_t algorithm) { 54 switch (algorithm) { 55 case KM_ALGORITHM_HMAC: 56 case KM_ALGORITHM_AES: 57 return false; 58 case KM_ALGORITHM_RSA: 59 case KM_ALGORITHM_EC: 60 return true; 61 } 62 63 // Unreachable. 64 assert(false); 65 return false; 66 } 67 68 bool OperationFactory::is_public_key_operation() const { 69 KeyType key_type = registry_key(); 70 71 if (!is_public_key_algorithm(key_type.algorithm)) 72 return false; 73 74 switch (key_type.purpose) { 75 case KM_PURPOSE_VERIFY: 76 case KM_PURPOSE_ENCRYPT: 77 return true; 78 case KM_PURPOSE_SIGN: 79 case KM_PURPOSE_DECRYPT: 80 case KM_PURPOSE_DERIVE_KEY: 81 return false; 82 }; 83 84 // Unreachable. 85 assert(false); 86 return false; 87 } 88 89 bool OperationFactory::GetAndValidatePadding(const AuthorizationSet& begin_params, const Key& key, 90 keymaster_padding_t* padding, 91 keymaster_error_t* error) const { 92 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE; 93 if (!begin_params.GetTagValue(TAG_PADDING, padding)) { 94 LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING)); 95 return false; 96 } else if (!supported(*padding)) { 97 LOG_E("Padding mode %d not supported", *padding); 98 return false; 99 } else if ( 100 // If it's a public key operation, all padding modes are authorized. 101 !is_public_key_operation() && 102 // Otherwise the key needs to authorize the specific mode. 103 !key.authorizations().Contains(TAG_PADDING, *padding) && 104 !key.authorizations().Contains(TAG_PADDING_OLD, *padding)) { 105 LOG_E("Padding mode %d was specified, but not authorized by key", *padding); 106 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE; 107 return false; 108 } 109 110 *error = KM_ERROR_OK; 111 return true; 112 } 113 114 bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key, 115 keymaster_digest_t* digest, 116 keymaster_error_t* error) const { 117 *error = KM_ERROR_UNSUPPORTED_DIGEST; 118 if (!begin_params.GetTagValue(TAG_DIGEST, digest)) { 119 LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST)); 120 return false; 121 } else if (!supported(*digest)) { 122 LOG_E("Digest %d not supported", *digest); 123 return false; 124 } else if ( 125 // If it's a public key operation, all digests are authorized. 126 !is_public_key_operation() && 127 // Otherwise the key needs to authorize the specific digest. 128 !key.authorizations().Contains(TAG_DIGEST, *digest) && 129 !key.authorizations().Contains(TAG_DIGEST_OLD, *digest)) { 130 LOG_E("Digest %d was specified, but not authorized by key", *digest); 131 *error = KM_ERROR_INCOMPATIBLE_DIGEST; 132 return false; 133 } 134 *error = KM_ERROR_OK; 135 return true; 136 } 137 138 keymaster_error_t Operation::CreateOperationHandle(const KeymasterContext& context, 139 keymaster_operation_handle_t* op_handle) { 140 return context.GenerateRandom(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)); 141 } 142 143 keymaster_error_t Operation::UpdateForFinish(const AuthorizationSet& input_params, 144 const Buffer& input) { 145 if (!input_params.empty() || input.available_read()) { 146 size_t input_consumed; 147 Buffer output; 148 AuthorizationSet output_params; 149 keymaster_error_t error = 150 Update(input_params, input, &output_params, &output, &input_consumed); 151 if (error != KM_ERROR_OK) 152 return error; 153 assert(input_consumed == input.available_read()); 154 assert(output_params.empty()); 155 assert(output.available_read() == 0); 156 } 157 158 return KM_ERROR_OK; 159 } 160 161 } // namespace keymaster 162