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 }