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.

407 regels
13 KiB

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