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.

153 lines
4.4 KiB

  1. #include <stdint.h>
  2. #include "xmss_commons.h"
  3. #include "hash.h"
  4. #include "wots.h"
  5. #include "hash_address.h"
  6. #include "params.h"
  7. /**
  8. * Helper method for pseudorandom key generation.
  9. * Expands an n-byte array into a len*n byte array using the `prf` function.
  10. */
  11. static void expand_seed(const xmss_params *params,
  12. unsigned char *outseeds, const unsigned char *inseed)
  13. {
  14. uint32_t i;
  15. unsigned char ctr[32];
  16. for (i = 0; i < params->wots_len; i++) {
  17. ull_to_bytes(ctr, i, 32);
  18. prf(params, outseeds + i*params->n, ctr, inseed, params->n);
  19. }
  20. }
  21. /**
  22. * Computes the chaining function.
  23. * out and in have to be n-byte arrays.
  24. *
  25. * Interprets in as start-th value of the chain.
  26. * addr has to contain the address of the chain.
  27. */
  28. static void gen_chain(const xmss_params *params,
  29. unsigned char *out, const unsigned char *in,
  30. unsigned int start, unsigned int steps,
  31. const unsigned char *pub_seed, uint32_t addr[8])
  32. {
  33. uint32_t i;
  34. for (i = 0; i < params->n; i++) {
  35. out[i] = in[i];
  36. }
  37. for (i = start; i < (start+steps) && i < params->wots_w; i++) {
  38. set_hash_addr(addr, i);
  39. hash_f(params, out, out, pub_seed, addr);
  40. }
  41. }
  42. /**
  43. * base_w algorithm as described in draft.
  44. * Interprets an array of bytes as integers in base w.
  45. */
  46. static void base_w(const xmss_params *params,
  47. int *output, const int out_len, const unsigned char *input)
  48. {
  49. int in = 0;
  50. int out = 0;
  51. uint8_t total = 0;
  52. int bits = 0;
  53. int i;
  54. for (i = 0; i < out_len; i++) {
  55. if (bits == 0) {
  56. total = input[in];
  57. in++;
  58. bits += 8;
  59. }
  60. bits -= params->wots_log_w;
  61. output[out] = (total >> bits) & (params->wots_w - 1);
  62. out++;
  63. }
  64. }
  65. void wots_pkgen(const xmss_params *params,
  66. unsigned char *pk, const unsigned char *sk,
  67. const unsigned char *pub_seed, uint32_t addr[8])
  68. {
  69. uint32_t i;
  70. expand_seed(params, pk, sk);
  71. for (i = 0; i < params->wots_len; i++) {
  72. set_chain_addr(addr, i);
  73. gen_chain(params, pk + i*params->n, pk + i*params->n,
  74. 0, params->wots_w-1, pub_seed, addr);
  75. }
  76. }
  77. void wots_sign(const xmss_params *params,
  78. unsigned char *sig, const unsigned char *msg,
  79. const unsigned char *sk, const unsigned char *pub_seed,
  80. uint32_t addr[8])
  81. {
  82. int basew[params->wots_len];
  83. int csum = 0;
  84. unsigned char csum_bytes[((params->wots_len2 * params->wots_log_w) + 7) / 8];
  85. int csum_basew[params->wots_len2];
  86. uint32_t i;
  87. base_w(params, basew, params->wots_len1, msg);
  88. for (i = 0; i < params->wots_len1; i++) {
  89. csum += params->wots_w - 1 - basew[i];
  90. }
  91. csum = csum << (8 - ((params->wots_len2 * params->wots_log_w) % 8));
  92. ull_to_bytes(csum_bytes, csum, ((params->wots_len2 * params->wots_log_w) + 7) / 8);
  93. base_w(params, csum_basew, params->wots_len2, csum_bytes);
  94. for (i = 0; i < params->wots_len2; i++) {
  95. basew[params->wots_len1 + i] = csum_basew[i];
  96. }
  97. expand_seed(params, sig, sk);
  98. for (i = 0; i < params->wots_len; i++) {
  99. set_chain_addr(addr, i);
  100. gen_chain(params, sig + i*params->n, sig + i*params->n,
  101. 0, basew[i], pub_seed, addr);
  102. }
  103. }
  104. void wots_pk_from_sig(const xmss_params *params, unsigned char *pk,
  105. const unsigned char *sig, const unsigned char *msg,
  106. const unsigned char *pub_seed, uint32_t addr[8])
  107. {
  108. int basew[params->wots_len];
  109. int csum = 0;
  110. unsigned char csum_bytes[((params->wots_len2 * params->wots_log_w) + 7) / 8];
  111. int csum_basew[params->wots_len2];
  112. uint32_t i = 0;
  113. base_w(params, basew, params->wots_len1, msg);
  114. for (i=0; i < params->wots_len1; i++) {
  115. csum += params->wots_w - 1 - basew[i];
  116. }
  117. csum = csum << (8 - ((params->wots_len2 * params->wots_log_w) % 8));
  118. ull_to_bytes(csum_bytes, csum, ((params->wots_len2 * params->wots_log_w) + 7) / 8);
  119. base_w(params, csum_basew, params->wots_len2, csum_bytes);
  120. for (i = 0; i < params->wots_len2; i++) {
  121. basew[params->wots_len1 + i] = csum_basew[i];
  122. }
  123. for (i=0; i < params->wots_len; i++) {
  124. set_chain_addr(addr, i);
  125. gen_chain(params, pk + i*params->n, sig + i*params->n,
  126. basew[i], params->wots_w-1-basew[i], pub_seed, addr);
  127. }
  128. }