diff options
author | Rob Austein <sra@hactrn.net> | 2015-12-23 21:35:28 -0500 |
---|---|---|
committer | Rob Austein <sra@hactrn.net> | 2015-12-23 21:35:28 -0500 |
commit | a1e4e4fe7331338ece1a6d3ba01862a35a22f4ae (patch) | |
tree | bfccf359539f1d98d314eea4e3043e9f379cc3c1 | |
parent | 0fc5ab986329e48ac8de0fd8fa12455c1e6345af (diff) |
RPC interface to TRNG and (incomplete) PIN code.
-rw-r--r-- | GNUmakefile | 30 | ||||
-rw-r--r-- | aes_keywrap.c | 2 | ||||
-rw-r--r-- | core.c | 2 | ||||
-rw-r--r-- | csprng.c | 2 | ||||
-rw-r--r-- | hal.h | 46 | ||||
-rw-r--r-- | hal_internal.h | 83 | ||||
-rw-r--r-- | hal_io_eim.c | 2 | ||||
-rw-r--r-- | hal_io_i2c.c | 2 | ||||
-rw-r--r-- | hash.c | 6 | ||||
-rw-r--r-- | ks.c | 21 | ||||
-rw-r--r-- | ks_flash.c | 25 | ||||
-rw-r--r-- | ks_mmap.c | 19 | ||||
-rw-r--r-- | ks_volatile.c | 46 | ||||
-rw-r--r-- | modexp.c | 2 | ||||
-rw-r--r-- | pbkdf2.c | 2 | ||||
-rw-r--r-- | rpc_api.c (renamed from rpc.c) | 38 | ||||
-rw-r--r-- | rpc_client.c | 36 | ||||
-rw-r--r-- | rpc_hash.c | 8 | ||||
-rw-r--r-- | rpc_misc.c | 158 | ||||
-rw-r--r-- | rpc_pkey.c | 24 | ||||
-rw-r--r-- | rsa.c | 2 |
21 files changed, 425 insertions, 131 deletions
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 <assert.h> #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * How long the ciphertext will be for a given plaintext length. @@ -39,7 +39,7 @@ #include <string.h> #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * Each Cryptech core has a set of 4-byte registers, which are accessed @@ -37,7 +37,7 @@ #include <stdint.h> #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" #ifndef WAIT_FOR_CSPRNG_VALID #define WAIT_FOR_CSPRNG_VALID 1 @@ -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 */ @@ -205,13 +206,6 @@ extern hal_error_t hal_get_random(const hal_core_t *core, void *buffer, const si */ /* - * 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 <stdint.h> #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" #define I2C_dev "/dev/i2c-2" #define I2C_addr 0x0f @@ -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 <stdint.h> #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * HMAC magic numbers. @@ -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 @@ -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 @@ -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 <string.h> + #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: @@ -46,7 +46,7 @@ #include <assert.h> #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * Whether we want debug output. @@ -39,7 +39,7 @@ #include <stdint.h> #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" /* * Utility to encapsulate the HMAC operations. May need refactoring @@ -125,24 +125,24 @@ hal_error_t hal_rpc_get_random(void *buffer, const size_t 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, +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 || (which != HAL_RPC_USER_NORMAL && which != HAL_RPC_USER_SO)) + 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(which, newpin, newpin_len); + return misc_dispatch->set_pin(user, newpin, newpin_len); } -hal_error_t hal_rpc_login(const hal_rpc_client_handle_t client, - const hal_rpc_user_t user, +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_RPC_USER_NORMAL && user != HAL_RPC_USER_SO)) + 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_rpc_client_handle_t client) +hal_error_t hal_rpc_logout(const hal_client_handle_t client) { return misc_dispatch->logout(client); } @@ -167,8 +167,8 @@ hal_error_t hal_rpc_hash_get_algorithm(const hal_rpc_hash_handle_t hash, hal_dig 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_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) @@ -196,8 +196,8 @@ hal_error_t hal_rpc_hash_finalize(const hal_rpc_hash_handle_t hash, 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_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, @@ -213,8 +213,8 @@ hal_error_t hal_rpc_pkey_load(const hal_rpc_client_handle_t client, 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_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) @@ -224,8 +224,8 @@ hal_error_t hal_rpc_pkey_find(const hal_rpc_client_handle_t client, 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_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, @@ -238,8 +238,8 @@ hal_error_t hal_rpc_pkey_generate_rsa(const hal_rpc_client_handle_t client, 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_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, @@ -290,7 +290,7 @@ hal_error_t hal_rpc_pkey_get_public_key(const hal_rpc_pkey_handle_t pkey, 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, +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, @@ -302,7 +302,7 @@ hal_error_t hal_rpc_pkey_sign(const hal_rpc_session_handle_t session, 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, +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/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, @@ -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 <assert.h> + +#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: + */ @@ -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, @@ -73,7 +73,7 @@ #include <assert.h> #include "hal.h" -#include "verilog_constants.h" +#include "hal_internal.h" #include <tfm.h> #include "asn1_internal.h" |