25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
8.8 KiB

  1. /*
  2. xmss_commons.c 20160722
  3. Andreas Hülsing
  4. Joost Rijneveld
  5. Public domain.
  6. */
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdint.h>
  10. #include "hash.h"
  11. #include "hash_address.h"
  12. #include "params.h"
  13. #include "wots.h"
  14. #include "xmss_commons.h"
  15. void to_byte(unsigned char *out, unsigned long long in, uint32_t bytes)
  16. {
  17. int i;
  18. for (i = bytes-1; i >= 0; i--) {
  19. out[i] = in & 0xff;
  20. in = in >> 8;
  21. }
  22. }
  23. /**
  24. * Computes the leaf at a given address. First generates the WOTS key pair, then computes leaf using l_tree. As this happens position independent, we only require that addr encodes the right ltree-address.
  25. */
  26. void gen_leaf_wots(const xmss_params *params, unsigned char *leaf,
  27. const unsigned char *sk_seed, const unsigned char *pub_seed,
  28. uint32_t ltree_addr[8], uint32_t ots_addr[8])
  29. {
  30. unsigned char seed[params->n];
  31. unsigned char pk[params->wots_keysize];
  32. get_seed(params, seed, sk_seed, ots_addr);
  33. wots_pkgen(params, pk, seed, pub_seed, ots_addr);
  34. l_tree(params, leaf, pk, pub_seed, ltree_addr);
  35. }
  36. /**
  37. * Used for pseudorandom keygeneration,
  38. * generates the seed for the WOTS keypair at address addr
  39. *
  40. * takes params->n byte sk_seed and returns params->n byte seed using 32 byte address addr.
  41. */
  42. void get_seed(const xmss_params *params, unsigned char *seed,
  43. const unsigned char *sk_seed, uint32_t addr[8])
  44. {
  45. unsigned char bytes[32];
  46. // Make sure that chain addr, hash addr, and key bit are 0!
  47. set_chain_addr(addr, 0);
  48. set_hash_addr(addr, 0);
  49. set_key_and_mask(addr, 0);
  50. // Generate pseudorandom value
  51. addr_to_byte(bytes, addr);
  52. prf(params, seed, bytes, sk_seed, params->n);
  53. }
  54. /**
  55. * Computes a leaf from a WOTS public key using an L-tree.
  56. */
  57. void l_tree(const xmss_params *params, unsigned char *leaf, unsigned char *wots_pk,
  58. const unsigned char *pub_seed, uint32_t addr[8])
  59. {
  60. unsigned int l = params->wots_len;
  61. uint32_t i = 0;
  62. uint32_t height = 0;
  63. uint32_t bound;
  64. set_tree_height(addr, height);
  65. while (l > 1) {
  66. bound = l >> 1;
  67. for (i = 0; i < bound; i++) {
  68. set_tree_index(addr, i);
  69. hash_h(params, wots_pk + i*params->n, wots_pk + i*2*params->n, pub_seed, addr);
  70. }
  71. if (l & 1) {
  72. memcpy(wots_pk + (l >> 1)*params->n, wots_pk + (l - 1)*params->n, params->n);
  73. l = (l >> 1) + 1;
  74. }
  75. else {
  76. l = l >> 1;
  77. }
  78. height++;
  79. set_tree_height(addr, height);
  80. }
  81. memcpy(leaf, wots_pk, params->n);
  82. }
  83. /**
  84. * Computes a root node given a leaf and an authapth
  85. */
  86. static void validate_authpath(const xmss_params *params, unsigned char *root,
  87. const unsigned char *leaf, unsigned long leafidx,
  88. const unsigned char *authpath,
  89. const unsigned char *pub_seed, uint32_t addr[8])
  90. {
  91. uint32_t i, j;
  92. unsigned char buffer[2*params->n];
  93. // If leafidx is odd (last bit = 1), current path element is a right child and authpath has to go to the left.
  94. // Otherwise, it is the other way around
  95. if (leafidx & 1) {
  96. for (j = 0; j < params->n; j++) {
  97. buffer[params->n + j] = leaf[j];
  98. buffer[j] = authpath[j];
  99. }
  100. }
  101. else {
  102. for (j = 0; j < params->n; j++) {
  103. buffer[j] = leaf[j];
  104. buffer[params->n + j] = authpath[j];
  105. }
  106. }
  107. authpath += params->n;
  108. for (i = 0; i < params->tree_height-1; i++) {
  109. set_tree_height(addr, i);
  110. leafidx >>= 1;
  111. set_tree_index(addr, leafidx);
  112. if (leafidx & 1) {
  113. hash_h(params, buffer + params->n, buffer, pub_seed, addr);
  114. for (j = 0; j < params->n; j++) {
  115. buffer[j] = authpath[j];
  116. }
  117. }
  118. else {
  119. hash_h(params, buffer, buffer, pub_seed, addr);
  120. for (j = 0; j < params->n; j++) {
  121. buffer[j + params->n] = authpath[j];
  122. }
  123. }
  124. authpath += params->n;
  125. }
  126. set_tree_height(addr, params->tree_height - 1);
  127. leafidx >>= 1;
  128. set_tree_index(addr, leafidx);
  129. hash_h(params, root, buffer, pub_seed, addr);
  130. }
  131. /**
  132. * Verifies a given message signature pair under a given public key.
  133. */
  134. int xmss_core_sign_open(const xmss_params *params,
  135. unsigned char *m, unsigned long long *mlen,
  136. const unsigned char *sm, unsigned long long smlen,
  137. const unsigned char *pk)
  138. {
  139. unsigned long long i;
  140. unsigned long idx = 0;
  141. unsigned char wots_pk[params->wots_keysize];
  142. unsigned char pkhash[params->n];
  143. unsigned char root[params->n];
  144. unsigned char msg_h[params->n];
  145. unsigned char hash_key[3*params->n];
  146. unsigned char pub_seed[params->n];
  147. memcpy(pub_seed, pk + params->n, params->n);
  148. // Init addresses
  149. uint32_t ots_addr[8] = {0};
  150. uint32_t ltree_addr[8] = {0};
  151. uint32_t node_addr[8] = {0};
  152. set_type(ots_addr, 0);
  153. set_type(ltree_addr, 1);
  154. set_type(node_addr, 2);
  155. *mlen = smlen - params->bytes;
  156. // Extract index
  157. for (i = 0; i < params->index_len; i++) {
  158. idx |= ((unsigned long long)sm[i]) << (8*(params->index_len - 1 - i));
  159. }
  160. // Generate hash key (R || root || idx)
  161. memcpy(hash_key, sm + params->index_len, params->n);
  162. memcpy(hash_key + params->n, pk, params->n);
  163. to_byte(hash_key + 2*params->n, idx, params->n);
  164. // hash message
  165. h_msg(params, msg_h, sm + params->bytes, *mlen, hash_key, 3*params->n);
  166. sm += params->index_len + params->n;
  167. // Prepare Address
  168. set_ots_addr(ots_addr, idx);
  169. // Check WOTS signature
  170. wots_pk_from_sig(params, wots_pk, sm, msg_h, pub_seed, ots_addr);
  171. sm += params->wots_keysize;
  172. // Compute Ltree
  173. set_ltree_addr(ltree_addr, idx);
  174. l_tree(params, pkhash, wots_pk, pub_seed, ltree_addr);
  175. // Compute root
  176. validate_authpath(params, root, pkhash, idx, sm, pub_seed, node_addr);
  177. sm += params->tree_height*params->n;
  178. for (i = 0; i < params->n; i++) {
  179. if (root[i] != pk[i]) {
  180. for (i = 0; i < *mlen; i++) {
  181. m[i] = 0;
  182. }
  183. *mlen = -1;
  184. return -1;
  185. }
  186. }
  187. for (i = 0; i < *mlen; i++) {
  188. m[i] = sm[i];
  189. }
  190. return 0;
  191. }
  192. /**
  193. * Verifies a given message signature pair under a given public key.
  194. */
  195. int xmssmt_core_sign_open(const xmss_params *params,
  196. unsigned char *m, unsigned long long *mlen,
  197. const unsigned char *sm, unsigned long long smlen,
  198. const unsigned char *pk)
  199. {
  200. uint32_t idx_leaf;
  201. unsigned long long i;
  202. unsigned long long idx = 0;
  203. unsigned char wots_pk[params->wots_keysize];
  204. unsigned char pkhash[params->n];
  205. unsigned char root[params->n];
  206. unsigned char *msg_h = root;
  207. unsigned char hash_key[3*params->n];
  208. const unsigned char *pub_seed = pk + params->n;
  209. // Init addresses
  210. uint32_t ots_addr[8] = {0};
  211. uint32_t ltree_addr[8] = {0};
  212. uint32_t node_addr[8] = {0};
  213. set_type(ots_addr, 0);
  214. set_type(ltree_addr, 1);
  215. set_type(node_addr, 2);
  216. *mlen = smlen - params->bytes;
  217. // Extract index
  218. for (i = 0; i < params->index_len; i++) {
  219. idx |= ((unsigned long long)sm[i]) << (8*(params->index_len - 1 - i));
  220. }
  221. // Generate hash key (R || root || idx)
  222. memcpy(hash_key, sm + params->index_len, params->n);
  223. memcpy(hash_key + params->n, pk, params->n);
  224. to_byte(hash_key + 2*params->n, idx, params->n);
  225. // hash message
  226. h_msg(params, msg_h, sm + params->bytes, *mlen, hash_key, 3*params->n);
  227. sm += params->index_len + params->n;
  228. for (i = 0; i < params->d; i++) {
  229. // Prepare Address
  230. idx_leaf = (idx & ((1 << params->tree_height)-1));
  231. idx = idx >> params->tree_height;
  232. set_layer_addr(ots_addr, i);
  233. set_layer_addr(ltree_addr, i);
  234. set_layer_addr(node_addr, i);
  235. set_tree_addr(ltree_addr, idx);
  236. set_tree_addr(ots_addr, idx);
  237. set_tree_addr(node_addr, idx);
  238. set_ots_addr(ots_addr, idx_leaf);
  239. // Check WOTS signature
  240. wots_pk_from_sig(params, wots_pk, sm, root, pub_seed, ots_addr);
  241. sm += params->wots_keysize;
  242. // Compute Ltree
  243. set_ltree_addr(ltree_addr, idx_leaf);
  244. l_tree(params, pkhash, wots_pk, pub_seed, ltree_addr);
  245. // Compute root
  246. validate_authpath(params, root, pkhash, idx_leaf, sm, pub_seed, node_addr);
  247. sm += params->tree_height*params->n;
  248. }
  249. for (i = 0; i < params->n; i++) {
  250. if (root[i] != pk[i]) {
  251. for (i = 0; i < *mlen; i++) {
  252. m[i] = 0;
  253. }
  254. *mlen = -1;
  255. return -1;
  256. }
  257. }
  258. for (i = 0; i < *mlen; i++) {
  259. m[i] = sm[i];
  260. }
  261. return 0;
  262. }