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

404 lines
13 KiB

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