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.

160 regels
4.4 KiB

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