You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

xmss_core.c 13 KiB

9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
8 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
9 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. #include <stdlib.h>
  2. #include <string.h>
  3. #include <stdint.h>
  4. #include "hash.h"
  5. #include "hash_address.h"
  6. #include "params.h"
  7. #include "randombytes.h"
  8. #include "wots.h"
  9. #include "xmss_commons.h"
  10. #include "xmss_core.h"
  11. /**
  12. * Merkle's TreeHash algorithm. The address only needs to initialize the first 78 bits of addr. Everything else will be set by treehash.
  13. * Currently only used for key generation.
  14. *
  15. */
  16. static void treehash(const xmss_params *params, unsigned char *node, uint32_t index, const unsigned char *sk_seed, const unsigned char *pub_seed, const uint32_t addr[8])
  17. {
  18. uint32_t idx = index;
  19. // use three different addresses because at this point we use all three formats in parallel
  20. uint32_t ots_addr[8];
  21. uint32_t ltree_addr[8];
  22. uint32_t node_addr[8];
  23. // only copy layer and tree address parts
  24. memcpy(ots_addr, addr, 12);
  25. // type = ots
  26. set_type(ots_addr, 0);
  27. memcpy(ltree_addr, addr, 12);
  28. set_type(ltree_addr, 1);
  29. memcpy(node_addr, addr, 12);
  30. set_type(node_addr, 2);
  31. uint32_t lastnode, i;
  32. unsigned char stack[(params->tree_height+1)*params->n];
  33. uint16_t stacklevels[params->tree_height+1];
  34. unsigned int stackoffset=0;
  35. lastnode = idx+(1 << params->tree_height);
  36. for (; idx < lastnode; idx++) {
  37. set_ltree_addr(ltree_addr, idx);
  38. set_ots_addr(ots_addr, idx);
  39. gen_leaf_wots(params, stack+stackoffset*params->n, sk_seed, pub_seed, ltree_addr, ots_addr);
  40. stacklevels[stackoffset] = 0;
  41. stackoffset++;
  42. while (stackoffset>1 && stacklevels[stackoffset-1] == stacklevels[stackoffset-2]) {
  43. set_tree_height(node_addr, stacklevels[stackoffset-1]);
  44. set_tree_index(node_addr, (idx >> (stacklevels[stackoffset-1]+1)));
  45. hash_h(params, stack+(stackoffset-2)*params->n, stack+(stackoffset-2)*params->n, pub_seed, node_addr);
  46. stacklevels[stackoffset-2]++;
  47. stackoffset--;
  48. }
  49. }
  50. for (i = 0; i < params->n; i++) {
  51. node[i] = stack[i];
  52. }
  53. }
  54. /**
  55. * Computes the authpath and the root. This method is using a lot of space as we build the whole tree and then select the authpath nodes.
  56. * For more efficient algorithms see e.g. the chapter on hash-based signatures in Bernstein, Buchmann, Dahmen. "Post-quantum Cryptography", Springer 2009.
  57. * It returns the authpath in "authpath" with the node on level 0 at index 0.
  58. */
  59. static void compute_authpath_wots(const xmss_params *params, unsigned char *root, unsigned char *authpath, unsigned long leaf_idx, const unsigned char *sk_seed, unsigned char *pub_seed, uint32_t addr[8])
  60. {
  61. uint32_t i, j, level;
  62. unsigned char tree[2*(1 << params->tree_height)*params->n];
  63. uint32_t ots_addr[8];
  64. uint32_t ltree_addr[8];
  65. uint32_t node_addr[8];
  66. memcpy(ots_addr, addr, 12);
  67. set_type(ots_addr, 0);
  68. memcpy(ltree_addr, addr, 12);
  69. set_type(ltree_addr, 1);
  70. memcpy(node_addr, addr, 12);
  71. set_type(node_addr, 2);
  72. // Compute all leaves
  73. for (i = 0; i < (1U << params->tree_height); i++) {
  74. set_ltree_addr(ltree_addr, i);
  75. set_ots_addr(ots_addr, i);
  76. gen_leaf_wots(params, tree+((1 << params->tree_height)*params->n + i*params->n), sk_seed, pub_seed, ltree_addr, ots_addr);
  77. }
  78. level = 0;
  79. // Compute tree:
  80. // Outer loop: For each inner layer
  81. for (i = (1 << params->tree_height); i > 1; i>>=1) {
  82. set_tree_height(node_addr, level);
  83. // Inner loop: for each pair of sibling nodes
  84. for (j = 0; j < i; j+=2) {
  85. set_tree_index(node_addr, j>>1);
  86. hash_h(params, tree + (i>>1)*params->n + (j>>1) * params->n, tree + i*params->n + j*params->n, pub_seed, node_addr);
  87. }
  88. level++;
  89. }
  90. // copy authpath
  91. for (i = 0; i < params->tree_height; i++) {
  92. memcpy(authpath + i*params->n, tree + ((1 << params->tree_height)>>i)*params->n + ((leaf_idx >> i) ^ 1) * params->n, params->n);
  93. }
  94. // copy root
  95. memcpy(root, tree+params->n, params->n);
  96. }
  97. /*
  98. * Generates a XMSS key pair for a given parameter set.
  99. * Format sk: [(32bit) idx || SK_SEED || SK_PRF || PUB_SEED || root]
  100. * Format pk: [root || PUB_SEED] omitting algo oid.
  101. */
  102. int xmss_core_keypair(const xmss_params *params, unsigned char *pk, unsigned char *sk)
  103. {
  104. // Set idx = 0
  105. sk[0] = 0;
  106. sk[1] = 0;
  107. sk[2] = 0;
  108. sk[3] = 0;
  109. // Init SK_SEED (params->n byte), SK_PRF (params->n byte), and PUB_SEED (params->n byte)
  110. randombytes(sk+4, 3*params->n);
  111. // Copy PUB_SEED to public key
  112. memcpy(pk+params->n, sk+4+2*params->n, params->n);
  113. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  114. // Compute root
  115. treehash(params, pk, 0, sk+4, sk+4+2*params->n, addr);
  116. // copy root to sk
  117. memcpy(sk+4+3*params->n, pk, params->n);
  118. return 0;
  119. }
  120. /**
  121. * Signs a message.
  122. * Returns
  123. * 1. an array containing the signature followed by the message AND
  124. * 2. an updated secret key!
  125. *
  126. */
  127. int xmss_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen)
  128. {
  129. uint16_t i = 0;
  130. // Extract SK
  131. uint32_t idx = ((unsigned long)sk[0] << 24) | ((unsigned long)sk[1] << 16) | ((unsigned long)sk[2] << 8) | sk[3];
  132. unsigned char sk_seed[params->n];
  133. unsigned char sk_prf[params->n];
  134. unsigned char pub_seed[params->n];
  135. unsigned char hash_key[3*params->n];
  136. // index as 32 bytes string
  137. unsigned char idx_bytes_32[32];
  138. to_byte(idx_bytes_32, idx, 32);
  139. memcpy(sk_seed, sk+4, params->n);
  140. memcpy(sk_prf, sk+4+params->n, params->n);
  141. memcpy(pub_seed, sk+4+2*params->n, params->n);
  142. // Update SK
  143. sk[0] = ((idx + 1) >> 24) & 255;
  144. sk[1] = ((idx + 1) >> 16) & 255;
  145. sk[2] = ((idx + 1) >> 8) & 255;
  146. sk[3] = (idx + 1) & 255;
  147. // -- Secret key for this non-forward-secure version is now updated.
  148. // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
  149. // Init working params
  150. unsigned char R[params->n];
  151. unsigned char msg_h[params->n];
  152. unsigned char root[params->n];
  153. unsigned char ots_seed[params->n];
  154. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  155. // ---------------------------------
  156. // Message Hashing
  157. // ---------------------------------
  158. // Message Hash:
  159. // First compute pseudorandom value
  160. prf(params, R, idx_bytes_32, sk_prf, params->n);
  161. // Generate hash key (R || root || idx)
  162. memcpy(hash_key, R, params->n);
  163. memcpy(hash_key+params->n, sk+4+3*params->n, params->n);
  164. to_byte(hash_key+2*params->n, idx, params->n);
  165. // Then use it for message digest
  166. h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
  167. // Start collecting signature
  168. *smlen = 0;
  169. // Copy index to signature
  170. sm[0] = (idx >> 24) & 255;
  171. sm[1] = (idx >> 16) & 255;
  172. sm[2] = (idx >> 8) & 255;
  173. sm[3] = idx & 255;
  174. sm += 4;
  175. *smlen += 4;
  176. // Copy R to signature
  177. for (i = 0; i < params->n; i++)
  178. sm[i] = R[i];
  179. sm += params->n;
  180. *smlen += params->n;
  181. // ----------------------------------
  182. // Now we start to "really sign"
  183. // ----------------------------------
  184. // Prepare Address
  185. set_type(ots_addr, 0);
  186. set_ots_addr(ots_addr, idx);
  187. // Compute seed for OTS key pair
  188. get_seed(params, ots_seed, sk_seed, ots_addr);
  189. // Compute WOTS signature
  190. wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr);
  191. sm += params->wots_keysize;
  192. *smlen += params->wots_keysize;
  193. compute_authpath_wots(params, root, sm, idx, sk_seed, pub_seed, ots_addr);
  194. sm += params->tree_height*params->n;
  195. *smlen += params->tree_height*params->n;
  196. memcpy(sm, m, mlen);
  197. *smlen += mlen;
  198. return 0;
  199. }
  200. /*
  201. * Generates a XMSSMT key pair for a given parameter set.
  202. * Format sk: [(ceil(h/8) bit) idx || SK_SEED || SK_PRF || PUB_SEED]
  203. * Format pk: [root || PUB_SEED] omitting algo oid.
  204. */
  205. int xmssmt_core_keypair(const xmss_params *params, unsigned char *pk, unsigned char *sk)
  206. {
  207. uint16_t i;
  208. // Set idx = 0
  209. for (i = 0; i < params->index_len; i++) {
  210. sk[i] = 0;
  211. }
  212. // Init SK_SEED (params->n byte), SK_PRF (params->n byte), and PUB_SEED (params->n byte)
  213. randombytes(sk+params->index_len, 3*params->n);
  214. // Copy PUB_SEED to public key
  215. memcpy(pk+params->n, sk+params->index_len+2*params->n, params->n);
  216. // Set address to point on the single tree on layer d-1
  217. uint32_t addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  218. set_layer_addr(addr, (params->d-1));
  219. // Compute root
  220. treehash(params, pk, 0, sk+params->index_len, pk+params->n, addr);
  221. memcpy(sk+params->index_len+3*params->n, pk, params->n);
  222. return 0;
  223. }
  224. /**
  225. * Signs a message.
  226. * Returns
  227. * 1. an array containing the signature followed by the message AND
  228. * 2. an updated secret key!
  229. *
  230. */
  231. int xmssmt_core_sign(const xmss_params *params, unsigned char *sk, unsigned char *sm, unsigned long long *smlen, const unsigned char *m, unsigned long long mlen)
  232. {
  233. uint64_t idx_tree;
  234. uint32_t idx_leaf;
  235. uint64_t i;
  236. unsigned char sk_seed[params->n];
  237. unsigned char sk_prf[params->n];
  238. unsigned char pub_seed[params->n];
  239. // Init working params
  240. unsigned char R[params->n];
  241. unsigned char hash_key[3*params->n];
  242. unsigned char msg_h[params->n];
  243. unsigned char root[params->n];
  244. unsigned char ots_seed[params->n];
  245. uint32_t ots_addr[8] = {0, 0, 0, 0, 0, 0, 0, 0};
  246. unsigned char idx_bytes_32[32];
  247. // Extract SK
  248. unsigned long long idx = 0;
  249. for (i = 0; i < params->index_len; i++) {
  250. idx |= ((unsigned long long)sk[i]) << 8*(params->index_len - 1 - i);
  251. }
  252. memcpy(sk_seed, sk+params->index_len, params->n);
  253. memcpy(sk_prf, sk+params->index_len+params->n, params->n);
  254. memcpy(pub_seed, sk+params->index_len+2*params->n, params->n);
  255. // Update SK
  256. for (i = 0; i < params->index_len; i++) {
  257. sk[i] = ((idx + 1) >> 8*(params->index_len - 1 - i)) & 255;
  258. }
  259. // -- Secret key for this non-forward-secure version is now updated.
  260. // -- A productive implementation should use a file handle instead and write the updated secret key at this point!
  261. // ---------------------------------
  262. // Message Hashing
  263. // ---------------------------------
  264. // Message Hash:
  265. // First compute pseudorandom value
  266. to_byte(idx_bytes_32, idx, 32);
  267. prf(params, R, idx_bytes_32, sk_prf, params->n);
  268. // Generate hash key (R || root || idx)
  269. memcpy(hash_key, R, params->n);
  270. memcpy(hash_key+params->n, sk+params->index_len+3*params->n, params->n);
  271. to_byte(hash_key+2*params->n, idx, params->n);
  272. // Then use it for message digest
  273. h_msg(params, msg_h, m, mlen, hash_key, 3*params->n);
  274. // Start collecting signature
  275. *smlen = 0;
  276. // Copy index to signature
  277. for (i = 0; i < params->index_len; i++) {
  278. sm[i] = (idx >> 8*(params->index_len - 1 - i)) & 255;
  279. }
  280. sm += params->index_len;
  281. *smlen += params->index_len;
  282. // Copy R to signature
  283. for (i = 0; i < params->n; i++) {
  284. sm[i] = R[i];
  285. }
  286. sm += params->n;
  287. *smlen += params->n;
  288. // ----------------------------------
  289. // Now we start to "really sign"
  290. // ----------------------------------
  291. // Handle lowest layer separately as it is slightly different...
  292. // Prepare Address
  293. set_type(ots_addr, 0);
  294. idx_tree = idx >> params->tree_height;
  295. idx_leaf = (idx & ((1 << params->tree_height)-1));
  296. set_layer_addr(ots_addr, 0);
  297. set_tree_addr(ots_addr, idx_tree);
  298. set_ots_addr(ots_addr, idx_leaf);
  299. // Compute seed for OTS key pair
  300. get_seed(params, ots_seed, sk_seed, ots_addr);
  301. // Compute WOTS signature
  302. wots_sign(params, sm, msg_h, ots_seed, pub_seed, ots_addr);
  303. sm += params->wots_keysize;
  304. *smlen += params->wots_keysize;
  305. compute_authpath_wots(params, root, sm, idx_leaf, sk_seed, pub_seed, ots_addr);
  306. sm += params->tree_height*params->n;
  307. *smlen += params->tree_height*params->n;
  308. // Now loop over remaining layers...
  309. unsigned int j;
  310. for (j = 1; j < params->d; j++) {
  311. // Prepare Address
  312. idx_leaf = (idx_tree & ((1 << params->tree_height)-1));
  313. idx_tree = idx_tree >> params->tree_height;
  314. set_layer_addr(ots_addr, j);
  315. set_tree_addr(ots_addr, idx_tree);
  316. set_ots_addr(ots_addr, idx_leaf);
  317. // Compute seed for OTS key pair
  318. get_seed(params, ots_seed, sk_seed, ots_addr);
  319. // Compute WOTS signature
  320. wots_sign(params, sm, root, ots_seed, pub_seed, ots_addr);
  321. sm += params->wots_keysize;
  322. *smlen += params->wots_keysize;
  323. compute_authpath_wots(params, root, sm, idx_leaf, sk_seed, pub_seed, ots_addr);
  324. sm += params->tree_height*params->n;
  325. *smlen += params->tree_height*params->n;
  326. }
  327. memcpy(sm, m, mlen);
  328. *smlen += mlen;
  329. return 0;
  330. }