Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

175 wiersze
5.7 KiB

  1. #include <stdint.h>
  2. #include <string.h>
  3. #include <openssl/sha.h>
  4. #include "hash_address.h"
  5. #include "utils.h"
  6. #include "params.h"
  7. #include "hash.h"
  8. #include "fips202.h"
  9. #define XMSS_HASH_PADDING_F 0
  10. #define XMSS_HASH_PADDING_H 1
  11. #define XMSS_HASH_PADDING_HASH 2
  12. #define XMSS_HASH_PADDING_PRF 3
  13. #define XMSS_HASH_PADDING_PRF_KEYGEN 4
  14. void addr_to_bytes(unsigned char *bytes, const uint32_t addr[8])
  15. {
  16. int i;
  17. for (i = 0; i < 8; i++) {
  18. ull_to_bytes(bytes + i*4, 4, addr[i]);
  19. }
  20. }
  21. static int core_hash(const xmss_params *params,
  22. unsigned char *out,
  23. const unsigned char *in, unsigned long long inlen)
  24. {
  25. unsigned char buf[64];
  26. if (params->n == 24 && params->func == XMSS_SHA2) {
  27. SHA256(in, inlen, buf);
  28. memcpy(out, buf, 24);
  29. }
  30. else if (params->n == 24 && params->func == XMSS_SHAKE256) {
  31. shake256(out, 24, in, inlen);
  32. }
  33. else if (params->n == 32 && params->func == XMSS_SHA2) {
  34. SHA256(in, inlen, out);
  35. }
  36. else if (params->n == 32 && params->func == XMSS_SHAKE128) {
  37. shake128(out, 32, in, inlen);
  38. }
  39. else if (params->n == 32 && params->func == XMSS_SHAKE256) {
  40. shake256(out, 32, in, inlen);
  41. }
  42. else if (params->n == 64 && params->func == XMSS_SHA2) {
  43. SHA512(in, inlen, out);
  44. }
  45. else if (params->n == 64 && params->func == XMSS_SHAKE256) {
  46. shake256(out, 64, in, inlen);
  47. }
  48. else {
  49. return -1;
  50. }
  51. return 0;
  52. }
  53. /*
  54. * Computes PRF(key, in), for a key of params->n bytes, and a 32-byte input.
  55. */
  56. int prf(const xmss_params *params,
  57. unsigned char *out, const unsigned char in[32],
  58. const unsigned char *key)
  59. {
  60. unsigned char buf[params->padding_len + params->n + 32];
  61. ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF);
  62. memcpy(buf + params->padding_len, key, params->n);
  63. memcpy(buf + params->padding_len + params->n, in, 32);
  64. return core_hash(params, out, buf, params->padding_len + params->n + 32);
  65. }
  66. /*
  67. * Computes PRF_keygen(key, in), for a key of params->n bytes, and an input
  68. * of 32 + params->n bytes
  69. */
  70. int prf_keygen(const xmss_params *params,
  71. unsigned char *out, const unsigned char *in,
  72. const unsigned char *key)
  73. {
  74. unsigned char buf[params->padding_len + 2*params->n + 32];
  75. ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_PRF_KEYGEN);
  76. memcpy(buf + params->padding_len, key, params->n);
  77. memcpy(buf + params->padding_len + params->n, in, params->n + 32);
  78. return core_hash(params, out, buf, params->padding_len + 2*params->n + 32);
  79. }
  80. /*
  81. * Computes the message hash using R, the public root, the index of the leaf
  82. * node, and the message. Notably, it requires m_with_prefix to have 4*n bytes
  83. * of space before the message, to use for the prefix. This is necessary to
  84. * prevent having to move the message around (and thus allocate memory for it).
  85. */
  86. int hash_message(const xmss_params *params, unsigned char *out,
  87. const unsigned char *R, const unsigned char *root,
  88. unsigned long long idx,
  89. unsigned char *m_with_prefix, unsigned long long mlen)
  90. {
  91. /* We're creating a hash using input of the form:
  92. toByte(X, 32) || R || root || index || M */
  93. ull_to_bytes(m_with_prefix, params->padding_len, XMSS_HASH_PADDING_HASH);
  94. memcpy(m_with_prefix + params->padding_len, R, params->n);
  95. memcpy(m_with_prefix + params->padding_len + params->n, root, params->n);
  96. ull_to_bytes(m_with_prefix + params->padding_len + 2*params->n, params->n, idx);
  97. return core_hash(params, out, m_with_prefix, mlen + params->padding_len + 3*params->n);
  98. }
  99. /**
  100. * We assume the left half is in in[0]...in[n-1]
  101. */
  102. int thash_h(const xmss_params *params,
  103. unsigned char *out, const unsigned char *in,
  104. const unsigned char *pub_seed, uint32_t addr[8])
  105. {
  106. unsigned char buf[params->padding_len + 3 * params->n];
  107. unsigned char bitmask[2 * params->n];
  108. unsigned char addr_as_bytes[32];
  109. unsigned int i;
  110. /* Set the function padding. */
  111. ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_H);
  112. /* Generate the n-byte key. */
  113. set_key_and_mask(addr, 0);
  114. addr_to_bytes(addr_as_bytes, addr);
  115. prf(params, buf + params->padding_len, addr_as_bytes, pub_seed);
  116. /* Generate the 2n-byte mask. */
  117. set_key_and_mask(addr, 1);
  118. addr_to_bytes(addr_as_bytes, addr);
  119. prf(params, bitmask, addr_as_bytes, pub_seed);
  120. set_key_and_mask(addr, 2);
  121. addr_to_bytes(addr_as_bytes, addr);
  122. prf(params, bitmask + params->n, addr_as_bytes, pub_seed);
  123. for (i = 0; i < 2 * params->n; i++) {
  124. buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i];
  125. }
  126. return core_hash(params, out, buf, params->padding_len + 3 * params->n);
  127. }
  128. int thash_f(const xmss_params *params,
  129. unsigned char *out, const unsigned char *in,
  130. const unsigned char *pub_seed, uint32_t addr[8])
  131. {
  132. unsigned char buf[params->padding_len + 2 * params->n];
  133. unsigned char bitmask[params->n];
  134. unsigned char addr_as_bytes[32];
  135. unsigned int i;
  136. /* Set the function padding. */
  137. ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_F);
  138. /* Generate the n-byte key. */
  139. set_key_and_mask(addr, 0);
  140. addr_to_bytes(addr_as_bytes, addr);
  141. prf(params, buf + params->padding_len, addr_as_bytes, pub_seed);
  142. /* Generate the n-byte mask. */
  143. set_key_and_mask(addr, 1);
  144. addr_to_bytes(addr_as_bytes, addr);
  145. prf(params, bitmask, addr_as_bytes, pub_seed);
  146. for (i = 0; i < params->n; i++) {
  147. buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i];
  148. }
  149. return core_hash(params, out, buf, params->padding_len + 2 * params->n);
  150. }