[Cryptech-Commits] [sw/libhal] 01/11: RPC server stuff mostly written. Compiles, not yet tested. RPC public key extraction functions on hold pending ASN.1 cleanup.
git at cryptech.is
git at cryptech.is
Wed Dec 23 07:22:20 UTC 2015
This is an automated email from the git hooks/post-receive script.
sra at hactrn.net pushed a commit to branch rpc
in repository sw/libhal.
commit 86b35d757048aaa122237e1cb8fb33de9d53292d
Author: Rob Austein <sra at hactrn.net>
Date: Sun Dec 20 17:59:29 2015 -0500
RPC server stuff mostly written. Compiles, not yet tested. RPC
public key extraction functions on hold pending ASN.1 cleanup.
---
GNUmakefile | 24 +-
ecdsa.c | 42 +--
hal.h | 254 ++++++++++++--
rpc_internal.h => hal_internal.h | 137 +++++++-
hal_rpc.h | 243 -------------
ks.c | 280 +++++++++++++++
ks_flash.c | 71 ++++
ks_mmap.c | 115 ++++++
ks_volatile.c | 74 ++++
hal_rpc.c => rpc.c | 82 +++--
rpc_client.c | 53 +--
rpc_hash.c | 30 +-
rpc_pkey.c | 736 +++++++++++++++++++++++++++++++++++++++
rsa.c | 22 +-
tests/test-ecdsa.c | 14 +-
tests/test-ecdsa.h | 6 +-
16 files changed, 1776 insertions(+), 407 deletions(-)
diff --git a/GNUmakefile b/GNUmakefile
index 8fc0d14..e0b4730 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -27,22 +27,24 @@
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-# Number of static hash and HMAC state blocks to allocate
+# Number of static hash and HMAC state blocks to allocate.
+# Numbers pulled out of a hat, just testing.
STATIC_HASH_STATE_BLOCKS = 10
STATIC_HMAC_STATE_BLOCKS = 4
+STATIC_PKEY_STATE_BLOCKS = 6
-INC = hal.h
+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}
+ modexp.o rsa.o ecdsa.o asn1.o errorstrings.o ${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 = hal_rpc.o rpc_hash.o
+RPC_OBJ_COMMON = rpc.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
@@ -51,12 +53,20 @@ RPC_OBJ_SERVER = ${RPC_OBJ_COMMON} rpc_misc.o rpc_pkey.o
# needing a makefile conditional to handle all this properly
RPC_OBJ = ${RPC_OBJ_CLIENT}
+# XXX temporary
+$(warning TEMPORARY KLUDGE TO TEST rpc_pkey)
+RPC_OBJ += rpc_pkey.o
+
+# XXX temporary
+KS_OBJ = ks.o ks_mmap.o
+
TFMDIR := $(abspath ../thirdparty/libtfm)
CFLAGS += -g3 -Wall -fPIC -std=c99 -I${TFMDIR} -DHAL_ECDSA_DEBUG_ONLY_STATIC_TEST_VECTOR_RANDOM=1
LDFLAGS := -g3 -L${TFMDIR} -ltfm
CFLAGS += -DHAL_STATIC_HASH_STATE_BLOCKS=${STATIC_HASH_STATE_BLOCKS}
CFLAGS += -DHAL_STATIC_HMAC_STATE_BLOCKS=${STATIC_HMAC_STATE_BLOCKS}
+CFLAGS += -DHAL_STATIC_PKEY_STATE_BLOCKS=${STATIC_PKEY_STATE_BLOCKS}
all: ${LIB}
cd tests; ${MAKE} CFLAGS='${CFLAGS} -I..' LDFLAGS='${LDFLAGS}' $@
@@ -67,9 +77,9 @@ ${OBJ}: ${INC}
${LIB}: ${OBJ}
${AR} rcs $@ $^
-asn1.o rsa.o ecdsa.o: asn1_internal.h
-
-ecdsa.o: ecdsa_curves.h
+asn1.o rsa.o ecdsa.o: asn1_internal.h
+ecdsa.o: ecdsa_curves.h
+novena-eim.o hal_io_eim.o: novena-eim.h
test: all
cd tests; ${MAKE} -k $@
diff --git a/ecdsa.c b/ecdsa.c
index eeab252..703849b 100644
--- a/ecdsa.c
+++ b/ecdsa.c
@@ -150,8 +150,8 @@ typedef struct {
} ec_point_t;
struct hal_ecdsa_key {
- hal_ecdsa_key_type_t type; /* Public or private is */
- hal_ecdsa_curve_t curve; /* Curve descriptor */
+ hal_key_type_t type; /* Public or private */
+ hal_curve_name_t curve; /* Curve descriptor */
ec_point_t Q[1]; /* Public key */
fp_int d[1]; /* Private key */
};
@@ -181,7 +181,7 @@ const size_t hal_ecdsa_key_t_size = sizeof(struct hal_ecdsa_key);
* first time anything asks for any of them.
*/
-static const ecdsa_curve_t * const get_curve(const hal_ecdsa_curve_t curve)
+static const ecdsa_curve_t * const get_curve(const hal_curve_name_t curve)
{
static ecdsa_curve_t curve_p256, curve_p384, curve_p521;
static int initialized = 0;
@@ -230,10 +230,10 @@ static const ecdsa_curve_t * const get_curve(const hal_ecdsa_curve_t curve)
}
switch (curve) {
- case HAL_ECDSA_CURVE_P256: return &curve_p256;
- case HAL_ECDSA_CURVE_P384: return &curve_p384;
- case HAL_ECDSA_CURVE_P521: return &curve_p521;
- default: return NULL;
+ case HAL_CURVE_P256: return &curve_p256;
+ case HAL_CURVE_P384: return &curve_p384;
+ case HAL_CURVE_P521: return &curve_p521;
+ default: return NULL;
}
}
@@ -831,7 +831,7 @@ static int point_is_on_curve(const ec_point_t * const P,
hal_error_t hal_ecdsa_key_gen(const hal_core_t *core,
hal_ecdsa_key_t **key_,
void *keybuf, const size_t keybuf_len,
- const hal_ecdsa_curve_t curve_)
+ const hal_curve_name_t curve_)
{
const ecdsa_curve_t * const curve = get_curve(curve_);
hal_ecdsa_key_t *key = keybuf;
@@ -842,7 +842,7 @@ hal_error_t hal_ecdsa_key_gen(const hal_core_t *core,
memset(keybuf, 0, keybuf_len);
- key->type = HAL_ECDSA_PRIVATE;
+ key->type = HAL_KEY_TYPE_EC_PRIVATE;
key->curve = curve_;
if ((err = point_pick_random(curve, key->d, key->Q)) != HAL_OK)
@@ -859,7 +859,7 @@ hal_error_t hal_ecdsa_key_gen(const hal_core_t *core,
*/
hal_error_t hal_ecdsa_key_get_type(const hal_ecdsa_key_t * const key,
- hal_ecdsa_key_type_t *key_type)
+ hal_key_type_t *key_type)
{
if (key == NULL || key_type == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
@@ -873,7 +873,7 @@ hal_error_t hal_ecdsa_key_get_type(const hal_ecdsa_key_t * const key,
*/
hal_error_t hal_ecdsa_key_get_curve(const hal_ecdsa_key_t * const key,
- hal_ecdsa_curve_t *curve)
+ hal_curve_name_t *curve)
{
if (key == NULL || curve == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
@@ -929,7 +929,7 @@ void hal_ecdsa_key_clear(hal_ecdsa_key_t *key)
hal_error_t hal_ecdsa_key_load_public(hal_ecdsa_key_t **key_,
void *keybuf, const size_t keybuf_len,
- const hal_ecdsa_curve_t curve_,
+ const hal_curve_name_t curve_,
const uint8_t * const x, const size_t x_len,
const uint8_t * const y, const size_t y_len)
{
@@ -941,7 +941,7 @@ hal_error_t hal_ecdsa_key_load_public(hal_ecdsa_key_t **key_,
memset(keybuf, 0, keybuf_len);
- key->type = HAL_ECDSA_PUBLIC;
+ key->type = HAL_KEY_TYPE_EC_PUBLIC;
key->curve = curve_;
fp_read_unsigned_bin(key->Q->x, unconst_uint8_t(x), x_len);
@@ -966,7 +966,7 @@ hal_error_t hal_ecdsa_key_load_public(hal_ecdsa_key_t **key_,
hal_error_t hal_ecdsa_key_load_private(hal_ecdsa_key_t **key_,
void *keybuf, const size_t keybuf_len,
- const hal_ecdsa_curve_t curve_,
+ const hal_curve_name_t curve_,
const uint8_t * const x, const size_t x_len,
const uint8_t * const y, const size_t y_len,
const uint8_t * const d, const size_t d_len)
@@ -980,7 +980,7 @@ hal_error_t hal_ecdsa_key_load_private(hal_ecdsa_key_t **key_,
if ((err = hal_ecdsa_key_load_public(key_, keybuf, keybuf_len, curve_, x, x_len, y, y_len)) != HAL_OK)
return err;
- key->type = HAL_ECDSA_PRIVATE;
+ key->type = HAL_KEY_TYPE_EC_PRIVATE;
fp_read_unsigned_bin(key->d, unconst_uint8_t(d), d_len);
return HAL_OK;
}
@@ -1052,7 +1052,7 @@ size_t hal_ecdsa_key_to_ecpoint_len(const hal_ecdsa_key_t * const key)
hal_error_t hal_ecdsa_key_from_ecpoint(hal_ecdsa_key_t **key_,
void *keybuf, const size_t keybuf_len,
const uint8_t * const der, const size_t der_len,
- const hal_ecdsa_curve_t curve)
+ const hal_curve_name_t curve)
{
hal_ecdsa_key_t *key = keybuf;
@@ -1060,7 +1060,7 @@ hal_error_t hal_ecdsa_key_from_ecpoint(hal_ecdsa_key_t **key_,
return HAL_ERROR_BAD_ARGUMENTS;
memset(keybuf, 0, keybuf_len);
- key->type = HAL_ECDSA_PUBLIC;
+ key->type = HAL_KEY_TYPE_EC_PUBLIC;
key->curve = curve;
size_t hlen, vlen;
@@ -1106,7 +1106,7 @@ hal_error_t hal_ecdsa_key_from_ecpoint(hal_ecdsa_key_t **key_,
hal_error_t hal_ecdsa_key_to_der(const hal_ecdsa_key_t * const key,
uint8_t *der, size_t *der_len, const size_t der_max)
{
- if (key == NULL || key->type != HAL_ECDSA_PRIVATE)
+ if (key == NULL || key->type != HAL_KEY_TYPE_EC_PRIVATE)
return HAL_ERROR_BAD_ARGUMENTS;
const ecdsa_curve_t * const curve = get_curve(key->curve);
@@ -1215,7 +1215,7 @@ hal_error_t hal_ecdsa_key_from_der(hal_ecdsa_key_t **key_,
return HAL_ERROR_BAD_ARGUMENTS;
memset(keybuf, 0, keybuf_len);
- key->type = HAL_ECDSA_PRIVATE;
+ key->type = HAL_KEY_TYPE_EC_PRIVATE;
size_t hlen, vlen;
hal_error_t err;
@@ -1248,7 +1248,7 @@ hal_error_t hal_ecdsa_key_from_der(hal_ecdsa_key_t **key_,
if ((err = hal_asn1_decode_header(ASN1_OBJECT_IDENTIFIER, d, vlen, &hlen, &vlen)) != HAL_OK)
return err;
d += hlen;
- for (key->curve = (hal_ecdsa_curve_t) 0; (curve = get_curve(key->curve)) != NULL; key->curve++)
+ for (key->curve = (hal_curve_name_t) 0; (curve = get_curve(key->curve)) != NULL; key->curve++)
if (vlen == curve->oid_len && memcmp(d, curve->oid, vlen) == 0)
break;
if (curve == NULL)
@@ -1427,7 +1427,7 @@ hal_error_t hal_ecdsa_sign(const hal_core_t *core,
uint8_t *signature, size_t *signature_len, const size_t signature_max,
const hal_ecdsa_signature_format_t signature_format)
{
- if (key == NULL || hash == NULL || signature == NULL || signature_len == NULL || key->type != HAL_ECDSA_PRIVATE)
+ if (key == NULL || hash == NULL || signature == NULL || signature_len == NULL || key->type != HAL_KEY_TYPE_EC_PRIVATE)
return HAL_ERROR_BAD_ARGUMENTS;
const ecdsa_curve_t * const curve = get_curve(key->curve);
diff --git a/hal.h b/hal.h
index 1ccc491..4a1ef75 100644
--- a/hal.h
+++ b/hal.h
@@ -36,15 +36,19 @@
#ifndef _HAL_H_
#define _HAL_H_
+#include <stdint.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
/*
* A handy macro from cryptlib.
*/
#ifndef bitsToBytes
-#define bitsToBytes(x) (x / 8)
+#define bitsToBytes(x) ((x) / 8)
#endif
/*
- * Current name and version values.
+ * Current name and version values for crypto cores.
*
* Should these even be here? Dunno.
* Should the versions be here even if the names should be?
@@ -114,6 +118,10 @@
DEFINE_HAL_ERROR(HAL_ERROR_KEY_NOT_ON_CURVE, "EC key is not on its purported curve") \
DEFINE_HAL_ERROR(HAL_ERROR_INVALID_SIGNATURE, "Invalid signature") \
DEFINE_HAL_ERROR(HAL_ERROR_CORE_NOT_FOUND, "Requested core not found") \
+ DEFINE_HAL_ERROR(HAL_ERROR_KEYSTORE_ACCESS, "Could not access keystore") \
+ 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") \
END_OF_HAL_ERROR_LIST
/* Marker to forestall silly line continuation errors */
@@ -125,24 +133,21 @@ typedef enum { HAL_ERROR_LIST N_HAL_ERRORS } hal_error_t;
#undef DEFINE_HAL_ERROR
/*
- * Public functions.
+ * Error translation.
*/
-#include <stdint.h>
-#include <sys/types.h>
+extern const char *hal_error_string(const hal_error_t err);
/*
- * Typedef to isolate code from our current choice of representation
- * for a Cryptech bus address.
+ * Very low level public API for working directly with crypto cores.
*/
-typedef off_t hal_addr_t;
-
/*
- * Error translation.
+ * Typedef to isolate code from our current choice of representation
+ * for a Cryptech bus address.
*/
-extern const char *hal_error_string(const hal_error_t err);
+typedef off_t hal_addr_t;
/*
* Opaque structure representing a core.
@@ -186,7 +191,7 @@ extern hal_addr_t hal_core_base(const hal_core_t *core);
extern const hal_core_t * hal_core_iterate(const hal_core_t *core);
/*
- * Higher level public API.
+ * Slightly higher level public API, still working directly with cores.
*/
/*
@@ -340,10 +345,27 @@ extern hal_error_t hal_modexp(const hal_core_t *core,
/*
- * RSA.
+ * Key types and curves, used in various places.
*/
-typedef enum { HAL_RSA_PRIVATE, HAL_RSA_PUBLIC } hal_rsa_key_type_t;
+typedef enum {
+ HAL_KEY_TYPE_NONE,
+ HAL_KEY_TYPE_RSA_PRIVATE,
+ HAL_KEY_TYPE_RSA_PUBLIC,
+ HAL_KEY_TYPE_EC_PRIVATE,
+ HAL_KEY_TYPE_EC_PUBLIC
+} hal_key_type_t;
+
+typedef enum {
+ HAL_CURVE_NONE,
+ HAL_CURVE_P256,
+ HAL_CURVE_P384,
+ HAL_CURVE_P521
+} hal_curve_name_t;
+
+/*
+ * RSA.
+ */
typedef struct hal_rsa_key hal_rsa_key_t;
@@ -370,7 +392,7 @@ extern hal_error_t hal_rsa_key_load_public(hal_rsa_key_t **key,
const uint8_t * const e, const size_t e_len);
extern hal_error_t hal_rsa_key_get_type(const hal_rsa_key_t * const key,
- hal_rsa_key_type_t *key_type);
+ hal_key_type_t *key_type);
extern hal_error_t hal_rsa_key_get_modulus(const hal_rsa_key_t * const key,
uint8_t *modulus,
@@ -413,10 +435,6 @@ extern hal_error_t hal_rsa_key_from_der(hal_rsa_key_t **key,
* ECDSA.
*/
-typedef enum { HAL_ECDSA_PRIVATE, HAL_ECDSA_PUBLIC } hal_ecdsa_key_type_t;
-
-typedef enum { HAL_ECDSA_CURVE_P256, HAL_ECDSA_CURVE_P384, HAL_ECDSA_CURVE_P521 } hal_ecdsa_curve_t;
-
typedef enum { HAL_ECDSA_SIGNATURE_FORMAT_ASN1, HAL_ECDSA_SIGNATURE_FORMAT_PKCS11 } hal_ecdsa_signature_format_t;
typedef struct hal_ecdsa_key hal_ecdsa_key_t;
@@ -427,22 +445,22 @@ extern void hal_ecdsa_set_debug(const int onoff);
extern hal_error_t hal_ecdsa_key_load_private(hal_ecdsa_key_t **key,
void *keybuf, const size_t keybuf_len,
- const hal_ecdsa_curve_t curve,
+ const hal_curve_name_t curve,
const uint8_t * const x, const size_t x_len,
const uint8_t * const y, const size_t y_len,
const uint8_t * const d, const size_t d_len);
extern hal_error_t hal_ecdsa_key_load_public(hal_ecdsa_key_t **key,
void *keybuf, const size_t keybuf_len,
- const hal_ecdsa_curve_t curve,
+ const hal_curve_name_t curve,
const uint8_t * const x, const size_t x_len,
const uint8_t * const y, const size_t y_len);
extern hal_error_t hal_ecdsa_key_get_type(const hal_ecdsa_key_t * const key,
- hal_ecdsa_key_type_t *key_type);
+ hal_key_type_t *key_type);
extern hal_error_t hal_ecdsa_key_get_curve(const hal_ecdsa_key_t * const key,
- hal_ecdsa_curve_t *curve);
+ hal_curve_name_t *curve);
extern hal_error_t hal_ecdsa_key_get_public(const hal_ecdsa_key_t * const key,
uint8_t *x, size_t *x_len, const size_t x_max,
@@ -453,7 +471,7 @@ extern void hal_ecdsa_key_clear(hal_ecdsa_key_t *key);
extern hal_error_t hal_ecdsa_key_gen(const hal_core_t *core,
hal_ecdsa_key_t **key,
void *keybuf, const size_t keybuf_len,
- const hal_ecdsa_curve_t curve);
+ const hal_curve_name_t curve);
extern hal_error_t hal_ecdsa_key_to_der(const hal_ecdsa_key_t * const key,
uint8_t *der, size_t *der_len, const size_t der_max);
@@ -472,7 +490,7 @@ extern size_t hal_ecdsa_key_to_ecpoint_len(const hal_ecdsa_key_t * const key);
extern hal_error_t hal_ecdsa_key_from_ecpoint(hal_ecdsa_key_t **key,
void *keybuf, const size_t keybuf_len,
const uint8_t * const der, const size_t der_len,
- const hal_ecdsa_curve_t curve);
+ const hal_curve_name_t curve);
extern hal_error_t hal_ecdsa_sign(const hal_core_t *core,
const hal_ecdsa_key_t * const key,
@@ -486,6 +504,192 @@ extern hal_error_t hal_ecdsa_verify(const hal_core_t *core,
const uint8_t * const signature, const size_t signature_len,
const hal_ecdsa_signature_format_t signature_format);
+/*
+ * Higher level RPC-based mechanism for working with HSM at arm's
+ * length, using handles instead of direct access to the cores.
+ *
+ * Session handles are pretty much as in PKCS #11: from our viewpoint,
+ * a session is a lock-step stream of operations, so while operations
+ * from different sessions can interleave, operations within a single
+ * session cannot.
+ *
+ * Client handles are a small extension to the PKCS #11 model,
+ * intended to support multiple PKCS #11 using applications sharing a
+ * single HSM. Technically, sessions are per-client, but in practice
+ * there's no sane reason why we'd use the same session handle
+ * concurrently in multiple clients. Mostly, the client abstraction
+ * is to handle login and logout against the HSM's PIN. Clients add
+ * nothing whatsoever to the security model (the HSM has no way of
+ * knowing whether the host is lumping multiple applications into a
+ * single "client"), the point of the exercise is just to make the
+ * C_Login()/C_Logout() semantics work as expected in the presence of
+ * multiple applications.
+ *
+ * NB: Unlike the other handles used in this protocol, session and
+ * client handles are created by the client (host) side of the RPC
+ * 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 enum { HAL_RPC_USER_NONE, HAL_RPC_USER_NORMAL, HAL_RPC_USER_SO } hal_rpc_user_t;
+
+extern hal_error_t hal_rpc_set_pin(const hal_rpc_user_t which,
+ 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,
+ const char * const pin, const size_t pin_len);
+
+extern hal_error_t hal_rpc_logout(const hal_rpc_client_handle_t client);
+
+/*
+ * Get random bytes.
+ */
+
+extern hal_error_t hal_rpc_get_random(void *buffer, const size_t length);
+
+/*
+ * Combined hash and HMAC functions: pass NULL key for plain hashing.
+ */
+
+typedef struct { uint32_t handle; } hal_rpc_hash_handle_t;
+
+extern const hal_rpc_hash_handle_t hal_rpc_hash_handle_none;
+
+extern hal_error_t hal_rpc_hash_get_digest_length(const hal_digest_algorithm_t alg, size_t *length);
+
+extern 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);
+
+extern hal_error_t hal_rpc_hash_get_algorithm(const hal_rpc_hash_handle_t hash, hal_digest_algorithm_t *alg);
+
+/*
+ * Once started, a hash or HMAC operation is bound to a particular
+ * 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,
+ hal_rpc_hash_handle_t *hash,
+ const hal_digest_algorithm_t alg,
+ const uint8_t * const key, const size_t key_length);
+
+extern hal_error_t hal_rpc_hash_update(const hal_rpc_hash_handle_t hash,
+ const uint8_t * data, const size_t length);
+
+extern hal_error_t hal_rpc_hash_finalize(const hal_rpc_hash_handle_t hash,
+ uint8_t *digest, const size_t length);
+
+/*
+ * Public key functions.
+ *
+ * The _sign() and _verify() methods accept a hash OR an input string;
+ * either "hash" should be hal_rpc_hash_handle_none or input should be NULL,
+ * but not both.
+ *
+ * Use of client and session handles here needs a bit more thought.
+ *
+ * Client handles are straightforward: basically, anything that
+ * creates a new pkey handle should take a client handle, which should
+ * suffice, as object handles never cross clients.
+ *
+ * Session handles are more interesting, as PKCS #11's versions of
+ * session and object handles do in effect allow one session to hand
+ * an object handle to another session. So any action which can do
+ * significant work (ie, which is complicated enough that we can't
+ * guarantee an immediate response) needs to take a session handle.
+ *
+ * There will probably be a few cases where a session handle isn't
+ * strictly required but we ask for one anyway because the API turns
+ * out to be easier to understand that way (eg, we probably want to
+ * ask for a session handle anywhere we ask for a client handle,
+ * whether we need the session handle or not, so that users of this
+ * API don't have to remember which pkey-handle-creating calls require
+ * a session handle and which ones don't...).
+ */
+
+#define HAL_RPC_PKEY_NAME_MAX 128
+
+typedef struct { uint32_t handle; } hal_rpc_pkey_handle_t;
+
+typedef uint32_t hal_key_flags_t;
+
+#define HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE (1 << 0)
+#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,
+ 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);
+
+extern 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);
+
+extern 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_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,
+ 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);
+
+extern hal_error_t hal_rpc_pkey_close(const hal_rpc_pkey_handle_t pkey);
+
+extern hal_error_t hal_rpc_pkey_delete(const hal_rpc_pkey_handle_t pkey);
+
+extern hal_error_t hal_rpc_pkey_get_key_type(const hal_rpc_pkey_handle_t pkey,
+ hal_key_type_t *type);
+
+extern hal_error_t hal_rpc_pkey_get_key_flags(const hal_rpc_pkey_handle_t pkey,
+ hal_key_flags_t *flags);
+
+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_len_max);
+
+extern 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);
+
+extern 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);
+
+typedef struct {
+ hal_key_type_t type;
+ hal_curve_name_t curve;
+ hal_key_flags_t flags;
+ char name[HAL_RPC_PKEY_NAME_MAX];
+ size_t name_len;
+ /* ... */
+} hal_rpc_pkey_key_info_t;
+
+extern hal_error_t hal_rpc_pkey_list(hal_rpc_pkey_key_info_t *result,
+ unsigned *result_len,
+ const unsigned result_max);
+
#endif /* _HAL_H_ */
/*
diff --git a/rpc_internal.h b/hal_internal.h
similarity index 62%
rename from rpc_internal.h
rename to hal_internal.h
index b861ec7..3f7f600 100644
--- a/rpc_internal.h
+++ b/hal_internal.h
@@ -1,7 +1,7 @@
/*
- * rpc_internal.h
+ * hal_internal.h
* --------------
- * Internal (not public API) declarations for HAL RPC mechanism.
+ * Internal API declarations for libhal.
*
* Authors: Rob Austein, Paul Selkirk
* Copyright (c) 2015, NORDUnet A/S All rights reserved.
@@ -33,10 +33,10 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef _HAL_RPC_INTERNAL_H_
-#define _HAL_RPC_INTERNAL_H_
+#ifndef _HAL_INTERNAL_H_
+#define _HAL_INTERNAL_H_
-#include "hal_rpc.h"
+#include "hal.h"
/*
* Everything in this file is part of the internal API, that is,
@@ -119,16 +119,16 @@ typedef struct {
hal_error_t (*load)(const hal_rpc_client_handle_t client,
const hal_rpc_session_handle_t session,
hal_rpc_pkey_handle_t *pkey,
- const hal_rpc_pkey_key_type_t type,
- const hal_rpc_pkey_curve_t curve,
+ 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_rpc_pkey_flags_t flags);
+ 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_rpc_pkey_handle_t *pkey,
- const hal_rpc_pkey_key_type_t type,
+ 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,
@@ -137,22 +137,24 @@ typedef struct {
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_rpc_pkey_flags_t flags);
+ 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_rpc_pkey_handle_t *pkey,
const uint8_t * const name, const size_t name_len,
- const hal_rpc_pkey_curve_t curve,
- const hal_rpc_pkey_flags_t flags);
+ const hal_curve_name_t curve,
+ const hal_key_flags_t flags);
+
+ hal_error_t (*close)(const hal_rpc_pkey_handle_t pkey);
hal_error_t (*delete)(const hal_rpc_pkey_handle_t pkey);
hal_error_t (*get_key_type)(const hal_rpc_pkey_handle_t pkey,
- hal_rpc_pkey_key_type_t *key_type);
+ hal_key_type_t *key_type);
hal_error_t (*get_key_flags)(const hal_rpc_pkey_handle_t pkey,
- hal_rpc_pkey_flags_t *flags);
+ hal_key_flags_t *flags);
size_t (*get_public_key_len)(const hal_rpc_pkey_handle_t pkey);
@@ -163,13 +165,13 @@ typedef struct {
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 * output, const size_t output_len);
+ uint8_t * signature, size_t *signature_len, const size_t signature_max);
hal_error_t (*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,
- uint8_t * output, const size_t output_len);
+ const uint8_t * const signature, const size_t signature_len);
hal_error_t (*list)(hal_rpc_pkey_key_info_t *result,
unsigned *result_len,
@@ -182,7 +184,108 @@ extern const hal_rpc_misc_dispatch_t hal_rpc_local_misc_dispatch, hal_rpc_remote
extern const hal_rpc_hash_dispatch_t hal_rpc_local_hash_dispatch, hal_rpc_remote_hash_dispatch;
extern const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch, hal_rpc_remote_pkey_dispatch, hal_rpc_mixed_pkey_dispatch;
-#endif /* _HAL_RPC_INTERNAL_H_ */
+/*
+ * Keystore API.
+ *
+ * The original design for this subsystem used two separate tables,
+ * one for RSA keys, one for EC keys, because the RSA keys are so much
+ * larger than the EC keys. This led to unnecessarily complex and
+ * duplicated code, so for now we treat all keys the same, and waste
+ * the unneded space in the case of EC keys.
+ *
+ * Sizes for ASN.1-encoded keys, this may not be exact due to ASN.1
+ * INTEGER encoding rules but should be good enough for buffer sizing:
+ *
+ * 2048-bit RSA: 1194 bytes
+ * 4096-bit RSA: 2351 bytes
+ * 8192-bit RSA: 4655 bytes
+ * EC P-256: 121 bytes
+ * EC P-384: 167 bytes
+ * EC P-521: 223 bytes
+ *
+ * Plus we need a bit of AES-keywrap overhead, since we're storing the
+ * wrapped form (see hal_aes_keywrap_cyphertext_length()).
+ */
+
+#define HAL_KS_WRAPPED_KEYSIZE ((4655 + 15) & ~7)
+
+#ifndef HAL_STATIC_PKEY_STATE_BLOCKS
+#define HAL_STATIC_PKEY_STATE_BLOCKS 0
+#endif
+
+typedef struct {
+ hal_key_type_t type;
+ hal_curve_name_t curve;
+ hal_key_flags_t flags;
+ uint8_t name[HAL_RPC_PKEY_NAME_MAX];
+ size_t name_len;
+ uint8_t der[HAL_KS_WRAPPED_KEYSIZE];
+ size_t der_len;
+ uint8_t in_use;
+} hal_ks_key_t;
+
+typedef struct {
+#if HAL_STATIC_PKEY_STATE_BLOCKS > 0
+ hal_ks_key_t keys[HAL_STATIC_PKEY_STATE_BLOCKS];
+#endif
+} hal_ks_keydb_t;
+
+/*
+ * Internal functions within the keystore implementation. Think of
+ * these as concrete methods for the keystore API subclassed onto
+ * various storage technologies.
+ */
+
+extern const hal_ks_keydb_t *hal_ks_get_keydb(void);
+
+extern hal_error_t hal_ks_set_keydb(const hal_ks_key_t * const key,
+ const int loc);
+
+extern hal_error_t hal_ks_del_keydb(const int loc);
+
+extern hal_error_t hal_ks_get_kek(uint8_t *kek,
+ size_t *kek_len,
+ const size_t kek_max);
+
+/*
+ * Keystore API for use by the pkey implementation.
+ *
+ * In an attempt to emulate what current theory says will eventually
+ * be the behavior of the underlying Cryptech Verilog "hardware",
+ * these functions automatically apply the AES keywrap transformations.
+ *
+ * Unclear whether these should also call the ASN.1 encode/decode
+ * functions. For the moment, the answer is no, but we may need to
+ * revisit this as the underlying Verilog API evolves.
+ */
+
+extern hal_error_t hal_ks_store(const hal_key_type_t type,
+ const hal_curve_name_t curve,
+ const hal_key_flags_t flags,
+ const uint8_t * const name, const size_t name_len,
+ const uint8_t * const der, const size_t der_len,
+ int *hint);
+
+extern hal_error_t hal_ks_exists(const hal_key_type_t type,
+ const uint8_t * const name, const size_t name_len,
+ int *hint);
+
+extern hal_error_t hal_ks_fetch(const hal_key_type_t type,
+ const uint8_t * const name, const size_t name_len,
+ hal_curve_name_t *curve,
+ hal_key_flags_t *flags,
+ uint8_t *der, size_t *der_len, const size_t der_max,
+ int *hint);
+
+extern hal_error_t hal_ks_delete(const hal_key_type_t type,
+ const uint8_t * const name, const size_t name_len,
+ int *hint);
+
+extern hal_error_t hal_ks_list(hal_rpc_pkey_key_info_t *result,
+ unsigned *result_len,
+ const unsigned result_max);
+
+#endif /* _HAL_INTERNAL_H_ */
/*
* Local variables:
diff --git a/hal_rpc.h b/hal_rpc.h
deleted file mode 100644
index 553fb6b..0000000
--- a/hal_rpc.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/*
- * hal_rpc.h
- * ---------
- * Remote procedure call API to extrude libhal across the green/yellow boundary.
- *
- * Authors: Rob Austein, Paul Selkirk
- * 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.
- */
-
-#ifndef _HAL_RPC_H_
-#define _HAL_RPC_H_
-
-#include <stdint.h>
-#include <stdlib.h>
-#include "hal.h"
-
-/*
- * Session handles are pretty much as in PKCS #11: from our viewpoint,
- * a session is a lock-step stream of operations, so while operations
- * from different sessions can interleave, operations within a single
- * session cannot.
- *
- * Client handles are a small extension to the PKCS #11 model,
- * intended to support multiple PKCS #11 using applications sharing a
- * single HSM. Technically, sessions are per-client, but in practice
- * there's no sane reason why we'd use the same session handle
- * concurrently in multiple clients. Mostly, the client abstraction
- * is to handle login and logout against the HSM's PIN. Clients add
- * nothing whatsoever to the security model (the HSM has no way of
- * knowing whether the host is lumping multiple applications into a
- * single "client"), the point of the exercise is just to make the
- * C_Login()/C_Logout() semantics work as expected in the presence of
- * multiple applications.
- *
- * NB: Unlike other handles used in this protocol, session and client
- * handles are created by the client (host) side of the RPC 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 enum { HAL_RPC_USER_NONE, HAL_RPC_USER_NORMAL, HAL_RPC_USER_SO } hal_rpc_user_t;
-
-extern hal_error_t hal_rpc_set_pin(const hal_rpc_user_t which,
- 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,
- const char * const pin, const size_t pin_len);
-
-extern hal_error_t hal_rpc_logout(const hal_rpc_client_handle_t client);
-
-/*
- * Get random bytes.
- */
-
-extern hal_error_t hal_rpc_get_random(void *buffer, const size_t length);
-
-/*
- * Combined hash and HMAC functions: pass NULL key for plain hashing.
- */
-
-typedef struct { uint32_t handle; } hal_rpc_hash_handle_t;
-
-extern const hal_rpc_hash_handle_t hal_rpc_hash_handle_none;
-
-extern hal_error_t hal_rpc_hash_get_digest_length(const hal_digest_algorithm_t alg, size_t *length);
-
-extern 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);
-
-extern hal_error_t hal_rpc_hash_get_algorithm(const hal_rpc_hash_handle_t hash, hal_digest_algorithm_t *alg);
-
-/*
- * Once started, a hash or HMAC operation is bound to a particular
- * 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,
- hal_rpc_hash_handle_t *hash,
- const hal_digest_algorithm_t alg,
- const uint8_t * const key, const size_t key_length);
-
-extern hal_error_t hal_rpc_hash_update(const hal_rpc_hash_handle_t hash,
- const uint8_t * data, const size_t length);
-
-extern hal_error_t hal_rpc_hash_finalize(const hal_rpc_hash_handle_t hash,
- uint8_t *digest, const size_t length);
-
-/*
- * Public key functions.
- *
- * The _sign() and _verify() methods accept a hash OR an input string;
- * either "hash" should be hal_rpc_hash_handle_none or input should be NULL,
- * but not both.
- *
- * Use of client and session handles here needs a bit more thought.
- *
- * Client handles are straightforward: basically, anything that
- * creates a new pkey handle should take a client handle, which should
- * suffice, as object handles never cross clients.
- *
- * Session handles are more interesting, as PKCS #11's versions of
- * session and object handles do in effect allow one session to hand
- * an object handle to another session. So any action which can do
- * significant work (ie, which is complicated enough that we can't
- * guarantee an immediate response) needs to take a session handle.
- *
- * There will probably be a few cases where a session handle isn't
- * strictly required but we ask for one anyway because the API turns
- * out to be easier to understand that way (eg, we probably want to
- * ask for a session handle anywhere we ask for a client handle,
- * whether we need the session handle or not, so that users of this
- * API don't have to remember which pkey-handle-creating calls require
- * a session handle and which ones don't...).
- */
-
-#define HAL_RPC_PKEY_NAME_MAX 128
-
-typedef enum {
- HAL_RPC_PKEY_RSA_PRIVATE,
- HAL_RPC_PKEY_RSA_PUBLIC,
- HAL_RPC_PKEY_ECDSA_PRIVATE,
- HAL_RPC_PKEY_ECDSA_PUBLIC
-} hal_rpc_pkey_key_type_t;
-
-typedef enum {
- HAL_RPC_PKEY_CURVE_NONE,
- HAL_RPC_PKEY_CURVE_ECDSA_P256,
- HAL_RPC_PKEY_CURVE_ECDSA_P384,
- HAL_RPC_PKEY_CURVE_ECDSA_P521
-} hal_rpc_pkey_curve_t;
-
-typedef struct { uint32_t handle; } hal_rpc_pkey_handle_t;
-
-typedef uint32_t hal_rpc_pkey_flags_t;
-
-#define HAL_RPC_PKEY_FLAG_USAGE_DIGITALSIGNATURE (1 << 0)
-#define HAL_RPC_PKEY_FLAG_USAGE_KEYENCIPHERMENT (1 << 1)
-#define HAL_RPC_PKEY_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,
- hal_rpc_pkey_handle_t *pkey,
- const hal_rpc_pkey_key_type_t type,
- const hal_rpc_pkey_curve_t curve,
- const uint8_t * const name, const size_t name_len,
- const uint8_t * const der, const size_t der_len,
- const hal_rpc_pkey_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,
- hal_rpc_pkey_handle_t *pkey,
- const hal_rpc_pkey_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,
- 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_rpc_pkey_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,
- hal_rpc_pkey_handle_t *pkey,
- const uint8_t * const name, const size_t name_len,
- const hal_rpc_pkey_curve_t curve,
- const hal_rpc_pkey_flags_t flags);
-
-extern hal_error_t hal_rpc_pkey_delete(const hal_rpc_pkey_handle_t pkey);
-
-extern hal_error_t hal_rpc_pkey_get_key_type(const hal_rpc_pkey_handle_t pkey,
- hal_rpc_pkey_key_type_t *type);
-
-extern hal_error_t hal_rpc_pkey_get_key_flags(const hal_rpc_pkey_handle_t pkey,
- hal_rpc_pkey_flags_t *flags);
-
-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_len_max);
-
-extern 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 * output, const size_t output_len);
-
-extern 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,
- uint8_t * output, const size_t output_len);
-
-typedef struct {
- hal_rpc_pkey_key_type_t type;
- hal_rpc_pkey_curve_t curve;
- hal_rpc_pkey_flags_t flags;
- char name[HAL_RPC_PKEY_NAME_MAX];
- /* ... */
-} hal_rpc_pkey_key_info_t;
-
-extern hal_error_t hal_rpc_pkey_list(hal_rpc_pkey_key_info_t *result,
- unsigned *result_len,
- const unsigned result_max);
-
-#endif /* _HAL_RPC_H_ */
-
-/*
- * Local variables:
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/ks.c b/ks.c
new file mode 100644
index 0000000..072c624
--- /dev/null
+++ b/ks.c
@@ -0,0 +1,280 @@
+/*
+ * ks.c
+ * ----
+ * Keystore API. This is internal within libhal.
+ *
+ * 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 <string.h>
+#include <assert.h>
+
+#include "hal.h"
+#include "hal_internal.h"
+
+#define KEK_LENGTH (bitsToBytes(256))
+
+static inline int acceptable_key_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;
+ }
+}
+
+hal_error_t hal_ks_store(const hal_key_type_t type,
+ const hal_curve_name_t curve,
+ const hal_key_flags_t flags,
+ const uint8_t * const name, const size_t name_len,
+ const uint8_t * const der, const size_t der_len,
+ int *hint)
+{
+ if (name == NULL || name_len == 0 || der == NULL || der_len == 0 || !acceptable_key_type(type))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ if (name_len > HAL_RPC_PKEY_NAME_MAX)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ const hal_ks_keydb_t * const db = hal_ks_get_keydb();
+ hal_error_t err;
+ int hint_;
+
+ if (db == NULL)
+ return HAL_ERROR_KEYSTORE_ACCESS;
+
+ if (hint == NULL)
+ hint = &hint_;
+
+ *hint = -1;
+
+ for (int i = 0; i < sizeof(db->keys)/sizeof(*db->keys); i++) {
+ if (!db->keys[i].in_use && *hint < 0)
+ *hint = i;
+ if (db->keys[i].in_use &&
+ db->keys[i].type == type &&
+ db->keys[i].name_len == name_len && memcmp(db->keys[i].name, name, name_len) == 0)
+ return HAL_ERROR_KEY_NAME_IN_USE;
+ }
+
+ if (*hint < 0)
+ return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE;
+
+ hal_ks_key_t k;
+ memset(&k, 0, sizeof(k));
+
+ uint8_t kek[KEK_LENGTH];
+ size_t kek_len;
+
+ if ((err = hal_ks_get_kek(kek, &kek_len, sizeof(kek))) == HAL_OK)
+ err = hal_aes_keywrap(NULL, kek, kek_len, der, der_len, k.der, &k.der_len);
+
+ memset(kek, 0, sizeof(kek));
+
+ if (err != HAL_OK)
+ return err;
+
+ assert(name_len <= sizeof(k.name));
+ memcpy(k.name, name, name_len);
+ k.name_len = name_len;
+ k.type = type;
+ k.curve = curve;
+ k.flags = flags;
+
+ if ((err = hal_ks_set_keydb(&k, *hint)) != HAL_OK)
+ return err;
+
+ return HAL_OK;
+}
+
+static int find(const hal_ks_keydb_t * const db,
+ const hal_key_type_t type,
+ const uint8_t * const name, const size_t name_len,
+ int *hint)
+{
+ assert(db != NULL && name != NULL && name_len > 0 && acceptable_key_type(type));
+
+ if (hint != NULL && *hint >= 0 && *hint < sizeof(db->keys)/sizeof(*db->keys) &&
+ db->keys[*hint].in_use &&
+ db->keys[*hint].type == type &&
+ db->keys[*hint].name_len == name_len && memcmp(db->keys[*hint].name, name, name_len) == 0)
+ return 1;
+
+ for (int i = 0; i < sizeof(db->keys)/sizeof(*db->keys); i++) {
+ if (!db->keys[i].in_use ||
+ (hint != NULL && i == *hint) ||
+ db->keys[i].type != type ||
+ db->keys[i].name_len != name_len || memcmp(db->keys[i].name, name, name_len) != 0)
+ continue;
+ if (hint != NULL)
+ *hint = i;
+ return 1;
+ }
+
+ return 0;
+}
+
+hal_error_t hal_ks_exists(const hal_key_type_t type,
+ const uint8_t * const name, const size_t name_len,
+ int *hint)
+{
+ if (name == NULL || name_len == 0 || !acceptable_key_type(type))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ const hal_ks_keydb_t * const db = hal_ks_get_keydb();
+
+ if (db == NULL)
+ return HAL_ERROR_KEYSTORE_ACCESS;
+
+ if (find(db, type, name, name_len, hint))
+ return HAL_OK;
+ else
+ return HAL_ERROR_KEY_NOT_FOUND;
+}
+
+hal_error_t hal_ks_fetch(const hal_key_type_t type,
+ const uint8_t * const name, const size_t name_len,
+ hal_curve_name_t *curve,
+ hal_key_flags_t *flags,
+ uint8_t *der, size_t *der_len, const size_t der_max,
+ int *hint)
+{
+ if (name == NULL || name_len == 0 || !acceptable_key_type(type))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ const hal_ks_keydb_t * const db = hal_ks_get_keydb();
+ int hint_ = -1;
+
+ if (db == NULL)
+ return HAL_ERROR_KEYSTORE_ACCESS;
+
+ if (hint == NULL)
+ hint = &hint_;
+
+ if (!find(db, type, name, name_len, hint))
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ const hal_ks_key_t * const k = &db->keys[*hint];
+
+ if (curve != NULL)
+ *curve = k->curve;
+
+ if (flags != NULL)
+ *flags = k->flags;
+
+ if (der == NULL && der_len != NULL)
+ *der_len = k->der_len;
+
+ if (der != NULL) {
+ uint8_t kek[KEK_LENGTH];
+ size_t kek_len, der_len_;
+ hal_error_t err;
+
+ if (der_len == NULL)
+ der_len = &der_len_;
+
+ *der_len = der_max;
+
+ if ((err = hal_ks_get_kek(kek, &kek_len, sizeof(kek))) == HAL_OK)
+ err = hal_aes_keyunwrap(NULL, kek, kek_len, k->der, k->der_len, der, der_len);
+
+ memset(kek, 0, sizeof(kek));
+
+ if (err != HAL_OK)
+ return err;
+ }
+
+ return HAL_OK;
+}
+
+hal_error_t hal_ks_delete(const hal_key_type_t type,
+ const uint8_t * const name, const size_t name_len,
+ int *hint)
+{
+ if (name == NULL || name_len == 0 || !acceptable_key_type(type))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ const hal_ks_keydb_t * const db = hal_ks_get_keydb();
+ int hint_ = -1;
+
+ if (db == NULL)
+ return HAL_ERROR_KEYSTORE_ACCESS;
+
+ if (hint == NULL)
+ hint = &hint_;
+
+ if (!find(db, type, name, name_len, hint))
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ return hal_ks_del_keydb(*hint);
+}
+
+hal_error_t hal_ks_list(hal_rpc_pkey_key_info_t *result,
+ unsigned *result_len,
+ const unsigned result_max)
+{
+ if (result == NULL || result_len == 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;
+
+ *result_len = 0;
+
+ for (int i = 0; i < sizeof(db->keys)/sizeof(*db->keys); i++) {
+
+ if (!db->keys[i].in_use)
+ continue;
+
+ if (*result_len == result_max)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ result[*result_len].type = db->keys[i].type;
+ result[*result_len].curve = db->keys[i].curve;
+ result[*result_len].flags = db->keys[i].flags;
+ result[*result_len].name_len = db->keys[i].name_len;
+ memcpy(result[*result_len].name, db->keys[i].name, db->keys[i].name_len);
+ ++result_len;
+ }
+
+ return HAL_OK;
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/ks_flash.c b/ks_flash.c
new file mode 100644
index 0000000..ad9d2fe
--- /dev/null
+++ b/ks_flash.c
@@ -0,0 +1,71 @@
+/*
+ * ks_flash.c
+ * ----------
+ * Keystore implementation in flash memory.
+ *
+ * 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"
+
+static hal_ks_keydb_t *db;
+
+const hal_ks_keydb_t *hal_ks_get_keydb(void)
+{
+
+#error Not sure what goes here yet
+
+}
+
+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)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+#error Not sure what goes here yet either
+
+}
+
+hal_error_t hal_ks_del_keydb(const int loc)
+{
+ if (loc < 0 || loc >= sizeof(db.keys)/sizeof(*db.keys))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+#error Or what goes here
+
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/ks_mmap.c b/ks_mmap.c
new file mode 100644
index 0000000..3ff06a3
--- /dev/null
+++ b/ks_mmap.c
@@ -0,0 +1,115 @@
+/*
+ * ks_mmap.c
+ * ---------
+ * Keystore implementation over POSIX mmap().
+ *
+ * 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 <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <sys/errno.h>
+
+#include "hal.h"
+#include "hal_internal.h"
+
+#ifndef HAL_KS_MMAP_FILE
+#define HAL_KS_MMAP_FILE ".cryptech_hal_keystore"
+#endif
+
+static hal_ks_keydb_t *db;
+
+const hal_ks_keydb_t *hal_ks_get_keydb(void)
+{
+ if (db != NULL)
+ return db;
+
+ const char * const env = getenv("CRYPTECH_KEYSTORE");
+ const char * const home = getenv("HOME");
+ const char * const base = HAL_KS_MMAP_FILE;
+ const unsigned pagemask = getpagesize() - 1;
+ const size_t len = (sizeof(hal_ks_keydb_t) + pagemask) & ~pagemask;
+
+ char fn_[strlen(base) + (home == NULL ? 0 : strlen(home)) + 2];
+ const char *fn = fn_;
+ int fd;
+
+ if (env != NULL)
+ fn = env;
+ else if (home == NULL)
+ fn = base;
+ else
+ strcat(strcat(strcpy(fn_, home), "/"), base);
+
+ if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0) {
+ uint8_t zeros[len];
+ memset(zeros, 0, sizeof(zeros));
+ (void) write(fd, zeros, sizeof(zeros));
+ }
+ else if (errno == EEXIST) {
+ fd = open(fn, O_RDWR | O_CREAT, 0600);
+ }
+
+ if (fd >= 0)
+ db = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 0);
+
+ (void) close(fd);
+
+ 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)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ 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))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ db->keys[loc].in_use = 0;
+ memset(&db->keys[loc], 0, sizeof(db->keys[loc]));
+ return HAL_OK;
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/ks_volatile.c b/ks_volatile.c
new file mode 100644
index 0000000..756cd13
--- /dev/null
+++ b/ks_volatile.c
@@ -0,0 +1,74 @@
+/*
+ * ks_volatile.c
+ * -------------
+ * Keystore implementation in normal volatile internal memory.
+ *
+ * NB: This is only suitable for cases where you do not want the keystore
+ * to survive library exit, eg, for storing PKCS #11 session keys.
+ *
+ * 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"
+
+static hal_ks_keydb_t db;
+
+const hal_ks_keydb_t *hal_ks_get_keydb(void)
+{
+ 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)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ 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))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ memset(&db.keys[loc], 0, sizeof(db.keys[loc]));
+ return HAL_OK;
+}
+
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/hal_rpc.c b/rpc.c
similarity index 84%
rename from hal_rpc.c
rename to rpc.c
index 6ad198e..e0cb869 100644
--- a/hal_rpc.c
+++ b/rpc.c
@@ -33,7 +33,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "rpc_internal.h"
+#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
@@ -63,45 +64,45 @@ static const hal_rpc_pkey_dispatch_t * const pkey_dispatch = &hal_rpc_local_pkey
const hal_rpc_hash_handle_t hal_rpc_hash_handle_none = {0};
-static inline int check_pkey_type(const hal_rpc_pkey_key_type_t type)
+static inline int check_pkey_type(const hal_key_type_t type)
{
switch (type) {
- case HAL_RPC_PKEY_RSA_PRIVATE:
- case HAL_RPC_PKEY_RSA_PUBLIC:
- case HAL_RPC_PKEY_ECDSA_PRIVATE:
- case HAL_RPC_PKEY_ECDSA_PUBLIC:
+ 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_rpc_pkey_flags_t flags)
+static inline int check_pkey_flags(const hal_key_flags_t flags)
{
- return (flags &~ (HAL_RPC_PKEY_FLAG_USAGE_DIGITALSIGNATURE |
- HAL_RPC_PKEY_FLAG_USAGE_KEYENCIPHERMENT |
- HAL_RPC_PKEY_FLAG_USAGE_DATAENCIPHERMENT)) == 0;
+ 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_rpc_pkey_key_type_t type,
- const hal_rpc_pkey_curve_t curve,
- const hal_rpc_pkey_flags_t flags)
+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_RPC_PKEY_RSA_PRIVATE:
- case HAL_RPC_PKEY_RSA_PUBLIC:
- return curve == HAL_RPC_PKEY_CURVE_NONE;
+ case HAL_KEY_TYPE_RSA_PRIVATE:
+ case HAL_KEY_TYPE_RSA_PUBLIC:
+ return curve == HAL_CURVE_NONE;
- case HAL_RPC_PKEY_ECDSA_PRIVATE:
- case HAL_RPC_PKEY_ECDSA_PUBLIC:
+ case HAL_KEY_TYPE_EC_PRIVATE:
+ case HAL_KEY_TYPE_EC_PUBLIC:
switch (curve) {
- case HAL_RPC_PKEY_CURVE_ECDSA_P256:
- case HAL_RPC_PKEY_CURVE_ECDSA_P384:
- case HAL_RPC_PKEY_CURVE_ECDSA_P521:
+ case HAL_CURVE_P256:
+ case HAL_CURVE_P384:
+ case HAL_CURVE_P521:
return 1;
default:
return 0;
@@ -198,11 +199,11 @@ hal_error_t hal_rpc_hash_finalize(const hal_rpc_hash_handle_t hash,
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_rpc_pkey_key_type_t type,
- const hal_rpc_pkey_curve_t curve,
+ 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_rpc_pkey_flags_t flags)
+ const hal_key_flags_t flags)
{
if (pkey == NULL ||
name == NULL || name_len == 0 ||
@@ -215,7 +216,7 @@ hal_error_t hal_rpc_pkey_load(const hal_rpc_client_handle_t client,
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_rpc_pkey_key_type_t type,
+ 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))
@@ -229,9 +230,9 @@ hal_error_t hal_rpc_pkey_generate_rsa(const hal_rpc_client_handle_t client,
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_rpc_pkey_flags_t flags)
+ const hal_key_flags_t flags)
{
- if (pkey == NULL || name == NULL || name_len == 0 || key_len == 0 ||
+ 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);
@@ -241,22 +242,27 @@ 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_rpc_pkey_curve_t curve,
- const hal_rpc_pkey_flags_t flags)
+ 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_RPC_PKEY_ECDSA_PRIVATE, curve, flags))
+ !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_rpc_pkey_key_type_t *type)
+ hal_key_type_t *type)
{
if (type == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
@@ -264,7 +270,7 @@ hal_error_t hal_rpc_pkey_get_key_type(const hal_rpc_pkey_handle_t pkey,
}
hal_error_t hal_rpc_pkey_get_key_flags(const hal_rpc_pkey_handle_t pkey,
- hal_rpc_pkey_flags_t *flags)
+ hal_key_flags_t *flags)
{
if (flags == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
@@ -288,24 +294,24 @@ 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 * output, const size_t output_len)
+ uint8_t * signature, size_t *signature_len, const size_t signature_max)
{
- if (output == NULL || output_len == 0 ||
+ 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, output, output_len);
+ 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,
- uint8_t * output, const size_t output_len)
+ const uint8_t * const signature, const size_t signature_len)
{
- if (output == NULL || output_len == 0 ||
+ 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, output, output_len);
+ 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,
diff --git a/rpc_client.c b/rpc_client.c
index 20cc26f..0b13e58 100644
--- a/rpc_client.c
+++ b/rpc_client.c
@@ -33,7 +33,8 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "rpc_internal.h"
+#include "hal.h"
+#include "hal_internal.h"
/*
* RPC calls. Not implemented yet.
@@ -104,11 +105,11 @@ static hal_error_t hash_finalize(const hal_rpc_hash_handle_t hash,
static hal_error_t pkey_load(const hal_rpc_client_handle_t client,
const hal_rpc_session_handle_t session,
hal_rpc_pkey_handle_t *pkey,
- const hal_rpc_pkey_key_type_t type,
- const hal_rpc_pkey_curve_t curve,
+ 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_rpc_pkey_flags_t flags)
+ const hal_key_flags_t flags)
{
return HAL_ERROR_IMPOSSIBLE;
}
@@ -116,7 +117,7 @@ static hal_error_t pkey_load(const hal_rpc_client_handle_t client,
static hal_error_t pkey_find(const hal_rpc_client_handle_t client,
const hal_rpc_session_handle_t session,
hal_rpc_pkey_handle_t *pkey,
- const hal_rpc_pkey_key_type_t type,
+ const hal_key_type_t type,
const uint8_t * const name, const size_t name_len)
{
return HAL_ERROR_IMPOSSIBLE;
@@ -128,7 +129,7 @@ static hal_error_t pkey_generate_rsa(const hal_rpc_client_handle_t client,
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_rpc_pkey_flags_t flags)
+ const hal_key_flags_t flags)
{
return HAL_ERROR_IMPOSSIBLE;
}
@@ -137,8 +138,13 @@ static hal_error_t 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_rpc_pkey_curve_t curve,
- const hal_rpc_pkey_flags_t flags)
+ const hal_curve_name_t curve,
+ const hal_key_flags_t flags)
+{
+ return HAL_ERROR_IMPOSSIBLE;
+}
+
+static hal_error_t pkey_close(const hal_rpc_pkey_handle_t pkey)
{
return HAL_ERROR_IMPOSSIBLE;
}
@@ -149,13 +155,13 @@ static hal_error_t pkey_delete(const hal_rpc_pkey_handle_t pkey)
}
static hal_error_t pkey_get_key_type(const hal_rpc_pkey_handle_t pkey,
- hal_rpc_pkey_key_type_t *type)
+ hal_key_type_t *type)
{
return HAL_ERROR_IMPOSSIBLE;
}
static hal_error_t pkey_get_key_flags(const hal_rpc_pkey_handle_t pkey,
- hal_rpc_pkey_flags_t *flags)
+ hal_key_flags_t *flags)
{
return HAL_ERROR_IMPOSSIBLE;
}
@@ -175,7 +181,7 @@ static hal_error_t pkey_remote_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 * output, const size_t output_len)
+ uint8_t * signature, size_t *signature_len, const size_t signature_max)
{
return HAL_ERROR_IMPOSSIBLE;
}
@@ -184,7 +190,7 @@ static hal_error_t pkey_remote_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,
- uint8_t * output, const size_t output_len)
+ const uint8_t * const signature, const size_t signature_len)
{
return HAL_ERROR_IMPOSSIBLE;
}
@@ -208,10 +214,11 @@ static hal_error_t pkey_mixed_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 * output, const size_t output_len)
+ uint8_t * signature, size_t *signature_len, const size_t signature_max)
{
if (input != NULL)
- return pkey_remote_sign(session, pkey, hash, input, input_len, output, output_len);
+ return pkey_remote_sign(session, pkey, hash, input, input_len,
+ signature, signature_len, signature_max);
hal_digest_algorithm_t alg;
size_t digest_len;
@@ -226,17 +233,19 @@ static hal_error_t pkey_mixed_sign(const hal_rpc_session_handle_t session,
if ((err = hal_rpc_hash_finalize(hash, digest, digest_len)) != HAL_OK)
return err;
- return pkey_remote_sign(session, pkey, hal_rpc_hash_handle_none, digest, digest_len, output, output_len);
+ return pkey_remote_sign(session, pkey, hal_rpc_hash_handle_none, digest, digest_len,
+ signature, signature_len, signature_max);
}
static hal_error_t pkey_mixed_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,
- uint8_t * output, const size_t output_len)
+ const uint8_t * const signature, const size_t signature_len)
{
if (input != NULL)
- return pkey_remote_verify(session, pkey, hash, input, input_len, output, output_len);
+ return pkey_remote_verify(session, pkey, hash, input, input_len,
+ signature, signature_len);
hal_digest_algorithm_t alg;
size_t digest_len;
@@ -251,7 +260,8 @@ static hal_error_t pkey_mixed_verify(const hal_rpc_session_handle_t session,
if ((err = hal_rpc_hash_finalize(hash, digest, digest_len)) != HAL_OK)
return err;
- return pkey_remote_verify(session, pkey, hal_rpc_hash_handle_none, digest, digest_len, output, output_len);
+ return pkey_remote_verify(session, pkey, hal_rpc_hash_handle_none, digest, digest_len,
+ signature, signature_len);
}
/*
@@ -263,18 +273,19 @@ const hal_rpc_misc_dispatch_t hal_rpc_remote_misc_dispatch = {
};
const hal_rpc_hash_dispatch_t hal_rpc_remote_hash_dispatch = {
- hash_get_digest_len, hash_get_digest_algorithm_id, hash_get_algorithm, hash_initialize, hash_update, hash_finalize
+ hash_get_digest_len, hash_get_digest_algorithm_id, hash_get_algorithm,
+ hash_initialize, hash_update, hash_finalize
};
const hal_rpc_pkey_dispatch_t hal_rpc_remote_pkey_dispatch = {
- pkey_load, pkey_find, pkey_generate_rsa, pkey_generate_ec, pkey_delete,
+ pkey_load, pkey_find, pkey_generate_rsa, pkey_generate_ec, pkey_close, pkey_delete,
pkey_get_key_type, pkey_get_key_flags, pkey_get_public_key_len, pkey_get_public_key,
pkey_remote_sign, pkey_remote_verify,
pkey_list
};
const hal_rpc_pkey_dispatch_t hal_rpc_mixed_pkey_dispatch = {
- pkey_load, pkey_find, pkey_generate_rsa, pkey_generate_ec, pkey_delete,
+ pkey_load, pkey_find, pkey_generate_rsa, pkey_generate_ec, pkey_close, pkey_delete,
pkey_get_key_type, pkey_get_key_flags, pkey_get_public_key_len, pkey_get_public_key,
pkey_mixed_sign, pkey_mixed_verify,
pkey_list
diff --git a/rpc_hash.c b/rpc_hash.c
index 4ceadb6..86b8ae0 100644
--- a/rpc_hash.c
+++ b/rpc_hash.c
@@ -36,7 +36,7 @@
#include <string.h>
#include "hal.h"
-#include "rpc_internal.h"
+#include "hal_internal.h"
/*
* Need table and handle allocation, including some kind of in_use
@@ -94,10 +94,10 @@ static inline handle_slot_t *alloc_handle(const int is_hmac)
#if HAL_STATIC_HASH_STATE_BLOCKS > 0
if (!is_hmac) {
for (int i = 0; i < sizeof(hash_handle)/sizeof(*hash_handle); i++) {
- if (hash_handle[i].state.hash == NULL) {
- hash_handle[i].hash_handle.handle = i | glop;
- return &hash_handle[i];
- }
+ if (hash_handle[i].state.hash != NULL)
+ continue;
+ hash_handle[i].hash_handle.handle = i | glop;
+ return &hash_handle[i];
}
}
#endif
@@ -105,10 +105,10 @@ static inline handle_slot_t *alloc_handle(const int is_hmac)
#if HAL_STATIC_HMAC_STATE_BLOCKS > 0
if (is_hmac) {
for (int i = 0; i < sizeof(hmac_handle)/sizeof(*hmac_handle); i++) {
- if (hmac_handle[i].state.hmac == NULL) {
- hmac_handle[i].hash_handle.handle = i | glop | HANDLE_FLAG_HMAC;
- return &hmac_handle[i];
- }
+ if (hmac_handle[i].state.hmac != NULL)
+ continue;
+ hmac_handle[i].hash_handle.handle = i | glop | HANDLE_FLAG_HMAC;
+ return &hmac_handle[i];
}
}
#endif
@@ -134,7 +134,7 @@ static inline handle_slot_t *find_handle(const hal_rpc_hash_handle_t handle)
return &hash_handle[i];
#endif
-#if HAL_STATIC_HASH_STATE_BLOCKS > 0
+#if HAL_STATIC_HMAC_STATE_BLOCKS > 0
if (is_hmac && i < sizeof(hmac_handle)/sizeof(*hmac_handle) &&
hmac_handle[i].hash_handle.handle == handle.handle && hmac_handle[i].state.hmac != NULL)
return &hmac_handle[i];
@@ -227,10 +227,10 @@ static hal_error_t get_algorithm(const hal_rpc_hash_handle_t handle, hal_digest_
}
static hal_error_t 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)
+ 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)
{
const hal_hash_descriptor_t *descriptor;
handle_slot_t *slot;
@@ -254,7 +254,7 @@ static hal_error_t initialize(const hal_rpc_client_handle_t client,
}
static hal_error_t update(const hal_rpc_hash_handle_t handle,
- const uint8_t * data, const size_t length)
+ const uint8_t * data, const size_t length)
{
handle_slot_t *slot = find_handle(handle);
diff --git a/rpc_pkey.c b/rpc_pkey.c
new file mode 100644
index 0000000..8fece44
--- /dev/null
+++ b/rpc_pkey.c
@@ -0,0 +1,736 @@
+/*
+ * rpc_pkey.c
+ * ----------
+ * Remote procedure call server-side public key 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 <string.h>
+#include <assert.h>
+
+#include "hal.h"
+#include "hal_internal.h"
+
+typedef struct {
+ hal_rpc_client_handle_t client_handle;
+ hal_rpc_session_handle_t session_handle;
+ hal_rpc_pkey_handle_t pkey_handle;
+ hal_key_type_t type;
+ hal_curve_name_t curve;
+ hal_key_flags_t flags;
+ uint8_t name[HAL_RPC_PKEY_NAME_MAX];
+ size_t name_len;
+ int ks_hint;
+ /*
+ * This might be where we'd stash a (hal_core_t *) pointing to a
+ * core which has already been loaded with the key, if we were
+ * trying to be clever about using multiple signing cores. Moot
+ * point (ie, no way we could possibly test such a thing) as long as
+ * the FPGA is too small to hold more than one modexp core and ECDSA
+ * is entirely software, so skip it for now, but the implied
+ * semantics are interesting: a pkey handle starts to resemble an
+ * initialized signing core, and once all the cores are in use, one
+ * can't load another key without closing an existing pkey handle.
+ */
+} pkey_slot_t;
+
+#ifndef HAL_STATIC_PKEY_STATE_BLOCKS
+#define HAL_STATIC_PKEY_STATE_BLOCKS 0
+#endif
+
+#if HAL_STATIC_PKEY_STATE_BLOCKS > 0
+static pkey_slot_t pkey_handle[HAL_STATIC_PKEY_STATE_BLOCKS];
+#endif
+
+/*
+ * Handle allocation is simple: we look for an unused (name_len == 0)
+ * slot in the table, and, assuming we find one, construct a composite
+ * handle consisting of the index into the table and a counter whose
+ * sole purpose is to keep the same handle from reoccurring anytime
+ * soon, to help identify use-after-free bugs in calling code.
+ */
+
+static inline pkey_slot_t *alloc_slot(void)
+{
+#if HAL_STATIC_PKEY_STATE_BLOCKS > 0
+ static uint16_t next_glop = 0;
+ uint32_t glop = ++next_glop << 16;
+ next_glop %= 0xFFFF;
+
+ for (int i = 0; i < sizeof(pkey_handle)/sizeof(*pkey_handle); i++) {
+ if (pkey_handle[i].name_len > 0)
+ continue;
+ pkey_handle[i].pkey_handle.handle = i | glop;
+ pkey_handle[i].ks_hint = -1;
+ return &pkey_handle[i];
+ }
+#endif
+
+ return NULL;
+}
+
+/*
+ * Check a caller-supplied handle. Must be in range, in use, and have
+ * the right glop. Returns slot pointer on success, NULL otherwise.
+ */
+
+static inline pkey_slot_t *find_handle(const hal_rpc_pkey_handle_t handle)
+{
+#if HAL_STATIC_PKEY_STATE_BLOCKS > 0
+ const int i = (int) (handle.handle & 0xFFFF);
+
+ if (i < sizeof(pkey_handle)/sizeof(*pkey_handle) && pkey_handle[i].pkey_handle.handle == handle.handle)
+ return &pkey_handle[i];
+#endif
+
+ return NULL;
+}
+
+/*
+ * Construct a PKCS #1 DigestInfo object. This requires some (very
+ * basic) ASN.1 encoding, which we perform inline.
+ */
+
+static hal_error_t pkcs1_construct_digestinfo(const hal_rpc_hash_handle_t handle,
+ uint8_t *digest_info, size_t *digest_info_len, const size_t digest_info_max)
+{
+ assert(digest_info != NULL && digest_info_len != NULL);
+
+ hal_digest_algorithm_t alg;
+ size_t len, alg_len;
+ hal_error_t err;
+
+ if ((err = hal_rpc_hash_get_algorithm(handle, &alg)) != HAL_OK ||
+ (err = hal_rpc_hash_get_digest_length(alg, &len)) != HAL_OK ||
+ (err = hal_rpc_hash_get_digest_algorithm_id(alg, NULL, &alg_len, 0)) != HAL_OK)
+ return err;
+
+ *digest_info_len = len + alg_len + 4;
+
+ if (*digest_info_len >= digest_info_max)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ assert(*digest_info_len < 130);
+
+ uint8_t *d = digest_info;
+
+ *d++ = 0x30; /* SEQUENCE */
+ *d++ = (uint8_t) (*digest_info_len - 2);
+
+ if ((err = hal_rpc_hash_get_digest_algorithm_id(alg, d, NULL, alg_len)) != HAL_OK)
+ return err;
+ d += alg_len;
+
+ *d++ = 0x04; /* OCTET STRING */
+ *d++ = (uint8_t) len;
+
+ assert(digest_info + *digest_info_len == d + len);
+
+ return hal_rpc_hash_finalize(handle, d, len);
+}
+
+/*
+ * Pad an octet string with PKCS #1.5 padding for use with RSA.
+ *
+ * For the moment, this only handles type 01 encryption blocks, thus
+ * is only suitable for use with signature and verification. If and
+ * when we add support for encryption and decryption, this function
+ * should be extended to take an argument specifying the block type
+ * and include support for generating type 02 encryption blocks.
+ * Other than the block type code, the only difference is the padding
+ * value: for type 01 it's constant (0xFF), for type 02 it should be
+ * non-zero random bytes from the CSPRNG.
+ *
+ * We use memmove() instead of memcpy() so that the caller can
+ * construct the data to be padded in the same buffer.
+ */
+
+static hal_error_t pkcs1_5_pad(const uint8_t * const data, const size_t data_len,
+ uint8_t *block, const size_t block_len)
+{
+ assert(data != NULL && block != NULL);
+
+ /*
+ * Congregation will now please turn to RFC 2313 8.1 as we
+ * construct a PKCS #1.5 type 01 encryption block.
+ */
+
+ if (data_len > block_len - 11)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ memmove(block + block_len - data_len, data, data_len);
+
+ block[0] = 0x00;
+ block[1] = 0x01;
+
+ /* This is where we'd use non-zero random bytes if constructing a type 02 block. */
+ memset(block + 2, 0xFF, block_len - 3 - data_len);
+
+ block[block_len - data_len - 1] = 0x00;
+
+ return HAL_OK;
+}
+
+/*
+ * 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,
+ 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)
+{
+ pkey_slot_t *slot;
+ hal_error_t err;
+
+ assert(sizeof(slot->name) >= name_len && pkey != NULL);
+
+ if ((slot = alloc_slot()) == NULL)
+ return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE;
+
+ if ((err = hal_ks_store(type, curve, flags, name, name_len, der, der_len, &slot->ks_hint)) != HAL_OK)
+ return err;
+
+ memcpy(slot->name, name, name_len);
+ slot->client_handle = client;
+ slot->session_handle = session;
+ slot->type = type;
+ slot->curve = curve;
+ slot->flags = flags;
+ slot->name_len = name_len;
+
+ *pkey = slot->pkey_handle;
+ return HAL_OK;
+}
+
+/*
+ * 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,
+ hal_rpc_pkey_handle_t *pkey,
+ const hal_key_type_t type,
+ const uint8_t * const name, const size_t name_len)
+{
+ pkey_slot_t *slot;
+ hal_error_t err;
+
+ assert(sizeof(slot->name) >= name_len && pkey != NULL);
+
+ if ((slot = alloc_slot()) == NULL)
+ return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE;
+
+ if ((err = hal_ks_fetch(type, name, name_len, &slot->curve, &slot->flags, NULL, NULL, 0, &slot->ks_hint)) != HAL_OK)
+ return err;
+
+ memcpy(slot->name, name, name_len);
+ slot->client_handle = client;
+ slot->session_handle = session;
+ slot->type = type;
+ slot->name_len = name_len;
+
+ *pkey = slot->pkey_handle;
+ return HAL_OK;
+}
+
+/*
+ * 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,
+ 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)
+{
+ pkey_slot_t *slot;
+ hal_error_t err;
+
+ assert(sizeof(slot->name) >= name_len && pkey != NULL && (key_length & 7) == 0);
+
+ if ((slot = alloc_slot()) == NULL)
+ return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE;
+
+ uint8_t keybuf[hal_rsa_key_t_size];
+ hal_rsa_key_t *key = NULL;
+
+ if ((err = hal_rsa_key_gen(NULL, &key, keybuf, sizeof(keybuf), key_length / 8,
+ public_exponent, public_exponent_len)) != HAL_OK)
+ return err;
+
+ uint8_t der[hal_rsa_key_to_der_len(key)];
+ size_t der_len;
+
+ if ((err = hal_rsa_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK)
+ err = hal_ks_store(HAL_KEY_TYPE_RSA_PRIVATE, HAL_CURVE_NONE, flags,
+ name, name_len, der, der_len, &slot->ks_hint);
+
+ memset(keybuf, 0, sizeof(keybuf));
+ memset(der, 0, sizeof(der));
+
+ if (err != HAL_OK)
+ return err;
+
+ memcpy(slot->name, name, name_len);
+ slot->client_handle = client;
+ slot->session_handle = session;
+ slot->type = HAL_KEY_TYPE_RSA_PRIVATE;
+ slot->curve = HAL_CURVE_NONE;
+ slot->flags = flags;
+ slot->name_len = name_len;
+
+ *pkey = slot->pkey_handle;
+ return HAL_OK;
+}
+
+/*
+ * Generate a new EC key with supplied name, return a key handle.
+ * 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,
+ 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)
+{
+ pkey_slot_t *slot;
+ hal_error_t err;
+
+ assert(sizeof(slot->name) >= name_len && pkey != NULL);
+
+ if ((slot = alloc_slot()) == NULL)
+ return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE;
+
+ uint8_t keybuf[hal_ecdsa_key_t_size];
+ hal_ecdsa_key_t *key = NULL;
+
+ if ((err = hal_ecdsa_key_gen(NULL, &key, keybuf, sizeof(keybuf), curve)) != HAL_OK)
+ return err;
+
+ uint8_t der[hal_ecdsa_key_to_der_len(key)];
+ size_t der_len;
+
+ if ((err = hal_ecdsa_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK)
+ err = hal_ks_store(HAL_KEY_TYPE_EC_PRIVATE, curve, flags,
+ name, name_len, der, der_len, &slot->ks_hint);
+
+ memset(keybuf, 0, sizeof(keybuf));
+ memset(der, 0, sizeof(der));
+
+ if (err != HAL_OK)
+ return err;
+
+ memcpy(slot->name, name, name_len);
+ slot->client_handle = client;
+ slot->session_handle = session;
+ slot->type = HAL_KEY_TYPE_EC_PRIVATE;
+ slot->curve = curve;
+ slot->flags = flags;
+ slot->name_len = name_len;
+
+ *pkey = slot->pkey_handle;
+ return HAL_OK;
+}
+
+/*
+ * Discard key handle, leaving key intact.
+ */
+
+static hal_error_t close(const hal_rpc_pkey_handle_t pkey)
+{
+ pkey_slot_t *slot;
+
+ if ((slot = find_handle(pkey)) == NULL)
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ memset(slot, 0, sizeof(*slot));
+
+ return HAL_OK;
+}
+
+/*
+ * Delete a key from the store, given its key handle.
+ */
+
+static hal_error_t delete(const hal_rpc_pkey_handle_t pkey)
+{
+ pkey_slot_t *slot = find_handle(pkey);
+
+ if (slot == NULL)
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ hal_error_t err = hal_ks_delete(slot->type, slot->name, slot->name_len, &slot->ks_hint);
+
+ if (err == HAL_OK || err == HAL_ERROR_KEY_NOT_FOUND)
+ memset(slot, 0, sizeof(*slot));
+
+ return err;
+}
+
+/*
+ * Get type of key associated with handle.
+ */
+
+static hal_error_t get_key_type(const hal_rpc_pkey_handle_t pkey,
+ hal_key_type_t *type)
+{
+ if (type == NULL)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ pkey_slot_t *slot = find_handle(pkey);
+
+ if (slot == NULL)
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ *type = slot->type;
+
+ return HAL_OK;
+}
+
+/*
+ * Get flags of key associated with handle.
+ */
+
+static hal_error_t get_key_flags(const hal_rpc_pkey_handle_t pkey,
+ hal_key_flags_t *flags)
+{
+ if (flags == NULL)
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ pkey_slot_t *slot = find_handle(pkey);
+
+ if (slot == NULL)
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ *flags = slot->flags;
+
+ return HAL_OK;
+}
+
+/*
+ * Get length of public key associated with handle.
+ */
+
+static size_t get_public_key_len(const hal_rpc_pkey_handle_t pkey)
+{
+ return 0;
+}
+
+/*
+ * Get public key associated with handle.
+ */
+
+static hal_error_t get_public_key(const hal_rpc_pkey_handle_t pkey,
+ uint8_t *der, size_t *der_len, const size_t der_len_max)
+{
+ /*
+ * Still missing some of the public key format ASN.1 stuff, apparently. Feh.
+ */
+ return HAL_ERROR_IMPOSSIBLE;
+#warning get_public_key() not implemented
+}
+
+/*
+ * Sign something using private key associated with handle.
+ *
+ * RSA has enough quirks that it's simplest to split this out into
+ * algorithm-specific functions.
+ */
+
+static hal_error_t sign_rsa(uint8_t *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len,
+ const hal_rpc_hash_handle_t hash,
+ const uint8_t * input, size_t input_len,
+ uint8_t * signature, size_t *signature_len, const size_t signature_max)
+{
+ hal_rsa_key_t *key = NULL;
+ hal_error_t err;
+
+ assert(signature != NULL && signature_len != NULL);
+ assert((hash.handle == hal_rpc_hash_handle_none.handle) != (input == NULL || input_len == 0));
+
+ if ((err = hal_rsa_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK ||
+ (err = hal_rsa_key_get_modulus(key, NULL, signature_len, 0)) != HAL_OK)
+ return err;
+
+ if (*signature_len > signature_max)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ if (input == NULL) {
+ if ((err = pkcs1_construct_digestinfo(hash, signature, &input_len, *signature_len)) != HAL_OK)
+ return err;
+ input = signature;
+ }
+
+ if ((err = pkcs1_5_pad(input, input_len, signature, *signature_len)) != HAL_OK ||
+ (err = hal_rsa_decrypt(NULL, key, signature, *signature_len, signature, *signature_len)) != HAL_OK)
+ return err;
+
+ return HAL_OK;
+}
+
+static hal_error_t sign_ecdsa(uint8_t *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len,
+ const hal_rpc_hash_handle_t hash,
+ const uint8_t * input, size_t input_len,
+ uint8_t * signature, size_t *signature_len, const size_t signature_max)
+{
+ hal_ecdsa_key_t *key = NULL;
+ hal_error_t err;
+
+ assert(signature != NULL && signature_len != NULL);
+ assert((hash.handle == hal_rpc_hash_handle_none.handle) != (input == NULL || input_len == 0));
+
+ if ((err = hal_ecdsa_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK)
+ return err;
+
+ if (input == NULL) {
+ hal_digest_algorithm_t alg;
+
+ if ((err = hal_rpc_hash_get_algorithm(hash, &alg)) != HAL_OK ||
+ (err = hal_rpc_hash_get_digest_length(alg, &input_len)) != HAL_OK)
+ return err;
+
+ if (input_len < signature_max)
+ return HAL_ERROR_RESULT_TOO_LONG;
+
+ if ((err = hal_rpc_hash_finalize(hash, signature, input_len)) != HAL_OK)
+ return err;
+
+ input = signature;
+ }
+
+ if ((err = hal_ecdsa_sign(NULL, key, input, input_len, signature, signature_len, signature_max,
+ HAL_ECDSA_SIGNATURE_FORMAT_PKCS11)) != HAL_OK)
+ return err;
+
+ return HAL_OK;
+}
+
+static hal_error_t 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)
+{
+ pkey_slot_t *slot = find_handle(pkey);
+
+ if (slot == NULL)
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ hal_error_t (*signer)(uint8_t *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len,
+ 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);
+
+ switch (slot->type) {
+ case HAL_KEY_TYPE_RSA_PRIVATE:
+ signer = sign_rsa;
+ break;
+ case HAL_KEY_TYPE_EC_PRIVATE:
+ signer = sign_ecdsa;
+ break;
+ default:
+ return HAL_ERROR_UNSUPPORTED_KEY;
+ }
+
+ uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size ? hal_rsa_key_t_size : hal_ecdsa_key_t_size];
+ uint8_t der[HAL_KS_WRAPPED_KEYSIZE];
+ size_t der_len;
+ hal_error_t err;
+
+ err = hal_ks_fetch(slot->type, slot->name, slot->name_len, NULL, NULL, der, &der_len, sizeof(der), &slot->ks_hint);
+
+ if (err == HAL_OK)
+ err = signer(keybuf, sizeof(keybuf), der, der_len, hash, input, input_len, signature, signature_len, signature_max);
+
+ memset(keybuf, 0, sizeof(keybuf));
+ memset(der, 0, sizeof(der));
+
+ return err;
+}
+
+/*
+ * Verify something using private key associated with handle.
+ *
+ * RSA has enough quirks that it's simplest to split this out into
+ * algorithm-specific functions.
+ */
+
+static hal_error_t verify_rsa(uint8_t *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len,
+ const hal_rpc_hash_handle_t hash,
+ const uint8_t * input, size_t input_len,
+ const uint8_t * const signature, const size_t signature_len)
+{
+ uint8_t expected[signature_len], received[signature_len];
+ hal_rsa_key_t *key = NULL;
+ hal_error_t err;
+
+ assert(signature != NULL && signature_len > 0);
+ assert((hash.handle == hal_rpc_hash_handle_none.handle) != (input == NULL || input_len == 0));
+
+ if ((err = hal_rsa_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK)
+ return err;
+
+ if (input == NULL) {
+ if ((err = pkcs1_construct_digestinfo(hash, expected, &input_len, sizeof(expected))) != HAL_OK)
+ return err;
+ input = expected;
+ }
+
+ if ((err = pkcs1_5_pad(input, input_len, expected, sizeof(expected))) != HAL_OK ||
+ (err = hal_rsa_encrypt(NULL, key, signature, signature_len, received, sizeof(received))) != HAL_OK)
+ return err;
+
+ unsigned diff = 0;
+ for (int i = 0; i < signature_len; i++)
+ diff |= expected[i] ^ received[i];
+
+ if (diff != 0)
+ return HAL_ERROR_INVALID_SIGNATURE;
+
+ return HAL_OK;
+}
+
+static hal_error_t verify_ecdsa(uint8_t *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len,
+ const hal_rpc_hash_handle_t hash,
+ const uint8_t * input, size_t input_len,
+ const uint8_t * const signature, const size_t signature_len)
+{
+ uint8_t digest[signature_len];
+ hal_ecdsa_key_t *key = NULL;
+ hal_error_t err;
+
+ assert(signature != NULL && signature_len > 0);
+ assert((hash.handle == hal_rpc_hash_handle_none.handle) != (input == NULL || input_len == 0));
+
+ if ((err = hal_ecdsa_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK)
+ return err;
+
+ if (input == NULL) {
+ hal_digest_algorithm_t alg;
+
+ if ((err = hal_rpc_hash_get_algorithm(hash, &alg)) != HAL_OK ||
+ (err = hal_rpc_hash_get_digest_length(alg, &input_len)) != HAL_OK ||
+ (err = hal_rpc_hash_finalize(hash, digest, sizeof(digest))) != HAL_OK)
+ return err;
+
+ input = digest;
+ }
+
+ if ((err = hal_ecdsa_verify(NULL, key, input, input_len, signature, signature_len,
+ HAL_ECDSA_SIGNATURE_FORMAT_PKCS11)) != HAL_OK)
+ return err;
+
+ return HAL_OK;
+}
+
+static hal_error_t 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)
+{
+ pkey_slot_t *slot = find_handle(pkey);
+
+ if (slot == NULL)
+ return HAL_ERROR_KEY_NOT_FOUND;
+
+ hal_error_t (*verifier)(uint8_t *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len,
+ 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);
+
+ switch (slot->type) {
+ case HAL_KEY_TYPE_RSA_PRIVATE:
+ case HAL_KEY_TYPE_RSA_PUBLIC:
+ verifier = verify_rsa;
+ break;
+ case HAL_KEY_TYPE_EC_PRIVATE:
+ case HAL_KEY_TYPE_EC_PUBLIC:
+ verifier = verify_ecdsa;
+ break;
+ default:
+ return HAL_ERROR_UNSUPPORTED_KEY;
+ }
+
+ uint8_t keybuf[hal_rsa_key_t_size > hal_ecdsa_key_t_size ? hal_rsa_key_t_size : hal_ecdsa_key_t_size];
+ uint8_t der[HAL_KS_WRAPPED_KEYSIZE];
+ size_t der_len;
+ hal_error_t err;
+
+ err = hal_ks_fetch(slot->type, slot->name, slot->name_len, NULL, NULL, der, &der_len, sizeof(der), &slot->ks_hint);
+
+ if (err == HAL_OK)
+ err = verifier(keybuf, sizeof(keybuf), der, der_len, hash, input, input_len, signature, signature_len);
+
+ memset(keybuf, 0, sizeof(keybuf));
+ memset(der, 0, sizeof(der));
+
+ return err;
+}
+
+
+/*
+ * List keys in the key store.
+ */
+
+static hal_error_t list(hal_rpc_pkey_key_info_t *result,
+ unsigned *result_len,
+ const unsigned result_max)
+{
+ return hal_ks_list(result, result_len, result_max);
+}
+
+const hal_rpc_pkey_dispatch_t hal_rpc_local_pkey_dispatch = {
+ load, find, generate_rsa, generate_ec, close, delete,
+ get_key_type, get_key_flags, get_public_key_len, get_public_key,
+ sign, verify, list
+};
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/rsa.c b/rsa.c
index a03b41a..a901b24 100644
--- a/rsa.c
+++ b/rsa.c
@@ -116,7 +116,7 @@ void hal_rsa_set_blinding(const int onoff)
*/
struct hal_rsa_key {
- hal_rsa_key_type_t type; /* What kind of key this is */
+ hal_key_type_t type; /* What kind of key this is */
fp_int n[1]; /* The modulus */
fp_int e[1]; /* Public exponent */
fp_int d[1]; /* Private exponent */
@@ -454,7 +454,7 @@ void hal_rsa_key_clear(hal_rsa_key_t *key)
* calculate everything else from them.
*/
-static hal_error_t load_key(const hal_rsa_key_type_t type,
+static hal_error_t load_key(const hal_key_type_t type,
hal_rsa_key_t **key_,
void *keybuf, const size_t keybuf_len,
const uint8_t * const n, const size_t n_len,
@@ -477,12 +477,14 @@ static hal_error_t load_key(const hal_rsa_key_type_t type,
#define _(x) do { fp_init(key->x); if (x == NULL) goto fail; fp_read_unsigned_bin(key->x, unconst_uint8_t(x), x##_len); } while (0)
switch (type) {
- case HAL_RSA_PRIVATE:
+ case HAL_KEY_TYPE_RSA_PRIVATE:
_(d); _(p); _(q); _(u); _(dP); _(dQ);
- case HAL_RSA_PUBLIC:
+ case HAL_KEY_TYPE_RSA_PUBLIC:
_(n); _(e);
*key_ = key;
return HAL_OK;
+ default:
+ goto fail;
}
#undef _
@@ -506,7 +508,7 @@ hal_error_t hal_rsa_key_load_private(hal_rsa_key_t **key_,
const uint8_t * const dP, const size_t dP_len,
const uint8_t * const dQ, const size_t dQ_len)
{
- return load_key(HAL_RSA_PRIVATE, key_, keybuf, keybuf_len,
+ return load_key(HAL_KEY_TYPE_RSA_PRIVATE, key_, keybuf, keybuf_len,
n, n_len, e, e_len,
d, d_len, p, p_len, q, q_len, u, u_len, dP, dP_len, dQ, dQ_len);
}
@@ -516,7 +518,7 @@ hal_error_t hal_rsa_key_load_public(hal_rsa_key_t **key_,
const uint8_t * const n, const size_t n_len,
const uint8_t * const e, const size_t e_len)
{
- return load_key(HAL_RSA_PUBLIC, key_, keybuf, keybuf_len,
+ return load_key(HAL_KEY_TYPE_RSA_PUBLIC, key_, keybuf, keybuf_len,
n, n_len, e, e_len,
NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0);
}
@@ -526,7 +528,7 @@ hal_error_t hal_rsa_key_load_public(hal_rsa_key_t **key_,
*/
hal_error_t hal_rsa_key_get_type(const hal_rsa_key_t * const key,
- hal_rsa_key_type_t *key_type)
+ hal_key_type_t *key_type)
{
if (key == NULL || key_type == NULL)
return HAL_ERROR_BAD_ARGUMENTS;
@@ -625,7 +627,7 @@ hal_error_t hal_rsa_key_gen(const hal_core_t *core,
return HAL_ERROR_BAD_ARGUMENTS;
memset(keybuf, 0, keybuf_len);
- key->type = HAL_RSA_PRIVATE;
+ key->type = HAL_KEY_TYPE_RSA_PRIVATE;
fp_read_unsigned_bin(key->e, (uint8_t *) public_exponent, public_exponent_len);
if (key_length < bitsToBytes(1024) || key_length > bitsToBytes(8192))
@@ -690,7 +692,7 @@ hal_error_t hal_rsa_key_to_der(const hal_rsa_key_t * const key,
{
hal_error_t err = HAL_OK;
- if (key == NULL || der_len == NULL || key->type != HAL_RSA_PRIVATE)
+ if (key == NULL || der_len == NULL || key->type != HAL_KEY_TYPE_RSA_PRIVATE)
return HAL_ERROR_BAD_ARGUMENTS;
fp_int version[1] = INIT_FP_INT;
@@ -748,7 +750,7 @@ hal_error_t hal_rsa_key_from_der(hal_rsa_key_t **key_,
hal_rsa_key_t *key = keybuf;
- key->type = HAL_RSA_PRIVATE;
+ key->type = HAL_KEY_TYPE_RSA_PRIVATE;
hal_error_t err = HAL_OK;
size_t hlen, vlen;
diff --git a/tests/test-ecdsa.c b/tests/test-ecdsa.c
index ce8aee1..ae99616 100644
--- a/tests/test-ecdsa.c
+++ b/tests/test-ecdsa.c
@@ -203,7 +203,7 @@ static int test_against_static_vectors(const ecdsa_tc_t * const tc)
* Run one keygen/sign/verify test with a newly generated key.
*/
-static int test_keygen_sign_verify(const hal_ecdsa_curve_t curve)
+static int test_keygen_sign_verify(const hal_curve_name_t curve)
{
const hal_hash_descriptor_t *hash_descriptor = NULL;
@@ -213,17 +213,17 @@ static int test_keygen_sign_verify(const hal_ecdsa_curve_t curve)
switch (curve) {
- case HAL_ECDSA_CURVE_P256:
+ case HAL_CURVE_P256:
printf("ECDSA P-256 key generation / signature / verification test\n");
hash_descriptor = hal_hash_sha256;
break;
- case HAL_ECDSA_CURVE_P384:
+ case HAL_CURVE_P384:
printf("ECDSA P-384 key generation / signature / verification test\n");
hash_descriptor = hal_hash_sha384;
break;
- case HAL_ECDSA_CURVE_P521:
+ case HAL_CURVE_P521:
printf("ECDSA P-521 key generation / signature / verification test\n");
hash_descriptor = hal_hash_sha512;
break;
@@ -339,12 +339,12 @@ int main(int argc, char *argv[])
*/
if (csprng_core != NULL && sha256_core != NULL) {
- time_check(test_keygen_sign_verify(HAL_ECDSA_CURVE_P256));
+ time_check(test_keygen_sign_verify(HAL_CURVE_P256));
}
if (csprng_core != NULL && sha512_core != NULL) {
- time_check(test_keygen_sign_verify(HAL_ECDSA_CURVE_P384));
- time_check(test_keygen_sign_verify(HAL_ECDSA_CURVE_P521));
+ time_check(test_keygen_sign_verify(HAL_CURVE_P384));
+ time_check(test_keygen_sign_verify(HAL_CURVE_P521));
}
return !ok;
diff --git a/tests/test-ecdsa.h b/tests/test-ecdsa.h
index ca51858..a607d97 100644
--- a/tests/test-ecdsa.h
+++ b/tests/test-ecdsa.h
@@ -264,7 +264,7 @@ static const uint8_t p384_w[] = { /* 48 bytes */
};
typedef struct {
- hal_ecdsa_curve_t curve;
+ hal_curve_name_t curve;
const uint8_t * H; size_t H_len;
const uint8_t * M; size_t M_len;
const uint8_t * Qx; size_t Qx_len;
@@ -286,7 +286,7 @@ typedef struct {
} ecdsa_tc_t;
static const ecdsa_tc_t ecdsa_tc[] = {
- { HAL_ECDSA_CURVE_P256,
+ { HAL_CURVE_P256,
p256_H, sizeof(p256_H),
p256_M, sizeof(p256_M),
p256_Qx, sizeof(p256_Qx),
@@ -306,7 +306,7 @@ static const ecdsa_tc_t ecdsa_tc[] = {
p256_v, sizeof(p256_v),
p256_w, sizeof(p256_w),
},
- { HAL_ECDSA_CURVE_P384,
+ { HAL_CURVE_P384,
p384_H, sizeof(p384_H),
p384_M, sizeof(p384_M),
p384_Qx, sizeof(p384_Qx),
More information about the Commits
mailing list