Merge changes from topic 'trusty_km2_hal'
am: a4b40020ef
Change-Id: I31e2ef8b8a41876cc6c2288abde798e261d00247
This commit is contained in:
commit
e53621c1f2
8 changed files with 847 additions and 518 deletions
|
@ -32,7 +32,7 @@ include $(CLEAR_VARS)
|
|||
LOCAL_MODULE := trusty_keymaster_tipc
|
||||
LOCAL_SRC_FILES := \
|
||||
trusty_keymaster_device.cpp \
|
||||
trusty_keymaster_ipc.c \
|
||||
trusty_keymaster_ipc.cpp \
|
||||
trusty_keymaster_main.cpp
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libcrypto \
|
||||
|
@ -40,6 +40,7 @@ LOCAL_SHARED_LIBRARIES := \
|
|||
libkeymaster1 \
|
||||
libtrusty \
|
||||
libkeymaster_messages \
|
||||
libsoftkeymasterdevice \
|
||||
liblog
|
||||
|
||||
include $(BUILD_EXECUTABLE)
|
||||
|
@ -53,7 +54,7 @@ include $(CLEAR_VARS)
|
|||
LOCAL_MODULE := keystore.trusty
|
||||
LOCAL_MODULE_RELATIVE_PATH := hw
|
||||
LOCAL_SRC_FILES := module.cpp \
|
||||
trusty_keymaster_ipc.c \
|
||||
trusty_keymaster_ipc.cpp \
|
||||
trusty_keymaster_device.cpp
|
||||
LOCAL_CLFAGS = -fvisibility=hidden -Wall -Werror
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
|
|
|
@ -16,13 +16,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
// clang-format off
|
||||
|
||||
#define KEYMASTER_PORT "com.android.trusty.keymaster"
|
||||
#define KEYMASTER_MAX_BUFFER_LENGTH 4096
|
||||
|
||||
// Commands
|
||||
enum keymaster_command {
|
||||
KEYMASTER_RESP_BIT = 1,
|
||||
KEYMASTER_REQ_SHIFT = 1,
|
||||
enum keymaster_command : uint32_t {
|
||||
KEYMASTER_RESP_BIT = 1,
|
||||
KEYMASTER_REQ_SHIFT = 1,
|
||||
|
||||
KM_GENERATE_KEY = (0 << KEYMASTER_REQ_SHIFT),
|
||||
KM_BEGIN_OPERATION = (1 << KEYMASTER_REQ_SHIFT),
|
||||
|
@ -40,6 +42,9 @@ enum keymaster_command {
|
|||
KM_GET_SUPPORTED_IMPORT_FORMATS = (13 << KEYMASTER_REQ_SHIFT),
|
||||
KM_GET_SUPPORTED_EXPORT_FORMATS = (14 << KEYMASTER_REQ_SHIFT),
|
||||
KM_GET_KEY_CHARACTERISTICS = (15 << KEYMASTER_REQ_SHIFT),
|
||||
KM_ATTEST_KEY = (16 << KEYMASTER_REQ_SHIFT),
|
||||
KM_UPGRADE_KEY = (17 << KEYMASTER_REQ_SHIFT),
|
||||
KM_CONFIGURE = (18 << KEYMASTER_REQ_SHIFT),
|
||||
};
|
||||
|
||||
#ifdef __ANDROID__
|
||||
|
@ -50,8 +55,8 @@ enum keymaster_command {
|
|||
* @payload: start of the serialized command specific payload
|
||||
*/
|
||||
struct keymaster_message {
|
||||
uint32_t cmd;
|
||||
uint8_t payload[0];
|
||||
uint32_t cmd;
|
||||
uint8_t payload[0];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,14 +26,15 @@ using keymaster::TrustyKeymasterDevice;
|
|||
/*
|
||||
* Generic device handling
|
||||
*/
|
||||
static int trusty_keymaster_open(const hw_module_t* module, const char* name,
|
||||
hw_device_t** device) {
|
||||
if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
|
||||
static int trusty_keymaster_open(const hw_module_t* module, const char* name, hw_device_t** device) {
|
||||
if (strcmp(name, KEYSTORE_KEYMASTER) != 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
TrustyKeymasterDevice* dev = new TrustyKeymasterDevice(module);
|
||||
if (dev == NULL)
|
||||
if (dev == NULL) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
*device = dev->hw_device();
|
||||
// Do not delete dev; it will get cleaned up when the caller calls device->close(), and must
|
||||
// exist until then.
|
||||
|
@ -47,14 +48,14 @@ static struct hw_module_methods_t keystore_module_methods = {
|
|||
struct keystore_module HAL_MODULE_INFO_SYM __attribute__((visibility("default"))) = {
|
||||
.common =
|
||||
{
|
||||
.tag = HARDWARE_MODULE_TAG,
|
||||
.module_api_version = KEYMASTER_MODULE_API_VERSION_0_3,
|
||||
.hal_api_version = HARDWARE_HAL_API_VERSION,
|
||||
.id = KEYSTORE_HARDWARE_MODULE_ID,
|
||||
.name = "Trusty Keymaster HAL",
|
||||
.author = "The Android Open Source Project",
|
||||
.methods = &keystore_module_methods,
|
||||
.dso = 0,
|
||||
.reserved = {},
|
||||
.tag = HARDWARE_MODULE_TAG,
|
||||
.module_api_version = KEYMASTER_MODULE_API_VERSION_2_0,
|
||||
.hal_api_version = HARDWARE_HAL_API_VERSION,
|
||||
.id = KEYSTORE_HARDWARE_MODULE_ID,
|
||||
.name = "Trusty Keymaster HAL",
|
||||
.author = "The Android Open Source Project",
|
||||
.methods = &keystore_module_methods,
|
||||
.dso = 0,
|
||||
.reserved = {},
|
||||
},
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -14,19 +14,16 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef EXTERNAL_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
|
||||
#define EXTERNAL_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
|
||||
|
||||
#include <hardware/keymaster0.h>
|
||||
#ifndef TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
|
||||
#define TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
|
||||
|
||||
#include <hardware/keymaster2.h>
|
||||
#include <keymaster/android_keymaster_messages.h>
|
||||
|
||||
#include "keymaster_ipc.h"
|
||||
|
||||
namespace keymaster {
|
||||
|
||||
/**
|
||||
* Software OpenSSL-based Keymaster device.
|
||||
* Trusty Keymaster device.
|
||||
*
|
||||
* IMPORTANT MAINTAINER NOTE: Pointers to instances of this class must be castable to hw_device_t
|
||||
* and keymaster_device. This means it must remain a standard layout class (no virtual functions and
|
||||
|
@ -46,79 +43,111 @@ class TrustyKeymasterDevice {
|
|||
|
||||
keymaster_error_t session_error() { return error_; }
|
||||
|
||||
int generate_keypair(const keymaster_keypair_t key_type, const void* key_params,
|
||||
uint8_t** key_blob, size_t* key_blob_length);
|
||||
int import_keypair(const uint8_t* key, const size_t key_length, uint8_t** key_blob,
|
||||
size_t* key_blob_length);
|
||||
int get_keypair_public(const uint8_t* key_blob, const size_t key_blob_length,
|
||||
uint8_t** x509_data, size_t* x509_data_length);
|
||||
int sign_data(const void* signing_params, const uint8_t* key_blob, const size_t key_blob_length,
|
||||
const uint8_t* data, const size_t data_length, uint8_t** signed_data,
|
||||
size_t* signed_data_length);
|
||||
int verify_data(const void* signing_params, const uint8_t* key_blob,
|
||||
const size_t key_blob_length, const uint8_t* signed_data,
|
||||
const size_t signed_data_length, const uint8_t* signature,
|
||||
const size_t signature_length);
|
||||
keymaster_error_t configure(const keymaster_key_param_set_t* params);
|
||||
keymaster_error_t add_rng_entropy(const uint8_t* data, size_t data_length);
|
||||
keymaster_error_t generate_key(const keymaster_key_param_set_t* params,
|
||||
keymaster_key_blob_t* key_blob,
|
||||
keymaster_key_characteristics_t* characteristics);
|
||||
keymaster_error_t get_key_characteristics(const keymaster_key_blob_t* key_blob,
|
||||
const keymaster_blob_t* client_id,
|
||||
const keymaster_blob_t* app_data,
|
||||
keymaster_key_characteristics_t* character);
|
||||
keymaster_error_t import_key(const keymaster_key_param_set_t* params,
|
||||
keymaster_key_format_t key_format,
|
||||
const keymaster_blob_t* key_data, keymaster_key_blob_t* key_blob,
|
||||
keymaster_key_characteristics_t* characteristics);
|
||||
keymaster_error_t export_key(keymaster_key_format_t export_format,
|
||||
const keymaster_key_blob_t* key_to_export,
|
||||
const keymaster_blob_t* client_id,
|
||||
const keymaster_blob_t* app_data, keymaster_blob_t* export_data);
|
||||
keymaster_error_t attest_key(const keymaster_key_blob_t* key_to_attest,
|
||||
const keymaster_key_param_set_t* attest_params,
|
||||
keymaster_cert_chain_t* cert_chain);
|
||||
keymaster_error_t upgrade_key(const keymaster_key_blob_t* key_to_upgrade,
|
||||
const keymaster_key_param_set_t* upgrade_params,
|
||||
keymaster_key_blob_t* upgraded_key);
|
||||
keymaster_error_t begin(keymaster_purpose_t purpose, const keymaster_key_blob_t* key,
|
||||
const keymaster_key_param_set_t* in_params,
|
||||
keymaster_key_param_set_t* out_params,
|
||||
keymaster_operation_handle_t* operation_handle);
|
||||
keymaster_error_t update(keymaster_operation_handle_t operation_handle,
|
||||
const keymaster_key_param_set_t* in_params,
|
||||
const keymaster_blob_t* input, size_t* input_consumed,
|
||||
keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
|
||||
keymaster_error_t finish(keymaster_operation_handle_t operation_handle,
|
||||
const keymaster_key_param_set_t* in_params,
|
||||
const keymaster_blob_t* input, const keymaster_blob_t* signature,
|
||||
keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
|
||||
keymaster_error_t abort(keymaster_operation_handle_t operation_handle);
|
||||
|
||||
private:
|
||||
keymaster_error_t Send(uint32_t command, const Serializable& request,
|
||||
KeymasterResponse* response);
|
||||
keymaster_error_t Send(const GenerateKeyRequest& request, GenerateKeyResponse* response) {
|
||||
return Send(KM_GENERATE_KEY, request, response);
|
||||
}
|
||||
keymaster_error_t Send(const BeginOperationRequest& request, BeginOperationResponse* response) {
|
||||
return Send(KM_BEGIN_OPERATION, request, response);
|
||||
}
|
||||
keymaster_error_t Send(const UpdateOperationRequest& request,
|
||||
UpdateOperationResponse* response) {
|
||||
return Send(KM_UPDATE_OPERATION, request, response);
|
||||
}
|
||||
keymaster_error_t Send(const FinishOperationRequest& request,
|
||||
FinishOperationResponse* response) {
|
||||
return Send(KM_FINISH_OPERATION, request, response);
|
||||
}
|
||||
keymaster_error_t Send(const ImportKeyRequest& request, ImportKeyResponse* response) {
|
||||
return Send(KM_IMPORT_KEY, request, response);
|
||||
}
|
||||
keymaster_error_t Send(const ExportKeyRequest& request, ExportKeyResponse* response) {
|
||||
return Send(KM_EXPORT_KEY, request, response);
|
||||
}
|
||||
keymaster_error_t Send(const GetVersionRequest& request, GetVersionResponse* response) {
|
||||
return Send(KM_GET_VERSION, request, response);
|
||||
}
|
||||
|
||||
keymaster_error_t StoreSigningParams(const void* signing_params, const uint8_t* key_blob,
|
||||
size_t key_blob_length, AuthorizationSet* auth_set);
|
||||
void StoreNewKeyParams(AuthorizationSet* auth_set);
|
||||
keymaster_error_t GetPkcs8KeyAlgorithm(const uint8_t* key, size_t key_length,
|
||||
keymaster_algorithm_t* algorithm);
|
||||
|
||||
/*
|
||||
* These static methods are the functions referenced through the function pointers in
|
||||
* keymaster_device. They're all trivial wrappers.
|
||||
*/
|
||||
static int close_device(hw_device_t* dev);
|
||||
static int generate_keypair(const keymaster0_device_t* dev, const keymaster_keypair_t key_type,
|
||||
const void* key_params, uint8_t** keyBlob, size_t* keyBlobLength);
|
||||
static int import_keypair(const keymaster0_device_t* dev, const uint8_t* key,
|
||||
const size_t key_length, uint8_t** key_blob, size_t* key_blob_length);
|
||||
static int get_keypair_public(const keymaster0_device_t* dev, const uint8_t* key_blob,
|
||||
const size_t key_blob_length, uint8_t** x509_data,
|
||||
size_t* x509_data_length);
|
||||
static int sign_data(const keymaster0_device_t* dev, const void* signing_params,
|
||||
const uint8_t* key_blob, const size_t key_blob_length, const uint8_t* data,
|
||||
const size_t data_length, uint8_t** signed_data,
|
||||
size_t* signed_data_length);
|
||||
static int verify_data(const keymaster0_device_t* dev, const void* signing_params,
|
||||
const uint8_t* key_blob, const size_t key_blob_length,
|
||||
const uint8_t* signed_data, const size_t signed_data_length,
|
||||
const uint8_t* signature, const size_t signature_length);
|
||||
static keymaster_error_t configure(const keymaster2_device_t* dev,
|
||||
const keymaster_key_param_set_t* params);
|
||||
static keymaster_error_t add_rng_entropy(const keymaster2_device_t* dev, const uint8_t* data,
|
||||
size_t data_length);
|
||||
static keymaster_error_t generate_key(const keymaster2_device_t* dev,
|
||||
const keymaster_key_param_set_t* params,
|
||||
keymaster_key_blob_t* key_blob,
|
||||
keymaster_key_characteristics_t* characteristics);
|
||||
static keymaster_error_t get_key_characteristics(const keymaster2_device_t* dev,
|
||||
const keymaster_key_blob_t* key_blob,
|
||||
const keymaster_blob_t* client_id,
|
||||
const keymaster_blob_t* app_data,
|
||||
keymaster_key_characteristics_t* character);
|
||||
static keymaster_error_t import_key(const keymaster2_device_t* dev,
|
||||
const keymaster_key_param_set_t* params,
|
||||
keymaster_key_format_t key_format,
|
||||
const keymaster_blob_t* key_data,
|
||||
keymaster_key_blob_t* key_blob,
|
||||
keymaster_key_characteristics_t* characteristics);
|
||||
static keymaster_error_t export_key(const keymaster2_device_t* dev,
|
||||
keymaster_key_format_t export_format,
|
||||
const keymaster_key_blob_t* key_to_export,
|
||||
const keymaster_blob_t* client_id,
|
||||
const keymaster_blob_t* app_data,
|
||||
keymaster_blob_t* export_data);
|
||||
static keymaster_error_t attest_key(const keymaster2_device_t* dev,
|
||||
const keymaster_key_blob_t* key_to_attest,
|
||||
const keymaster_key_param_set_t* attest_params,
|
||||
keymaster_cert_chain_t* cert_chain);
|
||||
static keymaster_error_t upgrade_key(const keymaster2_device_t* dev,
|
||||
const keymaster_key_blob_t* key_to_upgrade,
|
||||
const keymaster_key_param_set_t* upgrade_params,
|
||||
keymaster_key_blob_t* upgraded_key);
|
||||
static keymaster_error_t delete_key(const keymaster2_device_t* dev,
|
||||
const keymaster_key_blob_t* key);
|
||||
static keymaster_error_t delete_all_keys(const keymaster2_device_t* dev);
|
||||
static keymaster_error_t begin(const keymaster2_device_t* dev, keymaster_purpose_t purpose,
|
||||
const keymaster_key_blob_t* key,
|
||||
const keymaster_key_param_set_t* in_params,
|
||||
keymaster_key_param_set_t* out_params,
|
||||
keymaster_operation_handle_t* operation_handle);
|
||||
static keymaster_error_t update(const keymaster2_device_t* dev,
|
||||
keymaster_operation_handle_t operation_handle,
|
||||
const keymaster_key_param_set_t* in_params,
|
||||
const keymaster_blob_t* input, size_t* input_consumed,
|
||||
keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
|
||||
static keymaster_error_t finish(const keymaster2_device_t* dev,
|
||||
keymaster_operation_handle_t operation_handle,
|
||||
const keymaster_key_param_set_t* in_params,
|
||||
const keymaster_blob_t* input, const keymaster_blob_t* signature,
|
||||
keymaster_key_param_set_t* out_params, keymaster_blob_t* output);
|
||||
static keymaster_error_t abort(const keymaster2_device_t* dev,
|
||||
keymaster_operation_handle_t operation_handle);
|
||||
|
||||
keymaster0_device_t device_;
|
||||
keymaster2_device_t device_;
|
||||
keymaster_error_t error_;
|
||||
int32_t message_version_;
|
||||
};
|
||||
|
||||
} // namespace keymaster
|
||||
|
||||
#endif // EXTERNAL_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
|
||||
#endif // TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_DEVICE_H_
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
#include <log/log.h>
|
||||
#include <trusty/tipc.h>
|
||||
|
||||
#include "trusty_keymaster_ipc.h"
|
||||
#include "keymaster_ipc.h"
|
||||
#include "trusty_keymaster_ipc.h"
|
||||
|
||||
#define TRUSTY_DEVICE_NAME "/dev/trusty-ipc-dev0"
|
||||
|
||||
|
@ -43,15 +43,15 @@ int trusty_keymaster_connect() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int trusty_keymaster_call(uint32_t cmd, void *in, uint32_t in_size, uint8_t *out,
|
||||
uint32_t *out_size) {
|
||||
int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
|
||||
uint32_t* out_size) {
|
||||
if (handle_ == 0) {
|
||||
ALOGE("not connected\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size_t msg_size = in_size + sizeof(struct keymaster_message);
|
||||
struct keymaster_message *msg = malloc(msg_size);
|
||||
struct keymaster_message* msg = reinterpret_cast<struct keymaster_message*>(malloc(msg_size));
|
||||
msg->cmd = cmd;
|
||||
memcpy(msg->payload, in, in_size);
|
||||
|
||||
|
@ -59,31 +59,30 @@ int trusty_keymaster_call(uint32_t cmd, void *in, uint32_t in_size, uint8_t *out
|
|||
free(msg);
|
||||
|
||||
if (rc < 0) {
|
||||
ALOGE("failed to send cmd (%d) to %s: %s\n", cmd,
|
||||
KEYMASTER_PORT, strerror(errno));
|
||||
ALOGE("failed to send cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
rc = read(handle_, out, *out_size);
|
||||
if (rc < 0) {
|
||||
ALOGE("failed to retrieve response for cmd (%d) to %s: %s\n",
|
||||
cmd, KEYMASTER_PORT, strerror(errno));
|
||||
ALOGE("failed to retrieve response for cmd (%d) to %s: %s\n", cmd, KEYMASTER_PORT,
|
||||
strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if ((size_t) rc < sizeof(struct keymaster_message)) {
|
||||
ALOGE("invalid response size (%d)\n", (int) rc);
|
||||
if ((size_t)rc < sizeof(struct keymaster_message)) {
|
||||
ALOGE("invalid response size (%d)\n", (int)rc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msg = (struct keymaster_message *) out;
|
||||
msg = (struct keymaster_message*)out;
|
||||
|
||||
if ((cmd | KEYMASTER_RESP_BIT) != msg->cmd) {
|
||||
ALOGE("invalid command (%d)", msg->cmd);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*out_size = ((size_t) rc) - sizeof(struct keymaster_message);
|
||||
*out_size = ((size_t)rc) - sizeof(struct keymaster_message);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -92,4 +91,3 @@ void trusty_keymaster_disconnect() {
|
|||
tipc_close(handle_);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,11 +14,16 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_IPC_H_
|
||||
#define TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_IPC_H_
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int trusty_keymaster_connect(void);
|
||||
int trusty_keymaster_call(uint32_t cmd, void *in, uint32_t in_size, uint8_t *out,
|
||||
uint32_t *out_size);
|
||||
int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out,
|
||||
uint32_t* out_size);
|
||||
void trusty_keymaster_disconnect(void);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif // TRUSTY_KEYMASTER_TRUSTY_KEYMASTER_IPC_H_
|
||||
|
|
|
@ -14,7 +14,10 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <keymaster/keymaster_configuration.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <memory>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
|
@ -102,6 +105,28 @@ unsigned char ec_privkey_pk8_der[] = {
|
|||
0xd1, 0x1f, 0xd4, 0x49, 0x49, 0xe0, 0xb2, 0x18, 0x3b, 0xfe};
|
||||
unsigned int ec_privkey_pk8_der_len = 138;
|
||||
|
||||
keymaster_key_param_t ec_params[] = {
|
||||
keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_EC),
|
||||
keymaster_param_long(KM_TAG_EC_CURVE, KM_EC_CURVE_P_521),
|
||||
keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN),
|
||||
keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY),
|
||||
keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
|
||||
keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED),
|
||||
};
|
||||
keymaster_key_param_set_t ec_param_set = {ec_params, sizeof(ec_params) / sizeof(*ec_params)};
|
||||
|
||||
keymaster_key_param_t rsa_params[] = {
|
||||
keymaster_param_enum(KM_TAG_ALGORITHM, KM_ALGORITHM_RSA),
|
||||
keymaster_param_int(KM_TAG_KEY_SIZE, 1024),
|
||||
keymaster_param_long(KM_TAG_RSA_PUBLIC_EXPONENT, 65537),
|
||||
keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_SIGN),
|
||||
keymaster_param_enum(KM_TAG_PURPOSE, KM_PURPOSE_VERIFY),
|
||||
keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE),
|
||||
keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
|
||||
keymaster_param_bool(KM_TAG_NO_AUTH_REQUIRED),
|
||||
};
|
||||
keymaster_key_param_set_t rsa_param_set = {rsa_params, sizeof(rsa_params) / sizeof(*rsa_params)};
|
||||
|
||||
struct EVP_PKEY_Delete {
|
||||
void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
|
||||
};
|
||||
|
@ -110,41 +135,70 @@ struct EVP_PKEY_CTX_Delete {
|
|||
void operator()(EVP_PKEY_CTX* p) { EVP_PKEY_CTX_free(p); }
|
||||
};
|
||||
|
||||
static bool do_operation(TrustyKeymasterDevice* device, keymaster_purpose_t purpose,
|
||||
keymaster_key_blob_t* key, keymaster_blob_t* input,
|
||||
keymaster_blob_t* signature, keymaster_blob_t* output) {
|
||||
keymaster_key_param_t params[] = {
|
||||
keymaster_param_enum(KM_TAG_PADDING, KM_PAD_NONE),
|
||||
keymaster_param_enum(KM_TAG_DIGEST, KM_DIGEST_NONE),
|
||||
};
|
||||
keymaster_key_param_set_t param_set = {params, sizeof(params) / sizeof(*params)};
|
||||
keymaster_operation_handle_t op_handle;
|
||||
keymaster_error_t error = device->begin(purpose, key, ¶m_set, nullptr, &op_handle);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Keymaster begin() failed: %d\n", error);
|
||||
return false;
|
||||
}
|
||||
size_t input_consumed;
|
||||
error = device->update(op_handle, nullptr, input, &input_consumed, nullptr, nullptr);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Keymaster update() failed: %d\n", error);
|
||||
return false;
|
||||
}
|
||||
if (input_consumed != input->data_length) {
|
||||
// This should never happen. If it does, it's a bug in the keymaster implementation.
|
||||
printf("Keymaster update() did not consume all data.\n");
|
||||
device->abort(op_handle);
|
||||
return false;
|
||||
}
|
||||
error = device->finish(op_handle, nullptr, nullptr, signature, nullptr, output);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Keymaster finish() failed: %d\n", error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool test_import_rsa(TrustyKeymasterDevice* device) {
|
||||
printf("===================\n");
|
||||
printf("= RSA Import Test =\n");
|
||||
printf("===================\n\n");
|
||||
|
||||
printf("=== Importing RSA keypair === \n");
|
||||
uint8_t* key;
|
||||
size_t size;
|
||||
int error = device->import_keypair(rsa_privkey_pk8_der, rsa_privkey_pk8_der_len, &key, &size);
|
||||
keymaster_key_blob_t key;
|
||||
keymaster_blob_t private_key = {rsa_privkey_pk8_der, rsa_privkey_pk8_der_len};
|
||||
int error = device->import_key(&rsa_param_set, KM_KEY_FORMAT_PKCS8, &private_key, &key, nullptr);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error importing key pair: %d\n\n", error);
|
||||
printf("Error importing RSA key: %d\n\n", error);
|
||||
return false;
|
||||
}
|
||||
UniquePtr<uint8_t[]> key_deleter(key);
|
||||
std::unique_ptr<const uint8_t[]> key_deleter(key.key_material);
|
||||
|
||||
printf("=== Signing with imported RSA key ===\n");
|
||||
keymaster_rsa_sign_params_t sign_params = {DIGEST_NONE, PADDING_NONE};
|
||||
size_t message_len = 1024 / 8;
|
||||
UniquePtr<uint8_t[]> message(new uint8_t[message_len]);
|
||||
std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
|
||||
memset(message.get(), 'a', message_len);
|
||||
uint8_t* signature;
|
||||
size_t signature_len;
|
||||
error = device->sign_data(&sign_params, key, size, message.get(), message_len, &signature,
|
||||
&signature_len);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error signing data with imported RSA key: %d\n\n", error);
|
||||
keymaster_blob_t input = {message.get(), message_len}, signature;
|
||||
|
||||
if (!do_operation(device, KM_PURPOSE_SIGN, &key, &input, nullptr, &signature)) {
|
||||
printf("Error signing data with imported RSA key\n\n");
|
||||
return false;
|
||||
}
|
||||
UniquePtr<uint8_t[]> signature_deleter(signature);
|
||||
std::unique_ptr<const uint8_t[]> signature_deleter(signature.data);
|
||||
|
||||
printf("=== Verifying with imported RSA key === \n");
|
||||
error = device->verify_data(&sign_params, key, size, message.get(), message_len, signature,
|
||||
signature_len);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error verifying data with imported RSA key: %d\n\n", error);
|
||||
if (!do_operation(device, KM_PURPOSE_VERIFY, &key, &input, &signature, nullptr)) {
|
||||
printf("Error verifying data with imported RSA key\n\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -158,67 +212,58 @@ static bool test_rsa(TrustyKeymasterDevice* device) {
|
|||
printf("============\n\n");
|
||||
|
||||
printf("=== Generating RSA key pair ===\n");
|
||||
keymaster_rsa_keygen_params_t params;
|
||||
params.public_exponent = 65537;
|
||||
params.modulus_size = 2048;
|
||||
|
||||
uint8_t* key;
|
||||
size_t size;
|
||||
int error = device->generate_keypair(TYPE_RSA, ¶ms, &key, &size);
|
||||
keymaster_key_blob_t key;
|
||||
int error = device->generate_key(&rsa_param_set, &key, nullptr);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error generating RSA key pair: %d\n\n", error);
|
||||
return false;
|
||||
}
|
||||
UniquePtr<uint8_t[]> deleter(key);
|
||||
std::unique_ptr<const uint8_t[]> key_deleter(key.key_material);
|
||||
|
||||
printf("=== Signing with RSA key === \n");
|
||||
keymaster_rsa_sign_params_t sign_params = {DIGEST_NONE, PADDING_NONE};
|
||||
size_t message_len = params.modulus_size / 8;
|
||||
UniquePtr<uint8_t[]> message(new uint8_t[message_len]);
|
||||
size_t message_len = 1024 / 8;
|
||||
std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
|
||||
memset(message.get(), 'a', message_len);
|
||||
uint8_t* signature;
|
||||
size_t signature_len;
|
||||
error = device->sign_data(&sign_params, key, size, message.get(), message_len, &signature,
|
||||
&signature_len);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error signing data with RSA key: %d\n\n", error);
|
||||
keymaster_blob_t input = {message.get(), message_len}, signature;
|
||||
|
||||
if (!do_operation(device, KM_PURPOSE_SIGN, &key, &input, nullptr, &signature)) {
|
||||
printf("Error signing data with RSA key\n\n");
|
||||
return false;
|
||||
}
|
||||
UniquePtr<uint8_t[]> signature_deleter(signature);
|
||||
std::unique_ptr<const uint8_t[]> signature_deleter(signature.data);
|
||||
|
||||
printf("=== Verifying with RSA key === \n");
|
||||
error = device->verify_data(&sign_params, key, size, message.get(), message_len, signature,
|
||||
signature_len);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error verifying data with RSA key: %d\n\n", error);
|
||||
if (!do_operation(device, KM_PURPOSE_VERIFY, &key, &input, &signature, nullptr)) {
|
||||
printf("Error verifying data with RSA key\n\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("=== Exporting RSA public key ===\n");
|
||||
uint8_t* exported_key;
|
||||
size_t exported_size;
|
||||
error = device->get_keypair_public(key, size, &exported_key, &exported_size);
|
||||
keymaster_blob_t exported_key;
|
||||
error = device->export_key(KM_KEY_FORMAT_X509, &key, nullptr, nullptr, &exported_key);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error exporting RSA public key: %d\n\n", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("=== Verifying with exported key ===\n");
|
||||
const uint8_t* tmp = exported_key;
|
||||
UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(d2i_PUBKEY(NULL, &tmp, exported_size));
|
||||
UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
|
||||
const uint8_t* tmp = exported_key.data;
|
||||
std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
|
||||
d2i_PUBKEY(NULL, &tmp, exported_key.data_length));
|
||||
std::unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
|
||||
if (EVP_PKEY_verify_init(ctx.get()) != 1) {
|
||||
printf("Error initializing openss EVP context\n");
|
||||
printf("Error initializing openss EVP context\n\n");
|
||||
return false;
|
||||
}
|
||||
if (EVP_PKEY_type(pkey->type) != EVP_PKEY_RSA) {
|
||||
printf("Exported key was the wrong type?!?\n");
|
||||
printf("Exported key was the wrong type?!?\n\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_NO_PADDING);
|
||||
if (EVP_PKEY_verify(ctx.get(), signature, signature_len, message.get(), message_len) != 1) {
|
||||
printf("Verification with exported pubkey failed.\n");
|
||||
if (EVP_PKEY_verify(ctx.get(), signature.data, signature.data_length, message.get(),
|
||||
message_len) != 1) {
|
||||
printf("Verification with exported pubkey failed.\n\n");
|
||||
return false;
|
||||
} else {
|
||||
printf("Verification succeeded\n");
|
||||
|
@ -234,35 +279,31 @@ static bool test_import_ecdsa(TrustyKeymasterDevice* device) {
|
|||
printf("=====================\n\n");
|
||||
|
||||
printf("=== Importing ECDSA keypair === \n");
|
||||
uint8_t* key;
|
||||
size_t size;
|
||||
int error = device->import_keypair(ec_privkey_pk8_der, ec_privkey_pk8_der_len, &key, &size);
|
||||
keymaster_key_blob_t key;
|
||||
keymaster_blob_t private_key = {ec_privkey_pk8_der, ec_privkey_pk8_der_len};
|
||||
int error = device->import_key(&ec_param_set, KM_KEY_FORMAT_PKCS8, &private_key, &key, nullptr);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error importing key pair: %d\n\n", error);
|
||||
printf("Error importing ECDSA key: %d\n\n", error);
|
||||
return false;
|
||||
}
|
||||
UniquePtr<uint8_t[]> deleter(key);
|
||||
std::unique_ptr<const uint8_t[]> deleter(key.key_material);
|
||||
|
||||
printf("=== Signing with imported ECDSA key ===\n");
|
||||
keymaster_ec_sign_params_t sign_params = {DIGEST_NONE};
|
||||
size_t message_len = 30 /* arbitrary */;
|
||||
UniquePtr<uint8_t[]> message(new uint8_t[message_len]);
|
||||
std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
|
||||
memset(message.get(), 'a', message_len);
|
||||
uint8_t* signature;
|
||||
size_t signature_len;
|
||||
error = device->sign_data(&sign_params, key, size, message.get(), message_len, &signature,
|
||||
&signature_len);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error signing data with imported ECDSA key: %d\n\n", error);
|
||||
keymaster_blob_t input = {message.get(), message_len}, signature;
|
||||
|
||||
if (!do_operation(device, KM_PURPOSE_SIGN, &key, &input, nullptr, &signature)) {
|
||||
printf("Error signing data with imported ECDSA key\n\n");
|
||||
return false;
|
||||
}
|
||||
UniquePtr<uint8_t[]> signature_deleter(signature);
|
||||
std::unique_ptr<const uint8_t[]> signature_deleter(signature.data);
|
||||
|
||||
printf("=== Verifying with imported ECDSA key === \n");
|
||||
error = device->verify_data(&sign_params, key, size, message.get(), message_len, signature,
|
||||
signature_len);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error verifying data with imported ECDSA key: %d\n\n", error);
|
||||
if (!do_operation(device, KM_PURPOSE_VERIFY, &key, &input, &signature, nullptr)) {
|
||||
printf("Error verifying data with imported ECDSA key\n\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -276,64 +317,57 @@ static bool test_ecdsa(TrustyKeymasterDevice* device) {
|
|||
printf("==============\n\n");
|
||||
|
||||
printf("=== Generating ECDSA key pair ===\n");
|
||||
keymaster_ec_keygen_params_t params;
|
||||
params.field_size = 521;
|
||||
uint8_t* key;
|
||||
size_t size;
|
||||
int error = device->generate_keypair(TYPE_EC, ¶ms, &key, &size);
|
||||
if (error != 0) {
|
||||
keymaster_key_blob_t key;
|
||||
int error = device->generate_key(&ec_param_set, &key, nullptr);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error generating ECDSA key pair: %d\n\n", error);
|
||||
return false;
|
||||
}
|
||||
UniquePtr<uint8_t[]> deleter(key);
|
||||
std::unique_ptr<const uint8_t[]> key_deleter(key.key_material);
|
||||
|
||||
printf("=== Signing with ECDSA key === \n");
|
||||
keymaster_ec_sign_params_t sign_params = {DIGEST_NONE};
|
||||
size_t message_len = 30 /* arbitrary */;
|
||||
UniquePtr<uint8_t[]> message(new uint8_t[message_len]);
|
||||
std::unique_ptr<uint8_t[]> message(new uint8_t[message_len]);
|
||||
memset(message.get(), 'a', message_len);
|
||||
uint8_t* signature;
|
||||
size_t signature_len;
|
||||
error = device->sign_data(&sign_params, key, size, message.get(), message_len, &signature,
|
||||
&signature_len);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error signing data with ECDSA key: %d\n\n", error);
|
||||
keymaster_blob_t input = {message.get(), message_len}, signature;
|
||||
|
||||
if (!do_operation(device, KM_PURPOSE_SIGN, &key, &input, nullptr, &signature)) {
|
||||
printf("Error signing data with ECDSA key\n\n");
|
||||
return false;
|
||||
}
|
||||
UniquePtr<uint8_t[]> signature_deleter(signature);
|
||||
std::unique_ptr<const uint8_t[]> signature_deleter(signature.data);
|
||||
|
||||
printf("=== Verifying with ECDSA key === \n");
|
||||
error = device->verify_data(&sign_params, key, size, message.get(), message_len, signature,
|
||||
signature_len);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error verifying data with ECDSA key: %d\n\n", error);
|
||||
if (!do_operation(device, KM_PURPOSE_VERIFY, &key, &input, &signature, nullptr)) {
|
||||
printf("Error verifying data with ECDSA key\n\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("=== Exporting ECDSA public key ===\n");
|
||||
uint8_t* exported_key;
|
||||
size_t exported_size;
|
||||
error = device->get_keypair_public(key, size, &exported_key, &exported_size);
|
||||
keymaster_blob_t exported_key;
|
||||
error = device->export_key(KM_KEY_FORMAT_X509, &key, nullptr, nullptr, &exported_key);
|
||||
if (error != KM_ERROR_OK) {
|
||||
printf("Error exporting ECDSA public key: %d\n\n", error);
|
||||
return false;
|
||||
}
|
||||
|
||||
printf("=== Verifying with exported key ===\n");
|
||||
const uint8_t* tmp = exported_key;
|
||||
UniquePtr<EVP_PKEY, EVP_PKEY_Delete> pkey(d2i_PUBKEY(NULL, &tmp, exported_size));
|
||||
UniquePtr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
|
||||
const uint8_t* tmp = exported_key.data;
|
||||
std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> pkey(
|
||||
d2i_PUBKEY(NULL, &tmp, exported_key.data_length));
|
||||
std::unique_ptr<EVP_PKEY_CTX, EVP_PKEY_CTX_Delete> ctx(EVP_PKEY_CTX_new(pkey.get(), NULL));
|
||||
if (EVP_PKEY_verify_init(ctx.get()) != 1) {
|
||||
printf("Error initializing openss EVP context\n");
|
||||
printf("Error initializing openssl EVP context\n\n");
|
||||
return false;
|
||||
}
|
||||
if (EVP_PKEY_type(pkey->type) != EVP_PKEY_EC) {
|
||||
printf("Exported key was the wrong type?!?\n");
|
||||
printf("Exported key was the wrong type?!?\n\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (EVP_PKEY_verify(ctx.get(), signature, signature_len, message.get(), message_len) != 1) {
|
||||
printf("Verification with exported pubkey failed.\n");
|
||||
if (EVP_PKEY_verify(ctx.get(), signature.data, signature.data_length, message.get(),
|
||||
message_len) != 1) {
|
||||
printf("Verification with exported pubkey failed.\n\n");
|
||||
return false;
|
||||
} else {
|
||||
printf("Verification succeeded\n");
|
||||
|
@ -344,8 +378,8 @@ static bool test_ecdsa(TrustyKeymasterDevice* device) {
|
|||
}
|
||||
|
||||
int main(void) {
|
||||
|
||||
TrustyKeymasterDevice device(NULL);
|
||||
keymaster::ConfigureDevice(reinterpret_cast<keymaster2_device_t*>(&device));
|
||||
if (device.session_error() != KM_ERROR_OK) {
|
||||
printf("Failed to initialize Trusty session: %d\n", device.session_error());
|
||||
return 1;
|
||||
|
|
Loading…
Reference in a new issue