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
supported(keymaster_padding_t padding) const26 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
supported(keymaster_block_mode_t block_mode) const35 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
supported(keymaster_digest_t digest) const44 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
is_public_key_algorithm(keymaster_algorithm_t algorithm)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
is_public_key_operation() const68 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
GetAndValidatePadding(const AuthorizationSet & begin_params,const Key & key,keymaster_padding_t * padding,keymaster_error_t * error) const89 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
GetAndValidateDigest(const AuthorizationSet & begin_params,const Key & key,keymaster_digest_t * digest,keymaster_error_t * error) const114 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
CreateOperationHandle(const KeymasterContext & context,keymaster_operation_handle_t * op_handle)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
UpdateForFinish(const AuthorizationSet & input_params,const Buffer & input)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