blob: 3180ab043cd4a427e000df736927371f65ae3910 [file] [log] [blame]
Shawn Willden63ac0432014-12-29 14:07:08 -07001/*
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
Shawn Willden117a0cc2015-06-01 07:05:41 -060017#include <keymaster/authorization_set.h>
Janis Danisevskisf54cc932017-05-10 15:29:10 -070018#include <keymaster/key.h>
19#include <keymaster/operation.h>
Shawn Willden117a0cc2015-06-01 07:05:41 -060020
Shawn Willden117a0cc2015-06-01 07:05:41 -060021
Shawn Willden63ac0432014-12-29 14:07:08 -070022namespace keymaster {
23
Shawn Willdend92591d2014-12-30 18:19:10 -070024bool 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
33bool 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
42bool 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
Shawn Willden294a2db2015-06-17 11:20:56 -060051inline bool is_public_key_algorithm(keymaster_algorithm_t algorithm) {
52 switch (algorithm) {
53 case KM_ALGORITHM_HMAC:
54 case KM_ALGORITHM_AES:
Shawn Willden7efc7722018-01-08 22:00:12 -070055 case KM_ALGORITHM_TRIPLE_DES:
Shawn Willden294a2db2015-06-17 11:20:56 -060056 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
67bool 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:
Shawn Willdendd7e8a02018-01-12 13:03:37 -070076 case KM_PURPOSE_WRAP:
Shawn Willden294a2db2015-06-17 11:20:56 -060077 return true;
78 case KM_PURPOSE_SIGN:
79 case KM_PURPOSE_DECRYPT:
Shawn Willdend4c83db2015-12-22 14:40:15 -070080 case KM_PURPOSE_DERIVE_KEY:
Shawn Willden294a2db2015-06-17 11:20:56 -060081 return false;
82 };
83
84 // Unreachable.
85 assert(false);
86 return false;
87}
88
Shawn Willden117a0cc2015-06-01 07:05:41 -060089bool 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;
Shawn Willdenbfd9ed72015-06-11 10:51:12 -060099 } else if (
Shawn Willden294a2db2015-06-17 11:20:56 -0600100 // If it's a public key operation, all padding modes are authorized.
101 !is_public_key_operation() &&
Shawn Willdenbfd9ed72015-06-11 10:51:12 -0600102 // Otherwise the key needs to authorize the specific mode.
103 !key.authorizations().Contains(TAG_PADDING, *padding) &&
104 !key.authorizations().Contains(TAG_PADDING_OLD, *padding)) {
Shawn Willden117a0cc2015-06-01 07:05:41 -0600105 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
114bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key,
115 keymaster_digest_t* digest,
116 keymaster_error_t* error) const {
Matthew Maurer90174bd2019-05-10 16:31:00 -0700117 return GetAndValidateDigest(begin_params, key, digest, error, false);
118}
119
120bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key,
121 keymaster_digest_t* digest, keymaster_error_t* error,
122 bool require_explicit_digest) const {
Shawn Willden117a0cc2015-06-01 07:05:41 -0600123 *error = KM_ERROR_UNSUPPORTED_DIGEST;
124 if (!begin_params.GetTagValue(TAG_DIGEST, digest)) {
Matthew Maurer90174bd2019-05-10 16:31:00 -0700125 if (require_explicit_digest) {
126 return false;
127 }
Janis Danisevskis5a44a2f2018-08-03 13:46:37 -0700128 if (key.authorizations().Contains(TAG_DIGEST, KM_DIGEST_NONE)) {
129 *digest = KM_DIGEST_NONE;
130 } else {
131 LOG_E("%d digests specified in begin params and NONE not authorized",
132 begin_params.GetTagCount(TAG_DIGEST));
133 return false;
134 }
Shawn Willden117a0cc2015-06-01 07:05:41 -0600135 } else if (!supported(*digest)) {
136 LOG_E("Digest %d not supported", *digest);
137 return false;
Shawn Willdenbfd9ed72015-06-11 10:51:12 -0600138 } else if (
Shawn Willden294a2db2015-06-17 11:20:56 -0600139 // If it's a public key operation, all digests are authorized.
140 !is_public_key_operation() &&
Shawn Willdenbfd9ed72015-06-11 10:51:12 -0600141 // Otherwise the key needs to authorize the specific digest.
142 !key.authorizations().Contains(TAG_DIGEST, *digest) &&
143 !key.authorizations().Contains(TAG_DIGEST_OLD, *digest)) {
Shawn Willden117a0cc2015-06-01 07:05:41 -0600144 LOG_E("Digest %d was specified, but not authorized by key", *digest);
145 *error = KM_ERROR_INCOMPATIBLE_DIGEST;
146 return false;
147 }
148 *error = KM_ERROR_OK;
149 return true;
150}
151
Shawn Willdencb647fe2016-01-27 12:59:13 -0700152keymaster_error_t Operation::UpdateForFinish(const AuthorizationSet& input_params,
153 const Buffer& input) {
154 if (!input_params.empty() || input.available_read()) {
155 size_t input_consumed;
156 Buffer output;
157 AuthorizationSet output_params;
158 keymaster_error_t error =
159 Update(input_params, input, &output_params, &output, &input_consumed);
160 if (error != KM_ERROR_OK)
161 return error;
162 assert(input_consumed == input.available_read());
163 assert(output_params.empty());
164 assert(output.available_read() == 0);
165 }
166
167 return KM_ERROR_OK;
168}
169
Shawn Willden63ac0432014-12-29 14:07:08 -0700170} // namespace keymaster