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