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