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.

155 lines
3.5 KiB

  1. /*
  2. hash.c version 20151120
  3. Andreas Hülsing
  4. Public domain.
  5. */
  6. #include "prg.h"
  7. #include <stddef.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <openssl/sha.h>
  11. #include <openssl/hmac.h>
  12. #include <openssl/evp.h>
  13. #define SET_KEY_BIT(a, b) (a[15] = (a[15] & 253) | ((b << 1) & 2))
  14. #define SET_BLOCK_BIT(a, b) (a[15] = (a[15] & 254) | (b & 1))
  15. #define WOTS_SELECT_KEY(a) (a[15] = (a[15] & 254) | 1)
  16. #define WOTS_SELECT_BLOCK(a) (a[15] = (a[15] & 254) | 0)
  17. /**
  18. * Implements PRF_m
  19. */
  20. int prf_m(unsigned char *out, const unsigned char *in, size_t inlen, const unsigned char *key, unsigned int keylen)
  21. {
  22. unsigned int length;
  23. if (keylen == 32) {
  24. HMAC(EVP_sha256(), key, keylen, in, inlen, out, &length);
  25. if (length != 32) {
  26. fprintf(stderr, "HMAC outputs %d bytes... That should not happen...", length);
  27. }
  28. return 0;
  29. }
  30. else {
  31. if (keylen == 64) {
  32. HMAC(EVP_sha512(), key, keylen, in, inlen, out, &length);
  33. if (length != 64) {
  34. fprintf(stderr, "HMAC outputs %d bytes... That should not happen...", length);
  35. }
  36. return 0;
  37. }
  38. }
  39. return 1;
  40. }
  41. /*
  42. * Implemts H_m
  43. */
  44. int hash_m(unsigned char *out, const unsigned char *in, unsigned long long inlen, const unsigned char *key, const unsigned int keylen, const unsigned int m)
  45. {
  46. unsigned int i;
  47. unsigned char buf[inlen + keylen + m];
  48. if (keylen != m){
  49. fprintf(stderr, "H_m takes m-bit keys, we got m=%d but a keylength of %d.\n", m, keylen);
  50. return 1;
  51. }
  52. for (i=0; i < m; i++) {
  53. buf[i] = 0x00;
  54. }
  55. for (i=0; i < keylen; i++) {
  56. buf[m + i] = key[i];
  57. }
  58. for (i=0; i < inlen; i++) {
  59. buf[m + keylen + i] = in[i];
  60. }
  61. if (m == 32) {
  62. SHA256(buf, inlen + keylen + m, out);
  63. return 0;
  64. }
  65. else {
  66. if (m == 64) {
  67. SHA512(buf, inlen + keylen + m, out);
  68. return 0;
  69. }
  70. }
  71. return 1;
  72. }
  73. /**
  74. * We assume the left half is in in[0]...in[n-1]
  75. */
  76. int hash_2n_n(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, unsigned char addr[16], const unsigned int n)
  77. {
  78. unsigned char buf[4*n];
  79. unsigned char key[n];
  80. unsigned char bitmask[2*n];
  81. unsigned int i;
  82. SET_KEY_BIT(addr, 1);
  83. SET_BLOCK_BIT(addr, 0);
  84. prg_with_counter(key, pub_seed, n, addr);
  85. SET_KEY_BIT(addr, 0);
  86. // Use MSB order
  87. prg_with_counter(bitmask, pub_seed, n, addr);
  88. SET_BLOCK_BIT(addr, 1);
  89. prg_with_counter(bitmask+n, pub_seed, n, addr);
  90. for (i = 0; i < n; i++) {
  91. buf[i] = 0x00;
  92. buf[n+i] = key[i];
  93. buf[2*n+i] = in[i] ^ bitmask[i];
  94. buf[3*n+i] = in[n+i] ^ bitmask[n+i];
  95. }
  96. if (n == 32) {
  97. SHA256(buf, 4*n, out);
  98. return 0;
  99. }
  100. else {
  101. if (n == 64) {
  102. SHA512(buf, 4*n, out);
  103. return 0;
  104. }
  105. else {
  106. fprintf(stderr, "Hash.c:hash_2n_n: Code only supports n=32 or n=64");
  107. return -1;
  108. }
  109. }
  110. }
  111. int hash_n_n(unsigned char *out, const unsigned char *in, const unsigned char *pub_seed, unsigned char addr[16], const unsigned int n)
  112. {
  113. unsigned char buf[3*n];
  114. unsigned char key[n];
  115. unsigned char bitmask[n];
  116. unsigned int i;
  117. WOTS_SELECT_KEY(addr);
  118. prg_with_counter(key, pub_seed, n, addr);
  119. WOTS_SELECT_BLOCK(addr);
  120. prg_with_counter(bitmask, pub_seed, n, addr);
  121. for (i = 0; i < n; i++) {
  122. buf[i] = 0x00;
  123. buf[n+i] = key[i];
  124. buf[2*n+i] = in[i] ^ bitmask[i];
  125. }
  126. if (n == 32) {
  127. SHA256(buf, 3*n, out);
  128. return 0;
  129. }
  130. else {
  131. if (n == 64) {
  132. SHA512(buf, 3*n, out);
  133. return 0;
  134. }
  135. else {
  136. fprintf(stderr, "Hash.c:hash_n_n: Code only supports n=32 or n=64");
  137. return -1;
  138. }
  139. }
  140. }