Merge "Add TrustyKeyMintDevice" into sc-dev
This commit is contained in:
commit
8caf16a46e
17 changed files with 981 additions and 18 deletions
|
@ -24,7 +24,7 @@
|
|||
int main() {
|
||||
::android::hardware::configureRpcThreadpool(1, true);
|
||||
auto trustyKeymaster = new keymaster::TrustyKeymaster();
|
||||
int err = trustyKeymaster->Initialize();
|
||||
int err = trustyKeymaster->Initialize(keymaster::KmVersion::KEYMASTER_3);
|
||||
if (err != 0) {
|
||||
LOG(FATAL) << "Could not initialize TrustyKeymaster (" << err << ")";
|
||||
return -1;
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
int main() {
|
||||
::android::hardware::configureRpcThreadpool(1, true);
|
||||
auto trustyKeymaster = new keymaster::TrustyKeymaster();
|
||||
int err = trustyKeymaster->Initialize();
|
||||
int err = trustyKeymaster->Initialize(keymaster::KmVersion::KEYMASTER_4);
|
||||
if (err != 0) {
|
||||
LOG(FATAL) << "Could not initialize TrustyKeymaster (" << err << ")";
|
||||
return -1;
|
||||
|
|
|
@ -80,6 +80,49 @@ cc_binary {
|
|||
vintf_fragments: ["4.0/android.hardware.keymaster@4.0-service.trusty.xml"],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "android.hardware.security.keymint-service.trusty",
|
||||
relative_install_path: "hw",
|
||||
init_rc: ["keymint/android.hardware.security.keymint-service.trusty.rc"],
|
||||
vintf_fragments: [
|
||||
"keymint/android.hardware.security.keymint-service.trusty.xml",
|
||||
],
|
||||
vendor: true,
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
],
|
||||
local_include_dirs: [
|
||||
"include",
|
||||
],
|
||||
srcs: [
|
||||
"TrustyKeymaster.cpp",
|
||||
"ipc/trusty_keymaster_ipc.cpp",
|
||||
"keymint/TrustyKeyMintDevice.cpp",
|
||||
"keymint/TrustyKeyMintOperation.cpp",
|
||||
"keymint/TrustySecureClock.cpp",
|
||||
"keymint/TrustySharedSecret.cpp",
|
||||
"keymint/service.cpp",
|
||||
],
|
||||
shared_libs: [
|
||||
"android.hardware.security.keymint-V1-ndk_platform",
|
||||
"android.hardware.security.secureclock-V1-ndk_platform",
|
||||
"android.hardware.security.sharedsecret-V1-ndk_platform",
|
||||
"lib_android_keymaster_keymint_utils",
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libhardware",
|
||||
"libkeymaster_messages",
|
||||
"libkeymint",
|
||||
"liblog",
|
||||
"libtrusty",
|
||||
],
|
||||
required: [
|
||||
"RemoteProvisioner",
|
||||
"android.hardware.hardware_keystore.xml",
|
||||
],
|
||||
}
|
||||
|
||||
prebuilt_etc {
|
||||
name: "keymaster_soft_attestation_keys.xml",
|
||||
vendor: true,
|
||||
|
|
|
@ -14,7 +14,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cutils/log.h>
|
||||
#define LOG_TAG "trusty_keymaster_hal"
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <keymaster/android_keymaster_messages.h>
|
||||
#include <keymaster/keymaster_configuration.h>
|
||||
#include <trusty_keymaster/TrustyKeymaster.h>
|
||||
|
@ -22,24 +24,28 @@
|
|||
|
||||
namespace keymaster {
|
||||
|
||||
int TrustyKeymaster::Initialize() {
|
||||
int TrustyKeymaster::Initialize(KmVersion version) {
|
||||
int err;
|
||||
|
||||
LOG(INFO) << "Initializing TrustyKeymaster as KmVersion: " << (int)version;
|
||||
|
||||
err = trusty_keymaster_connect();
|
||||
if (err) {
|
||||
ALOGE("Failed to connect to trusty keymaster %d", err);
|
||||
LOG(ERROR) << "Failed to connect to trusty keymaster (1st try)" << err;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Try GetVersion2 first.
|
||||
GetVersion2Request versionReq;
|
||||
versionReq.max_message_version = MessageVersion(version);
|
||||
GetVersion2Response versionRsp = GetVersion2(versionReq);
|
||||
if (versionRsp.error != KM_ERROR_OK) {
|
||||
ALOGW("TA appears not to support GetVersion2, falling back (err = %d)", versionRsp.error);
|
||||
LOG(WARNING) << "TA appears not to support GetVersion2, falling back (err = "
|
||||
<< versionRsp.error << ")";
|
||||
|
||||
err = trusty_keymaster_connect();
|
||||
if (err) {
|
||||
ALOGE("Failed to connect to trusty keymaster %d", err);
|
||||
LOG(FATAL) << "Failed to connect to trusty keymaster (2nd try) " << err;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -47,13 +53,13 @@ int TrustyKeymaster::Initialize() {
|
|||
GetVersionResponse versionRsp;
|
||||
GetVersion(versionReq, &versionRsp);
|
||||
if (versionRsp.error != KM_ERROR_OK) {
|
||||
ALOGE("Failed to get TA version %d", versionRsp.error);
|
||||
LOG(FATAL) << "Failed to get TA version " << versionRsp.error;
|
||||
return -1;
|
||||
} else {
|
||||
keymaster_error_t error;
|
||||
message_version_ = NegotiateMessageVersion(versionRsp, &error);
|
||||
if (error != KM_ERROR_OK) {
|
||||
ALOGE("Failed to negotiate message version %d", error);
|
||||
LOG(FATAL) << "Failed to negotiate message version " << error;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +75,7 @@ int TrustyKeymaster::Initialize() {
|
|||
Configure(req, &rsp);
|
||||
|
||||
if (rsp.error != KM_ERROR_OK) {
|
||||
ALOGE("Failed to configure keymaster %d", rsp.error);
|
||||
LOG(FATAL) << "Failed to configure keymaster " << rsp.error;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -87,7 +93,7 @@ static void ForwardCommand(enum keymaster_command command, const KeymasterMessag
|
|||
keymaster_error_t err;
|
||||
err = trusty_keymaster_send(command, req, rsp);
|
||||
if (err != KM_ERROR_OK) {
|
||||
ALOGE("Failed to send cmd %d err: %d", command, err);
|
||||
LOG(ERROR) << "Cmd " << command << " returned error: " << err;
|
||||
rsp->error = err;
|
||||
}
|
||||
}
|
||||
|
@ -137,14 +143,19 @@ void TrustyKeymaster::Configure(const ConfigureRequest& request, ConfigureRespon
|
|||
|
||||
void TrustyKeymaster::GenerateKey(const GenerateKeyRequest& request,
|
||||
GenerateKeyResponse* response) {
|
||||
GenerateKeyRequest datedRequest(request.message_version);
|
||||
datedRequest.key_description = request.key_description;
|
||||
if (message_version_ < 4) {
|
||||
// Pre-KeyMint we need to add TAG_CREATION_DATETIME if not provided by the caller.
|
||||
GenerateKeyRequest datedRequest(request.message_version);
|
||||
datedRequest.key_description = request.key_description;
|
||||
|
||||
if (!request.key_description.Contains(TAG_CREATION_DATETIME)) {
|
||||
datedRequest.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
|
||||
if (!request.key_description.Contains(TAG_CREATION_DATETIME)) {
|
||||
datedRequest.key_description.push_back(TAG_CREATION_DATETIME, java_time(time(NULL)));
|
||||
}
|
||||
|
||||
ForwardCommand(KM_GENERATE_KEY, datedRequest, response);
|
||||
} else {
|
||||
ForwardCommand(KM_GENERATE_KEY, request, response);
|
||||
}
|
||||
|
||||
ForwardCommand(KM_GENERATE_KEY, datedRequest, response);
|
||||
}
|
||||
|
||||
void TrustyKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
|
||||
|
@ -229,4 +240,16 @@ GetVersion2Response TrustyKeymaster::GetVersion2(const GetVersion2Request& reque
|
|||
return response;
|
||||
}
|
||||
|
||||
EarlyBootEndedResponse TrustyKeymaster::EarlyBootEnded() {
|
||||
EarlyBootEndedResponse response(message_version());
|
||||
ForwardCommand(KM_EARLY_BOOT_ENDED, EarlyBootEndedRequest(message_version()), &response);
|
||||
return response;
|
||||
}
|
||||
|
||||
DeviceLockedResponse TrustyKeymaster::DeviceLocked(const DeviceLockedRequest& request) {
|
||||
DeviceLockedResponse response(message_version());
|
||||
ForwardCommand(KM_DEVICE_LOCKED, request, &response);
|
||||
return response;
|
||||
}
|
||||
|
||||
} // namespace keymaster
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright 2021, The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
|
||||
#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
|
||||
#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
|
||||
|
||||
#include <trusty_keymaster/TrustyKeymaster.h>
|
||||
|
||||
namespace aidl::android::hardware::security::keymint::trusty {
|
||||
|
||||
using ::keymaster::TrustyKeymaster;
|
||||
using ::ndk::ScopedAStatus;
|
||||
using secureclock::TimeStampToken;
|
||||
using ::std::optional;
|
||||
using ::std::shared_ptr;
|
||||
using ::std::vector;
|
||||
|
||||
class TrustyKeyMintDevice : public BnKeyMintDevice {
|
||||
public:
|
||||
explicit TrustyKeyMintDevice(shared_ptr<TrustyKeymaster> impl) : impl_(std::move(impl)) {}
|
||||
virtual ~TrustyKeyMintDevice() = default;
|
||||
|
||||
ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
|
||||
|
||||
ScopedAStatus addRngEntropy(const vector<uint8_t>& data) override;
|
||||
|
||||
ScopedAStatus generateKey(const vector<KeyParameter>& keyParams,
|
||||
const optional<AttestationKey>& attestationKey,
|
||||
KeyCreationResult* creationResult) override;
|
||||
|
||||
ScopedAStatus getKeyCharacteristics(const vector<uint8_t>& keyBlob,
|
||||
const vector<uint8_t>& clientId,
|
||||
const vector<uint8_t>& appData,
|
||||
vector<KeyCharacteristics>* characteristics) override;
|
||||
|
||||
ScopedAStatus importKey(const vector<KeyParameter>& keyParams, KeyFormat keyFormat,
|
||||
const vector<uint8_t>& keyData,
|
||||
const optional<AttestationKey>& attestationKey,
|
||||
KeyCreationResult* creationResult) override;
|
||||
|
||||
ScopedAStatus importWrappedKey(const vector<uint8_t>& wrappedKeyData,
|
||||
const vector<uint8_t>& wrappingKeyBlob,
|
||||
const vector<uint8_t>& maskingKey,
|
||||
const vector<KeyParameter>& unwrappingParams,
|
||||
int64_t passwordSid, int64_t biometricSid,
|
||||
KeyCreationResult* creationResult) override;
|
||||
|
||||
ScopedAStatus upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
|
||||
const vector<KeyParameter>& upgradeParams,
|
||||
vector<uint8_t>* keyBlob) override;
|
||||
|
||||
ScopedAStatus deleteKey(const vector<uint8_t>& keyBlob) override;
|
||||
ScopedAStatus deleteAllKeys() override;
|
||||
ScopedAStatus destroyAttestationIds() override;
|
||||
|
||||
ScopedAStatus begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
|
||||
const vector<KeyParameter>& params,
|
||||
const optional<HardwareAuthToken>& authToken, BeginResult* result) override;
|
||||
|
||||
ScopedAStatus deviceLocked(bool passwordOnly,
|
||||
const optional<TimeStampToken>& timestampToken) override;
|
||||
ScopedAStatus earlyBootEnded() override;
|
||||
|
||||
ScopedAStatus convertStorageKeyToEphemeral(const std::vector<uint8_t>& storageKeyBlob,
|
||||
std::vector<uint8_t>* ephemeralKeyBlob) override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<TrustyKeymaster> impl_;
|
||||
SecurityLevel securityLevel_;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::security::keymint::trusty
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright 2021, The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
|
||||
#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
|
||||
|
||||
#include <trusty_keymaster/TrustyKeymaster.h>
|
||||
|
||||
#include <hardware/keymaster_defs.h>
|
||||
|
||||
namespace aidl::android::hardware::security::keymint {
|
||||
|
||||
using ::keymaster::TrustyKeymaster;
|
||||
using ::ndk::ScopedAStatus;
|
||||
using secureclock::TimeStampToken;
|
||||
using std::optional;
|
||||
using std::shared_ptr;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
class TrustyKeyMintOperation : public BnKeyMintOperation {
|
||||
public:
|
||||
explicit TrustyKeyMintOperation(shared_ptr<TrustyKeymaster> implementation,
|
||||
keymaster_operation_handle_t opHandle);
|
||||
virtual ~TrustyKeyMintOperation();
|
||||
|
||||
ScopedAStatus updateAad(const vector<uint8_t>& input,
|
||||
const optional<HardwareAuthToken>& authToken,
|
||||
const optional<TimeStampToken>& timestampToken) override;
|
||||
|
||||
ScopedAStatus update(const vector<uint8_t>& input, const optional<HardwareAuthToken>& authToken,
|
||||
const optional<TimeStampToken>& timestampToken,
|
||||
vector<uint8_t>* output) override;
|
||||
|
||||
ScopedAStatus finish(const optional<vector<uint8_t>>& input, //
|
||||
const optional<vector<uint8_t>>& signature, //
|
||||
const optional<HardwareAuthToken>& authToken, //
|
||||
const optional<TimeStampToken>& timestampToken,
|
||||
const optional<vector<uint8_t>>& confirmationToken,
|
||||
vector<uint8_t>* output) override;
|
||||
|
||||
ScopedAStatus abort() override;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<TrustyKeymaster> impl_;
|
||||
keymaster_operation_handle_t opHandle_;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::security::keymint
|
|
@ -25,7 +25,7 @@ class TrustyKeymaster {
|
|||
public:
|
||||
TrustyKeymaster();
|
||||
~TrustyKeymaster();
|
||||
int Initialize();
|
||||
int Initialize(KmVersion version);
|
||||
void GetVersion(const GetVersionRequest& request, GetVersionResponse* response);
|
||||
void SupportedAlgorithms(const SupportedAlgorithmsRequest& request,
|
||||
SupportedAlgorithmsResponse* response);
|
||||
|
@ -60,6 +60,8 @@ class TrustyKeymaster {
|
|||
ComputeSharedHmacResponse ComputeSharedHmac(const ComputeSharedHmacRequest& request);
|
||||
VerifyAuthorizationResponse VerifyAuthorization(const VerifyAuthorizationRequest& request);
|
||||
GetVersion2Response GetVersion2(const GetVersion2Request& request);
|
||||
EarlyBootEndedResponse EarlyBootEnded();
|
||||
DeviceLockedResponse DeviceLocked(const DeviceLockedRequest& request);
|
||||
|
||||
uint32_t message_version() const { return message_version_; }
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright 2021, The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/security/secureclock/BnSecureClock.h>
|
||||
#include <aidl/android/hardware/security/secureclock/TimeStampToken.h>
|
||||
#include <aidl/android/hardware/security/secureclock/Timestamp.h>
|
||||
|
||||
#include <trusty_keymaster/TrustyKeymaster.h>
|
||||
|
||||
namespace aidl::android::hardware::security::secureclock::trusty {
|
||||
|
||||
class TrustySecureClock : public BnSecureClock {
|
||||
public:
|
||||
explicit TrustySecureClock(std::shared_ptr<::keymaster::TrustyKeymaster> impl)
|
||||
: impl_(std::move(impl)) {}
|
||||
~TrustySecureClock() = default;
|
||||
::ndk::ScopedAStatus generateTimeStamp(int64_t challenge, TimeStampToken* token) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<::keymaster::TrustyKeymaster> impl_;
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::security::secureclock::trusty
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright 2021, The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/security/sharedsecret/BnSharedSecret.h>
|
||||
#include <aidl/android/hardware/security/sharedsecret/SharedSecretParameters.h>
|
||||
|
||||
#include <trusty_keymaster/TrustyKeymaster.h>
|
||||
|
||||
namespace aidl::android::hardware::security::sharedsecret::trusty {
|
||||
|
||||
class TrustySharedSecret : public BnSharedSecret {
|
||||
public:
|
||||
explicit TrustySharedSecret(std::shared_ptr<::keymaster::TrustyKeymaster> impl)
|
||||
: impl_(std::move(impl)) {}
|
||||
~TrustySharedSecret() = default;
|
||||
|
||||
::ndk::ScopedAStatus getSharedSecretParameters(SharedSecretParameters* params) override;
|
||||
::ndk::ScopedAStatus computeSharedSecret(const std::vector<SharedSecretParameters>& params,
|
||||
std::vector<uint8_t>* sharingCheck) override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<::keymaster::TrustyKeymaster> impl_;
|
||||
};
|
||||
} // namespace aidl::android::hardware::security::sharedsecret::trusty
|
|
@ -54,6 +54,8 @@ enum keymaster_command : uint32_t {
|
|||
KM_DESTROY_ATTESTATION_IDS = (24 << KEYMASTER_REQ_SHIFT),
|
||||
KM_IMPORT_WRAPPED_KEY = (25 << KEYMASTER_REQ_SHIFT),
|
||||
KM_GET_VERSION_2 = (28 << KEYMASTER_REQ_SHIFT),
|
||||
KM_EARLY_BOOT_ENDED = (29 << KEYMASTER_REQ_SHIFT),
|
||||
KM_DEVICE_LOCKED = (30 << KEYMASTER_REQ_SHIFT),
|
||||
|
||||
// Bootloader/provisioning calls.
|
||||
KM_SET_BOOT_PARAMS = (0x1000 << KEYMASTER_REQ_SHIFT),
|
||||
|
|
324
trusty/keymaster/keymint/TrustyKeyMintDevice.cpp
Normal file
324
trusty/keymaster/keymint/TrustyKeyMintDevice.cpp
Normal file
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
|
||||
* Copyright 2021, The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <trusty_keymaster/TrustyKeyMintDevice.h>
|
||||
|
||||
#define TAG TrustyKeyMintDevice
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <keymaster/android_keymaster_messages.h>
|
||||
#include <keymaster/authorization_set.h>
|
||||
|
||||
#include <KeyMintUtils.h>
|
||||
|
||||
#include <trusty_keymaster/TrustyKeyMintOperation.h>
|
||||
|
||||
namespace aidl::android::hardware::security::keymint::trusty {
|
||||
|
||||
using keymaster::KeymasterBlob;
|
||||
using keymaster::KeymasterKeyBlob;
|
||||
using keymaster::TAG_APPLICATION_DATA;
|
||||
using keymaster::TAG_APPLICATION_ID;
|
||||
using keymaster::TAG_AUTH_TOKEN;
|
||||
using km_utils::authToken2AidlVec;
|
||||
using km_utils::kmBlob2vector;
|
||||
using km_utils::kmError2ScopedAStatus;
|
||||
using km_utils::kmParam2Aidl;
|
||||
using km_utils::KmParamSet;
|
||||
using km_utils::kmParamSet2Aidl;
|
||||
using km_utils::legacy_enum_conversion;
|
||||
|
||||
namespace {
|
||||
|
||||
auto kSecurityLevel = SecurityLevel::TRUSTED_ENVIRONMENT;
|
||||
|
||||
KeyCharacteristics convertAuthSet(SecurityLevel securityLevel,
|
||||
const keymaster::AuthorizationSet& authorizations) {
|
||||
KeyCharacteristics retval{securityLevel, {}};
|
||||
std::transform(authorizations.begin(), authorizations.end(),
|
||||
std::back_inserter(retval.authorizations), kmParam2Aidl);
|
||||
return retval;
|
||||
}
|
||||
|
||||
vector<KeyCharacteristics> convertKeyCharacteristics(const keymaster::AuthorizationSet& sw_enforced,
|
||||
const keymaster::AuthorizationSet& hw_enforced,
|
||||
bool includeKeystoreEnforced = true) {
|
||||
KeyCharacteristics keyMintEnforced = convertAuthSet(kSecurityLevel, hw_enforced);
|
||||
KeyCharacteristics keystoreEnforced = convertAuthSet(SecurityLevel::KEYSTORE, sw_enforced);
|
||||
|
||||
vector<KeyCharacteristics> retval;
|
||||
retval.reserve(2);
|
||||
|
||||
if (!keyMintEnforced.authorizations.empty()) retval.push_back(std::move(keyMintEnforced));
|
||||
if (includeKeystoreEnforced && !keystoreEnforced.authorizations.empty()) {
|
||||
retval.push_back(std::move(keystoreEnforced));
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Certificate convertCertificate(const keymaster_blob_t& cert) {
|
||||
return {std::vector<uint8_t>(cert.data, cert.data + cert.data_length)};
|
||||
}
|
||||
|
||||
vector<Certificate> convertCertificateChain(const keymaster::CertificateChain& chain) {
|
||||
vector<Certificate> retval;
|
||||
std::transform(chain.begin(), chain.end(), std::back_inserter(retval), convertCertificate);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void addClientAndAppData(const vector<uint8_t>& clientId, const vector<uint8_t>& appData,
|
||||
::keymaster::AuthorizationSet* params) {
|
||||
params->Clear();
|
||||
if (clientId.size()) params->push_back(TAG_APPLICATION_ID, clientId.data(), clientId.size());
|
||||
if (appData.size()) params->push_back(TAG_APPLICATION_DATA, appData.data(), appData.size());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
|
||||
info->versionNumber = 1;
|
||||
info->securityLevel = kSecurityLevel;
|
||||
info->keyMintName = "TrustyKeyMintDevice";
|
||||
info->keyMintAuthorName = "Google";
|
||||
info->timestampTokenRequired = false;
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::addRngEntropy(const vector<uint8_t>& data) {
|
||||
if (data.size() == 0) return ScopedAStatus::ok();
|
||||
if (data.size() > 2048) {
|
||||
LOG(DEBUG) << "Too-large entropy update of " << data.size() << " bytes.";
|
||||
return kmError2ScopedAStatus(KM_ERROR_INVALID_INPUT_LENGTH);
|
||||
}
|
||||
|
||||
keymaster::AddEntropyRequest request(impl_->message_version());
|
||||
request.random_data.Reinitialize(data.data(), data.size());
|
||||
|
||||
keymaster::AddEntropyResponse response(impl_->message_version());
|
||||
impl_->AddRngEntropy(request, &response);
|
||||
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::generateKey(const vector<KeyParameter>& keyParams,
|
||||
const optional<AttestationKey>& attestationKey,
|
||||
KeyCreationResult* creationResult) {
|
||||
keymaster::GenerateKeyRequest request(impl_->message_version());
|
||||
request.key_description.Reinitialize(KmParamSet(keyParams));
|
||||
if (attestationKey) {
|
||||
request.attestation_signing_key_blob =
|
||||
KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
|
||||
request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
|
||||
request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
|
||||
attestationKey->issuerSubjectName.size());
|
||||
}
|
||||
|
||||
keymaster::GenerateKeyResponse response(impl_->message_version());
|
||||
impl_->GenerateKey(request, &response);
|
||||
|
||||
if (response.error != KM_ERROR_OK) return kmError2ScopedAStatus(response.error);
|
||||
|
||||
creationResult->keyBlob = kmBlob2vector(response.key_blob);
|
||||
creationResult->keyCharacteristics =
|
||||
convertKeyCharacteristics(response.unenforced, response.enforced);
|
||||
creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::getKeyCharacteristics(
|
||||
const vector<uint8_t>& keyBlob,
|
||||
const vector<uint8_t>& clientId, //
|
||||
const vector<uint8_t>& appData, //
|
||||
vector<KeyCharacteristics>* characteristics) {
|
||||
keymaster::GetKeyCharacteristicsRequest request(impl_->message_version());
|
||||
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
|
||||
addClientAndAppData(clientId, appData, &request.additional_params);
|
||||
|
||||
keymaster::GetKeyCharacteristicsResponse response(impl_->message_version());
|
||||
impl_->GetKeyCharacteristics(request, &response);
|
||||
|
||||
if (response.error != KM_ERROR_OK) return kmError2ScopedAStatus(response.error);
|
||||
|
||||
*characteristics = convertKeyCharacteristics(response.unenforced, response.enforced,
|
||||
false /* includeKeystoreEnforced */);
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::importKey(const vector<KeyParameter>& keyParams,
|
||||
KeyFormat keyFormat, const vector<uint8_t>& keyData,
|
||||
const optional<AttestationKey>& attestationKey,
|
||||
KeyCreationResult* creationResult) {
|
||||
keymaster::ImportKeyRequest request(impl_->message_version());
|
||||
request.key_description.Reinitialize(KmParamSet(keyParams));
|
||||
request.key_format = legacy_enum_conversion(keyFormat);
|
||||
request.key_data = KeymasterKeyBlob(keyData.data(), keyData.size());
|
||||
if (attestationKey) {
|
||||
request.attestation_signing_key_blob =
|
||||
KeymasterKeyBlob(attestationKey->keyBlob.data(), attestationKey->keyBlob.size());
|
||||
request.attest_key_params.Reinitialize(KmParamSet(attestationKey->attestKeyParams));
|
||||
request.issuer_subject = KeymasterBlob(attestationKey->issuerSubjectName.data(),
|
||||
attestationKey->issuerSubjectName.size());
|
||||
}
|
||||
|
||||
keymaster::ImportKeyResponse response(impl_->message_version());
|
||||
impl_->ImportKey(request, &response);
|
||||
|
||||
if (response.error != KM_ERROR_OK) {
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
creationResult->keyBlob = kmBlob2vector(response.key_blob);
|
||||
creationResult->keyCharacteristics =
|
||||
convertKeyCharacteristics(response.unenforced, response.enforced);
|
||||
creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
|
||||
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::importWrappedKey(const vector<uint8_t>& wrappedKeyData,
|
||||
const vector<uint8_t>& wrappingKeyBlob, //
|
||||
const vector<uint8_t>& maskingKey,
|
||||
const vector<KeyParameter>& unwrappingParams,
|
||||
int64_t passwordSid, //
|
||||
int64_t biometricSid,
|
||||
KeyCreationResult* creationResult) {
|
||||
keymaster::ImportWrappedKeyRequest request(impl_->message_version());
|
||||
request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
|
||||
request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
|
||||
request.SetMaskingKeyMaterial(maskingKey.data(), maskingKey.size());
|
||||
request.additional_params.Reinitialize(KmParamSet(unwrappingParams));
|
||||
request.password_sid = static_cast<uint64_t>(passwordSid);
|
||||
request.biometric_sid = static_cast<uint64_t>(biometricSid);
|
||||
|
||||
keymaster::ImportWrappedKeyResponse response(impl_->message_version());
|
||||
impl_->ImportWrappedKey(request, &response);
|
||||
|
||||
if (response.error != KM_ERROR_OK) {
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
creationResult->keyBlob = kmBlob2vector(response.key_blob);
|
||||
creationResult->keyCharacteristics =
|
||||
convertKeyCharacteristics(response.unenforced, response.enforced);
|
||||
creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
|
||||
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::upgradeKey(const vector<uint8_t>& keyBlobToUpgrade,
|
||||
const vector<KeyParameter>& upgradeParams,
|
||||
vector<uint8_t>* keyBlob) {
|
||||
keymaster::UpgradeKeyRequest request(impl_->message_version());
|
||||
request.SetKeyMaterial(keyBlobToUpgrade.data(), keyBlobToUpgrade.size());
|
||||
request.upgrade_params.Reinitialize(KmParamSet(upgradeParams));
|
||||
|
||||
keymaster::UpgradeKeyResponse response(impl_->message_version());
|
||||
impl_->UpgradeKey(request, &response);
|
||||
|
||||
if (response.error != KM_ERROR_OK) {
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
*keyBlob = kmBlob2vector(response.upgraded_key);
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
|
||||
keymaster::DeleteKeyRequest request(impl_->message_version());
|
||||
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
|
||||
|
||||
keymaster::DeleteKeyResponse response(impl_->message_version());
|
||||
impl_->DeleteKey(request, &response);
|
||||
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::deleteAllKeys() {
|
||||
// There's nothing to be done to delete software key blobs.
|
||||
keymaster::DeleteAllKeysRequest request(impl_->message_version());
|
||||
keymaster::DeleteAllKeysResponse response(impl_->message_version());
|
||||
impl_->DeleteAllKeys(request, &response);
|
||||
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::destroyAttestationIds() {
|
||||
return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::begin(KeyPurpose purpose, const vector<uint8_t>& keyBlob,
|
||||
const vector<KeyParameter>& params,
|
||||
const optional<HardwareAuthToken>& authToken,
|
||||
BeginResult* result) {
|
||||
keymaster::BeginOperationRequest request(impl_->message_version());
|
||||
request.purpose = legacy_enum_conversion(purpose);
|
||||
request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
|
||||
request.additional_params.Reinitialize(KmParamSet(params));
|
||||
|
||||
vector<uint8_t> vector_token = authToken2AidlVec(authToken);
|
||||
request.additional_params.push_back(
|
||||
TAG_AUTH_TOKEN, reinterpret_cast<uint8_t*>(vector_token.data()), vector_token.size());
|
||||
|
||||
keymaster::BeginOperationResponse response(impl_->message_version());
|
||||
impl_->BeginOperation(request, &response);
|
||||
|
||||
if (response.error != KM_ERROR_OK) {
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
result->params = kmParamSet2Aidl(response.output_params);
|
||||
result->challenge = response.op_handle;
|
||||
result->operation = ndk::SharedRefBase::make<TrustyKeyMintOperation>(impl_, response.op_handle);
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::deviceLocked(
|
||||
bool passwordOnly, const std::optional<secureclock::TimeStampToken>& timestampToken) {
|
||||
keymaster::DeviceLockedRequest request(impl_->message_version());
|
||||
request.passwordOnly = passwordOnly;
|
||||
if (timestampToken.has_value()) {
|
||||
request.token.challenge = timestampToken->challenge;
|
||||
request.token.mac = {timestampToken->mac.data(), timestampToken->mac.size()};
|
||||
request.token.timestamp = timestampToken->timestamp.milliSeconds;
|
||||
}
|
||||
keymaster::DeviceLockedResponse response = impl_->DeviceLocked(request);
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::earlyBootEnded() {
|
||||
keymaster::EarlyBootEndedResponse response = impl_->EarlyBootEnded();
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintDevice::convertStorageKeyToEphemeral(
|
||||
const std::vector<uint8_t>& storageKeyBlob, std::vector<uint8_t>* ephemeralKeyBlob) {
|
||||
keymaster::ExportKeyRequest request(impl_->message_version());
|
||||
request.SetKeyMaterial(storageKeyBlob.data(), storageKeyBlob.size());
|
||||
request.key_format = KM_KEY_FORMAT_RAW;
|
||||
|
||||
keymaster::ExportKeyResponse response(impl_->message_version());
|
||||
impl_->ExportKey(request, &response);
|
||||
|
||||
if (response.error != KM_ERROR_OK) return kmError2ScopedAStatus(response.error);
|
||||
if (response.key_data) {
|
||||
*ephemeralKeyBlob = {response.key_data, response.key_data + response.key_data_length};
|
||||
}
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::security::keymint::trusty
|
168
trusty/keymaster/keymint/TrustyKeyMintOperation.cpp
Normal file
168
trusty/keymaster/keymint/TrustyKeyMintOperation.cpp
Normal file
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
* Copyright 2021, The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <trusty_keymaster/TrustyKeyMintOperation.h>
|
||||
|
||||
#define TAG TrustyKeyMintOperation
|
||||
#include <android-base/logging.h>
|
||||
|
||||
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
|
||||
#include <aidl/android/hardware/security/secureclock/ISecureClock.h>
|
||||
|
||||
#include <KeyMintUtils.h>
|
||||
#include <keymaster/android_keymaster.h>
|
||||
#include <trusty_keymaster/ipc/trusty_keymaster_ipc.h>
|
||||
|
||||
namespace aidl::android::hardware::security::keymint {
|
||||
|
||||
using ::keymaster::AbortOperationRequest;
|
||||
using ::keymaster::AbortOperationResponse;
|
||||
using ::keymaster::FinishOperationRequest;
|
||||
using ::keymaster::FinishOperationResponse;
|
||||
using ::keymaster::TAG_ASSOCIATED_DATA;
|
||||
using ::keymaster::TAG_AUTH_TOKEN;
|
||||
using ::keymaster::UpdateOperationRequest;
|
||||
using ::keymaster::UpdateOperationResponse;
|
||||
using km_utils::authToken2AidlVec;
|
||||
using km_utils::kmError2ScopedAStatus;
|
||||
using secureclock::TimeStampToken;
|
||||
|
||||
TrustyKeyMintOperation::TrustyKeyMintOperation(shared_ptr<TrustyKeymaster> implementation,
|
||||
keymaster_operation_handle_t opHandle)
|
||||
: impl_(std::move(implementation)), opHandle_(opHandle) {}
|
||||
|
||||
TrustyKeyMintOperation::~TrustyKeyMintOperation() {
|
||||
if (opHandle_ != 0) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintOperation::updateAad(
|
||||
const vector<uint8_t>& input, const optional<HardwareAuthToken>& /* authToken */,
|
||||
const optional<TimeStampToken>& /* timestampToken */) {
|
||||
UpdateOperationRequest request(impl_->message_version());
|
||||
request.op_handle = opHandle_;
|
||||
request.additional_params.push_back(TAG_ASSOCIATED_DATA, input.data(), input.size());
|
||||
|
||||
UpdateOperationResponse response(impl_->message_version());
|
||||
impl_->UpdateOperation(request, &response);
|
||||
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintOperation::update(const vector<uint8_t>& input,
|
||||
const optional<HardwareAuthToken>& authToken,
|
||||
const optional<TimeStampToken>& /* timestampToken */,
|
||||
vector<uint8_t>* output) {
|
||||
if (!output) return kmError2ScopedAStatus(KM_ERROR_OUTPUT_PARAMETER_NULL);
|
||||
|
||||
UpdateOperationRequest request(impl_->message_version());
|
||||
request.op_handle = opHandle_;
|
||||
if (authToken) {
|
||||
auto tokenAsVec(authToken2AidlVec(*authToken));
|
||||
request.additional_params.push_back(TAG_AUTH_TOKEN, tokenAsVec.data(), tokenAsVec.size());
|
||||
}
|
||||
|
||||
size_t serialized_size = request.SerializedSize();
|
||||
if (serialized_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
|
||||
return kmError2ScopedAStatus(KM_ERROR_INVALID_INPUT_LENGTH);
|
||||
}
|
||||
|
||||
const uint8_t* input_pos = input.data();
|
||||
const uint8_t* input_end = input.data() + input.size();
|
||||
const size_t max_chunk_size = TRUSTY_KEYMASTER_SEND_BUF_SIZE - serialized_size;
|
||||
output->clear();
|
||||
|
||||
while (input_pos < input_end) {
|
||||
size_t to_send = std::min(max_chunk_size, static_cast<size_t>(input_end - input_pos));
|
||||
LOG(DEBUG) << "update: Sending " << to_send << " of " << (input_end - input_pos)
|
||||
<< " bytes";
|
||||
request.input.Reinitialize(input_pos, to_send);
|
||||
|
||||
UpdateOperationResponse response(impl_->message_version());
|
||||
impl_->UpdateOperation(request, &response);
|
||||
if (response.error != KM_ERROR_OK) {
|
||||
opHandle_ = 0; // Operation has ended, the handle is invalid. This saves an abort().
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
input_pos += response.input_consumed;
|
||||
output->insert(output->end(), response.output.begin(), response.output.end());
|
||||
}
|
||||
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintOperation::finish(
|
||||
const optional<vector<uint8_t>>& input, //
|
||||
const optional<vector<uint8_t>>& signature, //
|
||||
const optional<HardwareAuthToken>& authToken,
|
||||
const optional<TimeStampToken>& /* timestampToken */,
|
||||
const optional<vector<uint8_t>>& /* confirmationToken */, vector<uint8_t>* output) {
|
||||
if (!output) {
|
||||
return ScopedAStatus(AStatus_fromServiceSpecificError(
|
||||
static_cast<int32_t>(ErrorCode::OUTPUT_PARAMETER_NULL)));
|
||||
}
|
||||
output->clear();
|
||||
|
||||
FinishOperationRequest request(impl_->message_version());
|
||||
request.op_handle = opHandle_;
|
||||
if (signature) request.signature.Reinitialize(signature->data(), signature->size());
|
||||
size_t serialized_size = request.SerializedSize();
|
||||
if (serialized_size > TRUSTY_KEYMASTER_SEND_BUF_SIZE) {
|
||||
return kmError2ScopedAStatus(KM_ERROR_INVALID_INPUT_LENGTH);
|
||||
}
|
||||
|
||||
if (input) {
|
||||
const size_t max_chunk_size = TRUSTY_KEYMASTER_SEND_BUF_SIZE - serialized_size;
|
||||
|
||||
if (input->size() > max_chunk_size) {
|
||||
LOG(DEBUG) << "Sending an update to process finish() data";
|
||||
// Use update to process all but the last max_chunk_size bytes.
|
||||
auto result = update({input->begin(), input->end() - max_chunk_size}, authToken,
|
||||
std::nullopt /* timestampToken */, output);
|
||||
if (!result.isOk()) return result;
|
||||
|
||||
// Process the last max_chunk_size with finish.
|
||||
request.input.Reinitialize(input->data() + (input->size() - max_chunk_size),
|
||||
max_chunk_size);
|
||||
} else {
|
||||
request.input.Reinitialize(input->data(), input->size());
|
||||
}
|
||||
}
|
||||
|
||||
FinishOperationResponse response(impl_->message_version());
|
||||
impl_->FinishOperation(request, &response);
|
||||
opHandle_ = 0;
|
||||
|
||||
if (response.error != KM_ERROR_OK) return kmError2ScopedAStatus(response.error);
|
||||
|
||||
*output = {response.output.begin(), response.output.end()};
|
||||
return ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ScopedAStatus TrustyKeyMintOperation::abort() {
|
||||
AbortOperationRequest request(impl_->message_version());
|
||||
request.op_handle = opHandle_;
|
||||
|
||||
AbortOperationResponse response(impl_->message_version());
|
||||
impl_->AbortOperation(request, &response);
|
||||
opHandle_ = 0;
|
||||
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::security::keymint
|
42
trusty/keymaster/keymint/TrustySecureClock.cpp
Normal file
42
trusty/keymaster/keymint/TrustySecureClock.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright 2021, The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <trusty_keymaster/TrustySecureClock.h>
|
||||
|
||||
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
|
||||
|
||||
#include <KeyMintUtils.h>
|
||||
|
||||
namespace aidl::android::hardware::security::secureclock::trusty {
|
||||
|
||||
using keymint::km_utils::kmBlob2vector;
|
||||
using keymint::km_utils::kmError2ScopedAStatus;
|
||||
|
||||
::ndk::ScopedAStatus TrustySecureClock::generateTimeStamp(int64_t challenge,
|
||||
TimeStampToken* token) {
|
||||
keymaster::VerifyAuthorizationRequest request(impl_->message_version());
|
||||
request.challenge = challenge;
|
||||
|
||||
auto response = impl_->VerifyAuthorization(request);
|
||||
if (response.error != KM_ERROR_OK) return kmError2ScopedAStatus(response.error);
|
||||
|
||||
token->challenge = response.token.challenge;
|
||||
token->timestamp.milliSeconds = static_cast<int64_t>(response.token.timestamp);
|
||||
token->mac = kmBlob2vector(response.token.mac);
|
||||
return ::ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::security::secureclock::trusty
|
54
trusty/keymaster/keymint/TrustySharedSecret.cpp
Normal file
54
trusty/keymaster/keymint/TrustySharedSecret.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright 2020, The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <trusty_keymaster/TrustySharedSecret.h>
|
||||
|
||||
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
|
||||
#include <keymaster/android_keymaster.h>
|
||||
#include "KeyMintUtils.h"
|
||||
|
||||
namespace aidl::android::hardware::security::sharedsecret::trusty {
|
||||
|
||||
using keymint::km_utils::kmBlob2vector;
|
||||
using keymint::km_utils::kmError2ScopedAStatus;
|
||||
|
||||
::ndk::ScopedAStatus TrustySharedSecret::getSharedSecretParameters(SharedSecretParameters* params) {
|
||||
auto response = impl_->GetHmacSharingParameters();
|
||||
params->seed = kmBlob2vector(response.params.seed);
|
||||
params->nonce = {std::begin(response.params.nonce), std::end(response.params.nonce)};
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
::ndk::ScopedAStatus TrustySharedSecret::computeSharedSecret(
|
||||
const std::vector<SharedSecretParameters>& params, std::vector<uint8_t>* sharingCheck) {
|
||||
keymaster::ComputeSharedHmacRequest request(impl_->message_version());
|
||||
request.params_array.params_array = new keymaster::HmacSharingParameters[params.size()];
|
||||
request.params_array.num_params = params.size();
|
||||
for (size_t i = 0; i < params.size(); ++i) {
|
||||
request.params_array.params_array[i].seed = {params[i].seed.data(), params[i].seed.size()};
|
||||
if (sizeof(request.params_array.params_array[i].nonce) != params[i].nonce.size()) {
|
||||
return kmError2ScopedAStatus(KM_ERROR_INVALID_ARGUMENT);
|
||||
}
|
||||
memcpy(request.params_array.params_array[i].nonce, params[i].nonce.data(),
|
||||
params[i].nonce.size());
|
||||
}
|
||||
|
||||
auto response = impl_->ComputeSharedHmac(request);
|
||||
if (response.error == KM_ERROR_OK) *sharingCheck = kmBlob2vector(response.sharing_check);
|
||||
return kmError2ScopedAStatus(response.error);
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::security::sharedsecret::trusty
|
|
@ -0,0 +1,4 @@
|
|||
service vendor.keymint-trusty /vendor/bin/hw/android.hardware.security.keymint-service.trusty
|
||||
class early_hal
|
||||
user nobody
|
||||
group drmrpc
|
|
@ -0,0 +1,14 @@
|
|||
<manifest version="1.0" type="device">
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.security.keymint</name>
|
||||
<fqname>IKeyMintDevice/default</fqname>
|
||||
</hal>
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.security.secureclock</name>
|
||||
<fqname>ISecureClock/default</fqname>
|
||||
</hal>
|
||||
<hal format="aidl">
|
||||
<name>android.hardware.security.sharedsecret</name>
|
||||
<fqname>ISharedSecret/default</fqname>
|
||||
</hal>
|
||||
</manifest>
|
58
trusty/keymaster/keymint/service.cpp
Normal file
58
trusty/keymaster/keymint/service.cpp
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright 2021, The Android Open Source Project
|
||||
*
|
||||
* 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 "android.hardware.security.keymint-service.trusty"
|
||||
#include <android-base/logging.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
#include <trusty_keymaster/TrustyKeyMintDevice.h>
|
||||
#include <trusty_keymaster/TrustySecureClock.h>
|
||||
#include <trusty_keymaster/TrustySharedSecret.h>
|
||||
|
||||
using aidl::android::hardware::security::keymint::trusty::TrustyKeyMintDevice;
|
||||
using aidl::android::hardware::security::secureclock::trusty::TrustySecureClock;
|
||||
using aidl::android::hardware::security::sharedsecret::trusty::TrustySharedSecret;
|
||||
|
||||
template <typename T, class... Args>
|
||||
std::shared_ptr<T> addService(Args&&... args) {
|
||||
std::shared_ptr<T> service = std::make_shared<T>(std::forward<Args>(args)...);
|
||||
auto instanceName = std::string(T::descriptor) + "/default";
|
||||
LOG(ERROR) << "Adding service instance: " << instanceName;
|
||||
auto status = AServiceManager_addService(service->asBinder().get(), instanceName.c_str());
|
||||
CHECK(status == STATUS_OK) << "Failed to add service " << instanceName;
|
||||
return service;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto trustyKeymaster = std::make_shared<keymaster::TrustyKeymaster>();
|
||||
int err = trustyKeymaster->Initialize(keymaster::KmVersion::KEYMINT_1);
|
||||
if (err != 0) {
|
||||
LOG(FATAL) << "Could not initialize TrustyKeymaster for KeyMint (" << err << ")";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Zero threads seems like a useless pool but below we'll join this thread to it, increasing
|
||||
// the pool size to 1.
|
||||
ABinderProcess_setThreadPoolMaxThreadCount(0);
|
||||
|
||||
auto keyMint = addService<TrustyKeyMintDevice>(trustyKeymaster);
|
||||
auto secureClock = addService<TrustySecureClock>(trustyKeymaster);
|
||||
auto sharedSecret = addService<TrustySharedSecret>(trustyKeymaster);
|
||||
|
||||
ABinderProcess_joinThreadPool();
|
||||
return EXIT_FAILURE; // should not reach
|
||||
}
|
Loading…
Reference in a new issue