• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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