6 #ifndef CRYPTOPP_IMPORTS
30 assert(value==0 || reg.
size()>0);
35 SetWords(reg+1, 0, reg.
size()-1);
42 CopyWords(reg, t.reg, reg.
size());
47 const size_t nbytes = nbits/8 + 1;
50 buf[0] = (byte)
Crop(buf[0], nbits % 8);
58 if (bitLength%WORD_BITS)
59 result.reg[result.reg.
size()-1] = (word)
Crop(result.reg[result.reg.
size()-1], bitLength%WORD_BITS);
63 void PolynomialMod2::SetBit(
size_t n,
int value)
68 reg[n/WORD_BITS] |= (word(1) << (n%WORD_BITS));
72 if (n/WORD_BITS < reg.
size())
73 reg[n/WORD_BITS] &= ~(word(1) << (n%WORD_BITS));
79 if (n/WORD_SIZE >= reg.
size())
82 return byte(reg[n/WORD_SIZE] >> ((n%WORD_SIZE)*8));
88 reg[n/WORD_SIZE] &= ~(word(0xff) << 8*(n%WORD_SIZE));
89 reg[n/WORD_SIZE] |= (word(value) << 8*(n%WORD_SIZE));
106 if (t1 > t0 || t2 > t0)
107 throw InvalidArgument(
"PolynomialMod2: coefficients must be in descending order");
125 if (t1 > t0 || t2 > t0 || t3 > t0 || t4 > t0)
126 throw InvalidArgument(
"PolynomialMod2: coefficients must be in descending order");
156 void PolynomialMod2::Decode(
const byte *input,
size_t inputLen)
159 Decode(store, inputLen);
172 for (
size_t i=inputLen; i > 0; i--)
176 reg[(i-1)/WORD_SIZE] |= word(b) << ((i-1)%WORD_SIZE)*8;
182 for (
size_t i=outputLen; i > 0; i--)
196 if (!dec.IsDefiniteLength() || dec.RemainingLength() != length)
204 return (
unsigned int)CountWords(reg, reg.
size());
211 return (wordCount-1)*WORD_SIZE +
BytePrecision(reg[wordCount-1]);
220 return (wordCount-1)*WORD_BITS +
BitPrecision(reg[wordCount-1]);
229 for (i=0; i<reg.
size(); i++)
243 XorWords(reg, t.reg, t.reg.
size());
249 if (b.reg.size() >= reg.
size())
252 XorWords(result.reg, reg, b.reg, reg.
size());
253 CopyWords(result.reg+reg.
size(), b.reg+reg.
size(), b.reg.size()-reg.
size());
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());
268 AndWords(result.reg, reg, b.reg, result.reg.size());
276 for (
int i=b.Degree(); i>=0; i--)
280 XorWords(result.reg, reg, reg.
size());
287 static const word map[16] = {0, 1, 4, 5, 16, 17, 20, 21, 64, 65, 68, 69, 80, 81, 84, 85};
291 for (
unsigned i=0; i<reg.
size(); i++)
295 for (j=0; j<WORD_BITS; j+=8)
296 result.reg[2*i] |= map[(reg[i] >> (j/2)) % 16] << j;
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;
311 int degree = divisor.
Degree();
318 for (
int i=dividend.
Degree(); i>=0; i--)
321 remainder.reg[0] |= dividend[i];
322 if (remainder[degree])
324 remainder -= divisor;
347 int x; CRYPTOPP_UNUSED(x);
365 *r = (u << 1) | carry;
366 carry = u >> (WORD_BITS-1);
373 reg[reg.
size()-1] = carry;
379 const int shiftWords = n / WORD_BITS;
380 const int shiftBits = n % WORD_BITS;
388 *r = (u << shiftBits) | carry;
389 carry = u >> (WORD_BITS-shiftBits);
397 const size_t carryIndex = reg.
size();
398 reg.
Grow(reg.
size()+shiftWords+!!shiftBits);
399 reg[carryIndex] = carry;
406 for (i = (
int)reg.
size()-1; i>=shiftWords; i--)
407 reg[i] = reg[i-shiftWords];
420 int shiftWords = n / WORD_BITS;
421 int shiftBits = n % WORD_BITS;
426 word *r=reg+reg.
size()-1;
434 *r = (u >> shiftBits) | carry;
435 carry = u << (WORD_BITS-shiftBits);
442 for (i=0; i<reg.
size()-shiftWords; i++)
443 reg[i] = reg[i+shiftWords];
444 for (; i<reg.
size(); i++)
463 bool PolynomialMod2::operator!()
const
465 for (
unsigned i=0; i<reg.
size(); i++)
466 if (reg[i])
return false;
474 for (i=0; i<smallerSize; i++)
475 if (reg[i] != rhs.reg[i])
return false;
477 for (i=smallerSize; i<reg.
size(); i++)
478 if (reg[i] != 0)
return false;
480 for (i=smallerSize; i<rhs.reg.
size(); i++)
481 if (rhs.reg[i] != 0)
return false;
486 std::ostream& operator<<(std::ostream& out,
const PolynomialMod2 &a)
489 long f = out.flags() & std::ios::basefield;
511 return out <<
'0' << suffix;
516 static const char upper[]=
"0123456789ABCDEF";
517 static const char lower[]=
"0123456789abcdef";
518 const char* vec = (out.flags() & std::ios::uppercase) ? upper : lower;
520 for (i=0; i*bits < a.BitCount(); i++)
523 for (
int j=0; j<bits; j++)
524 digit |= a[i*bits+j] << j;
531 if (i && (i%block)==0)
535 return out << suffix;
556 for (
int i=1; i<=d/2; i++)
558 u = u.Squared()%(*this);
572 GF2NP::Element GF2NP::SquareRoot(
const Element &a)
const
575 for (
unsigned int i=1; i<m; i++)
580 GF2NP::Element GF2NP::HalfTrace(
const Element &a)
const
584 for (
unsigned int i=1; i<=(m-1)/2; i++)
589 GF2NP::Element GF2NP::SolveQuadraticEquation(
const Element &a)
const
598 z = PolynomialMod2::Zero();
600 for (
unsigned int i=1; i<=m-1; i++)
607 }
while (w.IsZero());
616 GF2NT::GF2NT(
unsigned int t0,
unsigned int t1,
unsigned int t2)
622 assert(t0 > t1 && t1 > t2 && t2==0);
625 if (t1 > t0 || t2 > t0)
626 throw InvalidArgument(
"GF2NT: coefficients must be in descending order");
631 if (t0-t1 < WORD_BITS)
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();
642 SetWords(T, 0, 3*m_modulus.reg.size());
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());
653 ShiftWordsRightByWords(f, fgLen, 1);
656 assert(bcLen <= m_modulus.reg.size());
657 ShiftWordsLeftByWords(c, bcLen, 1);
670 if (t==1 && CountWords(f, fgLen)==1)
675 ShiftWordsRightByBits(f, fgLen, 1);
676 t=ShiftWordsLeftByBits(c, bcLen, 1);
680 ShiftWordsRightByBits(f, fgLen, i);
681 t=ShiftWordsLeftByBits(c, bcLen, i);
687 assert(bcLen <= m_modulus.reg.size());
690 if (f[fgLen-1]==0 && g[fgLen-1]==0)
693 if (f[fgLen-1] < g[fgLen-1])
699 XorWords(f, g, fgLen);
700 XorWords(b, c, bcLen);
703 while (k >= WORD_BITS)
714 for (
unsigned int j=0; j<WORD_BITS-t1; j++)
715 temp ^= ((temp >> j) & 1) << (t1 + j);
717 b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
720 b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
724 b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
725 b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
728 b[t0/WORD_BITS-1] ^= temp;
735 word temp = b[0] << (WORD_BITS - k);
740 for (
unsigned int j=0; j<WORD_BITS-t1; j++)
743 assert(t1+j < WORD_BITS);
744 temp ^= ((temp >> j) & 1) << (t1 + j);
749 b[t1/WORD_BITS-1] ^= temp << t1%WORD_BITS;
753 b[t1/WORD_BITS] ^= temp >> (WORD_BITS - t1%WORD_BITS);
757 b[t0/WORD_BITS-1] ^= temp << t0%WORD_BITS;
758 b[t0/WORD_BITS] ^= temp >> (WORD_BITS - t0%WORD_BITS);
761 b[t0/WORD_BITS-1] ^= temp;
764 CopyWords(result.reg.
begin(), b, result.reg.
size());
770 size_t aSize =
STDMIN(a.reg.size(), result.reg.
size());
771 Element r((word)0, m);
773 for (
int i=m-1; i>=0; i--)
777 ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
778 XorWords(r.reg.begin(), m_modulus.reg, r.reg.size());
781 ShiftWordsLeftByBits(r.reg.begin(), r.reg.size(), 1);
784 XorWords(r.reg.begin(), a.reg, aSize);
788 r.reg.begin()[r.reg.size()-1] = (word)
Crop(r.reg[r.reg.size()-1], m%WORD_BITS);
790 CopyWords(result.reg.
begin(), r.reg.begin(), result.reg.
size());
794 const GF2NT::Element& GF2NT::Reduced(
const Element &a)
const
796 if (t0-t1 < WORD_BITS)
797 return m_domain.Mod(a, m_modulus);
808 b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
809 b[i-t0/WORD_BITS-1] ^= temp << (WORD_BITS - t0%WORD_BITS);
812 b[i-t0/WORD_BITS] ^= temp;
814 if ((t0-t1)%WORD_BITS)
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);
820 b[i-(t0-t1)/WORD_BITS] ^= temp;
825 word mask = ((word)1<<(t0%WORD_BITS))-1;
826 word temp = b[i] & ~mask;
829 b[i-t0/WORD_BITS] ^= temp >> t0%WORD_BITS;
831 if ((t0-t1)%WORD_BITS)
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);
837 assert(temp << (WORD_BITS - (t0-t1)%WORD_BITS) == 0);
840 b[i-(t0-t1)/WORD_BITS] ^= temp;
843 SetWords(result.reg.
begin(), 0, result.reg.
size());
850 a.DEREncodeAsOctetString(out, MaxElementByteLength());
855 a.BERDecodeAsOctetString(in, MaxElementByteLength());
861 ASN1::characteristic_two_field().DEREncode(seq);
864 ASN1::tpBasis().DEREncode(parameters);
866 parameters.MessageEnd();
873 ASN1::characteristic_two_field().DEREncode(seq);
876 ASN1::ppBasis().DEREncode(parameters);
881 pentanomial.MessageEnd();
882 parameters.MessageEnd();
891 if (
OID(seq) != ASN1::characteristic_two_field())
897 if (oid == ASN1::tpBasis())
901 result.reset(
new GF2NT(m, t1, 0));
903 else if (oid == ASN1::ppBasis())
905 unsigned int t1, t2, t3;
910 pentanomial.MessageEnd();
911 result.reset(
new GF2NPP(m, t3, t2, t1, 0));
918 parameters.MessageEnd();
921 return result.release();