Counter Strike : Global Offensive Source Code
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.

145 lines
5.4 KiB

  1. // pssr.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #include "pssr.h"
  4. #include <functional>
  5. NAMESPACE_BEGIN(CryptoPP)
  6. // more in dll.cpp
  7. template<> const byte EMSA2HashId<RIPEMD160>::id = 0x31;
  8. template<> const byte EMSA2HashId<RIPEMD128>::id = 0x32;
  9. template<> const byte EMSA2HashId<Whirlpool>::id = 0x37;
  10. #ifndef CRYPTOPP_IMPORTS
  11. size_t PSSR_MEM_Base::MinRepresentativeBitLength(size_t hashIdentifierLength, size_t digestLength) const
  12. {
  13. size_t saltLen = SaltLen(digestLength);
  14. size_t minPadLen = MinPadLen(digestLength);
  15. return 9 + 8*(minPadLen + saltLen + digestLength + hashIdentifierLength);
  16. }
  17. size_t PSSR_MEM_Base::MaxRecoverableLength(size_t representativeBitLength, size_t hashIdentifierLength, size_t digestLength) const
  18. {
  19. if (AllowRecovery())
  20. return SaturatingSubtract(representativeBitLength, MinRepresentativeBitLength(hashIdentifierLength, digestLength)) / 8;
  21. return 0;
  22. }
  23. bool PSSR_MEM_Base::IsProbabilistic() const
  24. {
  25. return SaltLen(1) > 0;
  26. }
  27. bool PSSR_MEM_Base::AllowNonrecoverablePart() const
  28. {
  29. return true;
  30. }
  31. bool PSSR_MEM_Base::RecoverablePartFirst() const
  32. {
  33. return false;
  34. }
  35. void PSSR_MEM_Base::ComputeMessageRepresentative(RandomNumberGenerator &rng,
  36. const byte *recoverableMessage, size_t recoverableMessageLength,
  37. HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
  38. byte *representative, size_t representativeBitLength) const
  39. {
  40. assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
  41. const size_t u = hashIdentifier.second + 1;
  42. const size_t representativeByteLength = BitsToBytes(representativeBitLength);
  43. const size_t digestSize = hash.DigestSize();
  44. const size_t saltSize = SaltLen(digestSize);
  45. byte *const h = representative + representativeByteLength - u - digestSize;
  46. SecByteBlock digest(digestSize), salt(saltSize);
  47. hash.Final(digest);
  48. rng.GenerateBlock(salt, saltSize);
  49. // compute H = hash of M'
  50. byte c[8];
  51. PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
  52. PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
  53. hash.Update(c, 8);
  54. hash.Update(recoverableMessage, recoverableMessageLength);
  55. hash.Update(digest, digestSize);
  56. hash.Update(salt, saltSize);
  57. hash.Final(h);
  58. // compute representative
  59. GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize, false);
  60. byte *xorStart = representative + representativeByteLength - u - digestSize - salt.size() - recoverableMessageLength - 1;
  61. xorStart[0] ^= 1;
  62. xorbuf(xorStart + 1, recoverableMessage, recoverableMessageLength);
  63. xorbuf(xorStart + 1 + recoverableMessageLength, salt, salt.size());
  64. memcpy(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second);
  65. representative[representativeByteLength - 1] = hashIdentifier.second ? 0xcc : 0xbc;
  66. if (representativeBitLength % 8 != 0)
  67. representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
  68. }
  69. DecodingResult PSSR_MEM_Base::RecoverMessageFromRepresentative(
  70. HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
  71. byte *representative, size_t representativeBitLength,
  72. byte *recoverableMessage) const
  73. {
  74. assert(representativeBitLength >= MinRepresentativeBitLength(hashIdentifier.second, hash.DigestSize()));
  75. const size_t u = hashIdentifier.second + 1;
  76. const size_t representativeByteLength = BitsToBytes(representativeBitLength);
  77. const size_t digestSize = hash.DigestSize();
  78. const size_t saltSize = SaltLen(digestSize);
  79. const byte *const h = representative + representativeByteLength - u - digestSize;
  80. SecByteBlock digest(digestSize);
  81. hash.Final(digest);
  82. DecodingResult result(0);
  83. bool &valid = result.isValidCoding;
  84. size_t &recoverableMessageLength = result.messageLength;
  85. valid = (representative[representativeByteLength - 1] == (hashIdentifier.second ? 0xcc : 0xbc)) && valid;
  86. valid = VerifyBufsEqual(representative + representativeByteLength - u, hashIdentifier.first, hashIdentifier.second) && valid;
  87. GetMGF().GenerateAndMask(hash, representative, representativeByteLength - u - digestSize, h, digestSize);
  88. if (representativeBitLength % 8 != 0)
  89. representative[0] = (byte)Crop(representative[0], representativeBitLength % 8);
  90. // extract salt and recoverableMessage from DB = 00 ... || 01 || M || salt
  91. byte *salt = representative + representativeByteLength - u - digestSize - saltSize;
  92. byte *M = std::find_if(representative, salt-1, std::bind2nd(std::not_equal_to<byte>(), 0));
  93. recoverableMessageLength = salt-M-1;
  94. if (*M == 0x01
  95. && (size_t)(M - representative - (representativeBitLength % 8 != 0)) >= MinPadLen(digestSize)
  96. && recoverableMessageLength <= MaxRecoverableLength(representativeBitLength, hashIdentifier.second, digestSize))
  97. {
  98. memcpy(recoverableMessage, M+1, recoverableMessageLength);
  99. }
  100. else
  101. {
  102. recoverableMessageLength = 0;
  103. valid = false;
  104. }
  105. // verify H = hash of M'
  106. byte c[8];
  107. PutWord(false, BIG_ENDIAN_ORDER, c, (word32)SafeRightShift<29>(recoverableMessageLength));
  108. PutWord(false, BIG_ENDIAN_ORDER, c+4, word32(recoverableMessageLength << 3));
  109. hash.Update(c, 8);
  110. hash.Update(recoverableMessage, recoverableMessageLength);
  111. hash.Update(digest, digestSize);
  112. hash.Update(salt, saltSize);
  113. valid = hash.Verify(h) && valid;
  114. if (!AllowRecovery() && valid && recoverableMessageLength != 0)
  115. {throw NotImplemented("PSSR_MEM: message recovery disabled");}
  116. return result;
  117. }
  118. #endif
  119. NAMESPACE_END