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.

204 lines
5.2 KiB

  1. // rw.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #include "rw.h"
  4. #include "asn.h"
  5. #include "integer.h"
  6. #include "nbtheory.h"
  7. #include "modarith.h"
  8. #ifndef CRYPTOPP_IMPORTS
  9. NAMESPACE_BEGIN(CryptoPP)
  10. void RWFunction::BERDecode(BufferedTransformation &bt)
  11. {
  12. BERSequenceDecoder seq(bt);
  13. m_n.BERDecode(seq);
  14. seq.MessageEnd();
  15. }
  16. void RWFunction::DEREncode(BufferedTransformation &bt) const
  17. {
  18. DERSequenceEncoder seq(bt);
  19. m_n.DEREncode(seq);
  20. seq.MessageEnd();
  21. }
  22. Integer RWFunction::ApplyFunction(const Integer &in) const
  23. {
  24. DoQuickSanityCheck();
  25. Integer out = in.Squared()%m_n;
  26. const word r = 12;
  27. // this code was written to handle both r = 6 and r = 12,
  28. // but now only r = 12 is used in P1363
  29. const word r2 = r/2;
  30. const word r3a = (16 + 5 - r) % 16; // n%16 could be 5 or 13
  31. const word r3b = (16 + 13 - r) % 16;
  32. const word r4 = (8 + 5 - r/2) % 8; // n%8 == 5
  33. switch (out % 16)
  34. {
  35. case r:
  36. break;
  37. case r2:
  38. case r2+8:
  39. out <<= 1;
  40. break;
  41. case r3a:
  42. case r3b:
  43. out.Negate();
  44. out += m_n;
  45. break;
  46. case r4:
  47. case r4+8:
  48. out.Negate();
  49. out += m_n;
  50. out <<= 1;
  51. break;
  52. default:
  53. out = Integer::Zero();
  54. }
  55. return out;
  56. }
  57. bool RWFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
  58. {
  59. CRYPTOPP_UNUSED(rng), CRYPTOPP_UNUSED(level);
  60. bool pass = true;
  61. pass = pass && m_n > Integer::One() && m_n%8 == 5;
  62. return pass;
  63. }
  64. bool RWFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
  65. {
  66. return GetValueHelper(this, name, valueType, pValue).Assignable()
  67. CRYPTOPP_GET_FUNCTION_ENTRY(Modulus)
  68. ;
  69. }
  70. void RWFunction::AssignFrom(const NameValuePairs &source)
  71. {
  72. AssignFromHelper(this, source)
  73. CRYPTOPP_SET_FUNCTION_ENTRY(Modulus)
  74. ;
  75. }
  76. // *****************************************************************************
  77. // private key operations:
  78. // generate a random private key
  79. void InvertibleRWFunction::GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg)
  80. {
  81. int modulusSize = 2048;
  82. alg.GetIntValue("ModulusSize", modulusSize) || alg.GetIntValue("KeySize", modulusSize);
  83. if (modulusSize < 16)
  84. throw InvalidArgument("InvertibleRWFunction: specified modulus length is too small");
  85. AlgorithmParameters primeParam = MakeParametersForTwoPrimesOfEqualSize(modulusSize);
  86. m_p.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("EquivalentTo", 3)("Mod", 8)));
  87. m_q.GenerateRandom(rng, CombinedNameValuePairs(primeParam, MakeParameters("EquivalentTo", 7)("Mod", 8)));
  88. m_n = m_p * m_q;
  89. m_u = m_q.InverseMod(m_p);
  90. }
  91. void InvertibleRWFunction::BERDecode(BufferedTransformation &bt)
  92. {
  93. BERSequenceDecoder seq(bt);
  94. m_n.BERDecode(seq);
  95. m_p.BERDecode(seq);
  96. m_q.BERDecode(seq);
  97. m_u.BERDecode(seq);
  98. seq.MessageEnd();
  99. }
  100. void InvertibleRWFunction::DEREncode(BufferedTransformation &bt) const
  101. {
  102. DERSequenceEncoder seq(bt);
  103. m_n.DEREncode(seq);
  104. m_p.DEREncode(seq);
  105. m_q.DEREncode(seq);
  106. m_u.DEREncode(seq);
  107. seq.MessageEnd();
  108. }
  109. Integer InvertibleRWFunction::CalculateInverse(RandomNumberGenerator &rng, const Integer &x) const
  110. {
  111. DoQuickSanityCheck();
  112. ModularArithmetic modn(m_n);
  113. Integer r, rInv;
  114. do {
  115. // do this in a loop for people using small numbers for testing
  116. r.Randomize(rng, Integer::One(), m_n - Integer::One());
  117. // Fix for CVE-2015-2141. Thanks to Evgeny Sidorov for reporting.
  118. // Squaring to satisfy Jacobi requirements suggested by Jean-Pierre Münch.
  119. r = modn.Square(r);
  120. rInv = modn.MultiplicativeInverse(r);
  121. } while (rInv.IsZero());
  122. Integer re = modn.Square(r);
  123. re = modn.Multiply(re, x); // blind
  124. Integer cp=re%m_p, cq=re%m_q;
  125. if (Jacobi(cp, m_p) * Jacobi(cq, m_q) != 1)
  126. {
  127. cp = cp.IsOdd() ? (cp+m_p) >> 1 : cp >> 1;
  128. cq = cq.IsOdd() ? (cq+m_q) >> 1 : cq >> 1;
  129. }
  130. #pragma omp parallel
  131. #pragma omp sections
  132. {
  133. #pragma omp section
  134. cp = ModularSquareRoot(cp, m_p);
  135. #pragma omp section
  136. cq = ModularSquareRoot(cq, m_q);
  137. }
  138. Integer y = CRT(cq, m_q, cp, m_p, m_u);
  139. y = modn.Multiply(y, rInv); // unblind
  140. y = STDMIN(y, m_n-y);
  141. if (ApplyFunction(y) != x) // check
  142. throw Exception(Exception::OTHER_ERROR, "InvertibleRWFunction: computational error during private key operation");
  143. return y;
  144. }
  145. bool InvertibleRWFunction::Validate(RandomNumberGenerator &rng, unsigned int level) const
  146. {
  147. bool pass = RWFunction::Validate(rng, level);
  148. pass = pass && m_p > Integer::One() && m_p%8 == 3 && m_p < m_n;
  149. pass = pass && m_q > Integer::One() && m_q%8 == 7 && m_q < m_n;
  150. pass = pass && m_u.IsPositive() && m_u < m_p;
  151. if (level >= 1)
  152. {
  153. pass = pass && m_p * m_q == m_n;
  154. pass = pass && m_u * m_q % m_p == 1;
  155. }
  156. if (level >= 2)
  157. pass = pass && VerifyPrime(rng, m_p, level-2) && VerifyPrime(rng, m_q, level-2);
  158. return pass;
  159. }
  160. bool InvertibleRWFunction::GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
  161. {
  162. return GetValueHelper<RWFunction>(this, name, valueType, pValue).Assignable()
  163. CRYPTOPP_GET_FUNCTION_ENTRY(Prime1)
  164. CRYPTOPP_GET_FUNCTION_ENTRY(Prime2)
  165. CRYPTOPP_GET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
  166. ;
  167. }
  168. void InvertibleRWFunction::AssignFrom(const NameValuePairs &source)
  169. {
  170. AssignFromHelper<RWFunction>(this, source)
  171. CRYPTOPP_SET_FUNCTION_ENTRY(Prime1)
  172. CRYPTOPP_SET_FUNCTION_ENTRY(Prime2)
  173. CRYPTOPP_SET_FUNCTION_ENTRY(MultiplicativeInverseOfPrime2ModPrime1)
  174. ;
  175. }
  176. NAMESPACE_END
  177. #endif