xmss.c (3207B)
1 #include "xmss.h" 2 3 /* 4 * Compute the root of a Merkle subtree of WOTS+ public keys. 5 * 6 * Returns length of written output. 7 */ 8 int xmss_node(uint8_t *out, const uint8_t sk_seed[ENN], const uint64_t i, 9 const uint64_t z, const uint8_t pk_seed[ENN], 10 uint32_t adrs[ADRS_LEN]) { 11 if (z > HP || i >= (1 << (HP - z))) 12 return 0; 13 14 if (z == 0) { 15 adrs[ADRS_TYPE_IDX] = WOTS_HASH; 16 adrs[ADRS_KEYPAIR_IDX] = htobe32((uint32_t)i); 17 bzero(&adrs[ADRS_CHAIN_ADDRESS_IDX], 2 * sizeof(*adrs)); 18 19 wotsp_pkgen(out, sk_seed, pk_seed, adrs); 20 } else { 21 uint8_t buffer[2 * ENN]; 22 uint8_t *left = buffer; 23 uint8_t *right = buffer + ENN; 24 25 #ifndef NDEBUG 26 int r = xmss_node(left, sk_seed, 2 * i, z - 1, pk_seed, adrs); 27 assert(r == ENN); 28 r = xmss_node(right, sk_seed, 2 * i + 1, z - 1, pk_seed, adrs); 29 assert(r == ENN); 30 #else 31 xmss_node(left, sk_seed, 2 * i, z - 1, pk_seed, adrs); 32 xmss_node(right, sk_seed, 2 * i + 1, z - 1, pk_seed, adrs); 33 #endif 34 35 adrs[ADRS_TYPE_IDX] = TREE; 36 adrs[ADRS_KEYPAIR_IDX] = 0; // padding zero for TREE type 37 adrs[ADRS_TREE_HEIGHT_IDX] = htobe32((uint32_t)z); 38 adrs[ADRS_TREE_INDEX_IDX] = htobe32((uint32_t)i); 39 40 hash_h(out, pk_seed, adrs, buffer); 41 } 42 43 return ENN; 44 } 45 46 /* 47 * Generate an XMSS signature 48 */ 49 int xmss_sign(uint8_t *out, const uint8_t m[ENN], const uint8_t sk_seed[ENN], 50 const uint64_t idx, const uint8_t pk_seed[ENN], 51 uint32_t adrs[ADRS_LEN]) { 52 assert(idx <= (1 << HP)); 53 size_t j; 54 55 uint8_t *auth = out + (WOTSP_LEN * ENN); 56 uint64_t k; 57 for (j = 0; j < HP; j++) { 58 k = (idx >> j) ^ 0x01; 59 xmss_node(auth, sk_seed, k, j, pk_seed, adrs); 60 auth += ENN; 61 } 62 63 adrs[ADRS_TYPE_IDX] = WOTS_HASH; 64 adrs[ADRS_KEYPAIR_IDX] = htobe32((uint32_t)idx); 65 bzero(&adrs[ADRS_CHAIN_ADDRESS_IDX], 2 * sizeof(*adrs)); 66 67 wotsp_sign(out, m, sk_seed, pk_seed, adrs); 68 69 return 0; 70 } 71 72 /* 73 * Compute an XMSS public key from an XMSS signature 74 */ 75 int xmss_pk_from_sig(uint8_t *out, const uint64_t idx, const uint8_t *sig, 76 const uint8_t m[ENN], const uint8_t pk_seed[ENN], 77 uint32_t adrs[ADRS_LEN]) { 78 adrs[ADRS_TYPE_IDX] = WOTS_HASH; 79 adrs[ADRS_KEYPAIR_IDX] = htobe32((uint32_t)idx); 80 bzero(&adrs[ADRS_CHAIN_ADDRESS_IDX], 2 * sizeof(*adrs)); 81 82 const uint8_t *auth = sig + (WOTSP_LEN * ENN); 83 uint8_t node_data[3 * ENN]; 84 85 wotsp_pk_from_sig(node_data + ENN, sig, m, ENN, pk_seed, adrs); 86 87 adrs[ADRS_TYPE_IDX] = TREE; 88 adrs[ADRS_KEYPAIR_IDX] = 0; // padding zero for TREE type 89 adrs[ADRS_TREE_INDEX_IDX] = htobe32((uint32_t)idx); 90 91 size_t k; 92 for (k = 0; k < HP; k++) { 93 adrs[ADRS_TREE_HEIGHT_IDX] = htobe32((uint32_t)k + 1); 94 uint32_t ti = betoh32(adrs[ADRS_TREE_INDEX_IDX]); 95 if ((idx >> k) % 2 == 0) { 96 adrs[ADRS_TREE_INDEX_IDX] = htobe32(ti >> 1); 97 memcpy(node_data + 2 * ENN, auth + k * ENN, ENN); 98 hash_h(node_data + ENN, pk_seed, adrs, node_data + ENN); 99 } else { 100 adrs[ADRS_TREE_INDEX_IDX] = htobe32((ti - 1) >> 1); 101 memcpy(node_data, auth + k * ENN, ENN); 102 hash_h(node_data + ENN, pk_seed, adrs, node_data); 103 } 104 } 105 106 memcpy(out, node_data + ENN, ENN); 107 108 return 0; 109 }