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.

636 lines
22 KiB

  1. #ifndef CRYPTOPP_GFPCRYPT_H
  2. #define CRYPTOPP_GFPCRYPT_H
  3. /** \file
  4. Implementation of schemes based on DL over GF(p)
  5. */
  6. #include "config.h"
  7. #if CRYPTOPP_MSC_VERSION
  8. # pragma warning(push)
  9. # pragma warning(disable: 4189)
  10. #endif
  11. #include "cryptlib.h"
  12. #include "pubkey.h"
  13. #include "integer.h"
  14. #include "modexppc.h"
  15. #include "algparam.h"
  16. #include "smartptr.h"
  17. #include "sha.h"
  18. #include "asn.h"
  19. #include "hmac.h"
  20. #include "misc.h"
  21. NAMESPACE_BEGIN(CryptoPP)
  22. CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters<Integer>;
  23. //! _
  24. class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBased : public ASN1CryptoMaterial<DL_GroupParameters<Integer> >
  25. {
  26. typedef DL_GroupParameters_IntegerBased ThisClass;
  27. public:
  28. void Initialize(const DL_GroupParameters_IntegerBased &params)
  29. {Initialize(params.GetModulus(), params.GetSubgroupOrder(), params.GetSubgroupGenerator());}
  30. void Initialize(RandomNumberGenerator &rng, unsigned int pbits)
  31. {GenerateRandom(rng, MakeParameters("ModulusSize", (int)pbits));}
  32. void Initialize(const Integer &p, const Integer &g)
  33. {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(ComputeGroupOrder(p)/2);}
  34. void Initialize(const Integer &p, const Integer &q, const Integer &g)
  35. {SetModulusAndSubgroupGenerator(p, g); SetSubgroupOrder(q);}
  36. // ASN1Object interface
  37. void BERDecode(BufferedTransformation &bt);
  38. void DEREncode(BufferedTransformation &bt) const;
  39. // GeneratibleCryptoMaterial interface
  40. /*! parameters: (ModulusSize, SubgroupOrderSize (optional)) */
  41. void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
  42. bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const;
  43. void AssignFrom(const NameValuePairs &source);
  44. // DL_GroupParameters
  45. const Integer & GetSubgroupOrder() const {return m_q;}
  46. Integer GetGroupOrder() const {return GetFieldType() == 1 ? GetModulus()-Integer::One() : GetModulus()+Integer::One();}
  47. bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
  48. bool ValidateElement(unsigned int level, const Integer &element, const DL_FixedBasePrecomputation<Integer> *precomp) const;
  49. bool FastSubgroupCheckAvailable() const {return GetCofactor() == 2;}
  50. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  51. // Cygwin i386 crash at -O3; see .
  52. void EncodeElement(bool reversible, const Element &element, byte *encoded) const;
  53. unsigned int GetEncodedElementSize(bool reversible) const;
  54. #else
  55. void EncodeElement(bool reversible, const Element &element, byte *encoded) const
  56. {CRYPTOPP_UNUSED(reversible); element.Encode(encoded, GetModulus().ByteCount());}
  57. unsigned int GetEncodedElementSize(bool reversible) const
  58. {CRYPTOPP_UNUSED(reversible); return GetModulus().ByteCount();}
  59. #endif
  60. Integer DecodeElement(const byte *encoded, bool checkForGroupMembership) const;
  61. Integer ConvertElementToInteger(const Element &element) const
  62. {return element;}
  63. Integer GetMaxExponent() const;
  64. static std::string CRYPTOPP_API StaticAlgorithmNamePrefix() {return "";}
  65. OID GetAlgorithmID() const;
  66. virtual const Integer & GetModulus() const =0;
  67. virtual void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) =0;
  68. void SetSubgroupOrder(const Integer &q)
  69. {m_q = q; ParametersChanged();}
  70. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  71. virtual ~DL_GroupParameters_IntegerBased() {}
  72. #endif
  73. protected:
  74. Integer ComputeGroupOrder(const Integer &modulus) const
  75. {return modulus-(GetFieldType() == 1 ? 1 : -1);}
  76. // GF(p) = 1, GF(p^2) = 2
  77. virtual int GetFieldType() const =0;
  78. virtual unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const;
  79. private:
  80. Integer m_q;
  81. };
  82. //! _
  83. template <class GROUP_PRECOMP, class BASE_PRECOMP = DL_FixedBasePrecomputationImpl<CPP_TYPENAME GROUP_PRECOMP::Element> >
  84. class CRYPTOPP_NO_VTABLE DL_GroupParameters_IntegerBasedImpl : public DL_GroupParametersImpl<GROUP_PRECOMP, BASE_PRECOMP, DL_GroupParameters_IntegerBased>
  85. {
  86. typedef DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> ThisClass;
  87. public:
  88. typedef typename GROUP_PRECOMP::Element Element;
  89. // GeneratibleCryptoMaterial interface
  90. bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
  91. {return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();}
  92. void AssignFrom(const NameValuePairs &source)
  93. {AssignFromHelper<DL_GroupParameters_IntegerBased>(this, source);}
  94. // DL_GroupParameters
  95. const DL_FixedBasePrecomputation<Element> & GetBasePrecomputation() const {return this->m_gpc;}
  96. DL_FixedBasePrecomputation<Element> & AccessBasePrecomputation() {return this->m_gpc;}
  97. // IntegerGroupParameters
  98. const Integer & GetModulus() const {return this->m_groupPrecomputation.GetModulus();}
  99. const Integer & GetGenerator() const {return this->m_gpc.GetBase(this->GetGroupPrecomputation());}
  100. void SetModulusAndSubgroupGenerator(const Integer &p, const Integer &g) // these have to be set together
  101. {this->m_groupPrecomputation.SetModulus(p); this->m_gpc.SetBase(this->GetGroupPrecomputation(), g); this->ParametersChanged();}
  102. // non-inherited
  103. bool operator==(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
  104. {return GetModulus() == rhs.GetModulus() && GetGenerator() == rhs.GetGenerator() && this->GetSubgroupOrder() == rhs.GetSubgroupOrder();}
  105. bool operator!=(const DL_GroupParameters_IntegerBasedImpl<GROUP_PRECOMP, BASE_PRECOMP> &rhs) const
  106. {return !operator==(rhs);}
  107. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  108. virtual ~DL_GroupParameters_IntegerBasedImpl() {}
  109. #endif
  110. };
  111. CRYPTOPP_DLL_TEMPLATE_CLASS DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>;
  112. //! GF(p) group parameters
  113. class CRYPTOPP_DLL DL_GroupParameters_GFP : public DL_GroupParameters_IntegerBasedImpl<ModExpPrecomputation>
  114. {
  115. public:
  116. // DL_GroupParameters
  117. bool IsIdentity(const Integer &element) const {return element == Integer::One();}
  118. void SimultaneousExponentiate(Element *results, const Element &base, const Integer *exponents, unsigned int exponentsCount) const;
  119. // NameValuePairs interface
  120. bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
  121. {
  122. return GetValueHelper<DL_GroupParameters_IntegerBased>(this, name, valueType, pValue).Assignable();
  123. }
  124. // used by MQV
  125. Element MultiplyElements(const Element &a, const Element &b) const;
  126. Element CascadeExponentiate(const Element &element1, const Integer &exponent1, const Element &element2, const Integer &exponent2) const;
  127. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  128. virtual ~DL_GroupParameters_GFP() {}
  129. #endif
  130. protected:
  131. int GetFieldType() const {return 1;}
  132. };
  133. //! GF(p) group parameters that default to same primes
  134. class CRYPTOPP_DLL DL_GroupParameters_GFP_DefaultSafePrime : public DL_GroupParameters_GFP
  135. {
  136. public:
  137. typedef NoCofactorMultiplication DefaultCofactorOption;
  138. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  139. virtual ~DL_GroupParameters_GFP_DefaultSafePrime() {}
  140. #endif
  141. protected:
  142. unsigned int GetDefaultSubgroupOrderSize(unsigned int modulusSize) const {return modulusSize-1;}
  143. };
  144. //! GDSA algorithm
  145. template <class T>
  146. class DL_Algorithm_GDSA : public DL_ElgamalLikeSignatureAlgorithm<T>
  147. {
  148. public:
  149. static const char * CRYPTOPP_API StaticAlgorithmName() {return "DSA-1363";}
  150. void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
  151. {
  152. const Integer &q = params.GetSubgroupOrder();
  153. r %= q;
  154. Integer kInv = k.InverseMod(q);
  155. s = (kInv * (x*r + e)) % q;
  156. assert(!!r && !!s);
  157. }
  158. bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
  159. {
  160. const Integer &q = params.GetSubgroupOrder();
  161. if (r>=q || r<1 || s>=q || s<1)
  162. return false;
  163. Integer w = s.InverseMod(q);
  164. Integer u1 = (e * w) % q;
  165. Integer u2 = (r * w) % q;
  166. // verify r == (g^u1 * y^u2 mod p) mod q
  167. return r == params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(u1, u2)) % q;
  168. }
  169. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  170. virtual ~DL_Algorithm_GDSA() {}
  171. #endif
  172. };
  173. CRYPTOPP_DLL_TEMPLATE_CLASS DL_Algorithm_GDSA<Integer>;
  174. //! NR algorithm
  175. template <class T>
  176. class DL_Algorithm_NR : public DL_ElgamalLikeSignatureAlgorithm<T>
  177. {
  178. public:
  179. static const char * CRYPTOPP_API StaticAlgorithmName() {return "NR";}
  180. void Sign(const DL_GroupParameters<T> &params, const Integer &x, const Integer &k, const Integer &e, Integer &r, Integer &s) const
  181. {
  182. const Integer &q = params.GetSubgroupOrder();
  183. r = (r + e) % q;
  184. s = (k - x*r) % q;
  185. assert(!!r);
  186. }
  187. bool Verify(const DL_GroupParameters<T> &params, const DL_PublicKey<T> &publicKey, const Integer &e, const Integer &r, const Integer &s) const
  188. {
  189. const Integer &q = params.GetSubgroupOrder();
  190. if (r>=q || r<1 || s>=q)
  191. return false;
  192. // check r == (m_g^s * m_y^r + m) mod m_q
  193. return r == (params.ConvertElementToInteger(publicKey.CascadeExponentiateBaseAndPublicElement(s, r)) + e) % q;
  194. }
  195. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  196. virtual ~DL_Algorithm_NR() {}
  197. #endif
  198. };
  199. /*! DSA public key format is defined in 7.3.3 of RFC 2459. The
  200. private key format is defined in 12.9 of PKCS #11 v2.10. */
  201. template <class GP>
  202. class DL_PublicKey_GFP : public DL_PublicKeyImpl<GP>
  203. {
  204. public:
  205. void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &y)
  206. {this->AccessGroupParameters().Initialize(params); this->SetPublicElement(y);}
  207. void Initialize(const Integer &p, const Integer &g, const Integer &y)
  208. {this->AccessGroupParameters().Initialize(p, g); this->SetPublicElement(y);}
  209. void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &y)
  210. {this->AccessGroupParameters().Initialize(p, q, g); this->SetPublicElement(y);}
  211. // X509PublicKey
  212. void BERDecodePublicKey(BufferedTransformation &bt, bool, size_t)
  213. {this->SetPublicElement(Integer(bt));}
  214. void DEREncodePublicKey(BufferedTransformation &bt) const
  215. {this->GetPublicElement().DEREncode(bt);}
  216. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  217. virtual ~DL_PublicKey_GFP() {}
  218. #endif
  219. };
  220. //! DL private key (in GF(p) groups)
  221. template <class GP>
  222. class DL_PrivateKey_GFP : public DL_PrivateKeyImpl<GP>
  223. {
  224. public:
  225. void Initialize(RandomNumberGenerator &rng, unsigned int modulusBits)
  226. {this->GenerateRandomWithKeySize(rng, modulusBits);}
  227. void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &g)
  228. {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupGenerator", g));}
  229. void Initialize(RandomNumberGenerator &rng, const Integer &p, const Integer &q, const Integer &g)
  230. {this->GenerateRandom(rng, MakeParameters("Modulus", p)("SubgroupOrder", q)("SubgroupGenerator", g));}
  231. void Initialize(const DL_GroupParameters_IntegerBased &params, const Integer &x)
  232. {this->AccessGroupParameters().Initialize(params); this->SetPrivateExponent(x);}
  233. void Initialize(const Integer &p, const Integer &g, const Integer &x)
  234. {this->AccessGroupParameters().Initialize(p, g); this->SetPrivateExponent(x);}
  235. void Initialize(const Integer &p, const Integer &q, const Integer &g, const Integer &x)
  236. {this->AccessGroupParameters().Initialize(p, q, g); this->SetPrivateExponent(x);}
  237. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  238. virtual ~DL_PrivateKey_GFP() {}
  239. #endif
  240. };
  241. //! DL signing/verification keys (in GF(p) groups)
  242. struct DL_SignatureKeys_GFP
  243. {
  244. typedef DL_GroupParameters_GFP GroupParameters;
  245. typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
  246. typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
  247. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  248. virtual ~DL_SignatureKeys_GFP() {}
  249. #endif
  250. };
  251. //! DL encryption/decryption keys (in GF(p) groups)
  252. struct DL_CryptoKeys_GFP
  253. {
  254. typedef DL_GroupParameters_GFP_DefaultSafePrime GroupParameters;
  255. typedef DL_PublicKey_GFP<GroupParameters> PublicKey;
  256. typedef DL_PrivateKey_GFP<GroupParameters> PrivateKey;
  257. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  258. virtual ~DL_CryptoKeys_GFP() {}
  259. #endif
  260. };
  261. //! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
  262. template <class BASE>
  263. class DL_PublicKey_GFP_OldFormat : public BASE
  264. {
  265. public:
  266. void BERDecode(BufferedTransformation &bt)
  267. {
  268. BERSequenceDecoder seq(bt);
  269. Integer v1(seq);
  270. Integer v2(seq);
  271. Integer v3(seq);
  272. if (seq.EndReached())
  273. {
  274. this->AccessGroupParameters().Initialize(v1, v1/2, v2);
  275. this->SetPublicElement(v3);
  276. }
  277. else
  278. {
  279. Integer v4(seq);
  280. this->AccessGroupParameters().Initialize(v1, v2, v3);
  281. this->SetPublicElement(v4);
  282. }
  283. seq.MessageEnd();
  284. }
  285. void DEREncode(BufferedTransformation &bt) const
  286. {
  287. DERSequenceEncoder seq(bt);
  288. this->GetGroupParameters().GetModulus().DEREncode(seq);
  289. if (this->GetGroupParameters().GetCofactor() != 2)
  290. this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
  291. this->GetGroupParameters().GetGenerator().DEREncode(seq);
  292. this->GetPublicElement().DEREncode(seq);
  293. seq.MessageEnd();
  294. }
  295. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  296. virtual ~DL_PublicKey_GFP_OldFormat() {}
  297. #endif
  298. };
  299. //! provided for backwards compatibility, this class uses the old non-standard Crypto++ key format
  300. template <class BASE>
  301. class DL_PrivateKey_GFP_OldFormat : public BASE
  302. {
  303. public:
  304. void BERDecode(BufferedTransformation &bt)
  305. {
  306. BERSequenceDecoder seq(bt);
  307. Integer v1(seq);
  308. Integer v2(seq);
  309. Integer v3(seq);
  310. Integer v4(seq);
  311. if (seq.EndReached())
  312. {
  313. this->AccessGroupParameters().Initialize(v1, v1/2, v2);
  314. this->SetPrivateExponent(v4 % (v1/2)); // some old keys may have x >= q
  315. }
  316. else
  317. {
  318. Integer v5(seq);
  319. this->AccessGroupParameters().Initialize(v1, v2, v3);
  320. this->SetPrivateExponent(v5);
  321. }
  322. seq.MessageEnd();
  323. }
  324. void DEREncode(BufferedTransformation &bt) const
  325. {
  326. DERSequenceEncoder seq(bt);
  327. this->GetGroupParameters().GetModulus().DEREncode(seq);
  328. if (this->GetGroupParameters().GetCofactor() != 2)
  329. this->GetGroupParameters().GetSubgroupOrder().DEREncode(seq);
  330. this->GetGroupParameters().GetGenerator().DEREncode(seq);
  331. this->GetGroupParameters().ExponentiateBase(this->GetPrivateExponent()).DEREncode(seq);
  332. this->GetPrivateExponent().DEREncode(seq);
  333. seq.MessageEnd();
  334. }
  335. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  336. virtual ~DL_PrivateKey_GFP_OldFormat() {}
  337. #endif
  338. };
  339. //! <a href="http://www.weidai.com/scan-mirror/sig.html#DSA-1363">DSA-1363</a>
  340. template <class H>
  341. struct GDSA : public DL_SS<
  342. DL_SignatureKeys_GFP,
  343. DL_Algorithm_GDSA<Integer>,
  344. DL_SignatureMessageEncodingMethod_DSA,
  345. H>
  346. {
  347. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  348. virtual ~GDSA() {}
  349. #endif
  350. };
  351. //! <a href="http://www.weidai.com/scan-mirror/sig.html#NR">NR</a>
  352. template <class H>
  353. struct NR : public DL_SS<
  354. DL_SignatureKeys_GFP,
  355. DL_Algorithm_NR<Integer>,
  356. DL_SignatureMessageEncodingMethod_NR,
  357. H>
  358. {
  359. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  360. virtual ~NR() {}
  361. #endif
  362. };
  363. //! DSA group parameters, these are GF(p) group parameters that are allowed by the DSA standard
  364. class CRYPTOPP_DLL DL_GroupParameters_DSA : public DL_GroupParameters_GFP
  365. {
  366. public:
  367. /*! also checks that the lengths of p and q are allowed by the DSA standard */
  368. bool ValidateGroup(RandomNumberGenerator &rng, unsigned int level) const;
  369. /*! parameters: (ModulusSize), or (Modulus, SubgroupOrder, SubgroupGenerator) */
  370. /*! ModulusSize must be between DSA::MIN_PRIME_LENGTH and DSA::MAX_PRIME_LENGTH, and divisible by DSA::PRIME_LENGTH_MULTIPLE */
  371. void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &alg);
  372. static bool CRYPTOPP_API IsValidPrimeLength(unsigned int pbits)
  373. {return pbits >= MIN_PRIME_LENGTH && pbits <= MAX_PRIME_LENGTH && pbits % PRIME_LENGTH_MULTIPLE == 0;}
  374. enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
  375. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  376. virtual ~DL_GroupParameters_DSA() {}
  377. #endif
  378. };
  379. template <class H>
  380. class DSA2;
  381. //! DSA keys
  382. struct DL_Keys_DSA
  383. {
  384. typedef DL_PublicKey_GFP<DL_GroupParameters_DSA> PublicKey;
  385. typedef DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> > PrivateKey;
  386. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  387. virtual ~DL_Keys_DSA() {}
  388. #endif
  389. };
  390. //! <a href="http://en.wikipedia.org/wiki/Digital_Signature_Algorithm">DSA</a>, as specified in FIPS 186-3
  391. // class named DSA2 instead of DSA for backwards compatibility (DSA was a non-template class)
  392. template <class H>
  393. class DSA2 : public DL_SS<
  394. DL_Keys_DSA,
  395. DL_Algorithm_GDSA<Integer>,
  396. DL_SignatureMessageEncodingMethod_DSA,
  397. H,
  398. DSA2<H> >
  399. {
  400. public:
  401. static std::string CRYPTOPP_API StaticAlgorithmName() {return "DSA/" + (std::string)H::StaticAlgorithmName();}
  402. #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
  403. enum {MIN_PRIME_LENGTH = 1024, MAX_PRIME_LENGTH = 3072, PRIME_LENGTH_MULTIPLE = 1024};
  404. #endif
  405. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  406. virtual ~DSA2() {}
  407. #endif
  408. };
  409. //! DSA with SHA-1, typedef'd for backwards compatibility
  410. typedef DSA2<SHA> DSA;
  411. CRYPTOPP_DLL_TEMPLATE_CLASS DL_PublicKey_GFP<DL_GroupParameters_DSA>;
  412. CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_GFP<DL_GroupParameters_DSA>;
  413. CRYPTOPP_DLL_TEMPLATE_CLASS DL_PrivateKey_WithSignaturePairwiseConsistencyTest<DL_PrivateKey_GFP<DL_GroupParameters_DSA>, DSA2<SHA> >;
  414. //! the XOR encryption method, for use with DL-based cryptosystems
  415. template <class MAC, bool DHAES_MODE>
  416. class DL_EncryptionAlgorithm_Xor : public DL_SymmetricEncryptionAlgorithm
  417. {
  418. public:
  419. bool ParameterSupported(const char *name) const {return strcmp(name, Name::EncodingParameters()) == 0;}
  420. size_t GetSymmetricKeyLength(size_t plaintextLength) const
  421. {return plaintextLength + MAC::DEFAULT_KEYLENGTH;}
  422. size_t GetSymmetricCiphertextLength(size_t plaintextLength) const
  423. {return plaintextLength + MAC::DIGESTSIZE;}
  424. size_t GetMaxSymmetricPlaintextLength(size_t ciphertextLength) const
  425. {return (unsigned int)SaturatingSubtract(ciphertextLength, (unsigned int)MAC::DIGESTSIZE);}
  426. void SymmetricEncrypt(RandomNumberGenerator &rng, const byte *key, const byte *plaintext, size_t plaintextLength, byte *ciphertext, const NameValuePairs &parameters) const
  427. {
  428. CRYPTOPP_UNUSED(rng);
  429. const byte *cipherKey = NULL, *macKey = NULL;
  430. if (DHAES_MODE)
  431. {
  432. macKey = key;
  433. cipherKey = key + MAC::DEFAULT_KEYLENGTH;
  434. }
  435. else
  436. {
  437. cipherKey = key;
  438. macKey = key + plaintextLength;
  439. }
  440. ConstByteArrayParameter encodingParameters;
  441. parameters.GetValue(Name::EncodingParameters(), encodingParameters);
  442. if (plaintextLength) // Coverity finding
  443. xorbuf(ciphertext, plaintext, cipherKey, plaintextLength);
  444. MAC mac(macKey);
  445. mac.Update(ciphertext, plaintextLength);
  446. mac.Update(encodingParameters.begin(), encodingParameters.size());
  447. if (DHAES_MODE)
  448. {
  449. byte L[8] = {0,0,0,0};
  450. PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
  451. mac.Update(L, 8);
  452. }
  453. mac.Final(ciphertext + plaintextLength);
  454. }
  455. DecodingResult SymmetricDecrypt(const byte *key, const byte *ciphertext, size_t ciphertextLength, byte *plaintext, const NameValuePairs &parameters) const
  456. {
  457. size_t plaintextLength = GetMaxSymmetricPlaintextLength(ciphertextLength);
  458. const byte *cipherKey, *macKey;
  459. if (DHAES_MODE)
  460. {
  461. macKey = key;
  462. cipherKey = key + MAC::DEFAULT_KEYLENGTH;
  463. }
  464. else
  465. {
  466. cipherKey = key;
  467. macKey = key + plaintextLength;
  468. }
  469. ConstByteArrayParameter encodingParameters;
  470. parameters.GetValue(Name::EncodingParameters(), encodingParameters);
  471. MAC mac(macKey);
  472. mac.Update(ciphertext, plaintextLength);
  473. mac.Update(encodingParameters.begin(), encodingParameters.size());
  474. if (DHAES_MODE)
  475. {
  476. byte L[8] = {0,0,0,0};
  477. PutWord(false, BIG_ENDIAN_ORDER, L+4, word32(encodingParameters.size()));
  478. mac.Update(L, 8);
  479. }
  480. if (!mac.Verify(ciphertext + plaintextLength))
  481. return DecodingResult();
  482. if (plaintextLength) // Coverity finding
  483. xorbuf(plaintext, ciphertext, cipherKey, plaintextLength);
  484. return DecodingResult(plaintextLength);
  485. }
  486. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  487. virtual ~DL_EncryptionAlgorithm_Xor() {}
  488. #endif
  489. };
  490. //! _
  491. template <class T, bool DHAES_MODE, class KDF>
  492. class DL_KeyDerivationAlgorithm_P1363 : public DL_KeyDerivationAlgorithm<T>
  493. {
  494. public:
  495. bool ParameterSupported(const char *name) const {return strcmp(name, Name::KeyDerivationParameters()) == 0;}
  496. void Derive(const DL_GroupParameters<T> &params, byte *derivedKey, size_t derivedLength, const T &agreedElement, const T &ephemeralPublicKey, const NameValuePairs &parameters) const
  497. {
  498. SecByteBlock agreedSecret;
  499. if (DHAES_MODE)
  500. {
  501. agreedSecret.New(params.GetEncodedElementSize(true) + params.GetEncodedElementSize(false));
  502. params.EncodeElement(true, ephemeralPublicKey, agreedSecret);
  503. params.EncodeElement(false, agreedElement, agreedSecret + params.GetEncodedElementSize(true));
  504. }
  505. else
  506. {
  507. agreedSecret.New(params.GetEncodedElementSize(false));
  508. params.EncodeElement(false, agreedElement, agreedSecret);
  509. }
  510. ConstByteArrayParameter derivationParameters;
  511. parameters.GetValue(Name::KeyDerivationParameters(), derivationParameters);
  512. KDF::DeriveKey(derivedKey, derivedLength, agreedSecret, agreedSecret.size(), derivationParameters.begin(), derivationParameters.size());
  513. }
  514. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  515. virtual ~DL_KeyDerivationAlgorithm_P1363() {}
  516. #endif
  517. };
  518. //! Discrete Log Integrated Encryption Scheme, AKA <a href="http://www.weidai.com/scan-mirror/ca.html#DLIES">DLIES</a>
  519. template <class COFACTOR_OPTION = NoCofactorMultiplication, bool DHAES_MODE = true>
  520. struct DLIES
  521. : public DL_ES<
  522. DL_CryptoKeys_GFP,
  523. DL_KeyAgreementAlgorithm_DH<Integer, COFACTOR_OPTION>,
  524. DL_KeyDerivationAlgorithm_P1363<Integer, DHAES_MODE, P1363_KDF2<SHA1> >,
  525. DL_EncryptionAlgorithm_Xor<HMAC<SHA1>, DHAES_MODE>,
  526. DLIES<> >
  527. {
  528. static std::string CRYPTOPP_API StaticAlgorithmName() {return "DLIES";} // TODO: fix this after name is standardized
  529. #ifndef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562
  530. virtual ~DLIES() {}
  531. #endif
  532. };
  533. NAMESPACE_END
  534. #if CRYPTOPP_MSC_VERSION
  535. # pragma warning(pop)
  536. #endif
  537. #endif