| /* |
| ** |
| ** Copyright 2017, The Android Open Source Project |
| ** Copyright 2020, Fairphone B.V. |
| ** |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| */ |
| |
| #define LOG_TAG "KM0_passthrough" |
| #include <keymaster/contexts/keymaster0_passthrough_context.h> |
| |
| #include <memory> |
| |
| #include <log/log.h> |
| |
| |
| namespace keymaster { |
| |
| Keymaster0PassthroughContext::Keymaster0PassthroughContext(keymaster0_device_t *dev) |
| : PureSoftKeymasterContext() { |
| km0_engine_.reset(new Keymaster0Engine(dev)); |
| // This discards the parent, software-only RSA and EC factories. |
| rsa_factory_.reset(new RsaKeymaster0KeyFactory(this, km0_engine_.get())); |
| ec_factory_.reset(new EcdsaKeymaster0KeyFactory(this, km0_engine_.get())); |
| } |
| |
| Keymaster0PassthroughContext::~Keymaster0PassthroughContext() { |
| } |
| |
| keymaster_error_t Keymaster0PassthroughContext::ParseKeyBlob(const KeymasterKeyBlob& blob, |
| const AuthorizationSet& additional_params, |
| UniquePtr<Key>* key) const { |
| // Try software first, where we can be sure it behaves as expected if it |
| // cannot parse the blob. |
| keymaster_error_t error = PureSoftKeymasterContext::ParseKeyBlob(blob, additional_params, key); |
| if (error == KM_ERROR_OK) { |
| ALOGD("Software keymaster successfully parsed the key blob."); |
| return error; |
| } |
| ALOGD("Software keymaster cannot parse the blob; trying legacy hardware keymaster."); |
| |
| // KM0 doesn't provide an interface to get key characteristics. Instead, we |
| // have to make assumptions here and check for failures reported by the |
| // hardware engine. |
| |
| // Declare that all operations shall be handled by the hardware keymaster. |
| AuthorizationSet hw_enforced; |
| hw_enforced.push_back(TAG_PURPOSE, KM_PURPOSE_SIGN); |
| hw_enforced.push_back(TAG_PURPOSE, KM_PURPOSE_VERIFY); |
| hw_enforced.push_back(TAG_PURPOSE, KM_PURPOSE_ENCRYPT); |
| hw_enforced.push_back(TAG_PURPOSE, KM_PURPOSE_DECRYPT); |
| hw_enforced.push_back(TAG_ALL_USERS); |
| hw_enforced.push_back(TAG_NO_AUTH_REQUIRED); |
| // The FP2/msm8974 legacy Android 6 Qualcomm keymaster supports RSA only, no |
| // digest, no padding. |
| hw_enforced.push_back(TAG_ALGORITHM, KM_ALGORITHM_RSA); |
| hw_enforced.push_back(TAG_DIGEST, KM_DIGEST_NONE); |
| hw_enforced.push_back(TAG_PADDING, KM_PAD_NONE); |
| AuthorizationSet sw_enforced; |
| |
| // The factory takes ownership of the object, so we need a copy. |
| auto key_material = blob; |
| error = rsa_factory_->LoadKey(move(key_material), additional_params, move(hw_enforced), |
| move(sw_enforced), key); |
| |
| if (error == KM_ERROR_OK) { |
| ALOGI("Legacy hardware keymaster reports success while parsing the key blob."); |
| } else { |
| ALOGI("Legacy hardware keymaster reports failure while parsing the key blob: %i", error); |
| } |
| return error; |
| } |
| |
| } |