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

176 lines
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 3*n plus
  83. * the length of the padding as free space available before the message,
  84. * to use for the prefix. This is necessary to prevent having to move the
  85. * message around (and thus allocate memory for it).
  86. */
  87. int hash_message(const xmss_params *params, unsigned char *out,
  88. const unsigned char *R, const unsigned char *root,
  89. unsigned long long idx,
  90. unsigned char *m_with_prefix, unsigned long long mlen)
  91. {
  92. /* We're creating a hash using input of the form:
  93. toByte(X, 32) || R || root || index || M */
  94. ull_to_bytes(m_with_prefix, params->padding_len, XMSS_HASH_PADDING_HASH);
  95. memcpy(m_with_prefix + params->padding_len, R, params->n);
  96. memcpy(m_with_prefix + params->padding_len + params->n, root, params->n);
  97. ull_to_bytes(m_with_prefix + params->padding_len + 2*params->n, params->n, idx);
  98. return core_hash(params, out, m_with_prefix, mlen + params->padding_len + 3*params->n);
  99. }
  100. /**
  101. * We assume the left half is in in[0]...in[n-1]
  102. */
  103. int thash_h(const xmss_params *params,
  104. unsigned char *out, const unsigned char *in,
  105. const unsigned char *pub_seed, uint32_t addr[8])
  106. {
  107. unsigned char buf[params->padding_len + 3 * params->n];
  108. unsigned char bitmask[2 * params->n];
  109. unsigned char addr_as_bytes[32];
  110. unsigned int i;
  111. /* Set the function padding. */
  112. ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_H);
  113. /* Generate the n-byte key. */
  114. set_key_and_mask(addr, 0);
  115. addr_to_bytes(addr_as_bytes, addr);
  116. prf(params, buf + params->padding_len, addr_as_bytes, pub_seed);
  117. /* Generate the 2n-byte mask. */
  118. set_key_and_mask(addr, 1);
  119. addr_to_bytes(addr_as_bytes, addr);
  120. prf(params, bitmask, addr_as_bytes, pub_seed);
  121. set_key_and_mask(addr, 2);
  122. addr_to_bytes(addr_as_bytes, addr);
  123. prf(params, bitmask + params->n, addr_as_bytes, pub_seed);
  124. for (i = 0; i < 2 * params->n; i++) {
  125. buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i];
  126. }
  127. return core_hash(params, out, buf, params->padding_len + 3 * params->n);
  128. }
  129. int thash_f(const xmss_params *params,
  130. unsigned char *out, const unsigned char *in,
  131. const unsigned char *pub_seed, uint32_t addr[8])
  132. {
  133. unsigned char buf[params->padding_len + 2 * params->n];
  134. unsigned char bitmask[params->n];
  135. unsigned char addr_as_bytes[32];
  136. unsigned int i;
  137. /* Set the function padding. */
  138. ull_to_bytes(buf, params->padding_len, XMSS_HASH_PADDING_F);
  139. /* Generate the n-byte key. */
  140. set_key_and_mask(addr, 0);
  141. addr_to_bytes(addr_as_bytes, addr);
  142. prf(params, buf + params->padding_len, addr_as_bytes, pub_seed);
  143. /* Generate the n-byte mask. */
  144. set_key_and_mask(addr, 1);
  145. addr_to_bytes(addr_as_bytes, addr);
  146. prf(params, bitmask, addr_as_bytes, pub_seed);
  147. for (i = 0; i < params->n; i++) {
  148. buf[params->padding_len + params->n + i] = in[i] ^ bitmask[i];
  149. }
  150. return core_hash(params, out, buf, params->padding_len + 2 * params->n);
  151. }