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 return false; 80 }; 81 82 // Unreachable. 83 assert(false); 84 return false; 85 } 86 87 bool OperationFactory::GetAndValidatePadding(const AuthorizationSet& begin_params, const Key& key, 88 keymaster_padding_t* padding, 89 keymaster_error_t* error) const { 90 *error = KM_ERROR_UNSUPPORTED_PADDING_MODE; 91 if (!begin_params.GetTagValue(TAG_PADDING, padding)) { 92 LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING)); 93 return false; 94 } else if (!supported(*padding)) { 95 LOG_E("Padding mode %d not supported", *padding); 96 return false; 97 } else if ( 98 // If it's a public key operation, all padding modes are authorized. 99 !is_public_key_operation() && 100 // Otherwise the key needs to authorize the specific mode. 101 !key.authorizations().Contains(TAG_PADDING, *padding) && 102 !key.authorizations().Contains(TAG_PADDING_OLD, *padding)) { 103 LOG_E("Padding mode %d was specified, but not authorized by key", *padding); 104 *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE; 105 return false; 106 } 107 108 *error = KM_ERROR_OK; 109 return true; 110 } 111 112 bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key, 113 keymaster_digest_t* digest, 114 keymaster_error_t* error) const { 115 *error = KM_ERROR_UNSUPPORTED_DIGEST; 116 if (!begin_params.GetTagValue(TAG_DIGEST, digest)) { 117 LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST)); 118 return false; 119 } else if (!supported(*digest)) { 120 LOG_E("Digest %d not supported", *digest); 121 return false; 122 } else if ( 123 // If it's a public key operation, all digests are authorized. 124 !is_public_key_operation() && 125 // Otherwise the key needs to authorize the specific digest. 126 !key.authorizations().Contains(TAG_DIGEST, *digest) && 127 !key.authorizations().Contains(TAG_DIGEST_OLD, *digest)) { 128 LOG_E("Digest %d was specified, but not authorized by key", *digest); 129 *error = KM_ERROR_INCOMPATIBLE_DIGEST; 130 return false; 131 } 132 *error = KM_ERROR_OK; 133 return true; 134 } 135 136 } // namespace keymaster 137