Crypto++  5.6.4
Free C++ class library of cryptographic schemes
gf2n.cpp
1 // gf2n.cpp - written and placed in the public domain by Wei Dai
2 
3 #include "pch.h"
4 #include "config.h"
5 
6 #ifndef CRYPTOPP_IMPORTS
7 
8 #include "cryptlib.h"
9 #include "algebra.h"
10 #include "randpool.h"
11 #include "filters.h"
12 #include "smartptr.h"
13 #include "words.h"
14 #include "misc.h"
15 #include "gf2n.h"
16 #include "asn.h"
17 #include "oids.h"
18 
19 #include <iostream>
20 
21 NAMESPACE_BEGIN(CryptoPP)
22 
24 {
25 }
26 
27 PolynomialMod2::PolynomialMod2(word value, size_t bitLength)
28  : reg(BitsToWords(bitLength))
29 {
30  assert(value==0 || reg.size()>0);
31 
32  if (reg.size() > 0)
33  {
34  reg[0] = value;
35  SetWords(reg+1, 0, reg.size()-1);
36  }
37 }
38 
40  : reg(t.reg.size())
41 {
42  CopyWords(reg, t.reg, reg.size());
43 }
44 
45 void PolynomialMod2::Randomize(RandomNumberGenerator &rng, size_t nbits)
46 {
47  const size_t nbytes = nbits/8 + 1;
48  SecByteBlock buf(nbytes);
49  rng.GenerateBlock(buf, nbytes);
50  buf[0] = (byte)Crop(buf[0], nbits % 8);
51  Decode(buf, nbytes);
52 }
53 
55 {
56  PolynomialMod2 result((word)0, bitLength);
57  SetWords(result.reg, word(SIZE_MAX), result.reg.size());
58  if (bitLength%WORD_BITS)
59  result.reg[result.reg.size()-1] = (word)Crop(result.reg[result.reg.size()-1], bitLength%WORD_BITS);
60  return result;
61 }
62 
63 void PolynomialMod2::SetBit(size_t n, int value)
64 {
65  if (value)
66  {
67  reg.CleanGrow(n/WORD_BITS + 1);
68  reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS));
69  }
70  else
71  {
72  if (n/WORD_BITS < reg.size())
73  reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS));
74  }
75 }
76 
77 byte PolynomialMod2::GetByte(size_t n) const
78 {
79  if (n/WORD_SIZE >= reg.size())
80  return 0;
81  else
82  return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
83 }
84 
85 void PolynomialMod2::SetByte(size_t n, byte value)
86 {
87  reg.CleanGrow(BytesToWords(n+1));
88  reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
89  reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
90 }
91 
93 {
94  PolynomialMod2 r((word)0, i+1);
95  r.SetBit(i);
96  return r;
97 }
98 
99 PolynomialMod2 PolynomialMod2::Trinomial(size_t t0, size_t t1, size_t t2)
100 {
101  // Asserts and checks due to Bing Shi
102  assert(t0 > t1);
103  assert(t1 > t2);
104 
105  // The test is odd because of ECIES<EC2N>. The basis is t0, but the other coefficients are not in descending order.
106  if (t1 > t0 || t2 > t0)
107  throw InvalidArgument("PolynomialMod2: coefficients must be in descending order");
108 
109  PolynomialMod2 r((word)0, t0+1);
110  r.SetBit(t0);
111  r.SetBit(t1);
112  r.SetBit(t2);
113  return r;
114 }
115 
116 PolynomialMod2 PolynomialMod2::Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4)
117 {
118  // Asserts and checks due to Bing Shi
119  assert(t0 > t1);
120  assert(t1 > t2);
121  assert(t2 > t3);
122  assert(t3 > t4);
123 
124  // The test is odd because of ECIES<EC2N>. The basis is t0, but the other coefficients are not in descending order.
125  if (t1 > t0 || t2 > t0 || t3 > t0 || t4 > t0)
126  throw InvalidArgument("PolynomialMod2: coefficients must be in descending order");
127 
128  PolynomialMod2 r((word)0, t0+1);
129  r.SetBit(t0);
130  r.SetBit(t1);
131  r.SetBit(t2);
132  r.SetBit(t3);
133  r.SetBit(t4);
134  return r;
135 }
136 
137 template <word i>
139 {
140  PolynomialMod2 * operator()() const
141  {
142  return new PolynomialMod2(i);
143  }
144 };
145 
146 const PolynomialMod2 &PolynomialMod2::Zero()
147 {
148  return Singleton<PolynomialMod2>().Ref();
149 }
150 
151 const PolynomialMod2 &PolynomialMod2::One()
152 {
154 }
155 
156 void PolynomialMod2::Decode(const byte *input, size_t inputLen)
157 {
158  StringStore store(input, inputLen);
159  Decode(store, inputLen);
160 }
161 
162 void PolynomialMod2::Encode(byte *output, size_t outputLen) const
163 {
164  ArraySink sink(output, outputLen);
165  Encode(sink, outputLen);
166 }
167 
168 void PolynomialMod2::Decode(BufferedTransformation &bt, size_t inputLen)
169 {
170  reg.CleanNew(BytesToWords(inputLen));
171 
172  for (size_t i=inputLen; i > 0; i--)
173  {
174  byte b;
175  bt.Get(b);
176  reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8;
177  }
178 }
179 
180 void PolynomialMod2::Encode(BufferedTransformation &bt, size_t outputLen) const
181 {
182  for (size_t i=outputLen; i > 0; i--)
183  bt.Put(GetByte(i-1));
184 }
185 
187 {
188  DERGeneralEncoder enc(bt, OCTET_STRING);
189  Encode(enc, length);
190  enc.MessageEnd();
191 }
192 
194 {
195  BERGeneralDecoder dec(bt, OCTET_STRING);
196  if (!dec.IsDefiniteLength() || dec.RemainingLength() != length)
197  BERDecodeError();
198  Decode(dec, length);
199  dec.MessageEnd();
200 }
201 
202 unsigned int PolynomialMod2::WordCount() const
203 {
204  return (unsigned int)CountWords(reg, reg.size());
205 }
206 
207 unsigned int PolynomialMod2::ByteCount() const
208 {
209  unsigned wordCount = WordCount();
210  if (wordCount)
211  return (wordCount-1)*WORD_SIZE + BytePrecision(reg[wordCount-1]);
212  else
213  return 0;
214 }
215 
216 unsigned int PolynomialMod2::BitCount() const
217 {
218  unsigned wordCount = WordCount();
219  if (wordCount)
220  return (wordCount-1)*WORD_BITS + BitPrecision(reg[wordCount-1]);
221  else
222  return 0;
223 }
224 
225 unsigned int PolynomialMod2::Parity() const
226 {
227  unsigned i;
228  word temp=0;
229  for (i=0; i<reg.size(); i++)
230  temp ^= reg[i];
231  return CryptoPP::Parity(temp);
232 }
233 
234 PolynomialMod2& PolynomialMod2::operator=(const PolynomialMod2& t)
235 {
236  reg.Assign(t.reg);
237  return *this;
238 }
239 
240 PolynomialMod2& PolynomialMod2::operator^=(const PolynomialMod2& t)
241 {
242  reg.CleanGrow(t.reg.size());
243  XorWords(reg, t.reg, t.reg.size());
244  return *this;
245 }
246 
247 PolynomialMod2 PolynomialMod2::Xor(const PolynomialMod2 &b) const
248 {
249  if (b.reg.size() >= reg.size())
250  {
251  PolynomialMod2 result((word)0, b.reg.size()*WORD_BITS);
252  XorWords(result.reg, reg, b.reg, reg.size());
253  CopyWords(result.reg+reg.size(), b.reg+reg.size(), b.reg.size()-reg.size());
254  return result;
255  }
256  else
257  {
258  PolynomialMod2 result((word)0, reg.size()*WORD_BITS);
259  XorWords(result.reg, reg, b.reg, b.reg.size());
260  CopyWords(result.reg+b.reg.size(), reg+b.reg.size(), reg.size()-b.reg.size());
261  return result;
262  }
263 }
264 
265 PolynomialMod2 PolynomialMod2::And(const PolynomialMod2 &b) const
266 {
267  PolynomialMod2 result((word)0, WORD_BITS*STDMIN(reg.size(), b.reg.size()));
268  AndWords(result.reg, reg, b.reg, result.reg.size());
269  return result;
270 }
271 
272 PolynomialMod2 PolynomialMod2::Times(const PolynomialMod2 &b) const
273 {
274  PolynomialMod2 result((word)0, BitCount() + b.BitCount());
275 
276  for (int i=b.Degree(); i>=0; i--)
277  {
278  result <<= 1;
279  if (b[i])
280  XorWords(result.reg, reg, reg.size());
281  }
282  return result;
283 }
284 
285 PolynomialMod2 PolynomialMod2::Squared() const
286 {
287  static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85};
288 
289  PolynomialMod2 result((word)0, 2*reg.size()*WORD_BITS);
290 
291  for (unsigned i=0; i<reg.size(); i++)
292  {
293  unsigned j;
294 
295  for (j=0; j<WORD_BITS; j+=8)
296  result.reg[2*i] |= map[(reg[i] >> (j/2)) % 16] << j;
297 
298  for (j=0; j<WORD_BITS; j+=8)
299  result.reg[2*i+1] |= map[(reg[i] >> (j/2 + WORD_BITS/2)) % 16] << j;
300  }
301 
302  return result;
303 }
304 
306  const PolynomialMod2 &dividend, const PolynomialMod2 &divisor)
307 {
308  if (!divisor)
310 
311  int degree = divisor.Degree();
312  remainder.reg.CleanNew(BitsToWords(degree+1));
313  if (dividend.BitCount() >= divisor.BitCount())
314  quotient.reg.CleanNew(BitsToWords(dividend.BitCount() - divisor.BitCount() + 1));
315  else
316  quotient.reg.CleanNew(0);
317 
318  for (int i=dividend.Degree(); i>=0; i--)
319  {
320  remainder <<= 1;
321  remainder.reg[0] |= dividend[i];
322  if (remainder[degree])
323  {
324  remainder -= divisor;
325  quotient.SetBit(i);
326  }
327  }
328 }
329 
330 PolynomialMod2 PolynomialMod2::DividedBy(const PolynomialMod2 &b) const
331 {
332  PolynomialMod2 remainder, quotient;
333  PolynomialMod2::Divide(remainder, quotient, *this, b);
334  return quotient;
335 }
336 
337 PolynomialMod2 PolynomialMod2::Modulo(const PolynomialMod2 &b) const
338 {
339  PolynomialMod2 remainder, quotient;
340  PolynomialMod2::Divide(remainder, quotient, *this, b);
341  return remainder;
342 }
343 
344 PolynomialMod2& PolynomialMod2::operator<<=(unsigned int n)
345 {
346 #if !defined(NDEBUG)
347  int x; CRYPTOPP_UNUSED(x);
348  assert(SafeConvert(n,x));
349 #endif
350 
351  if (!reg.size())
352  return *this;
353 
354  int i;
355  word u;
356  word carry=0;
357  word *r=reg;
358 
359  if (n==1) // special case code for most frequent case
360  {
361  i = (int)reg.size();
362  while (i--)
363  {
364  u = *r;
365  *r = (u << 1) | carry;
366  carry = u >> (WORD_BITS-1);
367  r++;
368  }
369 
370  if (carry)
371  {
372  reg.Grow(reg.size()+1);
373  reg[reg.size()-1] = carry;
374  }
375 
376  return *this;
377  }
378 
379  const int shiftWords = n / WORD_BITS;
380  const int shiftBits = n % WORD_BITS;
381 
382  if (shiftBits)
383  {
384  i = (int)reg.size();
385  while (i--)
386  {
387  u = *r;
388  *r = (u << shiftBits) | carry;
389  carry = u >> (WORD_BITS-shiftBits);
390  r++;
391  }
392  }
393 
394  if (carry)
395  {
396  // Thanks to Apatryda, http://github.com/weidai11/cryptopp/issues/64
397  const size_t carryIndex = reg.size();
398  reg.Grow(reg.size()+shiftWords+!!shiftBits);
399  reg[carryIndex] = carry;
400  }
401  else
402  reg.Grow(reg.size()+shiftWords);
403 
404  if (shiftWords)
405  {
406  for (i = (int)reg.size()-1; i>=shiftWords; i--)
407  reg[i] = reg[i-shiftWords];
408  for (; i>=0; i--)
409  reg[i] = 0;
410  }
411 
412  return *this;
413 }
414 
415 PolynomialMod2& PolynomialMod2::operator>>=(unsigned int n)
416 {
417  if (!reg.size())
418  return *this;
419 
420  int shiftWords = n / WORD_BITS;
421  int shiftBits = n % WORD_BITS;
422 
423  size_t i;
424  word u;
425  word carry=0;
426  word *r=reg+reg.size()-1;
427 
428  if (shiftBits)
429  {
430  i = reg.size();
431  while (i--)
432  {
433  u = *r;
434  *r = (u >> shiftBits) | carry;
435  carry = u << (WORD_BITS-shiftBits);
436  r--;
437  }
438  }
439 
440  if (shiftWords)
441  {
442  for (i=0; i<reg.size()-shiftWords; i++)
443  reg[i] = reg[i+shiftWords];
444  for (; i<reg.size(); i++)
445  reg[i] = 0;
446  }
447 
448  return *this;
449 }
450 
451 PolynomialMod2 PolynomialMod2::operator<<(unsigned int n) const
452 {
453  PolynomialMod2 result(*this);
454  return result<<=n;
455 }
456 
457 PolynomialMod2 PolynomialMod2::operator>>(unsigned int n) const
458 {
459  PolynomialMod2 result(*this);
460  return result>>=n;
461 }
462 
463 bool PolynomialMod2::operator!() const
464 {
465  for (unsigned i=0; i<reg.size(); i++)
466  if (reg[i]) return false;
467  return true;
468 }
469 
470 bool PolynomialMod2::Equals(const PolynomialMod2 &rhs) const
471 {
472  size_t i, smallerSize = STDMIN(reg.size(), rhs.reg.size());
473 
474  for (i=0; i<smallerSize; i++)
475  if (reg[i] != rhs.reg[i]) return false;
476 
477  for (i=smallerSize; i<reg.size(); i++)
478  if (reg[i] != 0) return false;
479 
480  for (i=smallerSize; i<rhs.reg.size(); i++)
481  if (rhs.reg[i] != 0) return false;
482 
483  return true;
484 }
485 
486 std::ostream& operator<<(std::ostream& out, const PolynomialMod2 &a)
487 {
488  // Get relevant conversion specifications from ostream.
489  long f = out.flags() & std::ios::basefield; // Get base digits.
490  int bits, block;
491  char suffix;
492  switch(f)
493  {
494  case std::ios::oct :
495  bits = 3;
496  block = 4;
497  suffix = 'o';
498  break;
499  case std::ios::hex :
500  bits = 4;
501  block = 2;
502  suffix = 'h';
503  break;
504  default :
505  bits = 1;
506  block = 8;
507  suffix = 'b';
508  }
509 
510  if (!a)
511  return out << '0' << suffix;
512 
513  SecBlock<char> s(a.BitCount()/bits+1);
514  unsigned i;
515 
516  static const char upper[]="0123456789ABCDEF";
517  static const char lower[]="0123456789abcdef";
518  const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower;
519 
520  for (i=0; i*bits < a.BitCount(); i++)
521  {
522  int digit=0;
523  for (int j=0; j<bits; j++)
524  digit |= a[i*bits+j] << j;
525  s[i]=vec[digit];
526  }
527 
528  while (i--)
529  {
530  out << s[i];
531  if (i && (i%block)==0)
532  out << ',';
533  }
534 
535  return out << suffix;
536 }
537 
539 {
540  return EuclideanDomainOf<PolynomialMod2>().Gcd(a, b);
541 }
542 
544 {
545  typedef EuclideanDomainOf<PolynomialMod2> Domain;
546  return QuotientRing<Domain>(Domain(), modulus).MultiplicativeInverse(*this);
547 }
548 
550 {
551  signed int d = Degree();
552  if (d <= 0)
553  return false;
554 
555  PolynomialMod2 t(2), u(t);
556  for (int i=1; i<=d/2; i++)
557  {
558  u = u.Squared()%(*this);
559  if (!Gcd(u+t, *this).IsUnit())
560  return false;
561  }
562  return true;
563 }
564 
565 // ********************************************************
566 
567 GF2NP::GF2NP(const PolynomialMod2 &modulus)
568  : QuotientRing<EuclideanDomainOf<PolynomialMod2> >(EuclideanDomainOf<PolynomialMod2>(), modulus), m(modulus.Degree())
569 {
570 }
571 
572 GF2NP::Element GF2NP::SquareRoot(const Element &a) const
573 {
574  Element r = a;
575  for (unsigned int i=1; i<m; i++)
576  r = Square(r);
577  return r;
578 }
579 
580 GF2NP::Element GF2NP::HalfTrace(const Element &a) const
581 {
582  assert(m%2 == 1);
583  Element h = a;
584  for (unsigned int i=1; i<=(m-1)/2; i++)
585  h = Add(Square(Square(h)), a);
586  return h;
587 }
588 
589 GF2NP::Element GF2NP::SolveQuadraticEquation(const Element &a) const
590 {
591  if (m%2 == 0)
592  {
593  Element z, w;
594  RandomPool rng;
595  do
596  {
597  Element p((RandomNumberGenerator &)rng, m);
598  z = PolynomialMod2::Zero();
599  w = p;
600  for (unsigned int i=1; i<=m-1; i++)
601  {
602  w = Square(w);
603  z = Square(z);
604  Accumulate(z, Multiply(w, a));
605  Accumulate(w, p);
606  }
607  } while (w.IsZero());
608  return z;
609  }
610  else
611  return HalfTrace(a);
612 }
613 
614 // ********************************************************
615 
616 GF2NT::GF2NT(unsigned int t0, unsigned int t1, unsigned int t2)
617  : GF2NP(PolynomialMod2::Trinomial(t0, t1, t2))
618  , t0(t0), t1(t1)
619  , result((word)0, m)
620 {
621  // Asserts and checks due to Bing Shi
622  assert(t0 > t1 && t1 > t2 && t2==0);
623 
624  // The test is odd because of ECIES<EC2N>. The basis is t0, but the other coefficients are not in descending order.
625  if (t1 > t0 || t2 > t0)
626  throw InvalidArgument("GF2NT: coefficients must be in descending order");
627 }
628 
629 const GF2NT::Element& GF2NT::MultiplicativeInverse(const Element &a) const
630 {
631  if (t0-t1 < WORD_BITS)
633 
634  SecWordBlock T(m_modulus.reg.size() * 4);
635  word *b = T;
636  word *c = T+m_modulus.reg.size();
637  word *f = T+2*m_modulus.reg.size();
638  word *g = T+3*m_modulus.reg.size();
639  size_t bcLen=1, fgLen=m_modulus.reg.size();
640  unsigned int k=0;
641 
642  SetWords(T, 0, 3*m_modulus.reg.size());
643  b[0]=1;
644  assert(a.reg.size() <= m_modulus.reg.size());
645  CopyWords(f, a.reg, a.reg.size());
646  CopyWords(g, m_modulus.reg, m_modulus.reg.size());
647 
648  while (1)
649  {
650  word t=f[0];
651  while (!t)
652  {
653  ShiftWordsRightByWords(f, fgLen, 1);
654  if (c[bcLen-1])
655  bcLen++;
656  assert(bcLen <= m_modulus.reg.size());
657  ShiftWordsLeftByWords(c, bcLen, 1);
658  k+=WORD_BITS;
659  t=f[0];
660  }
661 
662  unsigned int i=0;
663  while (t%2 == 0)
664  {
665  t>>=1;
666  i++;
667  }
668  k+=i;
669 
670  if (t==1 && CountWords(f, fgLen)==1)
671  break;
672 
673  if (i==1)
674  {
675  ShiftWordsRightByBits(f, fgLen, 1);
676  t=ShiftWordsLeftByBits(c, bcLen, 1);
677  }
678  else
679  {
680  ShiftWordsRightByBits(f, fgLen, i);
681  t=ShiftWordsLeftByBits(c, bcLen, i);
682  }
683  if (t)
684  {
685  c[bcLen] = t;
686  bcLen++;
687  assert(bcLen <= m_modulus.reg.size());
688  }
689 
690  if (f[fgLen-1]==0 && g[fgLen-1]==0)
691  fgLen--;
692 
693  if (f[fgLen-1] < g[fgLen-1])
694  {
695  std::swap(f, g);
696  std::swap(b, c);
697  }
698 
699  XorWords(f, g, fgLen);
700  XorWords(b, c, bcLen);
701  }
702 
703  while (k >= WORD_BITS)
704  {
705  word temp = b[0];
706  // right shift b
707  for (unsigned i=0; i+1<BitsToWords(m); i++)
708  b[i] = b[i+1];
709  b[BitsToWords(m)-1] = 0;
710 
711  // TODO: the shift by "t1+j" (64-bits) is being flagged as potential UB
712  // temp ^= ((temp >> j) & 1) << ((t1 + j) & (sizeof(temp)*8-1));
713  if (t1 < WORD_BITS)
714  for (unsigned int j=0; j<WORD_BITS-t1; j++)
715  temp ^= ((temp >> j) & 1) << (t1 + j);
716  else
717  b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
718 
719  if (t1 % WORD_BITS)
720  b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
721 
722  if (t0%WORD_BITS)
723  {
724  b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
725  b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
726  }
727  else
728  b[t0/WORD_BITS-1] ^= temp;
729 
730  k -= WORD_BITS;
731  }
732 
733  if (k)
734  {
735  word temp = b[0] << (WORD_BITS - k);
736  ShiftWordsRightByBits(b, BitsToWords(m), k);
737 
738  if (t1 < WORD_BITS)
739  {
740  for (unsigned int j=0; j<WORD_BITS-t1; j++)
741  {
742  // Coverity finding on shift amount of 'word x << (t1+j)'.
743  assert(t1+j < WORD_BITS);
744  temp ^= ((temp >> j) & 1) << (t1 + j);
745  }
746  }
747  else
748  {
749  b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
750  }
751 
752  if (t1 % WORD_BITS)
753  b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
754 
755  if (t0%WORD_BITS)
756  {
757  b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
758  b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
759  }
760  else
761  b[t0/WORD_BITS-1] ^= temp;
762  }
763 
764  CopyWords(result.reg.begin(), b, result.reg.size());
765  return result;
766 }
767 
768 const GF2NT::Element& GF2NT::Multiply(const Element &a, const Element &b) const
769 {
770  size_t aSize = STDMIN(a.reg.size(), result.reg.size());
771  Element r((word)0, m);
772 
773  for (int i=m-1; i>=0; i--)
774  {
775  if (r[m-1])
776  {
777  ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
778  XorWords(r.reg.begin(), m_modulus.reg, r.reg.size());
779  }
780  else
781  ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
782 
783  if (b[i])
784  XorWords(r.reg.begin(), a.reg, aSize);
785  }
786 
787  if (m%WORD_BITS)
788  r.reg.begin()[r.reg.size()-1] = (word)Crop(r.reg[r.reg.size()-1], m%WORD_BITS);
789 
790  CopyWords(result.reg.begin(), r.reg.begin(), result.reg.size());
791  return result;
792 }
793 
794 const GF2NT::Element& GF2NT::Reduced(const Element &a) const
795 {
796  if (t0-t1 < WORD_BITS)
797  return m_domain.Mod(a, m_modulus);
798 
799  SecWordBlock b(a.reg);
800 
801  size_t i;
802  for (i=b.size()-1; i>=BitsToWords(t0); i--)
803  {
804  word temp = b[i];
805 
806  if (t0%WORD_BITS)
807  {
808  b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
809  b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS);
810  }
811  else
812  b[i-t0/WORD_BITS] ^= temp;
813 
814  if ((t0-t1)%WORD_BITS)
815  {
816  b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
817  b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
818  }
819  else
820  b[i-(t0-t1)/WORD_BITS] ^= temp;
821  }
822 
823  if (i==BitsToWords(t0)-1 && t0%WORD_BITS)
824  {
825  word mask = ((word)1<<(t0%WORD_BITS))-1;
826  word temp = b[i] & ~mask;
827  b[i] &= mask;
828 
829  b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
830 
831  if ((t0-t1)%WORD_BITS)
832  {
833  b[i-(t0-t1)/WORD_BITS] ^= temp >> (t0-t1)%WORD_BITS;
834  if ((t0-t1)%WORD_BITS > t0%WORD_BITS)
835  b[i-(t0-t1)/WORD_BITS-1] ^= temp << (WORD_BITS - (t0-t1)%WORD_BITS);
836  else
837  assert(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0);
838  }
839  else
840  b[i-(t0-t1)/WORD_BITS] ^= temp;
841  }
842 
843  SetWords(result.reg.begin(), 0, result.reg.size());
844  CopyWords(result.reg.begin(), b, STDMIN(b.size(), result.reg.size()));
845  return result;
846 }
847 
848 void GF2NP::DEREncodeElement(BufferedTransformation &out, const Element &a) const
849 {
850  a.DEREncodeAsOctetString(out, MaxElementByteLength());
851 }
852 
853 void GF2NP::BERDecodeElement(BufferedTransformation &in, Element &a) const
854 {
855  a.BERDecodeAsOctetString(in, MaxElementByteLength());
856 }
857 
858 void GF2NT::DEREncode(BufferedTransformation &bt) const
859 {
860  DERSequenceEncoder seq(bt);
861  ASN1::characteristic_two_field().DEREncode(seq);
862  DERSequenceEncoder parameters(seq);
863  DEREncodeUnsigned(parameters, m);
864  ASN1::tpBasis().DEREncode(parameters);
865  DEREncodeUnsigned(parameters, t1);
866  parameters.MessageEnd();
867  seq.MessageEnd();
868 }
869 
870 void GF2NPP::DEREncode(BufferedTransformation &bt) const
871 {
872  DERSequenceEncoder seq(bt);
873  ASN1::characteristic_two_field().DEREncode(seq);
874  DERSequenceEncoder parameters(seq);
875  DEREncodeUnsigned(parameters, m);
876  ASN1::ppBasis().DEREncode(parameters);
877  DERSequenceEncoder pentanomial(parameters);
878  DEREncodeUnsigned(pentanomial, t3);
879  DEREncodeUnsigned(pentanomial, t2);
880  DEREncodeUnsigned(pentanomial, t1);
881  pentanomial.MessageEnd();
882  parameters.MessageEnd();
883  seq.MessageEnd();
884 }
885 
886 GF2NP * BERDecodeGF2NP(BufferedTransformation &bt)
887 {
888  member_ptr<GF2NP> result;
889 
890  BERSequenceDecoder seq(bt);
891  if (OID(seq) != ASN1::characteristic_two_field())
892  BERDecodeError();
893  BERSequenceDecoder parameters(seq);
894  unsigned int m;
895  BERDecodeUnsigned(parameters, m);
896  OID oid(parameters);
897  if (oid == ASN1::tpBasis())
898  {
899  unsigned int t1;
900  BERDecodeUnsigned(parameters, t1);
901  result.reset(new GF2NT(m, t1, 0));
902  }
903  else if (oid == ASN1::ppBasis())
904  {
905  unsigned int t1, t2, t3;
906  BERSequenceDecoder pentanomial(parameters);
907  BERDecodeUnsigned(pentanomial, t3);
908  BERDecodeUnsigned(pentanomial, t2);
909  BERDecodeUnsigned(pentanomial, t1);
910  pentanomial.MessageEnd();
911  result.reset(new GF2NPP(m, t3, t2, t1, 0));
912  }
913  else
914  {
915  BERDecodeError();
916  return NULL;
917  }
918  parameters.MessageEnd();
919  seq.MessageEnd();
920 
921  return result.release();
922 }
923 
924 NAMESPACE_END
925 
926 #endif
SecBlock::begin
iterator begin()
Provides an iterator pointing to the first element in the memory block.
Definition: secblock.h:499
Singleton::Ref
const T & Ref(...) const
Return a reference to the inner Singleton object.
Definition: misc.h:308
member_ptr< GF2NP >
SecWordBlock
SecBlock<word> typedef.
Definition: secblock.h:734
PolynomialMod2::Divide
static void Divide(PolynomialMod2 &r, PolynomialMod2 &q, const PolynomialMod2 &a, const PolynomialMod2 &d)
calculate r and q such that (a == d*q + r) && (deg(r) < deg(d))
Definition: gf2n.cpp:305
QuotientRing
Quotient ring.
Definition: algebra.h:387
gf2n.h
SecBlock::Grow
void Grow(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:673
PolynomialMod2::GetByte
byte GetByte(size_t n) const
return the n-th byte
Definition: gf2n.cpp:77
StringStore
String-based implementation of Store interface.
Definition: filters.h:1067
PolynomialMod2
Polynomial with Coefficients in GF(2)
Definition: gf2n.h:19
PolynomialMod2::InverseMod
PolynomialMod2 InverseMod(const PolynomialMod2 &) const
calculate multiplicative inverse of *this mod n
Definition: gf2n.cpp:543
DERSequenceEncoder
DER Sequence Encoder.
Definition: asn.h:306
DERGeneralEncoder
DER General Encoder.
Definition: asn.h:273
PolynomialMod2::DEREncodeAsOctetString
void DEREncodeAsOctetString(BufferedTransformation &bt, size_t length) const
encode value as big-endian octet string
Definition: gf2n.cpp:186
BufferedTransformation
Interface for buffered transformations.
Definition: cryptlib.h:1353
PolynomialMod2::Trinomial
static PolynomialMod2 Trinomial(size_t t0, size_t t1, size_t t2)
return x^t0 + x^t1 + x^t2 The coefficients should be provided in descending order.
Definition: gf2n.cpp:99
QuotientRing< EuclideanDomainOf< PolynomialMod2 > >::Accumulate
Element & Accumulate(Element &a, const Element &b) const
Definition: algebra.h:410
SecByteBlock
SecBlock<byte> typedef.
Definition: secblock.h:731
PolynomialMod2::ByteCount
unsigned int ByteCount() const
number of significant bytes = ceiling(BitCount()/8)
Definition: gf2n.cpp:207
QuotientRing::MultiplicativeInverse
const Element & MultiplicativeInverse(const Element &a) const
Calculate the multiplicative inverse of an element in the group.
Definition: algebra.cpp:70
smartptr.h
Classes for automatic resource management.
PolynomialMod2::SetByte
void SetByte(size_t n, byte value)
set the n-th byte to value
Definition: gf2n.cpp:85
SIZE_MAX
#define SIZE_MAX
The maximum value of a machine word.
Definition: misc.h:95
PolynomialMod2::BERDecodeAsOctetString
void BERDecodeAsOctetString(BufferedTransformation &bt, size_t length)
decode value as big-endian octet string
Definition: gf2n.cpp:193
BufferedTransformation::Put
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1378
Singleton
Restricts the instantiation of a class to one static object without locks.
Definition: misc.h:265
SafeConvert
bool SafeConvert(T1 from, T2 &to)
Tests whether a conversion from -> to is safe to perform.
Definition: misc.h:517
PolynomialMod2::AllOnes
static PolynomialMod2 AllOnes(size_t n)
return x^(n-1) + ... + x + 1
Definition: gf2n.cpp:54
RandomNumberGenerator::GenerateBlock
virtual void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
Definition: cryptlib.cpp:330
PolynomialMod2::Parity
unsigned int Parity() const
sum modulo 2 of all coefficients
Definition: gf2n.cpp:225
BERGeneralDecoder
BER General Decoder.
Definition: asn.h:236
OID
Object Identifier.
Definition: asn.h:160
filters.h
Implementation of BufferedTransformation's attachment interface.
RandomNumberGenerator
Interface for random number generators.
Definition: cryptlib.h:1187
NewPolynomialMod2
Definition: gf2n.cpp:139
BERDecodeError
void BERDecodeError()
Raises a BERDecodeErr.
Definition: asn.h:62
BitsToWords
size_t BitsToWords(size_t bitCount)
Returns the number of words required for the specified number of bits.
Definition: misc.h:760
BytePrecision
unsigned int BytePrecision(const T &value)
Returns the number of 8-bit bytes or octets required for a value.
Definition: misc.h:623
randpool.h
Class file for Randomness Pool.
DEREncodeUnsigned
size_t DEREncodeUnsigned(BufferedTransformation &out, T w, byte asnTag=INTEGER)
DER Encode unsigned value.
Definition: asn.h:443
SecBlock::CleanGrow
void CleanGrow(size_type newSize)
Change size and preserve contents.
Definition: secblock.h:689
misc.h
Utility functions for the Crypto++ library.
PolynomialMod2::Degree
signed int Degree() const
the zero polynomial will return a degree of -1
Definition: gf2n.h:117
EuclideanDomainOf< PolynomialMod2 >
QuotientRing< EuclideanDomainOf< PolynomialMod2 > >::Square
const Element & Square(const Element &a) const
Definition: algebra.h:434
PolynomialMod2::Pentanomial
static PolynomialMod2 Pentanomial(size_t t0, size_t t1, size_t t2, size_t t3, size_t t4)
return x^t0 + x^t1 + x^t2 + x^t3 + x^t4 The coefficients should be provided in descending order.
Definition: gf2n.cpp:116
SecBlock::CleanNew
void CleanNew(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:660
STDMIN
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:467
ArraySink
Copy input to a memory buffer.
Definition: filters.h:1017
PolynomialMod2::PolynomialMod2
PolynomialMod2()
creates the zero polynomial
Definition: gf2n.cpp:23
GF2NP
GF(2^n) with Polynomial Basis.
Definition: gf2n.h:285
GF2NPP
GF(2^n) with Pentanomial Basis.
Definition: gf2n.h:345
asn.h
Classes and functions for working with ANS.1 objects.
oids.h
ASN.1 object identifiers for algorthms and schemes.
BitPrecision
unsigned int BitPrecision(const T &value)
Returns the number of bits required for a value.
Definition: misc.h:645
PolynomialMod2::WordCount
unsigned int WordCount() const
number of significant words = ceiling(ByteCount()/sizeof(word))
Definition: gf2n.cpp:202
PolynomialMod2::IsUnit
bool IsUnit() const
only 1 is a unit
Definition: gf2n.h:217
SecBlock::size
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:524
PolynomialMod2::Monomial
static PolynomialMod2 Monomial(size_t i)
return x^i
Definition: gf2n.cpp:92
InvalidArgument
An invalid argument was detected.
Definition: cryptlib.h:183
BufferedTransformation::Get
virtual size_t Get(byte &outByte)
Retrieve a 8-bit byte.
Definition: cryptlib.cpp:519
RandomPool
Randomness Pool.
Definition: randpool.h:26
SecBlock::Assign
void Assign(const T *ptr, size_type len)
Set contents and size from an array.
Definition: secblock.h:544
PolynomialMod2::Encode
void Encode(byte *output, size_t outputLen) const
encode in big-endian format
Definition: gf2n.cpp:162
QuotientRing< EuclideanDomainOf< PolynomialMod2 > >::Multiply
const Element & Multiply(const Element &a, const Element &b) const
Definition: algebra.h:431
PolynomialMod2::DivideByZero
divide by zero exception
Definition: gf2n.h:25
algebra.h
Classes for performing mathematics over different fields.
Crop
T Crop(T value, size_t bits)
Truncates the value to the specified number of bits.
Definition: misc.h:728
CryptoPP
Crypto++ library namespace.
GF2NT::MultiplicativeInverse
const Element & MultiplicativeInverse(const Element &a) const
Calculate the multiplicative inverse of an element in the group.
Definition: gf2n.cpp:629
PolynomialMod2::Gcd
static PolynomialMod2 Gcd(const PolynomialMod2 &a, const PolynomialMod2 &n)
greatest common divisor
Definition: gf2n.cpp:538
config.h
Library configuration file.
PolynomialMod2::IsIrreducible
bool IsIrreducible() const
check for irreducibility
Definition: gf2n.cpp:549
BytesToWords
size_t BytesToWords(size_t byteCount)
Returns the number of words required for the specified number of bytes.
Definition: misc.h:750
SecBlock
Secure memory block with allocator and cleanup.
Definition: secblock.h:438
AbstractEuclideanDomain::Gcd
virtual const Element & Gcd(const Element &a, const Element &b) const
Calculates the greatest common denominator in the ring.
Definition: algebra.cpp:56
Parity
unsigned int Parity(T value)
Returns the parity of a value.
Definition: misc.h:612
BERDecodeUnsigned
void BERDecodeUnsigned(BufferedTransformation &in, T &w, byte asnTag=INTEGER, T minValue=0, T maxValue=T(0xffffffff))
BER Decode unsigned value.
Definition: asn.h:479
QuotientRing< EuclideanDomainOf< PolynomialMod2 > >::Add
const Element & Add(const Element &a, const Element &b) const
Definition: algebra.h:407
cryptlib.h
Abstract base classes that provide a uniform interface to this library.
GF2NT
GF(2^n) with Trinomial Basis.
Definition: gf2n.h:321
BERSequenceDecoder
BER Sequence Decoder.
Definition: asn.h:296
GF2NT::Multiply
const Element & Multiply(const Element &a, const Element &b) const
Multiplies elements in the group.
Definition: gf2n.cpp:768
PolynomialMod2::BitCount
unsigned int BitCount() const
number of significant bits = Degree() + 1
Definition: gf2n.cpp:216