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 <keymaster/authorization_set.h> 18 #include <keymaster/key.h> 19 #include <keymaster/operation.h> 20 21 22 namespace keymaster { 23 24 bool OperationFactory::supported(keymaster_padding_t padding) const { 25 size_t padding_count; 26 const keymaster_padding_t* supported_paddings = SupportedPaddingModes(&padding_count); 27 for (size_t i = 0; i < padding_count; ++i) 28 if (padding == supported_paddings[i]) 29 return true; 30 return false; 31 } 32 33 bool OperationFactory::supported(keymaster_block_mode_t block_mode) const { 34 size_t block_mode_count; 35 const keymaster_block_mode_t* supported_block_modes = SupportedBlockModes(&block_mode_count); 36 for (size_t i = 0; i < block_mode_count; ++i) 37 if (block_mode == supported_block_modes[i]) 38 return true; 39 return false; 40 } 41 42 bool OperationFactory::supported(keymaster_digest_t digest) const { 43 size_t digest_count; 44 const keymaster_digest_t* supported_digests = SupportedDigests(&digest_count); 45 for (size_t i = 0; i < digest_count; ++i) 46 if (digest == supported_digests[i]) 47 return true; 48 return false; 49 } 50 51 inline bool is_public_key_algorithm(keymaster_algorithm_t algorithm) { 52 switch (algorithm) { 53 case KM_ALGORITHM_HMAC: 54 case KM_ALGORITHM_AES: 55 case KM_ALGORITHM_TRIPLE_DES: 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 case KM_PURPOSE_WRAP: 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::UpdateForFinish(const AuthorizationSet& input_params, 139 const Buffer& input) { 140 if (!input_params.empty() || input.available_read()) { 141 size_t input_consumed; 142 Buffer output; 143 AuthorizationSet output_params; 144 keymaster_error_t error = 145 Update(input_params, input, &output_params, &output, &input_consumed); 146 if (error != KM_ERROR_OK) 147 return error; 148 assert(input_consumed == input.available_read()); 149 assert(output_params.empty()); 150 assert(output.available_read() == 0); 151 } 152 153 return KM_ERROR_OK; 154 } 155 156 } // namespace keymaster 157