gestumblinde

Gestumblinde - reference implementation of SLH-DSA
git clone git://www.tkruger.se/gestumblinde.git
Log | Files | Refs | README

slh.c (3582B)


      1 #include "slh.h"
      2 
      3 static inline void idx_tree_mod_2d(idx_tree_t *x, const size_t s) {
      4   if (s >= 64) {
      5     size_t sp = s - 64;
      6     x->valhb &= (1ul << sp) - 1;
      7   } else {
      8     x->valhb = 0;
      9     x->vallb &= (1ull << s) - 1;
     10   }
     11 }
     12 
     13 static inline void set_tree_address(uint32_t adrs[ADRS_LEN], idx_tree_t idx) {
     14   idx_tree_t tmp;
     15   tmp.valhb = htobe32(idx.valhb);
     16   tmp.vallb = htobe64(idx.vallb);
     17 
     18   memcpy(&adrs[ADRS_TREE_ADDRESS_IDX], &tmp, sizeof(tmp));
     19 }
     20 
     21 void slh_keygen(uint8_t *sk, uint8_t *pk) {
     22   randombytes(sk, ENN);
     23   randombytes(sk + ENN, ENN);
     24   randombytes(pk, ENN);
     25   memcpy(sk + 2 * ENN, pk, ENN);
     26 
     27   uint32_t adrs[ADRS_LEN] = {0};
     28   adrs[ADRS_LAYER_ADDRESS_IDX] = htobe32(D - 1);
     29 
     30   xmss_node(pk + ENN, sk, 0, HP, pk, adrs);
     31 
     32   memcpy(sk + 3 * ENN, pk + ENN, ENN);
     33 }
     34 
     35 void slh_sign(uint8_t *out, const uint8_t *m, const size_t mlen,
     36               const uint8_t *sk, int randomize) {
     37   const uint8_t *sk_seed = sk;
     38   const uint8_t *sk_prf = sk + ENN;
     39   const uint8_t *pk_seed = sk + 2 * ENN;
     40   const uint8_t *pk_root = sk + 3 * ENN;
     41 
     42   uint8_t opt_rand[ENN];
     43   memcpy(opt_rand, pk_seed, ENN);
     44   if (randomize) {
     45     randombytes(opt_rand, ENN);
     46   }
     47 
     48   uint8_t *cout = out;
     49   hash_prf_msg(out, sk_prf, opt_rand, m, mlen);
     50 
     51   uint8_t digest[M];
     52   hash_h_msg(digest, M, cout, pk_seed, pk_root, m, mlen);
     53   cout += ENN;
     54 
     55   uint8_t *md = digest;
     56   uint8_t *tmp_idx_tree = digest + FORS_MD_LEN;
     57   uint8_t *tmp_idx_leaf = digest + FORS_MD_LEN + IDX_TREE_LEN;
     58 
     59   idx_tree_t idx_tree;
     60   memcpy((uint8_t *)&idx_tree + (sizeof(idx_tree) - IDX_TREE_LEN), tmp_idx_tree,
     61          IDX_TREE_LEN);
     62   idx_tree.valhb = htobe32(idx_tree.valhb);
     63   idx_tree.vallb = htobe64(idx_tree.vallb);
     64   idx_tree_mod_2d(&idx_tree, H - H / D);
     65   uint64_t idx_leaf = to_int(tmp_idx_leaf, IDX_LEAF_LEN);
     66   idx_leaf &= ((1 << (H / D)) - 1);
     67 
     68   uint32_t adrs[ADRS_LEN] = {0};
     69   set_tree_address(adrs, idx_tree);
     70   adrs[ADRS_TYPE_IDX] = FORS_TREE;
     71   adrs[ADRS_KEYPAIR_IDX] = htobe32(idx_leaf);
     72   bzero(&adrs[ADRS_KEYPAIR_IDX + 1], 2 * sizeof(*adrs));
     73 
     74   fors_sign(cout, md, sk_seed, pk_seed, adrs);
     75 
     76   uint8_t pk_fors[ENN];
     77   fors_pk_from_sig(pk_fors, cout, md, pk_seed, adrs);
     78   cout += FORS_SIG_LEN;
     79 
     80   ht_sign(cout, pk_fors, sk_seed, pk_seed, idx_tree, idx_leaf);
     81 }
     82 
     83 int slh_verify(const uint8_t *m, const size_t mlen, const uint8_t *sig,
     84                const size_t siglen, const uint8_t *pk) {
     85   if (siglen != (ENN * (1 + K * (1 + A) + H + D * WOTSP_LEN))) {
     86     return 0;
     87   }
     88 
     89   const uint8_t *pk_seed = pk;
     90   const uint8_t *pk_root = pk + ENN;
     91   const uint8_t *csig = sig;
     92   const uint8_t *sig_fors = sig + ENN;
     93   const uint8_t *sig_ht = sig + ENN + FORS_SIG_LEN;
     94 
     95   uint8_t digest[M];
     96   hash_h_msg(digest, M, csig, pk_seed, pk_root, m, mlen);
     97 
     98   uint8_t *md = digest;
     99   uint8_t *tmp_idx_tree = digest + FORS_MD_LEN;
    100   uint8_t *tmp_idx_leaf = digest + FORS_MD_LEN + IDX_TREE_LEN;
    101 
    102   idx_tree_t idx_tree;
    103   memcpy((uint8_t *)&idx_tree + (sizeof(idx_tree) - IDX_TREE_LEN), tmp_idx_tree,
    104          IDX_TREE_LEN);
    105   idx_tree.valhb = htobe32(idx_tree.valhb);
    106   idx_tree.vallb = htobe64(idx_tree.vallb);
    107   idx_tree_mod_2d(&idx_tree, H - H / D);
    108   uint64_t idx_leaf = to_int(tmp_idx_leaf, IDX_LEAF_LEN);
    109   idx_leaf &= ((1 << (H / D)) - 1);
    110 
    111   uint32_t adrs[ADRS_LEN] = {0};
    112   set_tree_address(adrs, idx_tree);
    113   adrs[ADRS_TYPE_IDX] = FORS_TREE;
    114   adrs[ADRS_KEYPAIR_IDX] = htobe32(idx_leaf);
    115   bzero(&adrs[ADRS_KEYPAIR_IDX + 1], 2 * sizeof(*adrs));
    116 
    117   uint8_t pk_fors[ENN];
    118   fors_pk_from_sig(pk_fors, sig_fors, md, pk_seed, adrs);
    119 
    120   return ht_verify(pk_fors, sig_ht, pk_seed, idx_tree, idx_leaf, pk_root);
    121 }