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.

155 lines
5.6 KiB

  1. // mqv.h - written and placed in the public domain by Wei Dai
  2. //! \file mqv.h
  3. //! \brief Classes for Menezes–Qu–Vanstone (MQV) key agreement
  4. #ifndef CRYPTOPP_MQV_H
  5. #define CRYPTOPP_MQV_H
  6. #include "cryptlib.h"
  7. #include "gfpcrypt.h"
  8. #include "modarith.h"
  9. #include "integer.h"
  10. #include "misc.h"
  11. NAMESPACE_BEGIN(CryptoPP)
  12. //! \class MQV_Domain
  13. //! \brief MQV domain for performing authenticated key agreement
  14. //! \tparam GROUP_PARAMETERS doamin parameters
  15. //! \tparam COFACTOR_OPTION cofactor option
  16. //! \details GROUP_PARAMETERS paramters include the curve coefcients and the base point.
  17. //! Binary curves use a polynomial to represent its characteristic, while prime curves
  18. //! use a prime number.
  19. template <class GROUP_PARAMETERS, class COFACTOR_OPTION = CPP_TYPENAME GROUP_PARAMETERS::DefaultCofactorOption>
  20. class MQV_Domain : public AuthenticatedKeyAgreementDomain
  21. {
  22. public:
  23. typedef GROUP_PARAMETERS GroupParameters;
  24. typedef typename GroupParameters::Element Element;
  25. typedef MQV_Domain<GROUP_PARAMETERS, COFACTOR_OPTION> Domain;
  26. MQV_Domain() {}
  27. MQV_Domain(const GroupParameters &params)
  28. : m_groupParameters(params) {}
  29. MQV_Domain(BufferedTransformation &bt)
  30. {m_groupParameters.BERDecode(bt);}
  31. template <class T1, class T2>
  32. MQV_Domain(T1 v1, T2 v2)
  33. {m_groupParameters.Initialize(v1, v2);}
  34. template <class T1, class T2, class T3>
  35. MQV_Domain(T1 v1, T2 v2, T3 v3)
  36. {m_groupParameters.Initialize(v1, v2, v3);}
  37. template <class T1, class T2, class T3, class T4>
  38. MQV_Domain(T1 v1, T2 v2, T3 v3, T4 v4)
  39. {m_groupParameters.Initialize(v1, v2, v3, v4);}
  40. const GroupParameters & GetGroupParameters() const {return m_groupParameters;}
  41. GroupParameters & AccessGroupParameters() {return m_groupParameters;}
  42. CryptoParameters & AccessCryptoParameters() {return AccessAbstractGroupParameters();}
  43. unsigned int AgreedValueLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(false);}
  44. unsigned int StaticPrivateKeyLength() const {return GetAbstractGroupParameters().GetSubgroupOrder().ByteCount();}
  45. unsigned int StaticPublicKeyLength() const {return GetAbstractGroupParameters().GetEncodedElementSize(true);}
  46. void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
  47. {
  48. Integer x(rng, Integer::One(), GetAbstractGroupParameters().GetMaxExponent());
  49. x.Encode(privateKey, StaticPrivateKeyLength());
  50. }
  51. void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
  52. {
  53. CRYPTOPP_UNUSED(rng);
  54. const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
  55. Integer x(privateKey, StaticPrivateKeyLength());
  56. Element y = params.ExponentiateBase(x);
  57. params.EncodeElement(true, y, publicKey);
  58. }
  59. unsigned int EphemeralPrivateKeyLength() const {return StaticPrivateKeyLength() + StaticPublicKeyLength();}
  60. unsigned int EphemeralPublicKeyLength() const {return StaticPublicKeyLength();}
  61. void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const
  62. {
  63. const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
  64. Integer x(rng, Integer::One(), params.GetMaxExponent());
  65. x.Encode(privateKey, StaticPrivateKeyLength());
  66. Element y = params.ExponentiateBase(x);
  67. params.EncodeElement(true, y, privateKey+StaticPrivateKeyLength());
  68. }
  69. void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const
  70. {
  71. CRYPTOPP_UNUSED(rng);
  72. memcpy(publicKey, privateKey+StaticPrivateKeyLength(), EphemeralPublicKeyLength());
  73. }
  74. bool Agree(byte *agreedValue,
  75. const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
  76. const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
  77. bool validateStaticOtherPublicKey=true) const
  78. {
  79. try
  80. {
  81. const DL_GroupParameters<Element> &params = GetAbstractGroupParameters();
  82. Element WW = params.DecodeElement(staticOtherPublicKey, validateStaticOtherPublicKey);
  83. Element VV = params.DecodeElement(ephemeralOtherPublicKey, true);
  84. Integer s(staticPrivateKey, StaticPrivateKeyLength());
  85. Integer u(ephemeralPrivateKey, StaticPrivateKeyLength());
  86. Element V = params.DecodeElement(ephemeralPrivateKey+StaticPrivateKeyLength(), false);
  87. const Integer &r = params.GetSubgroupOrder();
  88. Integer h2 = Integer::Power2((r.BitCount()+1)/2);
  89. Integer e = ((h2+params.ConvertElementToInteger(V)%h2)*s+u) % r;
  90. Integer tt = h2 + params.ConvertElementToInteger(VV) % h2;
  91. if (COFACTOR_OPTION::ToEnum() == NO_COFACTOR_MULTIPLICTION)
  92. {
  93. Element P = params.ExponentiateElement(WW, tt);
  94. P = m_groupParameters.MultiplyElements(P, VV);
  95. Element R[2];
  96. const Integer e2[2] = {r, e};
  97. params.SimultaneousExponentiate(R, P, e2, 2);
  98. if (!params.IsIdentity(R[0]) || params.IsIdentity(R[1]))
  99. return false;
  100. params.EncodeElement(false, R[1], agreedValue);
  101. }
  102. else
  103. {
  104. const Integer &k = params.GetCofactor();
  105. if (COFACTOR_OPTION::ToEnum() == COMPATIBLE_COFACTOR_MULTIPLICTION)
  106. e = ModularArithmetic(r).Divide(e, k);
  107. Element P = m_groupParameters.CascadeExponentiate(VV, k*e, WW, k*(e*tt%r));
  108. if (params.IsIdentity(P))
  109. return false;
  110. params.EncodeElement(false, P, agreedValue);
  111. }
  112. }
  113. catch (DL_BadElement &)
  114. {
  115. return false;
  116. }
  117. return true;
  118. }
  119. private:
  120. DL_GroupParameters<Element> & AccessAbstractGroupParameters() {return m_groupParameters;}
  121. const DL_GroupParameters<Element> & GetAbstractGroupParameters() const {return m_groupParameters;}
  122. GroupParameters m_groupParameters;
  123. };
  124. //! Menezes-Qu-Vanstone in GF(p) with key validation, AKA <a href="http://www.weidai.com/scan-mirror/ka.html#MQV">MQV</a>
  125. typedef MQV_Domain<DL_GroupParameters_GFP_DefaultSafePrime> MQV;
  126. NAMESPACE_END
  127. #endif