rserv.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4. #include <string.h>
  5. #include <openssl/sha.h>
  6. #include "ptwist.h"
  7. /* Check the given tag with the given context and private key. Return 0
  8. if the tag is properly formed, non-0 if not. If the tag is correct,
  9. set key to the resulting secret key. */
  10. static int check_tag(byte key[16], const byte privkey[PTWIST_BYTES],
  11. const byte tag[PTWIST_TAG_BYTES], const byte *context,
  12. size_t context_len)
  13. {
  14. int ret = -1;
  15. byte sharedsec[PTWIST_BYTES+context_len];
  16. byte taghashout[32];
  17. #if PTWIST_PUZZLE_STRENGTH > 0
  18. byte hashout[32];
  19. size_t puzzle_len = 16+PTWIST_RESP_BYTES;
  20. byte value_to_hash[puzzle_len];
  21. unsigned int firstbits;
  22. int firstpass = 0;
  23. #endif
  24. /* Compute the shared secret privkey*TAG */
  25. ptwist_pointmul(sharedsec, tag, privkey);
  26. /* Create the hash tag keys */
  27. memmove(sharedsec+PTWIST_BYTES, context, context_len);
  28. SHA256(sharedsec, PTWIST_BYTES, taghashout);
  29. #if PTWIST_PUZZLE_STRENGTH > 0
  30. /* Construct the proposed solution to the puzzle */
  31. memmove(value_to_hash, taghashout, 16);
  32. memmove(value_to_hash+16, tag+PTWIST_BYTES, PTWIST_RESP_BYTES);
  33. value_to_hash[16+PTWIST_RESP_BYTES-1] &= PTWIST_RESP_MASK;
  34. /* Hash the proposed solution and see if it is correct; that is, the
  35. * hash should start with PTWIST_PUZZLE_STRENGTH bits of 0s,
  36. * followed by the last PTWIST_HASH_SHOWBITS of the tag. */
  37. md_map_sh256(hashout, value_to_hash, puzzle_len);
  38. #if PTWIST_PUZZLE_STRENGTH < 32
  39. /* This assumes that you're on an architecture that doesn't care
  40. * about alignment, and is little endian. */
  41. firstbits = *(unsigned int*)hashout;
  42. if ((firstbits & PTWIST_PUZZLE_MASK) == 0) {
  43. firstpass = 1;
  44. }
  45. #else
  46. #error "Code assumes PTWIST_PUZZLE_STRENGTH < 32"
  47. #endif
  48. if (firstpass) {
  49. bn_t Hbn, Tbn;
  50. bn_new(Hbn);
  51. bn_new(Tbn);
  52. hashout[PTWIST_HASH_TOTBYTES-1] &= PTWIST_HASH_MASK;
  53. bn_read_bin(Hbn, hashout, PTWIST_HASH_TOTBYTES, BN_POS);
  54. bn_rsh(Hbn, Hbn, PTWIST_PUZZLE_STRENGTH);
  55. bn_read_bin(Tbn, tag+PTWIST_BYTES, PTWIST_TAG_BYTES-PTWIST_BYTES,
  56. BN_POS);
  57. bn_rsh(Tbn, Tbn, PTWIST_RESP_BITS);
  58. ret = (bn_cmp(Tbn,Hbn) != CMP_EQ);
  59. bn_free(Hbn);
  60. bn_free(Tbn);
  61. }
  62. #else
  63. /* We're not using a client puzzle, so just check that the first
  64. * PTWIST_HASH_SHOWBITS bits of the above hash fill out the rest
  65. * of the tag. If there's no puzzle, PTWIST_HASH_SHOWBITS must be
  66. * a multiple of 8. */
  67. ret = (memcmp(tag+PTWIST_BYTES, taghashout, PTWIST_HASH_SHOWBITS/8) != 0);
  68. #endif
  69. if (ret == 0) {
  70. memmove(key, taghashout+16, 16);
  71. }
  72. return ret;
  73. }
  74. int main(int argc, char **argv)
  75. {
  76. FILE *fp;
  77. int res;
  78. byte privkey[PTWIST_BYTES];
  79. byte tag[PTWIST_TAG_BYTES];
  80. int tottagged = 0;
  81. int totuntagged = 0;
  82. const char *tagsfile = argc > 1 ? argv[1] : "tags";
  83. /* Load the private key */
  84. fp = fopen("privkey", "rb");
  85. if (fp == NULL) {
  86. perror("fopen");
  87. exit(1);
  88. }
  89. res = fread(privkey, PTWIST_BYTES, 1, fp);
  90. if (res < 1) {
  91. perror("fread");
  92. exit(1);
  93. }
  94. fclose(fp);
  95. /* Validate the tags in the tags file */
  96. fp = fopen(tagsfile, "rb");
  97. if (fp == NULL) {
  98. perror("fopen");
  99. exit(1);
  100. }
  101. while (fread(tag, PTWIST_TAG_BYTES, 1, fp) == 1) {
  102. byte key[16];
  103. int res = check_tag(key, privkey, tag, (const byte *)"context", 7);
  104. tottagged += (!res);
  105. totuntagged += (!(!res));
  106. #if 0
  107. if (res) {
  108. printf("Untagged\n");
  109. } else {
  110. int j;
  111. for(j=0;j<16;++j) {
  112. printf("%02x", key[j]);
  113. }
  114. printf("\n");
  115. }
  116. #endif
  117. }
  118. fclose(fp);
  119. printf("%d tagged, %d untagged\n", tottagged, totuntagged);
  120. return 0;
  121. }