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.

149 lines
3.2 KiB

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