[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