Reintroduce KM0 decryption support
On Android 7 and earlier on FP2, the legacy API version 0.3 Qualcomm
keymaster is used to encrypt the data partition (FDE). Reintroduce
support for legacy keymasters, to be able to decrypt userdata after a
Android 7-to-9 upgrade.
Issue: FP2P-383
Issue: FP2P-506
Issue: FP2A10-123
Change-Id: I057dce6aaef37ebcd7769447a57455c9dd650234
diff --git a/Android.bp b/Android.bp
index dae6f71..69995a0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -240,6 +240,7 @@
"legacy_support/keymaster_passthrough_key.cpp",
"legacy_support/keymaster_passthrough_engine.cpp",
"legacy_support/keymaster_passthrough_operation.cpp",
+ "contexts/keymaster0_passthrough_context.cpp",
"contexts/keymaster1_passthrough_context.cpp",
"contexts/keymaster2_passthrough_context.cpp",
"ng/AndroidKeymaster3Device.cpp",
diff --git a/contexts/keymaster0_passthrough_context.cpp b/contexts/keymaster0_passthrough_context.cpp
new file mode 100644
index 0000000..6a0b77b
--- /dev/null
+++ b/contexts/keymaster0_passthrough_context.cpp
@@ -0,0 +1,83 @@
+/*
+**
+** 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;
+}
+
+} // namespace keymaster
diff --git a/include/keymaster/contexts/keymaster0_passthrough_context.h b/include/keymaster/contexts/keymaster0_passthrough_context.h
index cad9df6..9dac6f5 100644
--- a/include/keymaster/contexts/keymaster0_passthrough_context.h
+++ b/include/keymaster/contexts/keymaster0_passthrough_context.h
@@ -1,6 +1,7 @@
/*
**
** 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.
@@ -29,11 +30,11 @@
class Keymaster0PassthroughContext : public PureSoftKeymasterContext {
public:
- explicit Keymaster0PassthroughContext(keymaster0_device_t* dev) : PureSoftKeymasterContext() {
- km0_engine_.reset(new Keymaster0Engine(dev));
- rsa_factory_.reset(new RsaKeymaster0KeyFactory(this, km0_engine_.get()));
- ec_factory_.reset(new EcdsaKeymaster0KeyFactory(this, km0_engine_.get()));
- }
+ explicit Keymaster0PassthroughContext(keymaster0_device_t* dev);
+ ~Keymaster0PassthroughContext() override;
+ keymaster_error_t ParseKeyBlob(const KeymasterKeyBlob& blob,
+ const AuthorizationSet& additional_params,
+ UniquePtr<Key>* key) const override;
private:
UniquePtr<Keymaster0Engine> km0_engine_;