wotsp.c (4208B)
1 #include "wotsp.h" 2 3 /* 4 * Chaining function used in WOTS+. 5 */ 6 static inline void wotsp_chain(uint8_t out[ENN], const uint8_t X[ENN], 7 const uint64_t i, const uint64_t s, 8 const uint8_t pk_seed[ENN], 9 uint32_t adrs[ADRS_LEN]) { 10 assert(i + s < WOTSP_W); 11 12 uint8_t tmp[ENN]; 13 memcpy(tmp, X, ENN); 14 15 uint32_t j; 16 for (j = i; j < i + s; j++) { 17 adrs[ADRS_HASH_ADDRESS_IDX] = htobe32(j); 18 hash_f(tmp, pk_seed, adrs, tmp); 19 } 20 21 memcpy(out, tmp, ENN); 22 } 23 24 /* 25 * Generate a WOTS+ public key. 26 */ 27 int wotsp_pkgen(uint8_t *out, const uint8_t sk_seed[ENN], 28 const uint8_t pk_seed[ENN], uint32_t adrs[ADRS_LEN]) { 29 uint32_t sk_adrs[ADRS_LEN]; 30 uint8_t tmp[WOTSP_LEN * ENN]; 31 uint8_t *tmpp = tmp; 32 33 memcpy(sk_adrs, adrs, ADRS_TYPE_IDX * sizeof(*adrs)); 34 sk_adrs[ADRS_TYPE_IDX] = WOTS_PRF; 35 sk_adrs[ADRS_KEYPAIR_IDX] = adrs[ADRS_KEYPAIR_IDX]; 36 sk_adrs[ADRS_HASH_ADDRESS_IDX] = 0; 37 38 uint8_t prf_buffer[ENN]; 39 uint32_t be_i; 40 41 size_t i; 42 for (i = 0; i < WOTSP_LEN; i++) { 43 be_i = htobe32(i); 44 sk_adrs[ADRS_CHAIN_ADDRESS_IDX] = be_i; 45 hash_prf(prf_buffer, pk_seed, sk_seed, sk_adrs); 46 adrs[ADRS_CHAIN_ADDRESS_IDX] = be_i; 47 wotsp_chain(tmpp, prf_buffer, 0, WOTSP_W - 1, pk_seed, adrs); 48 tmpp += ENN; 49 } 50 51 uint32_t wotspk_adrs[ADRS_LEN]; 52 memcpy(wotspk_adrs, adrs, ADRS_TYPE_IDX * sizeof(*adrs)); 53 wotspk_adrs[ADRS_TYPE_IDX] = WOTS_PK; 54 wotspk_adrs[ADRS_KEYPAIR_IDX] = adrs[ADRS_KEYPAIR_IDX]; 55 wotspk_adrs[ADRS_CHAIN_ADDRESS_IDX] = 0; 56 wotspk_adrs[ADRS_HASH_ADDRESS_IDX] = 0; 57 hash_t(out, WOTSP_LEN, pk_seed, wotspk_adrs, tmp); 58 59 return 0; 60 } 61 62 /* 63 * Generate a WOTS+ signature on an n-byte message 64 */ 65 int wotsp_sign(uint8_t *out, const uint8_t *m, const uint8_t sk_seed[ENN], 66 const uint8_t pk_seed[ENN], uint32_t adrs[ADRS_LEN]) { 67 uint64_t csum = 0; 68 69 uint64_t msg[WOTSP_LEN]; 70 base_2b(msg, m, ENN, LGW, WOTSP_LEN1); 71 72 size_t i; 73 for (i = 0; i < WOTSP_LEN1; i++) { 74 assert(WOTSP_W > msg[i]); 75 csum += WOTSP_W - 1 - msg[i]; 76 } 77 78 csum <<= (8 - ((WOTSP_LEN2 * LGW) % 8)) % 8; 79 80 uint8_t csum_bytes[(WOTSP_LEN2 * LGW + 7) / 8]; 81 to_bytes(csum_bytes, (WOTSP_LEN2 * LGW + 7) / 8, csum); 82 base_2b(&msg[WOTSP_LEN1], csum_bytes, (WOTSP_LEN2 * LGW + 7) / 8, LGW, 83 WOTSP_LEN2); 84 85 uint32_t sk_adrs[ADRS_LEN] = {0}; 86 memcpy(sk_adrs, adrs, ADRS_TYPE_IDX * sizeof(*adrs)); 87 sk_adrs[ADRS_TYPE_IDX] = WOTS_PRF; 88 sk_adrs[ADRS_KEYPAIR_IDX] = adrs[ADRS_KEYPAIR_IDX]; 89 90 uint8_t *cout = out; 91 uint8_t sk[ENN]; 92 for (i = 0; i < WOTSP_LEN; i++) { 93 uint32_t be_i = htobe32(i); 94 sk_adrs[ADRS_CHAIN_ADDRESS_IDX] = be_i; 95 hash_prf(sk, pk_seed, sk_seed, sk_adrs); 96 adrs[ADRS_CHAIN_ADDRESS_IDX] = be_i; 97 wotsp_chain(cout, sk, 0, msg[i], pk_seed, adrs); 98 cout += ENN; 99 } 100 101 return 0; 102 } 103 104 /* 105 * Computes a WOTS+ public key from a message and its signature. 106 */ 107 int wotsp_pk_from_sig(uint8_t *out, const uint8_t *sig, const uint8_t *m, 108 const size_t nm, const uint8_t pk_seed[ENN], 109 uint32_t adrs[ADRS_LEN]) { 110 uint64_t csum = 0; 111 112 uint64_t msg[WOTSP_LEN]; 113 base_2b(msg, m, nm, LGW, WOTSP_LEN1); 114 115 size_t i; 116 for (i = 0; i < WOTSP_LEN1; i++) { 117 assert(WOTSP_W > msg[i]); 118 csum += WOTSP_W - 1 - msg[i]; 119 } 120 121 csum <<= (8 - ((WOTSP_LEN2 * LGW) % 8)) % 8; 122 123 uint8_t csum_bytes[(WOTSP_LEN2 * LGW + 7) / 8]; 124 to_bytes(csum_bytes, (WOTSP_LEN2 * LGW + 7) / 8, csum); 125 base_2b(&msg[WOTSP_LEN1], csum_bytes, (WOTSP_LEN2 * LGW + 7) / 8, LGW, 126 WOTSP_LEN2); 127 128 uint8_t tmp[WOTSP_LEN * ENN]; 129 const uint8_t *csig = sig; 130 uint8_t *cout = tmp; 131 for (i = 0; i < WOTSP_LEN; i++) { 132 adrs[ADRS_CHAIN_ADDRESS_IDX] = htobe32(i); 133 wotsp_chain(cout, csig, msg[i], WOTSP_W - 1 - msg[i], pk_seed, adrs); 134 cout += ENN; 135 csig += ENN; 136 } 137 138 uint32_t wotspk_adrs[ADRS_LEN]; 139 memcpy(wotspk_adrs, adrs, ADRS_TYPE_IDX * sizeof(*adrs)); 140 wotspk_adrs[ADRS_TYPE_IDX] = WOTS_PK; 141 wotspk_adrs[ADRS_KEYPAIR_IDX] = adrs[ADRS_KEYPAIR_IDX]; 142 wotspk_adrs[ADRS_CHAIN_ADDRESS_IDX] = 0; 143 wotspk_adrs[ADRS_HASH_ADDRESS_IDX] = 0; 144 145 hash_t(out, WOTSP_LEN, pk_seed, wotspk_adrs, tmp); 146 147 return 0; 148 }