1/*
2**
3** Copyright 2017, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9**     http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#include <keymaster/legacy_support/keymaster1_legacy_support.h>
19
20#include <android-base/logging.h>
21
22#include <assert.h>
23
24#include <algorithm>
25#include <vector>
26
27namespace keymaster {
28
29template <typename T> std::vector<T> make_vector(const T* array, size_t len) {
30    return std::vector<T>(array, array + len);
31}
32
33// This helper class implements just enough of the C++ standard collection interface to be able to
34// accept push_back calls, and it does nothing but count them.  It's useful when you want to count
35// insertions but not actually store anything.  It's used in digest_set_is_full below to count the
36// size of a set intersection.
37struct PushbackCounter {
38    struct value_type {
39        template <typename T> value_type(const T&) {}
40    };
41    void push_back(const value_type&) { ++count; }
42    size_t count = 0;
43};
44
45static std::vector<keymaster_digest_t> full_digest_list = {
46    KM_DIGEST_MD5,       KM_DIGEST_SHA1,      KM_DIGEST_SHA_2_224,
47    KM_DIGEST_SHA_2_256, KM_DIGEST_SHA_2_384, KM_DIGEST_SHA_2_512};
48
49template <typename Iter> static bool digest_set_is_full(Iter begin, Iter end) {
50    PushbackCounter counter;
51    std::set_intersection(begin, end, full_digest_list.begin(), full_digest_list.end(),
52                          std::back_inserter(counter));
53    return counter.count == full_digest_list.size();
54}
55
56static keymaster_error_t add_digests(const keymaster1_device_t* dev, keymaster_algorithm_t algorithm,
57                                     keymaster_purpose_t purpose,
58                                     Keymaster1LegacySupport::DigestMap* map, bool* supports_all) {
59    auto key = std::make_pair(algorithm, purpose);
60
61    keymaster_digest_t* digests;
62    size_t digests_length;
63    keymaster_error_t error =
64        dev->get_supported_digests(dev, algorithm, purpose, &digests, &digests_length);
65    if (error != KM_ERROR_OK) {
66        LOG(ERROR) << "Error " << error << " getting supported digests from keymaster1 device";
67        return error;
68    }
69    std::unique_ptr<keymaster_digest_t, Malloc_Delete> digests_deleter(digests);
70
71    auto digest_vec = make_vector(digests, digests_length);
72    *supports_all = digest_set_is_full(digest_vec.begin(), digest_vec.end());
73    (*map)[key] = std::move(digest_vec);
74    return error;
75}
76
77static keymaster_error_t map_digests(const keymaster1_device_t* dev,
78                                     Keymaster1LegacySupport::DigestMap* map,
79                                     bool* supports_all) {
80    map->clear();
81    *supports_all = true;
82
83    keymaster_algorithm_t sig_algorithms[] = {KM_ALGORITHM_RSA, KM_ALGORITHM_EC, KM_ALGORITHM_HMAC};
84    keymaster_purpose_t sig_purposes[] = {KM_PURPOSE_SIGN, KM_PURPOSE_VERIFY};
85    for (auto algorithm : sig_algorithms)
86        for (auto purpose : sig_purposes) {
87            bool alg_purpose_supports_all;
88            keymaster_error_t error =
89                add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
90            if (error != KM_ERROR_OK)
91                return error;
92            *supports_all &= alg_purpose_supports_all;
93        }
94
95    keymaster_algorithm_t crypt_algorithms[] = {KM_ALGORITHM_RSA};
96    keymaster_purpose_t crypt_purposes[] = {KM_PURPOSE_ENCRYPT, KM_PURPOSE_DECRYPT};
97    for (auto algorithm : crypt_algorithms)
98        for (auto purpose : crypt_purposes) {
99            bool alg_purpose_supports_all;
100            keymaster_error_t error =
101                add_digests(dev, algorithm, purpose, map, &alg_purpose_supports_all);
102            if (error != KM_ERROR_OK)
103                return error;
104            *supports_all &= alg_purpose_supports_all;
105        }
106
107    return KM_ERROR_OK;
108}
109
110Keymaster1LegacySupport::Keymaster1LegacySupport(const keymaster1_device_t* dev) {
111    map_digests(dev, &device_digests_, &supports_all_);
112}
113
114template <typename Collection, typename Value> bool contains(const Collection& c, const Value& v) {
115    return std::find(c.begin(), c.end(), v) != c.end();
116}
117
118template <typename T>
119static bool findUnsupportedDigest(keymaster_algorithm_t algorithm,
120                                  keymaster_purpose_t purpose,
121                                  const T& params,
122                                  const Keymaster1LegacySupport::DigestMap& digest_map) {
123    auto supported_digests = digest_map.find(std::make_pair(algorithm, purpose));
124    if (supported_digests == digest_map.end())
125        // Invalid algorith/purpose pair (e.g. EC encrypt).  Let the error be handled by HW module.
126        return false;
127
128    for (auto& entry : params)
129        if (entry.tag == TAG_DIGEST)
130            if (!contains(supported_digests->second, entry.enumerated)) {
131                LOG(WARNING) << "Digest " << entry.enumerated << " requested but not supported by KM1 hal";
132                return true;
133            }
134    return false;
135}
136
137template <typename T>
138bool requiresSoftwareDigesting(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
139                               const T& params,
140                               const Keymaster1LegacySupport::DigestMap& digest_map) {
141    switch (algorithm) {
142    case KM_ALGORITHM_AES:
143    case KM_ALGORITHM_TRIPLE_DES:
144        LOG(WARNING) << "Not performing software digesting for symmetric cipher keys";
145        return false;
146    case KM_ALGORITHM_HMAC:
147    case KM_ALGORITHM_RSA:
148    case KM_ALGORITHM_EC:
149        break;
150    }
151
152    if (!findUnsupportedDigest(algorithm, purpose, params, digest_map)) {
153        LOG(DEBUG) << "Requested digest(s) supported for algorithm " << algorithm << " and purpose " << purpose;
154        return false;
155    }
156
157    return true;
158}
159bool Keymaster1LegacySupport::RequiresSoftwareDigesting(
160        const AuthorizationSet& key_description) const {
161
162    keymaster_algorithm_t algorithm;
163    if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
164        // The hardware module will return an error during keygen.
165        return false;
166    }
167
168    if (supports_all_) return false;
169
170    for (auto& entry : key_description)
171        if (entry.tag == TAG_PURPOSE) {
172            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(entry.enumerated);
173            if (requiresSoftwareDigesting(algorithm, purpose, key_description, device_digests_))
174                return true;
175        }
176
177    return false;
178}
179
180bool Keymaster1LegacySupport::RequiresSoftwareDigesting(
181        const AuthProxy& key_description) const {
182
183    keymaster_algorithm_t algorithm;
184    if (!key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
185        // The hardware module will return an error during keygen.
186        return false;
187    }
188
189    if (supports_all_) return false;
190
191    for (auto& entry : key_description)
192        if (entry.tag == TAG_PURPOSE) {
193            keymaster_purpose_t purpose = static_cast<keymaster_purpose_t>(entry.enumerated);
194            if (requiresSoftwareDigesting(algorithm, purpose, key_description, device_digests_))
195                return true;
196        }
197
198    return false;
199}
200
201template<>
202keymaster_error_t
203Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::GenerateKey(
204        const AuthorizationSet& key_description,
205        KeymasterKeyBlob* key_blob, AuthorizationSet* hw_enforced,
206        AuthorizationSet* sw_enforced) const {
207    if (legacy_support_.RequiresSoftwareDigesting(key_description)) {
208        return software_digest_factory_.GenerateKey(key_description, key_blob, hw_enforced,
209                                             sw_enforced);
210    } else {
211        AuthorizationSet mutable_key_description = key_description;
212        keymaster_ec_curve_t curve;
213        if (key_description.GetTagValue(TAG_EC_CURVE, &curve)) {
214            // Keymaster1 doesn't know about EC curves. We need to translate to key size.
215            uint32_t key_size_from_curve;
216            keymaster_error_t error = EcCurveToKeySize(curve, &key_size_from_curve);
217            if (error != KM_ERROR_OK) {
218                return error;
219            }
220
221            uint32_t key_size_from_desc;
222            if (key_description.GetTagValue(TAG_KEY_SIZE, &key_size_from_desc)) {
223                if (key_size_from_desc != key_size_from_curve) {
224                    return KM_ERROR_INVALID_ARGUMENT;
225                }
226            } else {
227                mutable_key_description.push_back(TAG_KEY_SIZE, key_size_from_curve);
228            }
229        }
230
231        return passthrough_factory_.GenerateKey(mutable_key_description, key_blob, hw_enforced,
232                                                sw_enforced);
233    }
234}
235
236template<>
237keymaster_error_t
238Keymaster1ArbitrationFactory<EcdsaKeymaster1KeyFactory>::LoadKey(KeymasterKeyBlob&& key_material,
239        const AuthorizationSet& additional_params,
240        AuthorizationSet&& hw_enforced,
241        AuthorizationSet&& sw_enforced,
242        UniquePtr<Key>* key) const {
243    bool requires_software_digesting = legacy_support_.RequiresSoftwareDigesting(
244                                                           AuthProxy(hw_enforced, sw_enforced));
245    auto rc = software_digest_factory_.LoadKey(move(key_material), additional_params,
246                                               move(hw_enforced), move(sw_enforced), key);
247    if (rc != KM_ERROR_OK) return rc;
248    if (!requires_software_digesting) {
249        (*key)->key_factory() = & passthrough_factory_;
250    }
251    return KM_ERROR_OK;
252}
253
254template<>
255keymaster_error_t
256Keymaster1ArbitrationFactory<RsaKeymaster1KeyFactory>::LoadKey(KeymasterKeyBlob&& key_material,
257        const AuthorizationSet& additional_params,
258        AuthorizationSet&& hw_enforced,
259        AuthorizationSet&& sw_enforced,
260        UniquePtr<Key>* key) const {
261    bool requires_software_digesting = legacy_support_.RequiresSoftwareDigesting(
262                                                           AuthProxy(hw_enforced, sw_enforced));
263    auto rc = software_digest_factory_.LoadKey(move(key_material), additional_params,
264                                               move(hw_enforced), move(sw_enforced), key);
265    if (rc != KM_ERROR_OK) return rc;
266    if (!requires_software_digesting) {
267        (*key)->key_factory() = & passthrough_factory_;
268    }
269    return KM_ERROR_OK;
270}
271
272
273} // namespace keymaster
274