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     case KM_PURPOSE_DERIVE_KEY:
80         return false;
81     };
82 
83     // Unreachable.
84     assert(false);
85     return false;
86 }
87 
GetAndValidatePadding(const AuthorizationSet & begin_params,const Key & key,keymaster_padding_t * padding,keymaster_error_t * error) const88 bool OperationFactory::GetAndValidatePadding(const AuthorizationSet& begin_params, const Key& key,
89                                              keymaster_padding_t* padding,
90                                              keymaster_error_t* error) const {
91     *error = KM_ERROR_UNSUPPORTED_PADDING_MODE;
92     if (!begin_params.GetTagValue(TAG_PADDING, padding)) {
93         LOG_E("%d padding modes specified in begin params", begin_params.GetTagCount(TAG_PADDING));
94         return false;
95     } else if (!supported(*padding)) {
96         LOG_E("Padding mode %d not supported", *padding);
97         return false;
98     } else if (
99         // If it's a public key operation, all padding modes are authorized.
100         !is_public_key_operation() &&
101         // Otherwise the key needs to authorize the specific mode.
102         !key.authorizations().Contains(TAG_PADDING, *padding) &&
103         !key.authorizations().Contains(TAG_PADDING_OLD, *padding)) {
104         LOG_E("Padding mode %d was specified, but not authorized by key", *padding);
105         *error = KM_ERROR_INCOMPATIBLE_PADDING_MODE;
106         return false;
107     }
108 
109     *error = KM_ERROR_OK;
110     return true;
111 }
112 
GetAndValidateDigest(const AuthorizationSet & begin_params,const Key & key,keymaster_digest_t * digest,keymaster_error_t * error) const113 bool OperationFactory::GetAndValidateDigest(const AuthorizationSet& begin_params, const Key& key,
114                                             keymaster_digest_t* digest,
115                                             keymaster_error_t* error) const {
116     *error = KM_ERROR_UNSUPPORTED_DIGEST;
117     if (!begin_params.GetTagValue(TAG_DIGEST, digest)) {
118         LOG_E("%d digests specified in begin params", begin_params.GetTagCount(TAG_DIGEST));
119         return false;
120     } else if (!supported(*digest)) {
121         LOG_E("Digest %d not supported", *digest);
122         return false;
123     } else if (
124         // If it's a public key operation, all digests are authorized.
125         !is_public_key_operation() &&
126         // Otherwise the key needs to authorize the specific digest.
127         !key.authorizations().Contains(TAG_DIGEST, *digest) &&
128         !key.authorizations().Contains(TAG_DIGEST_OLD, *digest)) {
129         LOG_E("Digest %d was specified, but not authorized by key", *digest);
130         *error = KM_ERROR_INCOMPATIBLE_DIGEST;
131         return false;
132     }
133     *error = KM_ERROR_OK;
134     return true;
135 }
136 
UpdateForFinish(const AuthorizationSet & input_params,const Buffer & input)137 keymaster_error_t Operation::UpdateForFinish(const AuthorizationSet& input_params,
138                                              const Buffer& input) {
139     if (!input_params.empty() || input.available_read()) {
140         size_t input_consumed;
141         Buffer output;
142         AuthorizationSet output_params;
143         keymaster_error_t error =
144             Update(input_params, input, &output_params, &output, &input_consumed);
145         if (error != KM_ERROR_OK)
146             return error;
147         assert(input_consumed == input.available_read());
148         assert(output_params.empty());
149         assert(output.available_read() == 0);
150     }
151 
152     return KM_ERROR_OK;
153 }
154 
155 }  // namespace keymaster
156