Team Fortress 2 Source Code as on 22/4/2020
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.

170 lines
8.0 KiB

  1. // pubkey.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #include "config.h"
  4. #ifndef CRYPTOPP_IMPORTS
  5. #include "pubkey.h"
  6. #include "integer.h"
  7. #include "filters.h"
  8. NAMESPACE_BEGIN(CryptoPP)
  9. void P1363_MGF1KDF2_Common(HashTransformation &hash, byte *output, size_t outputLength, const byte *input, size_t inputLength, const byte *derivationParams, size_t derivationParamsLength, bool mask, unsigned int counterStart)
  10. {
  11. ArraySink *sink;
  12. HashFilter filter(hash, sink = mask ? new ArrayXorSink(output, outputLength) : new ArraySink(output, outputLength));
  13. word32 counter = counterStart;
  14. while (sink->AvailableSize() > 0)
  15. {
  16. filter.Put(input, inputLength);
  17. filter.PutWord32(counter++);
  18. filter.Put(derivationParams, derivationParamsLength);
  19. filter.MessageEnd();
  20. }
  21. }
  22. bool PK_DeterministicSignatureMessageEncodingMethod::VerifyMessageRepresentative(
  23. HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
  24. byte *representative, size_t representativeBitLength) const
  25. {
  26. SecByteBlock computedRepresentative(BitsToBytes(representativeBitLength));
  27. ComputeMessageRepresentative(NullRNG(), NULL, 0, hash, hashIdentifier, messageEmpty, computedRepresentative, representativeBitLength);
  28. return VerifyBufsEqual(representative, computedRepresentative, computedRepresentative.size());
  29. }
  30. bool PK_RecoverableSignatureMessageEncodingMethod::VerifyMessageRepresentative(
  31. HashTransformation &hash, HashIdentifier hashIdentifier, bool messageEmpty,
  32. byte *representative, size_t representativeBitLength) const
  33. {
  34. SecByteBlock recoveredMessage(MaxRecoverableLength(representativeBitLength, hashIdentifier.second, hash.DigestSize()));
  35. DecodingResult result = RecoverMessageFromRepresentative(
  36. hash, hashIdentifier, messageEmpty, representative, representativeBitLength, recoveredMessage);
  37. return result.isValidCoding && result.messageLength == 0;
  38. }
  39. void TF_SignerBase::InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const
  40. {
  41. PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
  42. HashIdentifier id = GetHashIdentifier();
  43. const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
  44. if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
  45. throw PK_SignatureScheme::KeyTooShort();
  46. size_t maxRecoverableLength = encoding.MaxRecoverableLength(MessageRepresentativeBitLength(), GetHashIdentifier().second, ma.AccessHash().DigestSize());
  47. if (maxRecoverableLength == 0)
  48. {throw NotImplemented("TF_SignerBase: this algorithm does not support messsage recovery or the key is too short");}
  49. if (recoverableMessageLength > maxRecoverableLength)
  50. throw InvalidArgument("TF_SignerBase: the recoverable message part is too long for the given key and algorithm");
  51. ma.m_recoverableMessage.Assign(recoverableMessage, recoverableMessageLength);
  52. encoding.ProcessRecoverableMessage(
  53. ma.AccessHash(),
  54. recoverableMessage, recoverableMessageLength,
  55. NULL, 0, ma.m_semisignature);
  56. }
  57. size_t TF_SignerBase::SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart) const
  58. {
  59. CRYPTOPP_UNUSED(restart);
  60. PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
  61. HashIdentifier id = GetHashIdentifier();
  62. const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
  63. if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
  64. throw PK_SignatureScheme::KeyTooShort();
  65. SecByteBlock representative(MessageRepresentativeLength());
  66. encoding.ComputeMessageRepresentative(rng,
  67. ma.m_recoverableMessage, ma.m_recoverableMessage.size(),
  68. ma.AccessHash(), id, ma.m_empty,
  69. representative, MessageRepresentativeBitLength());
  70. ma.m_empty = true;
  71. Integer r(representative, representative.size());
  72. size_t signatureLength = SignatureLength();
  73. GetTrapdoorFunctionInterface().CalculateRandomizedInverse(rng, r).Encode(signature, signatureLength);
  74. return signatureLength;
  75. }
  76. void TF_VerifierBase::InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const
  77. {
  78. PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
  79. HashIdentifier id = GetHashIdentifier();
  80. const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
  81. if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
  82. throw PK_SignatureScheme::KeyTooShort();
  83. ma.m_representative.New(MessageRepresentativeLength());
  84. Integer x = GetTrapdoorFunctionInterface().ApplyFunction(Integer(signature, signatureLength));
  85. if (x.BitCount() > MessageRepresentativeBitLength())
  86. x = Integer::Zero(); // don't return false here to prevent timing attack
  87. x.Encode(ma.m_representative, ma.m_representative.size());
  88. }
  89. bool TF_VerifierBase::VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const
  90. {
  91. PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
  92. HashIdentifier id = GetHashIdentifier();
  93. const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
  94. if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
  95. throw PK_SignatureScheme::KeyTooShort();
  96. bool result = encoding.VerifyMessageRepresentative(
  97. ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength());
  98. ma.m_empty = true;
  99. return result;
  100. }
  101. DecodingResult TF_VerifierBase::RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const
  102. {
  103. PK_MessageAccumulatorBase &ma = static_cast<PK_MessageAccumulatorBase &>(messageAccumulator);
  104. HashIdentifier id = GetHashIdentifier();
  105. const MessageEncodingInterface &encoding = GetMessageEncodingInterface();
  106. if (MessageRepresentativeBitLength() < encoding.MinRepresentativeBitLength(id.second, ma.AccessHash().DigestSize()))
  107. throw PK_SignatureScheme::KeyTooShort();
  108. DecodingResult result = encoding.RecoverMessageFromRepresentative(
  109. ma.AccessHash(), id, ma.m_empty, ma.m_representative, MessageRepresentativeBitLength(), recoveredMessage);
  110. ma.m_empty = true;
  111. return result;
  112. }
  113. DecodingResult TF_DecryptorBase::Decrypt(RandomNumberGenerator &rng, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
  114. {
  115. if (ciphertextLength != FixedCiphertextLength())
  116. throw InvalidArgument(AlgorithmName() + ": ciphertext length of " + IntToString(ciphertextLength) + " doesn't match the required length of " + IntToString(FixedCiphertextLength()) + " for this key");
  117. SecByteBlock paddedBlock(PaddedBlockByteLength());
  118. Integer x = GetTrapdoorFunctionInterface().CalculateInverse(rng, Integer(ciphertext, ciphertextLength));
  119. if (x.ByteCount() > paddedBlock.size())
  120. x = Integer::Zero(); // don't return false here to prevent timing attack
  121. x.Encode(paddedBlock, paddedBlock.size());
  122. return GetMessageEncodingInterface().Unpad(paddedBlock, PaddedBlockBitLength(), plaintext, parameters);
  123. }
  124. void TF_EncryptorBase::Encrypt(RandomNumberGenerator &rng, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
  125. {
  126. if (plaintextLength > FixedMaxPlaintextLength())
  127. {
  128. if (FixedMaxPlaintextLength() < 1)
  129. throw InvalidArgument(AlgorithmName() + ": this key is too short to encrypt any messages");
  130. else
  131. throw InvalidArgument(AlgorithmName() + ": message length of " + IntToString(plaintextLength) + " exceeds the maximum of " + IntToString(FixedMaxPlaintextLength()) + " for this public key");
  132. }
  133. SecByteBlock paddedBlock(PaddedBlockByteLength());
  134. GetMessageEncodingInterface().Pad(rng, plaintext, plaintextLength, paddedBlock, PaddedBlockBitLength(), parameters);
  135. GetTrapdoorFunctionInterface().ApplyRandomizedFunction(rng, Integer(paddedBlock, paddedBlock.size())).Encode(ciphertext, FixedCiphertextLength());
  136. }
  137. NAMESPACE_END
  138. #endif