gestumblinde

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

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 }