[Cryptech-Commits] [sw/libhal] 01/01: Merge branch 'hashsig'
git at cryptech.is
git at cryptech.is
Wed Jul 25 06:00:57 UTC 2018
This is an automated email from the git hooks/post-receive script.
paul at psgd.org pushed a commit to branch master
in repository sw/libhal.
commit 253f7b849c18455da0b5bae0c25fdca0e16c8015
Merge: 64d4157 653d6b4
Author: Paul Selkirk <paul at psgd.org>
AuthorDate: Tue Jul 24 22:56:11 2018 -0400
Merge branch 'hashsig'
Makefile | 6 +-
asn1.c | 183 ++++
asn1_internal.h | 15 +
ecdsa.c | 1 +
hal.h | 20 +-
hal_internal.h | 35 +-
hash.c | 2 +-
hashsig.c | 2122 ++++++++++++++++++++++++++++++++++++++++++++++
hashsig.h | 118 +++
ks.c | 16 +
ks.h | 4 +-
ks_volatile.c | 8 +-
locks.c | 5 +
pbkdf2.c | 2 +
rpc_api.c | 23 +
rpc_client.c | 144 ++--
rpc_pkey.c | 206 ++++-
rpc_server.c | 529 +++++-------
tests/Makefile | 4 +-
tests/test-hashsig.h | 925 ++++++++++++++++++++
tests/test-rpc_hashsig.c | 594 +++++++++++++
tests/test-xdr.c | 111 +++
xdr.c | 222 ++---
xdr_internal.h | 44 +-
24 files changed, 4792 insertions(+), 547 deletions(-)
diff --cc asn1.c
index 8d7f6f6,1799ac9..d57ec96
--- a/asn1.c
+++ b/asn1.c
@@@ -173,6 -207,88 +206,88 @@@ hal_error_t hal_asn1_encode_integer(con
return HAL_OK;
}
+ /*
+ * Encode an unsigned ASN.1 INTEGER from a uint32_t. If der is
+ * NULL, just return the length of what we would have encoded.
+ */
+
+ hal_error_t hal_asn1_encode_uint32(const uint32_t n,
+ uint8_t *der, size_t *der_len, const size_t der_max)
+ {
+ /*
+ * We only handle unsigned INTEGERs, so we need to pad data with a
+ * leading zero if the most significant bit is set, to avoid
+ * flipping the ASN.1 sign bit.
+ */
+
+ size_t vlen;
+ hal_error_t err;
+ size_t hlen;
+
+ /* DER says to use the minimum number of octets */
+ if (n < 0x80) vlen = 1;
+ else if (n < 0x8000) vlen = 2;
+ else if (n < 0x800000) vlen = 3;
+ else if (n < 0x80000000) vlen = 4;
+ else vlen = 5;
+
+ err = hal_asn1_encode_header(ASN1_INTEGER, vlen, der, &hlen, der_max);
+
+ if (der_len != NULL)
+ *der_len = hlen + vlen;
+
+ if (der == NULL || err != HAL_OK)
+ return err;
+
- assert(hlen + vlen <= der_max);
++ hal_assert(hlen + vlen <= der_max);
+
+ der += hlen;
+
+ uint32_t m = n;
+ for (size_t i = vlen; i > 0; --i) {
+ der[i - 1] = m & 0xff;
+ m >>= 8;
+ }
+
+ return HAL_OK;
+ }
+
+ /*
+ * Encode an ASN.1 OCTET STRING. If der is NULL, just return the length
+ * of what we would have encoded.
+ */
+
+ hal_error_t hal_asn1_encode_octet_string(const uint8_t * const data, const size_t data_len,
+ uint8_t *der, size_t *der_len, const size_t der_max)
+ {
+ if (data_len == 0 || (der != NULL && data == NULL))
+ return HAL_ERROR_BAD_ARGUMENTS;
+
+ size_t hlen;
+ hal_error_t err;
+
+ if ((err = hal_asn1_encode_header(ASN1_OCTET_STRING, data_len, NULL, &hlen, 0)) != HAL_OK)
+ return err;
+
+ if (der_len != NULL)
+ *der_len = hlen + data_len;
+
+ if (der == NULL)
+ return HAL_OK;
+
- assert(hlen + data_len <= der_max);
++ hal_assert(hlen + data_len <= der_max);
+
+ /*
+ * Handle data early, in case it was staged into our output buffer.
+ */
+ memmove(der + hlen, data, data_len);
+
+ if ((err = hal_asn1_encode_header(ASN1_OCTET_STRING, data_len, der, &hlen, der_max)) != HAL_OK)
+ return err;
+
+ return HAL_OK;
+ }
+
/*
* Encode a public key into a X.509 SubjectPublicKeyInfo (RFC 5280).
*/
diff --cc hal.h
index 5ae2381,a01b9bd..b544900
--- a/hal.h
+++ b/hal.h
@@@ -161,8 -161,8 +161,10 @@@
DEFINE_HAL_ERROR(HAL_ERROR_KEYSTORE_WRONG_BLOCK_TYPE, "Wrong block type in keystore") \
DEFINE_HAL_ERROR(HAL_ERROR_RPC_PROTOCOL_ERROR, "RPC protocol error") \
DEFINE_HAL_ERROR(HAL_ERROR_NOT_IMPLEMENTED, "Not implemented") \
+ DEFINE_HAL_ERROR(HAL_ERROR_CORE_REASSIGNED, "Core has been reassigned since last use") \
+ DEFINE_HAL_ERROR(HAL_ERROR_ASSERTION_FAILED, "Assertion failed") \
+ DEFINE_HAL_ERROR(HAL_ERROR_HASHSIG_KEY_EXHAUSTED, "Key exhausted") \
+ DEFINE_HAL_ERROR(HAL_ERROR_NOT_READY, "Not ready for this operation") \
END_OF_HAL_ERROR_LIST
/* Marker to forestall silly line continuation errors */
diff --cc hal_internal.h
index 742b67b,b698611..94546c3
--- a/hal_internal.h
+++ b/hal_internal.h
@@@ -47,21 -47,8 +47,21 @@@
* should be looking at this file.
*/
+/*
+ * Assertions, using our logger rather than printf() and assuming a
+ * hal_error_t return value.
+ */
+
+#define hal_assert(_whatever_) \
+ do { \
+ if (!(_whatever_)) { \
+ hal_log(HAL_LOG_ERROR, "Assertion failed: %s", #_whatever_); \
+ return HAL_ERROR_ASSERTION_FAILED; \
+ } \
+ } while (0)
+
/*
- * htonl is not available in arm-none-eabi headers or libc.
+ * htonl and htons are not available in arm-none-eabi headers or libc.
*/
#ifndef STM32F4XX
#include <arpa/inet.h>
@@@ -157,9 -152,8 +165,10 @@@ extern void hal_critical_section_start(
extern void hal_critical_section_end(void);
extern void hal_ks_lock(void);
extern void hal_ks_unlock(void);
+extern void hal_rsa_bf_lock(void);
+extern void hal_rsa_bf_unlock(void);
extern void hal_task_yield(void);
+ extern void hal_task_yield_maybe(void);
/*
* Thread sleep. Currently used only for bad-PIN delays.
diff --cc hash.c
index cb9eb1f,d1e55ff..2a63900
--- a/hash.c
+++ b/hash.c
@@@ -440,15 -423,18 +440,15 @@@ hal_error_t hal_hash_initialize(hal_cor
if (state_buffer != NULL && state_length < descriptor->hash_state_length)
return HAL_ERROR_BAD_ARGUMENTS;
- if ((err = check_core(&core, descriptor, &flags)) != HAL_OK)
+ if ((err = check_core(&core, descriptor, &flags, &pomace)) != HAL_OK)
return err;
-#if ! HAL_ONLY_USE_SOFTWARE_HASH_CORES
- /*
- * If we're using a Verilog core that can save/restore state, then we
- * free it after every operation, so that it can possibly be used by
- * another client.
- */
- if (descriptor->can_restore_state)
- hal_core_free(core);
-#endif
+ if ((flags & STATE_FLAG_FREE_CORE) != 0)
+ hal_core_free(core);
+
+ /* A dynamically allocated core that can't restore state isn't going to work. */
- if (!state->descriptor->can_restore_state && (flags & STATE_FLAG_FREE_CORE) != 0)
++ if (!descriptor->can_restore_state && (flags & STATE_FLAG_FREE_CORE) != 0)
+ return HAL_ERROR_BAD_ARGUMENTS;
if (state_buffer == NULL && (state = alloc_static_hash_state()) == NULL)
return HAL_ERROR_ALLOCATION_FAILURE;
diff --cc rpc_pkey.c
index 6ef520e,1aee050..e1521af
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@@ -520,6 -524,68 +521,68 @@@ static hal_error_t pkey_local_generate_
return HAL_OK;
}
+ /*
+ * Generate a new hash-tree key with supplied name, return a key handle.
+ */
+
+ static hal_error_t pkey_local_generate_hashsig(const hal_client_handle_t client,
+ const hal_session_handle_t session,
+ hal_pkey_handle_t *pkey,
+ hal_uuid_t *name,
+ const size_t hss_levels,
+ const lms_algorithm_t lms_type,
+ const lmots_algorithm_t lmots_type,
+ const hal_key_flags_t flags)
+ {
- assert(pkey != NULL && name != NULL);
++ hal_assert(pkey != NULL && name != NULL);
+
+ hal_hashsig_key_t *key = NULL;
+ hal_pkey_slot_t *slot;
+ hal_error_t err;
+
+ if ((err = check_writable(client, flags)) != HAL_OK)
+ return err;
+
+ if ((slot = alloc_slot(flags)) == NULL)
+ return HAL_ERROR_NO_KEY_SLOTS_AVAILABLE;
+
+ if ((err = hal_uuid_gen(&slot->name)) != HAL_OK)
+ return err;
+
+ slot->client = client;
+ slot->session = session;
+ slot->type = HAL_KEY_TYPE_HASHSIG_PRIVATE,
+ slot->curve = HAL_CURVE_NONE;
+ slot->flags = flags;
+
+ if ((err = hal_hashsig_key_gen(NULL, &key, hss_levels, lms_type, lmots_type)) != HAL_OK) {
+ slot->type = HAL_KEY_TYPE_NONE;
+ return err;
+ }
+
+ uint8_t der[hal_hashsig_private_key_to_der_len(key)];
+ size_t der_len;
+
+ if ((err = hal_hashsig_private_key_to_der(key, der, &der_len, sizeof(der))) == HAL_OK)
+ err = hal_ks_store(ks_from_flags(flags), slot, der, der_len);
+
+ /* There's nothing sensitive in the top-level private key, but we wipe
+ * the der anyway, for symmetry with other key types. The actual key buf
+ * is allocated internally and stays in memory, because everything else
+ * is linked off of it.
+ */
+ memset(der, 0, sizeof(der));
+
+ if (err != HAL_OK) {
+ slot->type = HAL_KEY_TYPE_NONE;
+ return err;
+ }
+
+ *pkey = slot->pkey;
+ *name = slot->name;
+ return HAL_OK;
+ }
+
/*
* Discard key handle, leaving key intact.
*/
@@@ -812,6 -914,44 +911,44 @@@ static hal_error_t pkey_local_sign_ecds
return HAL_OK;
}
+ static hal_error_t pkey_local_sign_hashsig(hal_pkey_slot_t *slot,
+ uint8_t *keybuf, const size_t keybuf_len,
+ const uint8_t * const der, const size_t der_len,
+ const hal_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_hashsig_key_t *key = NULL;
+ hal_error_t err;
+
- assert(signature != NULL && signature_len != NULL);
- assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0));
++ hal_assert(signature != NULL && signature_len != NULL);
++ hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0));
+
+ if ((err = hal_hashsig_private_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK)
+ return err;
+
+ if (input == NULL || input_len == 0) {
+ 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_hashsig_sign(NULL, key, input, input_len, signature, signature_len, signature_max)) != HAL_OK)
+ return err;
+
+ return HAL_OK;
+ }
+
static hal_error_t pkey_local_sign(const hal_pkey_handle_t pkey,
const hal_hash_handle_t hash,
const uint8_t * const input, const size_t input_len,
@@@ -957,6 -1103,40 +1100,40 @@@ static hal_error_t pkey_local_verify_ec
return HAL_OK;
}
+ static hal_error_t pkey_local_verify_hashsig(uint8_t *keybuf, const size_t keybuf_len, const hal_key_type_t type,
+ const uint8_t * const der, const size_t der_len,
+ const hal_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_hashsig_key_t *key = NULL;
+ hal_error_t err;
+
- assert(signature != NULL && signature_len > 0);
- assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0));
++ hal_assert(signature != NULL && signature_len > 0);
++ hal_assert((hash.handle == HAL_HANDLE_NONE) != (input == NULL || input_len == 0));
+
+ if ((err = hal_hashsig_public_key_from_der(&key, keybuf, keybuf_len, der, der_len)) != HAL_OK)
+ return err;
+
+ if (input == NULL || input_len == 0) {
+ 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_hashsig_verify(NULL, key, input, input_len, signature, signature_len)) != HAL_OK)
+ return err;
+
+ return HAL_OK;
+ }
+
static hal_error_t pkey_local_verify(const hal_pkey_handle_t pkey,
const hal_hash_handle_t hash,
const uint8_t * const input, const size_t input_len,
More information about the Commits
mailing list