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
supported(keymaster_padding_t padding) const25 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
supported(keymaster_block_mode_t block_mode) const34 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
supported(keymaster_digest_t digest) const43 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
is_public_key_algorithm(keymaster_algorithm_t algorithm)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
is_public_key_operation() const67 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
GetAndValidatePadding(const AuthorizationSet & begin_params,const Key & key,keymaster_padding_t * padding,keymaster_error_t * error) const87 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
GetAndValidateDigest(const AuthorizationSet & begin_params,const Key & key,keymaster_digest_t * digest,keymaster_error_t * error) const112 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