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.

903 lines
19 KiB

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