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.

882 lines
18 KiB

  1. // gf2n.cpp - written and placed in the public domain by Wei Dai
  2. #include "pch.h"
  3. #ifndef CRYPTOPP_IMPORTS
  4. #include "gf2n.h"
  5. #include "algebra.h"
  6. #include "words.h"
  7. #include "randpool.h"
  8. #include "asn.h"
  9. #include "oids.h"
  10. #include <iostream>
  11. NAMESPACE_BEGIN(CryptoPP)
  12. PolynomialMod2::PolynomialMod2()
  13. {
  14. }
  15. PolynomialMod2::PolynomialMod2(word value, size_t bitLength)
  16. : reg(BitsToWords(bitLength))
  17. {
  18. assert(value==0 || reg.size()>0);
  19. if (reg.size() > 0)
  20. {
  21. reg[0] = value;
  22. SetWords(reg+1, 0, reg.size()-1);
  23. }
  24. }
  25. PolynomialMod2::PolynomialMod2(const PolynomialMod2& t)
  26. : reg(t.reg.size())
  27. {
  28. CopyWords(reg, t.reg, reg.size());
  29. }
  30. void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits)
  31. {
  32. const size_t nbytes = nbits/8 + 1;
  33. SecByteBlock buf(nbytes);
  34. rng.GenerateBlock(buf, nbytes);
  35. buf[0] = (byte)Crop(buf[0], nbits % 8);
  36. Decode(buf, nbytes);
  37. }
  38. PolynomialMod2 PolynomialMod2::AllOnes(size_t bitLength)
  39. {
  40. PolynomialMod2 result((word)0, bitLength);
  41. SetWords(result.reg, ~(word)0, result.reg.size());
  42. if (bitLength%WORD_BITS)
  43. result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS);
  44. return result;
  45. }
  46. void PolynomialMod2::SetBit(size_t n, int value)
  47. {
  48. if (value)
  49. {
  50. reg.CleanGrow(n/WORD_BITS + 1);
  51. reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS));
  52. }
  53. else
  54. {
  55. if (n/WORD_BITS < reg.size())
  56. reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS));
  57. }
  58. }
  59. byte PolynomialMod2::GetByte(size_t n) const
  60. {
  61. if (n/WORD_SIZE >= reg.size())
  62. return 0;
  63. else
  64. return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
  65. }
  66. void PolynomialMod2::SetByte(size_t n, byte value)
  67. {
  68. reg.CleanGrow(BytesToWords(n+1));
  69. reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
  70. reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
  71. }
  72. PolynomialMod2 PolynomialMod2::Monomial(size_t i)
  73. {
  74. PolynomialMod2 r((word)0, i+1);
  75. r.SetBit(i);
  76. return r;
  77. }
  78. PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2)
  79. {
  80. PolynomialMod2 r((word)0, t0+1);
  81. r.SetBit(t0);
  82. r.SetBit(t1);
  83. r.SetBit(t2);
  84. return r;
  85. }
  86. PolynomialMod2 PolynomialMod2::Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4)
  87. {
  88. PolynomialMod2 r((word)0, t0+1);
  89. r.SetBit(t0);
  90. r.SetBit(t1);
  91. r.SetBit(t2);
  92. r.SetBit(t3);
  93. r.SetBit(t4);
  94. return r;
  95. }
  96. template <word i>
  97. struct NewPolynomialMod2
  98. {
  99. PolynomialMod2 * operator()() const
  100. {
  101. return new PolynomialMod2(i);
  102. }
  103. };
  104. const PolynomialMod2 &PolynomialMod2::Zero()
  105. {
  106. return Singleton<PolynomialMod2>().Ref();
  107. }
  108. const PolynomialMod2 &PolynomialMod2::One()
  109. {
  110. return Singleton<PolynomialMod2, NewPolynomialMod2<1> >().Ref();
  111. }
  112. void PolynomialMod2::Decode(const byte *input, size_t inputLen)
  113. {
  114. StringStore store(input, inputLen);
  115. Decode(store, inputLen);
  116. }
  117. void PolynomialMod2::Encode(byte *output, size_t outputLen) const
  118. {
  119. ArraySink sink(output, outputLen);
  120. Encode(sink, outputLen);
  121. }
  122. void PolynomialMod2::Decode(BufferedTransformation &bt, size_t inputLen)
  123. {
  124. reg.CleanNew(BytesToWords(inputLen));
  125. for (size_t i=inputLen; i > 0; i--)
  126. {
  127. byte b;
  128. bt.Get(b);
  129. reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8;
  130. }
  131. }
  132. void PolynomialMod2::Encode(BufferedTransformation &bt, size_t outputLen) const
  133. {
  134. for (size_t i=outputLen; i > 0; i--)
  135. bt.Put(GetByte(i-1));
  136. }
  137. void PolynomialMod2::DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const
  138. {
  139. DERGeneralEncoder enc(bt, OCTET_STRING);
  140. Encode(enc, length);
  141. enc.MessageEnd();
  142. }
  143. void PolynomialMod2::BERDecodeAsOctetString(BufferedTransformation &bt, size_t length)
  144. {
  145. BERGeneralDecoder dec(bt, OCTET_STRING);
  146. if (!dec.IsDefiniteLength() || dec.RemainingLength() != length)
  147. BERDecodeError();
  148. Decode(dec, length);
  149. dec.MessageEnd();
  150. }
  151. unsigned int PolynomialMod2::WordCount() const
  152. {
  153. return (unsigned int)CountWords(reg, reg.size());
  154. }
  155. unsigned int PolynomialMod2::ByteCount() const
  156. {
  157. unsigned wordCount = WordCount();
  158. if (wordCount)
  159. return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]);
  160. else
  161. return 0;
  162. }
  163. unsigned int PolynomialMod2::BitCount() const
  164. {
  165. unsigned wordCount = WordCount();
  166. if (wordCount)
  167. return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]);
  168. else
  169. return 0;
  170. }
  171. unsigned int PolynomialMod2::Parity() const
  172. {
  173. unsigned i;
  174. word temp=0;
  175. for (i=0; i<reg.size(); i++)
  176. temp ^= reg[i];
  177. return CryptoPP::Parity(temp);
  178. }
  179. PolynomialMod2& PolynomialMod2::operator=(const PolynomialMod2& t)
  180. {
  181. reg.Assign(t.reg);
  182. return *this;
  183. }
  184. PolynomialMod2& PolynomialMod2::operator^=(const PolynomialMod2& t)
  185. {
  186. reg.CleanGrow(t.reg.size());
  187. XorWords(reg, t.reg, t.reg.size());
  188. return *this;
  189. }
  190. PolynomialMod2 PolynomialMod2::Xor(const PolynomialMod2 &b) const
  191. {
  192. if (b.reg.size() >= reg.size())
  193. {
  194. PolynomialMod2 result((word)0, b.reg.size()*WORD_BITS);
  195. XorWords(result.reg, reg, b.reg, reg.size());
  196. CopyWords(result.reg+reg.size(), b.reg+reg.size(), b.reg.size()-reg.size());
  197. return result;
  198. }
  199. else
  200. {
  201. PolynomialMod2 result((word)0, reg.size()*WORD_BITS);
  202. XorWords(result.reg, reg, b.reg, b.reg.size());
  203. CopyWords(result.reg+b.reg.size(), reg+b.reg.size(), reg.size()-b.reg.size());
  204. return result;
  205. }
  206. }
  207. PolynomialMod2 PolynomialMod2::And(const PolynomialMod2 &b) const
  208. {
  209. PolynomialMod2 result((word)0, WORD_BITS*STDMIN(reg.size(), b.reg.size()));
  210. AndWords(result.reg, reg, b.reg, result.reg.size());
  211. return result;
  212. }
  213. PolynomialMod2 PolynomialMod2::Times(const PolynomialMod2 &b) const
  214. {
  215. PolynomialMod2 result((word)0, BitCount() + b.BitCount());
  216. for (int i=b.Degree(); i>=0; i--)
  217. {
  218. result <<= 1;
  219. if (b[i])
  220. XorWords(result.reg, reg, reg.size());
  221. }
  222. return result;
  223. }
  224. PolynomialMod2 PolynomialMod2::Squared() const
  225. {
  226. static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85};
  227. PolynomialMod2 result((word)0, 2*reg.size()*WORD_BITS);
  228. for (unsigned i=0; i<reg.size(); i++)
  229. {
  230. unsigned j;
  231. for (j=0; j<WORD_BITS; j+=8)
  232. result.reg[2*i] |= map[(reg[i] >> (j/2)) % 16] << j;
  233. for (j=0; j<WORD_BITS; j+=8)
  234. result.reg[2*i+1] |= map[(reg[i] >> (j/2 + WORD_BITS/2)) % 16] << j;
  235. }
  236. return result;
  237. }
  238. void PolynomialMod2::Divide(PolynomialMod2 &remainder, PolynomialMod2 &quotient,
  239. const PolynomialMod2 &dividend, const PolynomialMod2 &divisor)
  240. {
  241. if (!divisor)
  242. throw PolynomialMod2::DivideByZero();
  243. int degree = divisor.Degree();
  244. remainder.reg.CleanNew(BitsToWords(degree+1));
  245. if (dividend.BitCount() >= divisor.BitCount())
  246. quotient.reg.CleanNew(BitsToWords(dividend.BitCount() - divisor.BitCount() + 1));
  247. else
  248. quotient.reg.CleanNew(0);
  249. for (int i=dividend.Degree(); i>=0; i--)
  250. {
  251. remainder <<= 1;
  252. remainder.reg[0] |= dividend[i];
  253. if (remainder[degree])
  254. {
  255. remainder -= divisor;
  256. quotient.SetBit(i);
  257. }
  258. }
  259. }
  260. PolynomialMod2 PolynomialMod2::DividedBy(const PolynomialMod2 &b) const
  261. {
  262. PolynomialMod2 remainder, quotient;
  263. PolynomialMod2::Divide(remainder, quotient, *this, b);
  264. return quotient;
  265. }
  266. PolynomialMod2 PolynomialMod2::Modulo(const PolynomialMod2 &b) const
  267. {
  268. PolynomialMod2 remainder, quotient;
  269. PolynomialMod2::Divide(remainder, quotient, *this, b);
  270. return remainder;
  271. }
  272. PolynomialMod2& PolynomialMod2::operator<<=(unsigned int n)
  273. {
  274. if (!reg.size())
  275. return *this;
  276. int i;
  277. word u;
  278. word carry=0;
  279. word *r=reg;
  280. if (n==1) // special case code for most frequent case
  281. {
  282. i = (int)reg.size();
  283. while (i--)
  284. {
  285. u = *r;
  286. *r = (u << 1) | carry;
  287. carry = u >> (WORD_BITS-1);
  288. r++;
  289. }
  290. if (carry)
  291. {
  292. reg.Grow(reg.size()+1);
  293. reg[reg.size()-1] = carry;
  294. }
  295. return *this;
  296. }
  297. int shiftWords = n / WORD_BITS;
  298. int shiftBits = n % WORD_BITS;
  299. if (shiftBits)
  300. {
  301. i = (int)reg.size();
  302. while (i--)
  303. {
  304. u = *r;
  305. *r = (u << shiftBits) | carry;
  306. carry = u >> (WORD_BITS-shiftBits);
  307. r++;
  308. }
  309. }
  310. if (carry)
  311. {
  312. reg.Grow(reg.size()+shiftWords+1);
  313. reg[reg.size()-1] = carry;
  314. }
  315. else
  316. reg.Grow(reg.size()+shiftWords);
  317. if (shiftWords)
  318. {
  319. for (i = (int)reg.size()-1; i>=shiftWords; i--)
  320. reg[i] = reg[i-shiftWords];
  321. for (; i>=0; i--)
  322. reg[i] = 0;
  323. }
  324. return *this;
  325. }
  326. PolynomialMod2& PolynomialMod2::operator>>=(unsigned int n)
  327. {
  328. if (!reg.size())
  329. return *this;
  330. int shiftWords = n / WORD_BITS;
  331. int shiftBits = n % WORD_BITS;
  332. size_t i;
  333. word u;
  334. word carry=0;
  335. word *r=reg+reg.size()-1;
  336. if (shiftBits)
  337. {
  338. i = reg.size();
  339. while (i--)
  340. {
  341. u = *r;
  342. *r = (u >> shiftBits) | carry;
  343. carry = u << (WORD_BITS-shiftBits);
  344. r--;
  345. }
  346. }
  347. if (shiftWords)
  348. {
  349. for (i=0; i<reg.size()-shiftWords; i++)
  350. reg[i] = reg[i+shiftWords];
  351. for (; i<reg.size(); i++)
  352. reg[i] = 0;
  353. }
  354. return *this;
  355. }
  356. PolynomialMod2 PolynomialMod2::operator<<(unsigned int n) const
  357. {
  358. PolynomialMod2 result(*this);
  359. return result<<=n;
  360. }
  361. PolynomialMod2 PolynomialMod2::operator>>(unsigned int n) const
  362. {
  363. PolynomialMod2 result(*this);
  364. return result>>=n;
  365. }
  366. bool PolynomialMod2::operator!() const
  367. {
  368. for (unsigned i=0; i<reg.size(); i++)
  369. if (reg[i]) return false;
  370. return true;
  371. }
  372. bool PolynomialMod2::Equals(const PolynomialMod2 &rhs) const
  373. {
  374. size_t i, smallerSize = STDMIN(reg.size(), rhs.reg.size());
  375. for (i=0; i<smallerSize; i++)
  376. if (reg[i] != rhs.reg[i]) return false;
  377. for (i=smallerSize; i<reg.size(); i++)
  378. if (reg[i] != 0) return false;
  379. for (i=smallerSize; i<rhs.reg.size(); i++)
  380. if (rhs.reg[i] != 0) return false;
  381. return true;
  382. }
  383. std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a)
  384. {
  385. // Get relevant conversion specifications from ostream.
  386. long f = out.flags() & std::ios::basefield; // Get base digits.
  387. int bits, block;
  388. char suffix;
  389. switch(f)
  390. {
  391. case std::ios::oct :
  392. bits = 3;
  393. block = 4;
  394. suffix = 'o';
  395. break;
  396. case std::ios::hex :
  397. bits = 4;
  398. block = 2;
  399. suffix = 'h';
  400. break;
  401. default :
  402. bits = 1;
  403. block = 8;
  404. suffix = 'b';
  405. }
  406. if (!a)
  407. return out << '0' << suffix;
  408. SecBlock<char> s(a.BitCount()/bits+1);
  409. unsigned i;
  410. static const char upper[]="0123456789ABCDEF";
  411. static const char lower[]="0123456789abcdef";
  412. const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower;
  413. for (i=0; i*bits < a.BitCount(); i++)
  414. {
  415. int digit=0;
  416. for (int j=0; j<bits; j++)
  417. digit |= a[i*bits+j] << j;
  418. s[i]=vec[digit];
  419. }
  420. while (i--)
  421. {
  422. out << s[i];
  423. if (i && (i%block)==0)
  424. out << ',';
  425. }
  426. return out << suffix;
  427. }
  428. PolynomialMod2 PolynomialMod2::Gcd(const PolynomialMod2 &a, const PolynomialMod2 &b)
  429. {
  430. return EuclideanDomainOf<PolynomialMod2>().Gcd(a, b);
  431. }
  432. PolynomialMod2 PolynomialMod2::InverseMod(const PolynomialMod2 &modulus) const
  433. {
  434. typedef EuclideanDomainOf<PolynomialMod2> Domain;
  435. return QuotientRing<Domain>(Domain(), modulus).MultiplicativeInverse(*this);
  436. }
  437. bool PolynomialMod2::IsIrreducible() const
  438. {
  439. signed int d = Degree();
  440. if (d <= 0)
  441. return false;
  442. PolynomialMod2 t(2), u(t);
  443. for (int i=1; i<=d/2; i++)
  444. {
  445. u = u.Squared()%(*this);
  446. if (!Gcd(u+t, *this).IsUnit())
  447. return false;
  448. }
  449. return true;
  450. }
  451. // ********************************************************
  452. GF2NP::GF2NP(const PolynomialMod2 &modulus)
  453. : QuotientRing<EuclideanDomainOf<PolynomialMod2> >(EuclideanDomainOf<PolynomialMod2>(), modulus), m(modulus.Degree())
  454. {
  455. }
  456. GF2NP::Element GF2NP::SquareRoot(const Element &a) const
  457. {
  458. Element r = a;
  459. for (unsigned int i=1; i<m; i++)
  460. r = Square(r);
  461. return r;
  462. }
  463. GF2NP::Element GF2NP::HalfTrace(const Element &a) const
  464. {
  465. assert(m%2 == 1);
  466. Element h = a;
  467. for (unsigned int i=1; i<=(m-1)/2; i++)
  468. h = Add(Square(Square(h)), a);
  469. return h;
  470. }
  471. GF2NP::Element GF2NP::SolveQuadraticEquation(const Element &a) const
  472. {
  473. if (m%2 == 0)
  474. {
  475. Element z, w;
  476. RandomPool rng;
  477. do
  478. {
  479. Element p((RandomNumberGenerator &)rng, m);
  480. z = PolynomialMod2::Zero();
  481. w = p;
  482. for (unsigned int i=1; i<=m-1; i++)
  483. {
  484. w = Square(w);
  485. z = Square(z);
  486. Accumulate(z, Multiply(w, a));
  487. Accumulate(w, p);
  488. }
  489. } while (w.IsZero());
  490. return z;
  491. }
  492. else
  493. return HalfTrace(a);
  494. }
  495. // ********************************************************
  496. GF2NT::GF2NT(unsigned int t0, unsigned int t1, unsigned int t2)
  497. : GF2NP(PolynomialMod2::Trinomial(t0, t1, t2))
  498. , t0(t0), t1(t1)
  499. , result((word)0, m)
  500. {
  501. assert(t0 > t1 && t1 > t2 && t2==0);
  502. }
  503. const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const
  504. {
  505. if (t0-t1 < WORD_BITS)
  506. return GF2NP::MultiplicativeInverse(a);
  507. SecWordBlock T(m_modulus.reg.size() * 4);
  508. word *b = T;
  509. word *c = T+m_modulus.reg.size();
  510. word *f = T+2*m_modulus.reg.size();
  511. word *g = T+3*m_modulus.reg.size();
  512. size_t bcLen=1, fgLen=m_modulus.reg.size();
  513. unsigned int k=0;
  514. SetWords(T, 0, 3*m_modulus.reg.size());
  515. b[0]=1;
  516. assert(a.reg.size() <= m_modulus.reg.size());
  517. CopyWords(f, a.reg, a.reg.size());
  518. CopyWords(g, m_modulus.reg, m_modulus.reg.size());
  519. while (1)
  520. {
  521. word t=f[0];
  522. while (!t)
  523. {
  524. ShiftWordsRightByWords(f, fgLen, 1);
  525. if (c[bcLen-1])
  526. bcLen++;
  527. assert(bcLen <= m_modulus.reg.size());
  528. ShiftWordsLeftByWords(c, bcLen, 1);
  529. k+=WORD_BITS;
  530. t=f[0];
  531. }
  532. unsigned int i=0;
  533. while (t%2 == 0)
  534. {
  535. t>>=1;
  536. i++;
  537. }
  538. k+=i;
  539. if (t==1 && CountWords(f, fgLen)==1)
  540. break;
  541. if (i==1)
  542. {
  543. ShiftWordsRightByBits(f, fgLen, 1);
  544. t=ShiftWordsLeftByBits(c, bcLen, 1);
  545. }
  546. else
  547. {
  548. ShiftWordsRightByBits(f, fgLen, i);
  549. t=ShiftWordsLeftByBits(c, bcLen, i);
  550. }
  551. if (t)
  552. {
  553. c[bcLen] = t;
  554. bcLen++;
  555. assert(bcLen <= m_modulus.reg.size());
  556. }
  557. if (f[fgLen-1]==0 && g[fgLen-1]==0)
  558. fgLen--;
  559. if (f[fgLen-1] < g[fgLen-1])
  560. {
  561. std::swap(f, g);
  562. std::swap(b, c);
  563. }
  564. XorWords(f, g, fgLen);
  565. XorWords(b, c, bcLen);
  566. }
  567. while (k >= WORD_BITS)
  568. {
  569. word temp = b[0];
  570. // right shift b
  571. for (unsigned i=0; i+1<BitsToWords(m); i++)
  572. b[i] = b[i+1];
  573. b[BitsToWords(m)-1] = 0;
  574. if (t1 < WORD_BITS)
  575. for (unsigned int j=0; j<WORD_BITS-t1; j++)
  576. temp ^= ((temp >> j) & 1) << (t1 + j);
  577. else
  578. b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
  579. if (t1 % WORD_BITS)
  580. b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
  581. if (t0%WORD_BITS)
  582. {
  583. b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
  584. b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
  585. }
  586. else
  587. b[t0/WORD_BITS-1] ^= temp;
  588. k -= WORD_BITS;
  589. }
  590. if (k)
  591. {
  592. word temp = b[0] << (WORD_BITS - k);
  593. ShiftWordsRightByBits(b, BitsToWords(m), k);
  594. if (t1 < WORD_BITS)
  595. for (unsigned int j=0; j<WORD_BITS-t1; j++)
  596. temp ^= ((temp >> j) & 1) << (t1 + j);
  597. else
  598. b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
  599. if (t1 % WORD_BITS)
  600. b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
  601. if (t0%WORD_BITS)
  602. {
  603. b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
  604. b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
  605. }
  606. else
  607. b[t0/WORD_BITS-1] ^= temp;
  608. }
  609. CopyWords(result.reg.begin(), b, result.reg.size());
  610. return result;
  611. }
  612. const GF2NT::Element& GF2NT::Multiply(const Element &a, const Element &b) const
  613. {
  614. size_t aSize = STDMIN(a.reg.size(), result.reg.size());
  615. Element r((word)0, m);
  616. for (int i=m-1; i>=0; i--)
  617. {
  618. if (r[m-1])
  619. {
  620. ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
  621. XorWords(r.reg.begin(), m_modulus.reg, r.reg.size());
  622. }
  623. else
  624. ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
  625. if (b[i])
  626. XorWords(r.reg.begin(), a.reg, aSize);
  627. }
  628. if (m%WORD_BITS)
  629. r.reg.begin()[r.reg.size()-1] = (word)Crop(r.reg[r.reg.size()-1], m%WORD_BITS);
  630. CopyWords(result.reg.begin(), r.reg.begin(), result.reg.size());
  631. return result;
  632. }
  633. const GF2NT::Element& GF2NT::Reduced(const Element &a) const
  634. {
  635. if (t0-t1 < WORD_BITS)
  636. return m_domain.Mod(a, m_modulus);
  637. SecWordBlock b(a.reg);
  638. size_t i;
  639. for (i=b.size()-1; i>=BitsToWords(t0); i--)
  640. {
  641. word temp = b[i];
  642. if (t0%WORD_BITS)
  643. {
  644. b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
  645. b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS);
  646. }
  647. else
  648. b[i-t0/WORD_BITS] ^= temp;
  649. if ((t0-t1)%WORD_BITS)
  650. {
  651. b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
  652. b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
  653. }
  654. else
  655. b[i-(t0-t1)/WORD_BITS] ^= temp;
  656. }
  657. if (i==BitsToWords(t0)-1 && t0%WORD_BITS)
  658. {
  659. word mask = ((word)1<<(t0%WORD_BITS))-1;
  660. word temp = b[i] & ~mask;
  661. b[i] &= mask;
  662. b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
  663. if ((t0-t1)%WORD_BITS)
  664. {
  665. b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
  666. if ((t0-t1)%WORD_BITS > t0%WORD_BITS)
  667. b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
  668. else
  669. assert(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0);
  670. }
  671. else
  672. b[i-(t0-t1)/WORD_BITS] ^= temp;
  673. }
  674. SetWords(result.reg.begin(), 0, result.reg.size());
  675. CopyWords(result.reg.begin(), b, STDMIN(b.size(), result.reg.size()));
  676. return result;
  677. }
  678. void GF2NP::DEREncodeElement(BufferedTransformation &out, const Element &a) const
  679. {
  680. a.DEREncodeAsOctetString(out, MaxElementByteLength());
  681. }
  682. void GF2NP::BERDecodeElement(BufferedTransformation &in, Element &a) const
  683. {
  684. a.BERDecodeAsOctetString(in, MaxElementByteLength());
  685. }
  686. void GF2NT::DEREncode(BufferedTransformation &bt) const
  687. {
  688. DERSequenceEncoder seq(bt);
  689. ASN1::characteristic_two_field().DEREncode(seq);
  690. DERSequenceEncoder parameters(seq);
  691. DEREncodeUnsigned(parameters, m);
  692. ASN1::tpBasis().DEREncode(parameters);
  693. DEREncodeUnsigned(parameters, t1);
  694. parameters.MessageEnd();
  695. seq.MessageEnd();
  696. }
  697. void GF2NPP::DEREncode(BufferedTransformation &bt) const
  698. {
  699. DERSequenceEncoder seq(bt);
  700. ASN1::characteristic_two_field().DEREncode(seq);
  701. DERSequenceEncoder parameters(seq);
  702. DEREncodeUnsigned(parameters, m);
  703. ASN1::ppBasis().DEREncode(parameters);
  704. DERSequenceEncoder pentanomial(parameters);
  705. DEREncodeUnsigned(pentanomial, t3);
  706. DEREncodeUnsigned(pentanomial, t2);
  707. DEREncodeUnsigned(pentanomial, t1);
  708. pentanomial.MessageEnd();
  709. parameters.MessageEnd();
  710. seq.MessageEnd();
  711. }
  712. GF2NP * BERDecodeGF2NP(BufferedTransformation &bt)
  713. {
  714. // VC60 workaround: auto_ptr lacks reset()
  715. member_ptr<GF2NP> result;
  716. BERSequenceDecoder seq(bt);
  717. if (OID(seq) != ASN1::characteristic_two_field())
  718. BERDecodeError();
  719. BERSequenceDecoder parameters(seq);
  720. unsigned int m;
  721. BERDecodeUnsigned(parameters, m);
  722. OID oid(parameters);
  723. if (oid == ASN1::tpBasis())
  724. {
  725. unsigned int t1;
  726. BERDecodeUnsigned(parameters, t1);
  727. result.reset(new GF2NT(m, t1, 0));
  728. }
  729. else if (oid == ASN1::ppBasis())
  730. {
  731. unsigned int t1, t2, t3;
  732. BERSequenceDecoder pentanomial(parameters);
  733. BERDecodeUnsigned(pentanomial, t3);
  734. BERDecodeUnsigned(pentanomial, t2);
  735. BERDecodeUnsigned(pentanomial, t1);
  736. pentanomial.MessageEnd();
  737. result.reset(new GF2NPP(m, t3, t2, t1, 0));
  738. }
  739. else
  740. {
  741. BERDecodeError();
  742. return NULL;
  743. }
  744. parameters.MessageEnd();
  745. seq.MessageEnd();
  746. return result.release();
  747. }
  748. NAMESPACE_END
  749. #endif