From a1e4e4fe7331338ece1a6d3ba01862a35a22f4ae Mon Sep 17 00:00:00 2001 From: Rob Austein Date: Wed, 23 Dec 2015 21:35:28 -0500 Subject: RPC interface to TRNG and (incomplete) PIN code. --- GNUmakefile | 30 ++++-- aes_keywrap.c | 2 +- core.c | 2 +- csprng.c | 2 +- hal.h | 46 ++++---- hal_internal.h | 83 ++++++++++----- hal_io_eim.c | 2 +- hal_io_i2c.c | 2 +- hash.c | 6 +- ks.c | 21 ++++ ks_flash.c | 25 ++++- ks_mmap.c | 19 ++++ ks_volatile.c | 46 ++++++-- modexp.c | 2 +- pbkdf2.c | 2 +- rpc.c | 330 --------------------------------------------------------- rpc_api.c | 330 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ rpc_client.c | 36 +++---- rpc_hash.c | 8 +- rpc_misc.c | 158 +++++++++++++++++++++++++++ rpc_pkey.c | 24 ++--- rsa.c | 2 +- 22 files changed, 736 insertions(+), 442 deletions(-) delete mode 100644 rpc.c create mode 100644 rpc_api.c create mode 100644 rpc_misc.c diff --git a/GNUmakefile b/GNUmakefile index dc7fe50..a600dd3 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -36,29 +36,43 @@ STATIC_PKEY_STATE_BLOCKS = 6 INC = hal.h hal_internal.h LIB = libhal.a -OBJ = ${IO_OBJ} core.o csprng.o hash.o aes_keywrap.o pbkdf2.o \ - modexp.o rsa.o ecdsa.o asn1.o errorstrings.o ${RPC_OBJ} ${KS_OBJ} +OBJ = core.o csprng.o hash.o aes_keywrap.o pbkdf2.o \ + modexp.o rsa.o ecdsa.o asn1.o errorstrings.o \ + ${IO_OBJ} ${RPC_OBJ} ${KS_OBJ} + IO_OBJ_EIM = hal_io_eim.o novena-eim.o IO_OBJ_I2C = hal_io_i2c.o # Default I/O bus is EIM, override this to use I2C instead IO_OBJ = ${IO_OBJ_EIM} -RPC_OBJ_COMMON = rpc.o rpc_hash.o +RPC_OBJ_COMMON = rpc_api.o rpc_hash.o RPC_OBJ_CLIENT = ${RPC_OBJ_COMMON} rpc_client.o RPC_OBJ_SERVER = ${RPC_OBJ_COMMON} rpc_misc.o rpc_pkey.o # Default should be to build the RPC server code, but we haven't # written even the skeleton of that yet. We'll probably end up # needing a makefile conditional to handle all this properly -RPC_OBJ = ${RPC_OBJ_CLIENT} +RPC_OBJ = ${RPC_OBJ_SERVER} # XXX temporary -$(warning TEMPORARY KLUDGE TO TEST rpc_pkey) -RPC_OBJ += rpc_pkey.o +$(warning TEMPORARY KLUDGE TO TEST rpc_client) +RPC_OBJ += ${RPC_OBJ_CLIENT} -# XXX temporary -KS_OBJ = ks.o ks_mmap.o +KS_OBJ_COMMON = ks.o +KS_OBJ_MMAP = ${KS_OBJ_COMMON} ks_mmap.o +KS_OBJ_VOLATILE = ${KS_OBJ_COMMON} ks_volatile.o +KS_OBJ_FLASH = ${KS_OBJ_COMMON} ks_flash.o + +# The mmap and flash keystore implementations are both server code. +# +# The volatile keystore (conventional memory) is client code, to +# support using the same API for things like PKCS #11 "session" objects. +# +# Default at the moment is mmap, since that should work on the Novena +# and we haven't yet written the flash code for the bridge board. + +KS_OBJ = ${KS_OBJ_MMAP} TFMDIR := $(abspath ../thirdparty/libtfm) CFLAGS += -g3 -Wall -fPIC -std=c99 -I${TFMDIR} -DHAL_ECDSA_DEBUG_ONLY_STATIC_TEST_VECTOR_RANDOM=1 diff --git a/aes_keywrap.c b/aes_keywrap.c index 9d10ad9..d666624 100644 --- a/aes_keywrap.c +++ b/aes_keywrap.c @@ -48,7 +48,7 @@ #include #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * How long the ciphertext will be for a given plaintext length. diff --git a/core.c b/core.c index 44cf3f0..b7bf3b0 100644 --- a/core.c +++ b/core.c @@ -39,7 +39,7 @@ #include #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * Each Cryptech core has a set of 4-byte registers, which are accessed diff --git a/csprng.c b/csprng.c index 31a59d9..c6ae4e1 100644 --- a/csprng.c +++ b/csprng.c @@ -37,7 +37,7 @@ #include #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" #ifndef WAIT_FOR_CSPRNG_VALID #define WAIT_FOR_CSPRNG_VALID 1 diff --git a/hal.h b/hal.h index eefaa55..d95e475 100644 --- a/hal.h +++ b/hal.h @@ -122,6 +122,7 @@ DEFINE_HAL_ERROR(HAL_ERROR_KEY_NOT_FOUND, "Key not found") \ DEFINE_HAL_ERROR(HAL_ERROR_KEY_NAME_IN_USE, "Key name in use") \ DEFINE_HAL_ERROR(HAL_ERROR_NO_KEY_SLOTS_AVAILABLE, "No key slots available") \ + DEFINE_HAL_ERROR(HAL_ERROR_PIN_INCORRECT, "PIN incorrect") \ END_OF_HAL_ERROR_LIST /* Marker to forestall silly line continuation errors */ @@ -204,13 +205,6 @@ extern hal_error_t hal_get_random(const hal_core_t *core, void *buffer, const si * Hash and HMAC API. */ -/* - * Longest hash block and digest we support at the moment. - */ - -#define HAL_MAX_HASH_BLOCK_LENGTH SHA512_BLOCK_LEN -#define HAL_MAX_HASH_DIGEST_LENGTH SHA512_DIGEST_LEN - /* * Opaque driver structure for digest algorithms. */ @@ -544,19 +538,19 @@ extern hal_error_t hal_ecdsa_verify(const hal_core_t *core, * mechanism, not the server (HSM) side. */ -typedef struct { uint32_t handle; } hal_rpc_client_handle_t; -typedef struct { uint32_t handle; } hal_rpc_session_handle_t; +typedef struct { uint32_t handle; } hal_client_handle_t; +typedef struct { uint32_t handle; } hal_session_handle_t; -typedef enum { HAL_RPC_USER_NONE, HAL_RPC_USER_NORMAL, HAL_RPC_USER_SO } hal_rpc_user_t; +typedef enum { HAL_USER_NONE, HAL_USER_NORMAL, HAL_USER_SO, HAL_USER_WHEEL } hal_user_t; -extern hal_error_t hal_rpc_set_pin(const hal_rpc_user_t which, +extern hal_error_t hal_rpc_set_pin(const hal_user_t user, const char * const newpin, const size_t newpin_len); -extern hal_error_t hal_rpc_login(const hal_rpc_client_handle_t client, - const hal_rpc_user_t user, +extern hal_error_t hal_rpc_login(const hal_client_handle_t client, + const hal_user_t user, const char * const pin, const size_t pin_len); -extern hal_error_t hal_rpc_logout(const hal_rpc_client_handle_t client); +extern hal_error_t hal_rpc_logout(const hal_client_handle_t client); /* * Get random bytes. @@ -584,8 +578,8 @@ extern hal_error_t hal_rpc_hash_get_algorithm(const hal_rpc_hash_handle_t hash, * session, so we only need the client and session arguments to initialize. */ -extern hal_error_t hal_rpc_hash_initialize(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +extern hal_error_t hal_rpc_hash_initialize(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_hash_handle_t *hash, const hal_digest_algorithm_t alg, const uint8_t * const key, const size_t key_length); @@ -634,8 +628,8 @@ typedef uint32_t hal_key_flags_t; #define HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT (1 << 1) #define HAL_KEY_FLAG_USAGE_DATAENCIPHERMENT (1 << 2) -extern hal_error_t hal_rpc_pkey_load(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +extern hal_error_t hal_rpc_pkey_load(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, @@ -643,22 +637,22 @@ extern hal_error_t hal_rpc_pkey_load(const hal_rpc_client_handle_t client, const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags); -extern hal_error_t hal_rpc_pkey_find(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +extern hal_error_t hal_rpc_pkey_find(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const hal_key_type_t type, const uint8_t * const name, const size_t name_len); -extern hal_error_t hal_rpc_pkey_generate_rsa(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +extern hal_error_t hal_rpc_pkey_generate_rsa(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const uint8_t * const name, const size_t name_len, const unsigned key_length, const uint8_t * const public_exponent, const size_t public_exponent_len, const hal_key_flags_t flags); -extern hal_error_t hal_rpc_pkey_generate_ec(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +extern hal_error_t hal_rpc_pkey_generate_ec(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const uint8_t * const name, const size_t name_len, const hal_curve_name_t curve, @@ -679,13 +673,13 @@ extern size_t hal_rpc_pkey_get_public_key_len(const hal_rpc_pkey_handle_t pkey); extern hal_error_t hal_rpc_pkey_get_public_key(const hal_rpc_pkey_handle_t pkey, uint8_t *der, size_t *der_len, const size_t der_max); -extern hal_error_t hal_rpc_pkey_sign(const hal_rpc_session_handle_t session, +extern hal_error_t hal_rpc_pkey_sign(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, uint8_t * signature, size_t *signature_len, const size_t signature_max); -extern hal_error_t hal_rpc_pkey_verify(const hal_rpc_session_handle_t session, +extern hal_error_t hal_rpc_pkey_verify(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, diff --git a/hal_internal.h b/hal_internal.h index edb0d8f..176e1c8 100644 --- a/hal_internal.h +++ b/hal_internal.h @@ -37,21 +37,29 @@ #define _HAL_INTERNAL_H_ #include "hal.h" +#include "verilog_constants.h" + +/* + * Longest hash block and digest we support at the moment. + */ + +#define HAL_MAX_HASH_BLOCK_LENGTH SHA512_BLOCK_LEN +#define HAL_MAX_HASH_DIGEST_LENGTH SHA512_DIGEST_LEN /* * Everything in this file is part of the internal API, that is, * subject to change without notice. Nothing outside of libhal itself - * should be looking at this file. Access from outside of libhal - * should use the public hal_rpc_*() API. - * - * In particular, the breakdown of which functions go into which - * dispatch vectors is based entirely on pesky details like making - * sure that the right functions get linked in the right cases, and - * should not be construed as making any particular sense in any - * larger context. + * should be looking at this file. */ /* + * Dispatch structures for RPC implementation. + * + * The breakdown of which functions go into which dispatch vectors is + * based entirely on pesky details like making sure that the right + * functions get linked in the right cases, and should not be + * construed as making any particular sense in any larger context. + * * In theory eventually we might want a fully general mechanism to * allow us to dispatch arbitrary groups of functions either locally * or remotely on a per-user basis. In practice, we probably want to @@ -77,14 +85,14 @@ typedef struct { - hal_error_t (*set_pin)(const hal_rpc_user_t which, + hal_error_t (*set_pin)(const hal_user_t user, const char * const newpin, const size_t newpin_len); - hal_error_t (*login)(const hal_rpc_client_handle_t client, - const hal_rpc_user_t user, + hal_error_t (*login)(const hal_client_handle_t client, + const hal_user_t user, const char * const newpin, const size_t newpin_len); - hal_error_t (*logout)(const hal_rpc_client_handle_t client); + hal_error_t (*logout)(const hal_client_handle_t client); hal_error_t (*get_random)(void *buffer, const size_t length); @@ -100,8 +108,8 @@ typedef struct { hal_error_t (*get_algorithm)(const hal_rpc_hash_handle_t hash, hal_digest_algorithm_t *alg); - hal_error_t (*initialize)(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, + hal_error_t (*initialize)(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_hash_handle_t *hash, const hal_digest_algorithm_t alg, const uint8_t * const key, const size_t key_length); @@ -116,8 +124,8 @@ typedef struct { typedef struct { - hal_error_t (*load)(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, + hal_error_t (*load)(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, @@ -125,22 +133,22 @@ typedef struct { const uint8_t * const der, const size_t der_len, const hal_key_flags_t flags); - hal_error_t (*find)(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, + hal_error_t (*find)(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const hal_key_type_t type, const uint8_t * const name, const size_t name_len); - hal_error_t (*generate_rsa)(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, + hal_error_t (*generate_rsa)(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const uint8_t * const name, const size_t name_len, const unsigned key_length, const uint8_t * const public_exponent, const size_t public_exponent_len, const hal_key_flags_t flags); - hal_error_t (*generate_ec)(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, + hal_error_t (*generate_ec)(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const uint8_t * const name, const size_t name_len, const hal_curve_name_t curve, @@ -161,13 +169,13 @@ typedef struct { hal_error_t (*get_public_key)(const hal_rpc_pkey_handle_t pkey, uint8_t *der, size_t *der_len, const size_t der_max); - hal_error_t (*sign)(const hal_rpc_session_handle_t session, + hal_error_t (*sign)(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, uint8_t * signature, size_t *signature_len, const size_t signature_max); - hal_error_t (*verify)(const hal_rpc_session_handle_t session, + hal_error_t (*verify)(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, @@ -205,6 +213,11 @@ extern const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch, hal_rpc_remote * * Plus we need a bit of AES-keywrap overhead, since we're storing the * wrapped form (see hal_aes_keywrap_cyphertext_length()). + * + * We also need to store PINs somewhere, so they go into the keystore + * data structure even though they're not keys. Like keys, they're + * stored in a relatively safe form (PBKDF2), so while we would prefer + * to keep them private, they don't require tamper-protected RAM. */ #define HAL_KS_WRAPPED_KEYSIZE ((4655 + 15) & ~7) @@ -224,10 +237,26 @@ typedef struct { uint8_t in_use; } hal_ks_key_t; +#ifndef HAL_PIN_SALT_LENGTH +#define HAL_PIN_SALT_LENGTH 16 +#endif + +typedef struct { + uint32_t iterations; + uint8_t pin[HAL_MAX_HASH_DIGEST_LENGTH]; + uint8_t salt[HAL_PIN_SALT_LENGTH]; +} hal_ks_pin_t; + typedef struct { + #if HAL_STATIC_PKEY_STATE_BLOCKS > 0 hal_ks_key_t keys[HAL_STATIC_PKEY_STATE_BLOCKS]; #endif + + hal_ks_pin_t wheel_pin; + hal_ks_pin_t so_pin; + hal_ks_pin_t user_pin; + } hal_ks_keydb_t; /* @@ -285,6 +314,12 @@ extern hal_error_t hal_ks_list(hal_rpc_pkey_key_info_t *result, unsigned *result_len, const unsigned result_max); +extern hal_error_t hal_ks_get_pin(const hal_user_t user, + const hal_ks_pin_t **pin); + +extern hal_error_t hal_ks_set_pin(const hal_user_t user, + const hal_ks_pin_t * const pin); + #endif /* _HAL_INTERNAL_H_ */ /* diff --git a/hal_io_eim.c b/hal_io_eim.c index fbf1d67..e353451 100644 --- a/hal_io_eim.c +++ b/hal_io_eim.c @@ -39,7 +39,7 @@ #include "novena-eim.h" #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" static int debug = 0; static int inited = 0; diff --git a/hal_io_i2c.c b/hal_io_i2c.c index 7fb306e..e7dbbb6 100644 --- a/hal_io_i2c.c +++ b/hal_io_i2c.c @@ -41,7 +41,7 @@ #include #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" #define I2C_dev "/dev/i2c-2" #define I2C_addr 0x0f diff --git a/hash.c b/hash.c index 9ddc191..5af53a8 100644 --- a/hash.c +++ b/hash.c @@ -1,6 +1,6 @@ /* - * hashes.c - * -------- + * hash.c + * ------ * HAL interface to Cryptech hash cores. * * Authors: Joachim Strömbergson, Paul Selkirk, Rob Austein @@ -41,7 +41,7 @@ #include #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * HMAC magic numbers. diff --git a/ks.c b/ks.c index 072c624..7466b75 100644 --- a/ks.c +++ b/ks.c @@ -273,6 +273,27 @@ hal_error_t hal_ks_list(hal_rpc_pkey_key_info_t *result, return HAL_OK; } +hal_error_t hal_ks_get_pin(const hal_user_t user, + const hal_ks_pin_t **pin) +{ + if (pin == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + const hal_ks_keydb_t * const db = hal_ks_get_keydb(); + + if (db == NULL) + return HAL_ERROR_KEYSTORE_ACCESS; + + switch (user) { + case HAL_USER_WHEEL: *pin = &db->wheel_pin; break; + case HAL_USER_SO: *pin = &db->so_pin; break; + case HAL_USER_NORMAL: *pin = &db->user_pin; break; + default: return HAL_ERROR_BAD_ARGUMENTS; + } + + return HAL_OK; +} + /* * Local variables: * indent-tabs-mode: nil diff --git a/ks_flash.c b/ks_flash.c index ad9d2fe..ed05ab5 100644 --- a/ks_flash.c +++ b/ks_flash.c @@ -48,7 +48,7 @@ const hal_ks_keydb_t *hal_ks_get_keydb(void) hal_error_t hal_ks_set_keydb(const hal_ks_key_t * const key, const int loc) { - if (key == NULL || loc < 0 || loc >= sizeof(db.keys)/sizeof(*db.keys) || key->in_use) + if (key == NULL || loc < 0 || loc >= sizeof(db->keys)/sizeof(*db->keys) || key->in_use) return HAL_ERROR_BAD_ARGUMENTS; #error Not sure what goes here yet either @@ -57,13 +57,34 @@ hal_error_t hal_ks_set_keydb(const hal_ks_key_t * const key, hal_error_t hal_ks_del_keydb(const int loc) { - if (loc < 0 || loc >= sizeof(db.keys)/sizeof(*db.keys)) + if (loc < 0 || loc >= sizeof(db->keys)/sizeof(*db->keys)) return HAL_ERROR_BAD_ARGUMENTS; #error Or what goes here } +hal_error_t hal_ks_set_pin(const hal_user_t user, + const hal_ks_pin_t * const pin) +{ + if (pin == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_ks_pin_t *p = NULL; + + switch (user) { + case HAL_USER_WHEEL: p = &db->wheel_pin; break; + case HAL_USER_SO: p = &db->so_pin; break; + case HAL_USER_NORMAL: p = &db->user_pin; break; + default: return HAL_ERROR_BAD_ARGUMENTS; + } + +#error Or what goes here + + return HAL_OK; +} + + /* * Local variables: * indent-tabs-mode: nil diff --git a/ks_mmap.c b/ks_mmap.c index 7fef400..a4e6cde 100644 --- a/ks_mmap.c +++ b/ks_mmap.c @@ -116,6 +116,25 @@ hal_error_t hal_ks_del_keydb(const int loc) return HAL_OK; } +hal_error_t hal_ks_set_pin(const hal_user_t user, + const hal_ks_pin_t * const pin) +{ + if (pin == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_ks_pin_t *p = NULL; + + switch (user) { + case HAL_USER_WHEEL: p = &db->wheel_pin; break; + case HAL_USER_SO: p = &db->so_pin; break; + case HAL_USER_NORMAL: p = &db->user_pin; break; + default: return HAL_ERROR_BAD_ARGUMENTS; + } + + *p = *pin; + return HAL_OK; +} + /* * Local variables: * indent-tabs-mode: nil diff --git a/ks_volatile.c b/ks_volatile.c index 756cd13..2381f4c 100644 --- a/ks_volatile.c +++ b/ks_volatile.c @@ -36,36 +36,68 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include + #include "hal.h" #include "hal_internal.h" -static hal_ks_keydb_t db; +/* + * Splitting the different keystore backends out into separate files + * seemed like a good idea at the time, but the code is getting + * somewhat repetitive. Might want to re-merge and conditionalize in + * some other way. Deferred until we sort out ks_flash.c. + */ + +/* + * Use a one-element array here so that references can be pointer-based + * as in the other implementations, to ease re-merge at some later date. + */ + +static hal_ks_keydb_t db[1]; const hal_ks_keydb_t *hal_ks_get_keydb(void) { - return &db; + return db; } hal_error_t hal_ks_set_keydb(const hal_ks_key_t * const key, const int loc) { - if (key == NULL || loc < 0 || loc >= sizeof(db.keys)/sizeof(*db.keys) || key->in_use) + if (key == NULL || loc < 0 || loc >= sizeof(db->keys)/sizeof(*db->keys) || key->in_use) return HAL_ERROR_BAD_ARGUMENTS; - db.keys[loc] = *key; - db.keys[loc].in_use = 1; + db->keys[loc] = *key; + db->keys[loc].in_use = 1; return HAL_OK; } hal_error_t hal_ks_del_keydb(const int loc) { - if (loc < 0 || loc >= sizeof(db.keys)/sizeof(*db.keys)) + if (loc < 0 || loc >= sizeof(db->keys)/sizeof(*db->keys)) return HAL_ERROR_BAD_ARGUMENTS; - memset(&db.keys[loc], 0, sizeof(db.keys[loc])); + memset(&db->keys[loc], 0, sizeof(db->keys[loc])); return HAL_OK; } +hal_error_t hal_ks_set_pin(const hal_user_t user, + const hal_ks_pin_t * const pin) +{ + if (pin == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + + hal_ks_pin_t *p = NULL; + + switch (user) { + case HAL_USER_WHEEL: p = &db->wheel_pin; break; + case HAL_USER_SO: p = &db->so_pin; break; + case HAL_USER_NORMAL: p = &db->user_pin; break; + default: return HAL_ERROR_BAD_ARGUMENTS; + } + + *p = *pin; + return HAL_OK; +} /* * Local variables: diff --git a/modexp.c b/modexp.c index 72da95f..b84c51b 100644 --- a/modexp.c +++ b/modexp.c @@ -46,7 +46,7 @@ #include #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * Whether we want debug output. diff --git a/pbkdf2.c b/pbkdf2.c index 2020f2d..f361328 100644 --- a/pbkdf2.c +++ b/pbkdf2.c @@ -39,7 +39,7 @@ #include #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * Utility to encapsulate the HMAC operations. May need refactoring diff --git a/rpc.c b/rpc.c deleted file mode 100644 index b76c9cf..0000000 --- a/rpc.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * hal_rpc.c - * --------- - * Remote procedure call public API implementation. - * - * Authors: Rob Austein - * Copyright (c) 2015, NORDUnet A/S All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * - Neither the name of the NORDUnet nor the names of its contributors may - * be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS - * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED - * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING - * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "hal.h" -#include "hal_internal.h" - -#ifndef HAL_RPC_IS_CLIENT -#warning HAL_RPC_IS_CLIENT not set, assuming we're building for the HSM -#define HAL_RPC_IS_CLIENT 0 -#endif - -/* - * Maybe we'll let the client configure this at runtime, later. For - * now, wire in the obvious defaults: hashing is done locally, - * everything else is done via RPC. For the server everything is - * always done locally. - */ - -#if HAL_RPC_IS_CLIENT - -static const hal_rpc_misc_dispatch_t * const misc_dispatch = &hal_rpc_remote_misc_dispatch; -static const hal_rpc_hash_dispatch_t * const hash_dispatch = &hal_rpc_remote_hash_dispatch; -static const hal_rpc_pkey_dispatch_t * const pkey_dispatch = &hal_rpc_mixed_pkey_dispatch; - -#else - -static const hal_rpc_misc_dispatch_t * const misc_dispatch = &hal_rpc_local_misc_dispatch; -static const hal_rpc_hash_dispatch_t * const hash_dispatch = &hal_rpc_local_hash_dispatch; -static const hal_rpc_pkey_dispatch_t * const pkey_dispatch = &hal_rpc_local_pkey_dispatch; - -#endif - -const hal_rpc_hash_handle_t hal_rpc_hash_handle_none = {0}; - -static inline int check_pkey_type(const hal_key_type_t type) -{ - switch (type) { - case HAL_KEY_TYPE_RSA_PRIVATE: - case HAL_KEY_TYPE_RSA_PUBLIC: - case HAL_KEY_TYPE_EC_PRIVATE: - case HAL_KEY_TYPE_EC_PUBLIC: - return 1; - default: - return 0; - } -} - -static inline int check_pkey_flags(const hal_key_flags_t flags) -{ - return (flags &~ (HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE | - HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT | - HAL_KEY_FLAG_USAGE_DATAENCIPHERMENT)) == 0; -} - -static inline int check_pkey_type_curve_flags(const hal_key_type_t type, - const hal_curve_name_t curve, - const hal_key_flags_t flags) -{ - if (!check_pkey_flags(flags)) - return 0; - - switch (type) { - - case HAL_KEY_TYPE_RSA_PRIVATE: - case HAL_KEY_TYPE_RSA_PUBLIC: - return curve == HAL_CURVE_NONE; - - case HAL_KEY_TYPE_EC_PRIVATE: - case HAL_KEY_TYPE_EC_PUBLIC: - switch (curve) { - case HAL_CURVE_P256: - case HAL_CURVE_P384: - case HAL_CURVE_P521: - return 1; - default: - return 0; - } - - default: - return 0; - } -} - - -hal_error_t hal_rpc_get_random(void *buffer, const size_t length) -{ - if (buffer == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - if (length == 0) - return HAL_OK; - return misc_dispatch->get_random(buffer, length); -} - -#warning Perhaps we should be enforcing a minimum PIN length here - -hal_error_t hal_rpc_set_pin(const hal_rpc_user_t which, - const char * const newpin, const size_t newpin_len) -{ - if (newpin == NULL || newpin_len == 0 || (which != HAL_RPC_USER_NORMAL && which != HAL_RPC_USER_SO)) - return HAL_ERROR_BAD_ARGUMENTS; - return misc_dispatch->set_pin(which, newpin, newpin_len); -} - -hal_error_t hal_rpc_login(const hal_rpc_client_handle_t client, - const hal_rpc_user_t user, - const char * const pin, const size_t pin_len) -{ - if (pin == NULL || pin_len == 0 || (user != HAL_RPC_USER_NORMAL && user != HAL_RPC_USER_SO)) - return HAL_ERROR_BAD_ARGUMENTS; - return misc_dispatch->login(client, user, pin, pin_len); -} - -hal_error_t hal_rpc_logout(const hal_rpc_client_handle_t client) -{ - return misc_dispatch->logout(client); -} - -hal_error_t hal_rpc_hash_get_digest_length(const hal_digest_algorithm_t alg, size_t *length) -{ - if (length == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - return hash_dispatch->get_digest_length(alg, length); -} - -hal_error_t hal_rpc_hash_get_digest_algorithm_id(const hal_digest_algorithm_t alg, - uint8_t *id, size_t *len, const size_t len_max) -{ - return hash_dispatch->get_digest_algorithm_id(alg, id, len, len_max); -} - -hal_error_t hal_rpc_hash_get_algorithm(const hal_rpc_hash_handle_t hash, hal_digest_algorithm_t *alg) -{ - if (hash.handle == hal_rpc_hash_handle_none.handle || alg == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - return hash_dispatch->get_algorithm(hash, alg); -} - -hal_error_t hal_rpc_hash_initialize(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, - hal_rpc_hash_handle_t *hash, - const hal_digest_algorithm_t alg, - const uint8_t * const key, const size_t key_len) -{ - if (hash == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - return hash_dispatch->initialize(client, session, hash, alg, key, key_len); -} - -hal_error_t hal_rpc_hash_update(const hal_rpc_hash_handle_t hash, - const uint8_t * data, const size_t length) -{ - if (hash.handle == hal_rpc_hash_handle_none.handle || data == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - if (length == 0) - return HAL_OK; - return hash_dispatch->update(hash, data, length); -} - -hal_error_t hal_rpc_hash_finalize(const hal_rpc_hash_handle_t hash, - uint8_t *digest, const size_t length) -{ - if (hash.handle == hal_rpc_hash_handle_none.handle || digest == NULL || length == 0) - return HAL_ERROR_BAD_ARGUMENTS; - return hash_dispatch->finalize(hash, digest, length); -} - -hal_error_t hal_rpc_pkey_load(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, - hal_rpc_pkey_handle_t *pkey, - const hal_key_type_t type, - const hal_curve_name_t curve, - const uint8_t * const name, const size_t name_len, - const uint8_t * const der, const size_t der_len, - const hal_key_flags_t flags) -{ - if (pkey == NULL || - name == NULL || name_len == 0 || - der == NULL || der_len == 0 || - !check_pkey_type_curve_flags(type, curve, flags)) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->load(client, session, pkey, type, curve, name, name_len, der, der_len, flags); -} - -hal_error_t hal_rpc_pkey_find(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, - hal_rpc_pkey_handle_t *pkey, - const hal_key_type_t type, - const uint8_t * const name, const size_t name_len) -{ - if (pkey == NULL || name == NULL || name_len == 0 || !check_pkey_type(type)) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->find(client, session, pkey, type, name, name_len); -} - -hal_error_t hal_rpc_pkey_generate_rsa(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, - hal_rpc_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, - const unsigned key_len, - const uint8_t * const exp, const size_t exp_len, - const hal_key_flags_t flags) -{ - if (pkey == NULL || name == NULL || name_len == 0 || key_len == 0 || (key_len & 7) != 0 || - exp == NULL || exp_len == 0 || !check_pkey_flags(flags)) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->generate_rsa(client, session, pkey, name, name_len, key_len, exp, exp_len, flags); -} - -hal_error_t hal_rpc_pkey_generate_ec(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, - hal_rpc_pkey_handle_t *pkey, - const uint8_t * const name, const size_t name_len, - const hal_curve_name_t curve, - const hal_key_flags_t flags) -{ - if (pkey == NULL || name == NULL || name_len == 0 || - !check_pkey_type_curve_flags(HAL_KEY_TYPE_EC_PRIVATE, curve, flags)) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->generate_ec(client, session, pkey, name, name_len, curve, flags); -} - -hal_error_t hal_rpc_pkey_close(const hal_rpc_pkey_handle_t pkey) -{ - return pkey_dispatch->close(pkey); -} - -hal_error_t hal_rpc_pkey_delete(const hal_rpc_pkey_handle_t pkey) -{ - return pkey_dispatch->delete(pkey); -} - -hal_error_t hal_rpc_pkey_get_key_type(const hal_rpc_pkey_handle_t pkey, - hal_key_type_t *type) -{ - if (type == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->get_key_type(pkey, type); -} - -hal_error_t hal_rpc_pkey_get_key_flags(const hal_rpc_pkey_handle_t pkey, - hal_key_flags_t *flags) -{ - if (flags == NULL) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->get_key_flags(pkey, flags); -} - -size_t hal_rpc_pkey_get_public_key_len(const hal_rpc_pkey_handle_t pkey) -{ - return pkey_dispatch->get_public_key_len(pkey); -} - -hal_error_t hal_rpc_pkey_get_public_key(const hal_rpc_pkey_handle_t pkey, - uint8_t *der, size_t *der_len, const size_t der_max) -{ - if (der == NULL || der_len == NULL || der_max == 0) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->get_public_key(pkey, der, der_len, der_max); -} - -hal_error_t hal_rpc_pkey_sign(const hal_rpc_session_handle_t session, - const hal_rpc_pkey_handle_t pkey, - const hal_rpc_hash_handle_t hash, - const uint8_t * const input, const size_t input_len, - uint8_t * signature, size_t *signature_len, const size_t signature_max) -{ - if (signature == NULL || signature_len == NULL || signature_max == 0 || - (hash.handle == hal_rpc_hash_handle_none.handle) == (input == NULL || input_len == 0)) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->sign(session, pkey, hash, input, input_len, signature, signature_len, signature_max); -} - -hal_error_t hal_rpc_pkey_verify(const hal_rpc_session_handle_t session, - const hal_rpc_pkey_handle_t pkey, - const hal_rpc_hash_handle_t hash, - const uint8_t * const input, const size_t input_len, - const uint8_t * const signature, const size_t signature_len) -{ - if (signature == NULL || signature_len == 0 || - (hash.handle == hal_rpc_hash_handle_none.handle) == (input == NULL || input_len == 0)) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->verify(session, pkey, hash, input, input_len, signature, signature_len); -} - -hal_error_t hal_rpc_pkey_list(hal_rpc_pkey_key_info_t *result, - unsigned *result_len, - const unsigned result_max) -{ - if (result == NULL || result_len == NULL || result_max == 0) - return HAL_ERROR_BAD_ARGUMENTS; - return pkey_dispatch->list(result, result_len, result_max); -} - -/* - * Local variables: - * indent-tabs-mode: nil - * End: - */ diff --git a/rpc_api.c b/rpc_api.c new file mode 100644 index 0000000..3f4a6ac --- /dev/null +++ b/rpc_api.c @@ -0,0 +1,330 @@ +/* + * hal_rpc.c + * --------- + * Remote procedure call public API implementation. + * + * Authors: Rob Austein + * Copyright (c) 2015, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "hal.h" +#include "hal_internal.h" + +#ifndef HAL_RPC_IS_CLIENT +#warning HAL_RPC_IS_CLIENT not set, assuming we're building for the HSM +#define HAL_RPC_IS_CLIENT 0 +#endif + +/* + * Maybe we'll let the client configure this at runtime, later. For + * now, wire in the obvious defaults: hashing is done locally, + * everything else is done via RPC. For the server everything is + * always done locally. + */ + +#if HAL_RPC_IS_CLIENT + +static const hal_rpc_misc_dispatch_t * const misc_dispatch = &hal_rpc_remote_misc_dispatch; +static const hal_rpc_hash_dispatch_t * const hash_dispatch = &hal_rpc_remote_hash_dispatch; +static const hal_rpc_pkey_dispatch_t * const pkey_dispatch = &hal_rpc_mixed_pkey_dispatch; + +#else + +static const hal_rpc_misc_dispatch_t * const misc_dispatch = &hal_rpc_local_misc_dispatch; +static const hal_rpc_hash_dispatch_t * const hash_dispatch = &hal_rpc_local_hash_dispatch; +static const hal_rpc_pkey_dispatch_t * const pkey_dispatch = &hal_rpc_local_pkey_dispatch; + +#endif + +const hal_rpc_hash_handle_t hal_rpc_hash_handle_none = {0}; + +static inline int check_pkey_type(const hal_key_type_t type) +{ + switch (type) { + case HAL_KEY_TYPE_RSA_PRIVATE: + case HAL_KEY_TYPE_RSA_PUBLIC: + case HAL_KEY_TYPE_EC_PRIVATE: + case HAL_KEY_TYPE_EC_PUBLIC: + return 1; + default: + return 0; + } +} + +static inline int check_pkey_flags(const hal_key_flags_t flags) +{ + return (flags &~ (HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE | + HAL_KEY_FLAG_USAGE_KEYENCIPHERMENT | + HAL_KEY_FLAG_USAGE_DATAENCIPHERMENT)) == 0; +} + +static inline int check_pkey_type_curve_flags(const hal_key_type_t type, + const hal_curve_name_t curve, + const hal_key_flags_t flags) +{ + if (!check_pkey_flags(flags)) + return 0; + + switch (type) { + + case HAL_KEY_TYPE_RSA_PRIVATE: + case HAL_KEY_TYPE_RSA_PUBLIC: + return curve == HAL_CURVE_NONE; + + case HAL_KEY_TYPE_EC_PRIVATE: + case HAL_KEY_TYPE_EC_PUBLIC: + switch (curve) { + case HAL_CURVE_P256: + case HAL_CURVE_P384: + case HAL_CURVE_P521: + return 1; + default: + return 0; + } + + default: + return 0; + } +} + + +hal_error_t hal_rpc_get_random(void *buffer, const size_t length) +{ + if (buffer == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + if (length == 0) + return HAL_OK; + return misc_dispatch->get_random(buffer, length); +} + +#warning Perhaps we should be enforcing a minimum PIN length here + +hal_error_t hal_rpc_set_pin(const hal_user_t user, + const char * const newpin, const size_t newpin_len) +{ + if (newpin == NULL || newpin_len == 0 || (user != HAL_USER_NORMAL && user != HAL_USER_SO && user != HAL_USER_WHEEL)) + return HAL_ERROR_BAD_ARGUMENTS; + return misc_dispatch->set_pin(user, newpin, newpin_len); +} + +hal_error_t hal_rpc_login(const hal_client_handle_t client, + const hal_user_t user, + const char * const pin, const size_t pin_len) +{ + if (pin == NULL || pin_len == 0 || (user != HAL_USER_NORMAL && user != HAL_USER_SO && user != HAL_USER_WHEEL)) + return HAL_ERROR_BAD_ARGUMENTS; + return misc_dispatch->login(client, user, pin, pin_len); +} + +hal_error_t hal_rpc_logout(const hal_client_handle_t client) +{ + return misc_dispatch->logout(client); +} + +hal_error_t hal_rpc_hash_get_digest_length(const hal_digest_algorithm_t alg, size_t *length) +{ + if (length == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + return hash_dispatch->get_digest_length(alg, length); +} + +hal_error_t hal_rpc_hash_get_digest_algorithm_id(const hal_digest_algorithm_t alg, + uint8_t *id, size_t *len, const size_t len_max) +{ + return hash_dispatch->get_digest_algorithm_id(alg, id, len, len_max); +} + +hal_error_t hal_rpc_hash_get_algorithm(const hal_rpc_hash_handle_t hash, hal_digest_algorithm_t *alg) +{ + if (hash.handle == hal_rpc_hash_handle_none.handle || alg == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + return hash_dispatch->get_algorithm(hash, alg); +} + +hal_error_t hal_rpc_hash_initialize(const hal_client_handle_t client, + const hal_session_handle_t session, + hal_rpc_hash_handle_t *hash, + const hal_digest_algorithm_t alg, + const uint8_t * const key, const size_t key_len) +{ + if (hash == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + return hash_dispatch->initialize(client, session, hash, alg, key, key_len); +} + +hal_error_t hal_rpc_hash_update(const hal_rpc_hash_handle_t hash, + const uint8_t * data, const size_t length) +{ + if (hash.handle == hal_rpc_hash_handle_none.handle || data == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + if (length == 0) + return HAL_OK; + return hash_dispatch->update(hash, data, length); +} + +hal_error_t hal_rpc_hash_finalize(const hal_rpc_hash_handle_t hash, + uint8_t *digest, const size_t length) +{ + if (hash.handle == hal_rpc_hash_handle_none.handle || digest == NULL || length == 0) + return HAL_ERROR_BAD_ARGUMENTS; + return hash_dispatch->finalize(hash, digest, length); +} + +hal_error_t hal_rpc_pkey_load(const hal_client_handle_t client, + const hal_session_handle_t session, + hal_rpc_pkey_handle_t *pkey, + const hal_key_type_t type, + const hal_curve_name_t curve, + const uint8_t * const name, const size_t name_len, + const uint8_t * const der, const size_t der_len, + const hal_key_flags_t flags) +{ + if (pkey == NULL || + name == NULL || name_len == 0 || + der == NULL || der_len == 0 || + !check_pkey_type_curve_flags(type, curve, flags)) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->load(client, session, pkey, type, curve, name, name_len, der, der_len, flags); +} + +hal_error_t hal_rpc_pkey_find(const hal_client_handle_t client, + const hal_session_handle_t session, + hal_rpc_pkey_handle_t *pkey, + const hal_key_type_t type, + const uint8_t * const name, const size_t name_len) +{ + if (pkey == NULL || name == NULL || name_len == 0 || !check_pkey_type(type)) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->find(client, session, pkey, type, name, name_len); +} + +hal_error_t hal_rpc_pkey_generate_rsa(const hal_client_handle_t client, + const hal_session_handle_t session, + hal_rpc_pkey_handle_t *pkey, + const uint8_t * const name, const size_t name_len, + const unsigned key_len, + const uint8_t * const exp, const size_t exp_len, + const hal_key_flags_t flags) +{ + if (pkey == NULL || name == NULL || name_len == 0 || key_len == 0 || (key_len & 7) != 0 || + exp == NULL || exp_len == 0 || !check_pkey_flags(flags)) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->generate_rsa(client, session, pkey, name, name_len, key_len, exp, exp_len, flags); +} + +hal_error_t hal_rpc_pkey_generate_ec(const hal_client_handle_t client, + const hal_session_handle_t session, + hal_rpc_pkey_handle_t *pkey, + const uint8_t * const name, const size_t name_len, + const hal_curve_name_t curve, + const hal_key_flags_t flags) +{ + if (pkey == NULL || name == NULL || name_len == 0 || + !check_pkey_type_curve_flags(HAL_KEY_TYPE_EC_PRIVATE, curve, flags)) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->generate_ec(client, session, pkey, name, name_len, curve, flags); +} + +hal_error_t hal_rpc_pkey_close(const hal_rpc_pkey_handle_t pkey) +{ + return pkey_dispatch->close(pkey); +} + +hal_error_t hal_rpc_pkey_delete(const hal_rpc_pkey_handle_t pkey) +{ + return pkey_dispatch->delete(pkey); +} + +hal_error_t hal_rpc_pkey_get_key_type(const hal_rpc_pkey_handle_t pkey, + hal_key_type_t *type) +{ + if (type == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->get_key_type(pkey, type); +} + +hal_error_t hal_rpc_pkey_get_key_flags(const hal_rpc_pkey_handle_t pkey, + hal_key_flags_t *flags) +{ + if (flags == NULL) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->get_key_flags(pkey, flags); +} + +size_t hal_rpc_pkey_get_public_key_len(const hal_rpc_pkey_handle_t pkey) +{ + return pkey_dispatch->get_public_key_len(pkey); +} + +hal_error_t hal_rpc_pkey_get_public_key(const hal_rpc_pkey_handle_t pkey, + uint8_t *der, size_t *der_len, const size_t der_max) +{ + if (der == NULL || der_len == NULL || der_max == 0) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->get_public_key(pkey, der, der_len, der_max); +} + +hal_error_t hal_rpc_pkey_sign(const hal_session_handle_t session, + const hal_rpc_pkey_handle_t pkey, + const hal_rpc_hash_handle_t hash, + const uint8_t * const input, const size_t input_len, + uint8_t * signature, size_t *signature_len, const size_t signature_max) +{ + if (signature == NULL || signature_len == NULL || signature_max == 0 || + (hash.handle == hal_rpc_hash_handle_none.handle) == (input == NULL || input_len == 0)) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->sign(session, pkey, hash, input, input_len, signature, signature_len, signature_max); +} + +hal_error_t hal_rpc_pkey_verify(const hal_session_handle_t session, + const hal_rpc_pkey_handle_t pkey, + const hal_rpc_hash_handle_t hash, + const uint8_t * const input, const size_t input_len, + const uint8_t * const signature, const size_t signature_len) +{ + if (signature == NULL || signature_len == 0 || + (hash.handle == hal_rpc_hash_handle_none.handle) == (input == NULL || input_len == 0)) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->verify(session, pkey, hash, input, input_len, signature, signature_len); +} + +hal_error_t hal_rpc_pkey_list(hal_rpc_pkey_key_info_t *result, + unsigned *result_len, + const unsigned result_max) +{ + if (result == NULL || result_len == NULL || result_max == 0) + return HAL_ERROR_BAD_ARGUMENTS; + return pkey_dispatch->list(result, result_len, result_max); +} + +/* + * Local variables: + * indent-tabs-mode: nil + * End: + */ diff --git a/rpc_client.c b/rpc_client.c index 74ea92e..baac5ba 100644 --- a/rpc_client.c +++ b/rpc_client.c @@ -47,20 +47,20 @@ static hal_error_t get_random(void *buffer, const size_t length) return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t set_pin(const hal_rpc_user_t which, +static hal_error_t set_pin(const hal_user_t user, const char * const newpin, const size_t newpin_len) { return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t login(const hal_rpc_client_handle_t client, - const hal_rpc_user_t user, +static hal_error_t login(const hal_client_handle_t client, + const hal_user_t user, const char * const pin, const size_t pin_len) { return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t logout(const hal_rpc_client_handle_t client) +static hal_error_t logout(const hal_client_handle_t client) { return HAL_ERROR_IMPOSSIBLE; } @@ -81,8 +81,8 @@ static hal_error_t hash_get_algorithm(const hal_rpc_hash_handle_t hash, hal_dige return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t hash_initialize(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t hash_initialize(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_hash_handle_t *hash, const hal_digest_algorithm_t alg, const uint8_t * const key, const size_t key_len) @@ -102,8 +102,8 @@ static hal_error_t hash_finalize(const hal_rpc_hash_handle_t hash, return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t pkey_load(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t pkey_load(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, @@ -114,8 +114,8 @@ static hal_error_t pkey_load(const hal_rpc_client_handle_t client, return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t pkey_find(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t pkey_find(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const hal_key_type_t type, const uint8_t * const name, const size_t name_len) @@ -123,8 +123,8 @@ static hal_error_t pkey_find(const hal_rpc_client_handle_t client, return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t pkey_generate_rsa(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t pkey_generate_rsa(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const uint8_t * const name, const size_t name_len, const unsigned key_len, @@ -134,8 +134,8 @@ static hal_error_t pkey_generate_rsa(const hal_rpc_client_handle_t client, return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t pkey_generate_ec(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t pkey_generate_ec(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const uint8_t * const name, const size_t name_len, const hal_curve_name_t curve, @@ -177,7 +177,7 @@ static hal_error_t pkey_get_public_key(const hal_rpc_pkey_handle_t pkey, return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t pkey_remote_sign(const hal_rpc_session_handle_t session, +static hal_error_t pkey_remote_sign(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, @@ -186,7 +186,7 @@ static hal_error_t pkey_remote_sign(const hal_rpc_session_handle_t session, return HAL_ERROR_IMPOSSIBLE; } -static hal_error_t pkey_remote_verify(const hal_rpc_session_handle_t session, +static hal_error_t pkey_remote_verify(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, @@ -210,7 +210,7 @@ static hal_error_t pkey_list(hal_rpc_pkey_key_info_t *result, * pull the digest from the hash context and send that to the HSM. */ -static hal_error_t pkey_mixed_sign(const hal_rpc_session_handle_t session, +static hal_error_t pkey_mixed_sign(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, @@ -237,7 +237,7 @@ static hal_error_t pkey_mixed_sign(const hal_rpc_session_handle_t session, signature, signature_len, signature_max); } -static hal_error_t pkey_mixed_verify(const hal_rpc_session_handle_t session, +static hal_error_t pkey_mixed_verify(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, diff --git a/rpc_hash.c b/rpc_hash.c index 86b8ae0..407e581 100644 --- a/rpc_hash.c +++ b/rpc_hash.c @@ -47,8 +47,8 @@ */ typedef struct { - hal_rpc_client_handle_t client_handle; - hal_rpc_session_handle_t session_handle; + hal_client_handle_t client_handle; + hal_session_handle_t session_handle; hal_rpc_hash_handle_t hash_handle; union { hal_hash_state_t *hash; @@ -226,8 +226,8 @@ static hal_error_t get_algorithm(const hal_rpc_hash_handle_t handle, hal_digest_ return HAL_OK; } -static hal_error_t initialize(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t initialize(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_hash_handle_t *hash, const hal_digest_algorithm_t alg, const uint8_t * const key, const size_t key_len) diff --git a/rpc_misc.c b/rpc_misc.c new file mode 100644 index 0000000..2f1c9ad --- /dev/null +++ b/rpc_misc.c @@ -0,0 +1,158 @@ +/* + * rpc_misc.c + * ---------- + * RPC interface to TRNG and PIN functions + * + * Authors: Rob Austein + * Copyright (c) 2015, NORDUnet A/S All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of the NORDUnet nor the names of its contributors may + * be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "hal.h" +#include "hal_internal.h" + +static hal_error_t get_random(void *buffer, const size_t length) +{ + assert(buffer != NULL && length > 0); + + return hal_get_random(NULL, buffer, length); +} + +/* + * PINs, salt, and iteration count live in the keystore. + * + * We also need a client table in conventional memory (here, probably) + * to record login status. + * + * The USER and SO PINs correspond to PKCS #11. + * + * The WHEEL PIN is the one that's allowed to change the SO PIN. + * + * It's a bit unclear how we should manage changes to the WHEEL PIN. + * Implementing a factory default would be easy enough (just + * pre-compute and compile in a const hal_ks_pin_t), question is + * whether doing so provides anything useful. Certainly adds no real + * security, question is whether it would help prevent accidently + * bricking the HSM right out of the shrink wrap. + * + * More interesting question is whether we should ever allow the WHEEL + * PIN to be changed a second time without toasting the keystore. + * + * We also need a function which the rest of the library can use to + * check current login status for a particular hal_client_t. Don't + * know yet whether we need anything else. + */ + +#warning PIN code not yet fully implemented + +#ifndef HAL_PIN_MINIMUM_ITERATIONS +#define HAL_PIN_MINIMUM_ITERATIONS 10000 +#endif + +#ifndef HAL_PIN_DEFAULT_ITERATIONS +#define HAL_PIN_DEFAULT_ITERATIONS 20000 +#endif + +static hal_error_t set_pin(const hal_user_t user, + const char * const newpin, const size_t newpin_len) +{ + assert(newpin != NULL && newpin_len != 0); + +#warning Need access control to decide who is allowed to set this PIN +#warning Need length checks on supplied PIN + + const hal_ks_pin_t *pp; + hal_error_t err; + + if ((err = hal_ks_get_pin(user, &pp)) != HAL_OK) + return err; + + hal_ks_pin_t p = *pp; + + if (p.iterations == 0) + p.iterations = HAL_PIN_DEFAULT_ITERATIONS; + + if ((err = hal_get_random(NULL, p.salt, sizeof(p.salt))) != HAL_OK || + (err = hal_pbkdf2(NULL, hal_hash_sha256, + (const uint8_t *) newpin, newpin_len, + p.salt, sizeof(p.salt), + p.pin, sizeof(p.pin), p.iterations)) != HAL_OK || + (err = hal_ks_set_pin(user, &p)) != HAL_OK) + return err; + + return HAL_OK; +} + +static hal_error_t login(const hal_client_handle_t client, + const hal_user_t user, + const char * const pin, const size_t pin_len) +{ + assert(pin != NULL && pin_len != 0); + assert(user == HAL_USER_NORMAL || user == HAL_USER_SO || user == HAL_USER_WHEEL); + + const hal_ks_pin_t *p; + hal_error_t err; + + if ((err = hal_ks_get_pin(user, &p)) != HAL_OK) + return err; + + uint8_t buf[sizeof(p->pin)]; + + if ((err = hal_pbkdf2(NULL, hal_hash_sha256, (const uint8_t *) pin, pin_len, + p->salt, sizeof(p->salt), buf, sizeof(buf), p->iterations)) != HAL_OK) + return err; + + unsigned diff = 0; + for (int i = 0; i < sizeof(buf); i++) + diff |= buf[i] ^ p->pin[i]; + + if (diff != 0) + return HAL_ERROR_PIN_INCORRECT; + +#warning Do something with client table here + + return HAL_OK; +} + +static hal_error_t logout(const hal_client_handle_t client) +{ +#warning And do something else with client table here + return HAL_ERROR_IMPOSSIBLE; +} + +const hal_rpc_misc_dispatch_t hal_rpc_remote_misc_dispatch = { + set_pin, login, logout, get_random +}; + +/* + * Local variables: + * indent-tabs-mode: nil + * End: + */ diff --git a/rpc_pkey.c b/rpc_pkey.c index 3488537..fdbc7cc 100644 --- a/rpc_pkey.c +++ b/rpc_pkey.c @@ -40,8 +40,8 @@ #include "hal_internal.h" typedef struct { - hal_rpc_client_handle_t client_handle; - hal_rpc_session_handle_t session_handle; + hal_client_handle_t client_handle; + hal_session_handle_t session_handle; hal_rpc_pkey_handle_t pkey_handle; hal_key_type_t type; hal_curve_name_t curve; @@ -203,8 +203,8 @@ static hal_error_t pkcs1_5_pad(const uint8_t * const data, const size_t data_len * Receive key from application, store it with supplied name, return a key handle. */ -static hal_error_t load(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t load(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const hal_key_type_t type, const hal_curve_name_t curve, @@ -239,8 +239,8 @@ static hal_error_t load(const hal_rpc_client_handle_t client, * Look up a key given its name, return a key handle. */ -static hal_error_t find(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t find(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const hal_key_type_t type, const uint8_t * const name, const size_t name_len) @@ -270,8 +270,8 @@ static hal_error_t find(const hal_rpc_client_handle_t client, * Generate a new RSA key with supplied name, return a key handle. */ -static hal_error_t generate_rsa(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t generate_rsa(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const uint8_t * const name, const size_t name_len, const unsigned key_length, @@ -323,8 +323,8 @@ static hal_error_t generate_rsa(const hal_rpc_client_handle_t client, * At the moment, EC key == ECDSA key, but this is subject to change. */ -static hal_error_t generate_ec(const hal_rpc_client_handle_t client, - const hal_rpc_session_handle_t session, +static hal_error_t generate_ec(const hal_client_handle_t client, + const hal_session_handle_t session, hal_rpc_pkey_handle_t *pkey, const uint8_t * const name, const size_t name_len, const hal_curve_name_t curve, @@ -624,7 +624,7 @@ static hal_error_t sign_ecdsa(uint8_t *keybuf, const size_t keybuf_len, return HAL_OK; } -static hal_error_t sign(const hal_rpc_session_handle_t session, +static hal_error_t sign(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, @@ -744,7 +744,7 @@ static hal_error_t verify_ecdsa(uint8_t *keybuf, const size_t keybuf_len, return HAL_OK; } -static hal_error_t verify(const hal_rpc_session_handle_t session, +static hal_error_t verify(const hal_session_handle_t session, const hal_rpc_pkey_handle_t pkey, const hal_rpc_hash_handle_t hash, const uint8_t * const input, const size_t input_len, diff --git a/rsa.c b/rsa.c index 723d948..b257604 100644 --- a/rsa.c +++ b/rsa.c @@ -73,7 +73,7 @@ #include #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" #include #include "asn1_internal.h" -- cgit v1.2.3