[Cryptech-Commits] [sw/libhal] 02/06: Use the hashsig pseudorandom key generation method if the key is exportable.

git at cryptech.is git at cryptech.is
Mon Apr 1 00:59:33 UTC 2019


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 5b2d3d25f46e8c2a306d77e8d7b2e00f1b67011f
Author: Paul Selkirk <paul at psgd.org>
AuthorDate: Thu Feb 28 17:08:25 2019 -0500

    Use the hashsig pseudorandom key generation method if the key is exportable.
---
 hashsig.c                | 58 +++++++++++++++++++++++++++++++++++++++---------
 hashsig.h                |  3 ++-
 rpc_pkey.c               |  2 +-
 tests/test-rpc_hashsig.c | 12 +++++++---
 4 files changed, 60 insertions(+), 15 deletions(-)

diff --git a/hashsig.c b/hashsig.c
index 9c48805..65a9a8b 100644
--- a/hashsig.c
+++ b/hashsig.c
@@ -48,7 +48,7 @@ typedef struct { uint8_t bytes[16]; } bytestring16;
 
 #define u32str(X) htonl(X)
 #define u16str(X) htons(X)
-#define u8str(X) (X & 0xff)
+#define u8str(X) ((X) & 0xff)
 
 #define check(op) do { hal_error_t _err = (op); if (_err != HAL_OK) return _err; } while (0)
 
@@ -239,7 +239,7 @@ static inline size_t lmots_signature_len(lmots_parameter_t * const lmots)
  * public key components (x and K).
  * Let the caller worry about storage.
  */
-static hal_error_t lmots_generate(lmots_key_t * const key)
+static hal_error_t lmots_generate(lmots_key_t * const key, bytestring32 *seed)
 {
     if (key == NULL || key->type != HAL_KEY_TYPE_HASHSIG_LMOTS || key->lmots == NULL || key->x == NULL)
         return HAL_ERROR_BAD_ARGUMENTS;
@@ -252,13 +252,36 @@ static hal_error_t lmots_generate(lmots_key_t * const key)
     size_t p = key->lmots->p;
     size_t w = key->lmots->w;
 
+    if (seed == NULL) {
 //  4. compute the array x as follows:
 //     for ( i = 0; i < p; i = i + 1 ) {
 //       set x[i] to a uniformly random n-byte string
 //     }
 
-    for (size_t i = 0; i < p; ++i)
-        check(hal_rpc_get_random(&key->x[i], n));
+        for (size_t i = 0; i < p; ++i)
+            check(hal_rpc_get_random(&key->x[i], n));
+    }
+
+    else {
+        for (size_t i = 0; i < p; ++i) {
+// Appendix A.  Pseudorandom Key Generation
+//  x_q[i] = H(I || u32str(q) || u16str(i) || u8str(0xff) || SEED)
+
+            uint8_t statebuf[512];
+            hal_hash_state_t *state = NULL;
+            uint32_t l;
+            uint16_t s;
+            uint8_t b;
+
+            check(hal_hash_initialize(NULL, hal_hash_sha256, &state, statebuf, sizeof(statebuf)));
+            check(hal_hash_update(state, (const uint8_t *)&key->I, sizeof(key->I)));
+            l = u32str(key->q); check(hal_hash_update(state, (const uint8_t *)&l, sizeof(l)));
+            s = u16str(i); check(hal_hash_update(state, (const uint8_t *)&s, sizeof(s)));
+            b = u8str(0xff); check(hal_hash_update(state, (const uint8_t *)&b, sizeof(b)));
+            check(hal_hash_update(state, (const uint8_t *)seed, sizeof(bytestring32)));
+            check(hal_hash_finalize(state, (uint8_t *)&key->x[i], sizeof(bytestring32)));
+        }
+    }
 
 //   Algorithm 1: Generating a One Time Signature Public Key From a
 //   Private Key
@@ -711,7 +734,7 @@ static inline size_t lms_signature_len(lms_parameter_t * const lms, lmots_parame
  * public key components.
  * Let the caller worry about storage.
  */
-static hal_error_t lms_generate(lms_key_t *key)
+static hal_error_t lms_generate(lms_key_t *key, bytestring32 *seed)
 {
     if (key == NULL || key->type != HAL_KEY_TYPE_HASHSIG_LMS || key->lms == NULL || key->lmots == NULL || key->lmots_keys == NULL || key->T == NULL)
         return HAL_ERROR_BAD_ARGUMENTS;
@@ -744,7 +767,7 @@ static hal_error_t lms_generate(lms_key_t *key)
     for (size_t q = 0; q < h2; ++q) {
         /* generate the lmots private and public key components */
         lmots_key.q = q;
-        check(lmots_generate(&lmots_key));
+        check(lmots_generate(&lmots_key, seed));
 
         /* store the lmots key */
         uint8_t der[lmots_private_key_to_der_len(&lmots_key)];
@@ -1189,6 +1212,7 @@ struct hal_hashsig_key {
     lmots_parameter_t *lmots;
     bytestring16 I;
     bytestring32 T1;
+    bytestring32 seed;
     lms_key_t *lms_keys;
 };
 
@@ -1336,7 +1360,8 @@ hal_error_t hal_hashsig_key_gen(hal_core_t *core,
                                 hal_hashsig_key_t **key_,
                                 const size_t L,
                                 const hal_lms_algorithm_t lms_type,
-                                const hal_lmots_algorithm_t lmots_type)
+                                const hal_lmots_algorithm_t lmots_type,
+                                const hal_key_flags_t flags)
 {
     /* hss_alloc does most of the checks */
 
@@ -1359,7 +1384,17 @@ hal_error_t hal_hashsig_key_gen(hal_core_t *core,
     for (size_t i = 0; i < L; ++i) {
         lms_key_t * lms_key = &key->lms_keys[i];
 
-        check(lms_generate(lms_key));
+        if (flags & HAL_KEY_FLAG_EXPORTABLE && i == 0) {
+            bytestring32 *seed = &key->seed;
+            check(hal_rpc_get_random(seed, sizeof(*seed)));
+            check(lms_generate(lms_key, seed));
+        }
+        else {
+            /* hss_alloc zeroes out the allocation, so we know seed == {0}
+             * for later use (store/restore)
+             */
+            check(lms_generate(lms_key, NULL));
+        }
 
         if (i > 0)
             /* sign this tree with the previous */
@@ -1467,7 +1502,7 @@ hal_error_t hal_hashsig_sign(hal_core_t *core,
              * any additional memory.
              */
             check(lms_delete(lms_key));
-            check(lms_generate(lms_key));
+            check(lms_generate(lms_key, NULL));
             check(lms_sign(&key->lms_keys[d-1],
                            (const uint8_t * const)lms_key->pubkey, lms_key->pubkey_len,
                            lms_key->signature, NULL, lms_key->signature_len));
@@ -1623,6 +1658,7 @@ hal_error_t hal_hashsig_private_key_to_der(const hal_hashsig_key_t * const key,
     check(hal_asn1_encode_lmots_algorithm(key->lmots->type, NULL, &len, 0)); vlen += len;
     check(hal_asn1_encode_bytestring16(&key->I, NULL, &len, 0));             vlen += len;
     check(hal_asn1_encode_bytestring32(&key->T1, NULL, &len, 0));            vlen += len;
+    check(hal_asn1_encode_bytestring32(&key->seed, NULL, &len, 0));          vlen += len;
 
     check(hal_asn1_encode_header(ASN1_SEQUENCE, vlen, NULL, &hlen, 0));
 
@@ -1646,6 +1682,7 @@ hal_error_t hal_hashsig_private_key_to_der(const hal_hashsig_key_t * const key,
     check(hal_asn1_encode_lmots_algorithm(key->lmots->type, d, &len, vlen)); d += len; vlen -= len;
     check(hal_asn1_encode_bytestring16(&key->I, d, &len, vlen));             d += len; vlen -= len;
     check(hal_asn1_encode_bytestring32(&key->T1, d, &len, vlen));            d += len; vlen -= len;
+    check(hal_asn1_encode_bytestring32(&key->seed, d, &len, vlen));          d += len; vlen -= len;
 
     return hal_asn1_encode_pkcs8_privatekeyinfo(hal_asn1_oid_mts_hashsig, hal_asn1_oid_mts_hashsig_len,
                                                 NULL, 0, der, d - der, der, der_len, der_max);
@@ -1700,6 +1737,7 @@ hal_error_t hal_hashsig_private_key_from_der(hal_hashsig_key_t **key_,
     key->lmots = lmots_select_parameter_set(lmots_type);
     check(hal_asn1_decode_bytestring16(&key->I, d, &n, vlen));        d += n; vlen -= n;
     check(hal_asn1_decode_bytestring32(&key->T1, d, &n, vlen));       d += n; vlen -= n;
+    check(hal_asn1_decode_bytestring32(&key->seed, d, &n, vlen));     d += n; vlen -= n;
 
     if (d != privkey + privkey_len)
         return HAL_ERROR_ASN1_PARSE_FAILED;
@@ -2108,7 +2146,7 @@ hal_error_t hal_hashsig_ks_init(void)
         /* generate the lower-level lms keys */
         for (size_t i = 1; i < hss_key->L; ++i) {
             lms_key_t * lms_key = &hss_key->lms_keys[i];
-            if (lms_generate(lms_key) != HAL_OK)
+            if (lms_generate(lms_key, NULL) != HAL_OK)
                 goto fail;
 
             /* store the lms key */
diff --git a/hashsig.h b/hashsig.h
index ef8be42..505d0f3 100644
--- a/hashsig.h
+++ b/hashsig.h
@@ -43,7 +43,8 @@ extern hal_error_t hal_hashsig_key_gen(hal_core_t *core,
                                        hal_hashsig_key_t **key_,
                                        const size_t hss_levels,
                                        const hal_lms_algorithm_t lms_type,
-                                       const hal_lmots_algorithm_t lmots_type);
+                                       const hal_lmots_algorithm_t lmots_type,
+                                       const hal_key_flags_t flags);
 
 extern hal_error_t hal_hashsig_key_delete(const hal_hashsig_key_t * const key);
 
diff --git a/rpc_pkey.c b/rpc_pkey.c
index fe80a90..138dd73 100644
--- a/rpc_pkey.c
+++ b/rpc_pkey.c
@@ -555,7 +555,7 @@ static hal_error_t pkey_local_generate_hashsig(const hal_client_handle_t client,
   slot->curve   = HAL_CURVE_NONE;
   slot->flags   = flags;
 
-  if ((err = hal_hashsig_key_gen(NULL, &key, hss_levels, lms_type, lmots_type)) != HAL_OK) {
+  if ((err = hal_hashsig_key_gen(NULL, &key, hss_levels, lms_type, lmots_type, flags)) != HAL_OK) {
     slot->type = HAL_KEY_TYPE_NONE;
     return err;
   }
diff --git a/tests/test-rpc_hashsig.c b/tests/test-rpc_hashsig.c
index 8b9e509..2de5dfb 100644
--- a/tests/test-rpc_hashsig.c
+++ b/tests/test-rpc_hashsig.c
@@ -261,6 +261,7 @@ static hal_error_t dump_hss_signature(const uint8_t * const sig, const size_t le
 static int test_hashsig_sign(const size_t L,
                              const hal_lms_algorithm_t lms_type,
                              const hal_lmots_algorithm_t lmots_type,
+                             hal_key_flags_t flags,
                              size_t iterations,
                              int save, int keep)
 {
@@ -285,7 +286,7 @@ static int test_hashsig_sign(const size_t L,
                 lose("Error closing %s: %s\n", save_name, strerror(errno));
         }
 
-        hal_key_flags_t flags = HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE | HAL_KEY_FLAG_TOKEN;
+        flags |= HAL_KEY_FLAG_USAGE_DIGITALSIGNATURE | HAL_KEY_FLAG_TOKEN;
 
         printf("Starting hashsig key test: L %lu, lms type %u (h=%lu), lmots type %u (w=%lu)\n",
                L, lms_type, lms_type_to_h(lms_type), lmots_type, lmots_type_to_w(lmots_type));
@@ -461,6 +462,7 @@ int main(int argc, char *argv[])
     size_t lms_lo = 5, lms_hi = 0;
     size_t lmots_lo = 3, lmots_hi = 0;
     int save = 0, keep = 0;
+    hal_key_flags_t flags = 0;
     char *p;
     hal_error_t err;
     int ok = 1;
@@ -478,10 +480,11 @@ Usage: %s [-d] [-i] [-p pin] [-t] [-L n] [-l n] [-o n] [-n n] [-s] [-r file]\n\
        -s: save generated public key and signatures\n\
        -k: keep (don't delete) the generated keys on the hsm\n\
        -r: read and pretty-print a saved signature file\n\
+       -x: mark key as exportable\n\
 Numeric arguments can be a single number or a range, e.g. '1..4'\n";
 
     int opt;
-    while ((opt = getopt(argc, argv, "ditp:L:l:o:n:skr:h?")) != -1) {
+    while ((opt = getopt(argc, argv, "ditp:L:l:o:n:skr:xh?")) != -1) {
         switch (opt) {
         case 'd':
             debug = 1;
@@ -534,6 +537,9 @@ Numeric arguments can be a single number or a range, e.g. '1..4'\n";
             ok &= read_sig(optarg);
             do_default = 0;
             break;
+        case 'x':
+            flags = HAL_KEY_FLAG_EXPORTABLE;
+            break;
         case 'h':
         case '?':
             fprintf(stdout, usage, argv[0]);
@@ -576,7 +582,7 @@ Numeric arguments can be a single number or a range, e.g. '1..4'\n";
         for (size_t L = L_lo; L <= L_hi; ++L) {
             for (hal_lms_algorithm_t lms_type = lms_lo; lms_type <= lms_hi; ++lms_type) {
                 for (hal_lmots_algorithm_t lmots_type = lmots_lo; lmots_type <= lmots_hi; ++lmots_type) {
-                    ok &= test_hashsig_sign(L, lms_type, lmots_type, iterations, save, keep);
+                    ok &= test_hashsig_sign(L, lms_type, lmots_type, flags, iterations, save, keep);
                 }
             }
         }



More information about the Commits mailing list