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