rserv.c 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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. #include "rserv.h"
  8. /* Check the given tag with the given context and private key. Return 0
  9. if the tag is properly formed, non-0 if not. If the tag is correct,
  10. set key to the resulting secret key. */
  11. int check_tag(byte key[16], const byte privkey[PTWIST_BYTES],
  12. const byte tag[PTWIST_TAG_BYTES], const byte *context,
  13. size_t context_len)
  14. {
  15. int ret = -1;
  16. byte sharedsec[PTWIST_BYTES+context_len];
  17. byte taghashout[32];
  18. #if PTWIST_PUZZLE_STRENGTH > 0
  19. byte hashout[32];
  20. size_t puzzle_len = 16+PTWIST_RESP_BYTES;
  21. byte value_to_hash[puzzle_len];
  22. unsigned int firstbits;
  23. int firstpass = 0;
  24. #endif
  25. /* Compute the shared secret privkey*TAG */
  26. ptwist_pointmul(sharedsec, tag, privkey);
  27. /* Create the hash tag keys */
  28. memmove(sharedsec+PTWIST_BYTES, context, context_len);
  29. SHA256(sharedsec, PTWIST_BYTES, taghashout);
  30. #if PTWIST_PUZZLE_STRENGTH > 0
  31. /* Construct the proposed solution to the puzzle */
  32. memmove(value_to_hash, taghashout, 16);
  33. memmove(value_to_hash+16, tag+PTWIST_BYTES, PTWIST_RESP_BYTES);
  34. value_to_hash[16+PTWIST_RESP_BYTES-1] &= PTWIST_RESP_MASK;
  35. /* Hash the proposed solution and see if it is correct; that is, the
  36. * hash should start with PTWIST_PUZZLE_STRENGTH bits of 0s,
  37. * followed by the last PTWIST_HASH_SHOWBITS of the tag. */
  38. md_map_sh256(hashout, value_to_hash, puzzle_len);
  39. #if PTWIST_PUZZLE_STRENGTH < 32
  40. /* This assumes that you're on an architecture that doesn't care
  41. * about alignment, and is little endian. */
  42. firstbits = *(unsigned int*)hashout;
  43. if ((firstbits & PTWIST_PUZZLE_MASK) == 0) {
  44. firstpass = 1;
  45. }
  46. #else
  47. #error "Code assumes PTWIST_PUZZLE_STRENGTH < 32"
  48. #endif
  49. if (firstpass) {
  50. bn_t Hbn, Tbn;
  51. bn_new(Hbn);
  52. bn_new(Tbn);
  53. hashout[PTWIST_HASH_TOTBYTES-1] &= PTWIST_HASH_MASK;
  54. bn_read_bin(Hbn, hashout, PTWIST_HASH_TOTBYTES, BN_POS);
  55. bn_rsh(Hbn, Hbn, PTWIST_PUZZLE_STRENGTH);
  56. bn_read_bin(Tbn, tag+PTWIST_BYTES, PTWIST_TAG_BYTES-PTWIST_BYTES,
  57. BN_POS);
  58. bn_rsh(Tbn, Tbn, PTWIST_RESP_BITS);
  59. ret = (bn_cmp(Tbn,Hbn) != CMP_EQ);
  60. bn_free(Hbn);
  61. bn_free(Tbn);
  62. }
  63. #else
  64. /* We're not using a client puzzle, so just check that the first
  65. * PTWIST_HASH_SHOWBITS bits of the above hash fill out the rest
  66. * of the tag. If there's no puzzle, PTWIST_HASH_SHOWBITS must be
  67. * a multiple of 8. */
  68. ret = (memcmp(tag+PTWIST_BYTES, taghashout, PTWIST_HASH_SHOWBITS/8) != 0);
  69. #endif
  70. if (ret == 0) {
  71. memmove(key, taghashout+16, 16);
  72. }
  73. return ret;
  74. }