This commit is contained in:
Patrick Longa 2017-05-08 17:51:25 -07:00 коммит произвёл GitHub
Родитель 5f5d597e74
Коммит 4009a4c66b
67 изменённых файлов: 16991 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,264 @@
/*************************************************************************************
* FourQ: 4-dimensional decomposition on a Q-curve with CM in twisted Edwards form
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*
* Abstract: This MAGMA script is a condensed version of the script "FourQ-Extended-Theorem1".
* For simplicity and ease of readability, is not written in two-operand form,
* and works throughout in affine coordinates. It is intended to give a high-
* level overview of the algorithm.
*
* This code is based on the paper "FourQ: four-dimensional decompositions on a
* Q-curve over the Mersenne prime" by Craig Costello and Patrick Longa, in Advances
* in Cryptology - ASIACRYPT, 2015.
* Preprint available at http://eprint.iacr.org/2015/565.
**************************************************************************************/
clear;
// Define twisted Edwards curves E, Ehat and the isogenous Weierstrass curve W
p:=2^127-1; Fp:=GF(p); Fp2<i>:=ExtensionField<Fp,x|x^2+1>; AS<x,y>:=AffineSpace(Fp2,2);
d:=125317048443780598345676279555970305165*i + 4205857648805777768770;
E:=Curve(AS,[-x^2+y^2-(1+d*x^2*y^2)]);
dhat:=-1/(d+1);
Ehat:=Curve(AS,[-x^2+y^2-(1+dhat*x^2*y^2)]);
rt2:=2^64;
rt5:=87392807087336976318005368820707244464*i;
A:=-(30-8*rt5); B:=56-32*rt5;
W:=EllipticCurve([Fp2|A,B]);
mu:=2^256; // Scalars allowed in [0,mu)
DBL:=function(Q) // a=-1 twisted Edwards doubling
x:=Q[1]; y:=Q[2];
X:=2*x*y/(1+d*x^2*y^2);
Y:=(y^2+x^2)/(1-d*x^2*y^2);
return E![X,Y];
end function;
ADD:=function(Q,R) // a=-1 twisted Edwards addition
x1:=Q[1]; y1:=Q[2]; x2:=R[1]; y2:=R[2];
X:=(x1*y2+y1*x2)/(1+d*x1*x2*y1*y2);
Y:=(y1*y2+x1*x2)/(1-d*x1*x2*y1*y2);
return E![X,Y];
end function;
tau:=function(P) // Isogeny tau: E->Ehat
x:=P[1]; y:=P[2];
X:=2*x*y/((x^2+y^2)*Sqrt(dhat));
Y:=(x^2-y^2+2)/(y^2-x^2);
return Ehat![X,Y];
end function;
tau_dual:=function(P) // Isogeny tau_dual: Ehat->E
x:=P[1]; y:=P[2];
X:=2*x*y*Sqrt(dhat)/(x^2-y^2+2);
Y:=(y^2-x^2)/(y^2+x^2);
return E![X,Y];
end function;
delta:=function(P) // Isomorphism delta: W->Ehat
x:=P[1]; y:=P[2];
X:=Sqrt(-12-4*rt2-2*rt5*rt2)*(x-4)/y;
Y:=(x-4-(2*rt2+rt2*rt5))/(x-4+(2*rt2+rt2*rt5));
return Ehat![X,Y];
end function;
delta_inv:=function(P) // Isomorphism delta_inv: Ehat->W
x:=P[1]; y:=P[2];
X:=(2*rt2+rt2*rt5)*(y+1)/(1-y)+4;
Y:=(2*rt2+rt2*rt5)*(y+1)/(1-y)*Sqrt(-12-4*rt2-2*rt5*rt2)/x;
return W![X,Y];
end function;
phiW:=function(P) // Endomorphism phiW on the Weierstrass curve
x:=P[1]; y:=P[2];
X:=x^5+8*rt5*x^4+(40*rt5+260)*x^3+(720*rt5+640)*x^2+(656*rt5+4340)*x+(1920*rt5+960);
X:=X/(5*(x^2+4*rt5*x-1/5*(4*rt5-90))^2);
Y:=-y*(x^2+(4*rt5-8)*x-(12*rt5-26))*(x^4+(8*rt5+8)*x^3+28*x^2-(48*rt5+112)*x-32*rt5-124);
Y:=Y/(rt5*(x^2+4*rt5*x-1/5*(4*rt5-90)))^3;
return W![X^p,Y^p];
end function;
psiW:=function(P) // Endomorphism psiW on the Weierstrass curve
x:=P[1]; y:=P[2];
X:=-x/2-(9+4*rt5)/(x-4);
Y:=-y/(i*rt2)*(-1/2+(9+4*rt5)/(x-4)^2);
return W![X^p,Y^p];
end function;
phi:=function(P); // Endomorphism phi on E via composition
return tau_dual(delta(phiW(delta_inv(tau(P)))));
end function;
psi:=function(P); // Endomorphism psi on E via composition
return tau_dual(delta(psiW(delta_inv(tau(P)))));
end function;
decomposition:=function(m) // Scalar decomposition
alpha1:=Floor(50127518246259276682880317011538934615153226543083896339791*m/mu);
alpha2:=Floor(22358026531042503310338016640572204942053343837521088510715*m/mu);
alpha3:=Floor(5105580562119000402467322500999592531749084507000101675068*m/mu);
alpha4:=Floor(19494034873545274265741574254707851381713530791194721254848*m/mu);
a1:=m-alpha1*650487742939046294-alpha2*2110318963211420372-alpha3*1705647224544756482-alpha4*1400113754146392127+8234880650715616668;
a2:=alpha1*1397215820276968864+alpha2-alpha3*199320682881407569-alpha4*3540637644719456050+6483313240794689388;
a3:=-alpha1*523086274270593807-alpha2+alpha3*3336360048424633503+alpha4*471270406870313397+9066539331533273720;
a4:=alpha1*598824378691085905-alpha2*2727991412926801872-alpha3*765171327772315031+alpha4*1789345740969872106+7765751599377320055;
a1hat:=a1+1400113754146392127;
a2hat:=a2+3540637644719456050;
a3hat:=a3-471270406870313397;
a4hat:=a4-1789345740969872106;
if IsEven(a1) then
a1:=a1hat; a2:=a2hat; a3:=a3hat; a4:=a4hat;
end if;
a1:=IntegerToSequence(a1,2);
a2:=IntegerToSequence(a2,2);
a3:=IntegerToSequence(a3,2);
a4:=IntegerToSequence(a4,2);
// Padding
while #a1 ne 65 do Append(~a1,0); end while;
while #a2 ne 65 do Append(~a2,0); end while;
while #a3 ne 65 do Append(~a3,0); end while;
while #a4 ne 65 do Append(~a4,0); end while;
return a1,a2,a3,a4;
end function;
recode:=function(a1,a2,a3,a4) // Scalar recoding
a:=[a1,a2,a3,a4];
b:=[[0: i in [1..65]]: j in [1..4]];
b[1][65]:=1;
for i:=1 to 65 do
if i ne 65 then
b[1][i]:=2*a[1][i+1]-1;
end if;
for j:=2 to 4 do
b[j][i]:=b[1][i]*a[j][1];
aj:=SequenceToInteger(a[j],2);
aj:=Floor(aj div 2)-Floor(b[j][i] div 2);
if aj ne 0 then
a[j]:=IntegerToSequence(aj,2);
else
a[j]:=[0];
end if;
end for;
end for;
m:=b[1]; d:=[];
for i:=1 to 65 do
Append(~d,SequenceToInteger([Abs(b[2][i]),Abs(b[3][i]),Abs(b[4][i])],2)+1);
end for;
return m,d;
end function;
lookup_table:=function(P,phiP,psiP,psiphiP) // Building the lookup table
T:=[];
Append(~T,P);
Append(~T,ADD(phiP,T[1]));
Append(~T,ADD(psiP,T[1]));
Append(~T,ADD(psiP,T[2]));
Append(~T,ADD(psiphiP,T[1]));
Append(~T,ADD(psiphiP,T[2]));
Append(~T,ADD(psiphiP,T[3]));
Append(~T,ADD(psiphiP,T[4]));
return T;
end function;
generic_scalar_multiplication:=function(P,k) // Generic scalar multiplication used for testing
bits:=IntegerToSequence(k,2);
Q:=P;
for i:=#bits-1 to 1 by -1 do
Q:=DBL(Q);
if bits[i] eq 1 then
Q:=ADD(Q,P);
end if;
end for;
return Q;
end function;
fourQ_scalar_multiplication:=function(P,m) // Regular four-dimensional scalar multiplication
// Step 1 - Compute endomorphisms:
phiP:=phi(P); psiP:=psi(P); psiphiP:=psi(phiP);
// Step 2 - Precompute lookup table:
T:=lookup_table(P,phiP,psiP,psiphiP);
// Step 3 - Scalar decomposition:
a1,a2,a3,a4:=decomposition(m);
// Step 4 - Scalar recoding:
masks,indexes:=recode(a1,a2,a3,a4);
// Step 5 - Initialize
Q:=T[indexes[65]];
// Steps 6,7,8 - Main loop:
for i:=64 to 1 by -1 do
Q:=DBL(Q);
Ti:=T[indexes[i]];
if masks[i] eq -1 then
Ti:=E![-Ti[1],Ti[2]];
end if;
Q:=ADD(Q,Ti);
end for;
return Q; // no (Step 9) normalize here as Q is affine throughout
end function;
// Testing the full FourQ routine against a generic scalar multiplication
while true do
P:=generic_scalar_multiplication(tau_dual(delta(Random(W))),392); // Random N-torsion point
m:=Random(0,mu); // Random scalar
if (fourQ_scalar_multiplication(P,m) ne generic_scalar_multiplication(P,m)) then;
break;
else
printf "passed\n";
end if;
end while;
printf "failed";

Просмотреть файл

@ -0,0 +1,684 @@
/*************************************************************************************
* FourQ: 4-dimensional decomposition on a Q-curve with CM in twisted Edwards form
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*
* Abstract: This MAGMA script computes the full FourQ variable-based multiplication as
* detailed in Algorithm 2 of the paper. Inherently included in this script
* are the endomorphisms, the scalar decomposition and the scalar recoding
* routine in Algorithm 1.
* The code also verifies the operation counts and claims in Theorem 1.
*
* This code is based on the paper "FourQ: four-dimensional decompositions on a
* Q-curve over the Mersenne prime" by Craig Costello and Patrick Longa, in Advances
* in Cryptology - ASIACRYPT, 2015.
* Preprint available at http://eprint.iacr.org/2015/565.
**************************************************************************************/
clear;
// Define curve
p:=2^127-1; Fp:=GF(p); Fp2<i>:=ExtensionField<Fp,x|x^2+1>;
AS<x,y>:=AffineSpace(Fp2,2);
// The complete twisted Edwards curve and prime subgroup order
d:=125317048443780598345676279555970305165*i + 4205857648805777768770;
E:=Curve(AS,[-x^2+y^2-(1+d*x^2*y^2)]);
mu:=2^256; // Scalars allowed in [0,mu)
// CONSTANTS FOR ENDOMORPHISMS
// phi constants
cphi0:=49615650983565284830950896420241471514*i + 110680464442257309687;
cphi1:=131306912742858181648727312260439119609*i + 92233720368547758087;
cphi2:=160666015865631300014011952927357137809*i + 276701161105643274261;
cphi3:=107027644557995218531204623577807990436*i + 36893488147419103235;
cphi4:=24279268184862963117522688682631129173*i + 55340232221128654851;
cphi5:=92472642025247131565767320804994133491*i + 184467440737095516175;
cphi6:=14804100590025031399847337894104161255*i + 332041393326771929112;
cphi7:=76283848507754718862858058709728786458*i + 442721857769029238819;
cphi8:=41635071732389019719735756359456329456*i + 3135946492530623774960;
cphi9:=21045324596686230484035983431638590725*i + 39844967199212631493615;
// psi constants
cpsi1:=4095177184363520459066*i + 57123674603396429897431647433607300847;
cpsi2:=44824135016688633386011024159913800562*i + 4205857648805777768771;
cpsi3:=101947809620085063283442671593521101409*i + 110680464442257309705;
cpsi4:=68193373840384168448244632122363004318*i + 170141183460469231621006839273626796022;
// tau constant
ctau1:=221360928884514619410*i + 33754435779700894835198039471158097091;
// tau_dual constant
ctaudual1:=170141183460469231510326374831369486353*i + 99231301967130569661901792840482943028;
// CONSTANTS FOR SCALAR DECOMPOSITION
// The Babai-optimal basis
b11:=650487742939046294;
b12:=1397215820276968864; // negated
b13:=523086274270593807;
b14:=598824378691085905; // negated
b21:=2110318963211420372;
//b22:=1; // negated
//b23:=1;
b24:=2727991412926801872;
b31:=1705647224544756482;
b32:=199320682881407569;
b33:=3336360048424633503; // negated
b34:=765171327772315031;
b41:=1400113754146392127;
b42:=3540637644719456050;
b43:=471270406870313397; // negated
b44:=1789345740969872106; // negated
// The offset vector
c1:=8234880650715616668;
c2:=6483313240794689388;
c3:=9066539331533273720;
c4:=7765751599377320055;
// The precomputed fractions for the decomposition
ell1:=50127518246259276682880317011538934615153226543083896339791;
ell2:=22358026531042503310338016640572204942053343837521088510715;
ell3:=5105580562119000402467322500999592531749084507000101675068;
ell4:=19494034873545274265741574254707851381713530791194721254848;
/*
Function converts Q from representation R1 to R2. See Tables 2 and 3.
*/
R1toR2:=function(Q,Fp2_ops)
mul:=0; sqr:=0; add:=0;
Q[4]:=Q[4]+Q[4]; add+:=1;
t1:=Q[1]+Q[2]; add+:=1;
Q[2]:=Q[2]-Q[1]; add+:=1;
Q[1]:=t1;
Q[4]:=Q[4]*Q[5]; mul+:=1;
Q[3]:=Q[3]+Q[3]; add+:=1;
Q[4]:=d*Q[4]; mul+:=1;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
Prune(~Q);
return Q,Fp2_ops;
end function;
/*
Function converts Q from representation R1 to R3. See Tables 2 and 3.
*/
R1toR3:=function(Q,Fp2_ops)
mul:=0; sqr:=0; add:=0;
t1:=Q[1]+Q[2]; add+:=1;
Q[2]:=Q[2]-Q[1]; add+:=1;
Q[1]:=t1;
Q[4]:=Q[4]*Q[5]; mul+:=1;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
Prune(~Q);
return Q,Fp2_ops;
end function;
/*
Function converts Q from representation R2 to R4. See Tables 2 and 3.
*/
R2toR4:=function(Q,Fp2_ops)
mul:=0; sqr:=0; add:=0;
t1:=Q[1]-Q[2]; add+:=1;
Q[2]:=Q[1]+Q[2]; add+:=1;
Q[1]:=t1;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
Prune(~Q);
return Q,Fp2_ops;
end function;
/*
The DBL function on E. Only needs the (X,Y,Z) coordinates of input,
but outputs points in R1 as (X,Y,Z,Ta,Tb). See Section 5.3.
*/
DBL:=function(Q,Fp2_ops)
mul:=0; sqr:=0; add:=0;
t1:=Q[1]^2; sqr+:=1;
t2:=Q[2]^2; sqr+:=1;
Q[1]:=Q[1]+Q[2]; add+:=1;
T1b:=t1+t2; add+:=1;
t1:=t2-t1; add+:=1;
t2:=Q[3]^2; sqr+:=1;
T1a:=Q[1]^2; sqr+:=1;
T1a:=T1a-T1b; add+:=1;
t2:=t2+t2; add+:=1;
t2:=t2-t1; add+:=1;
Q[2]:=t1*T1b; mul+:=1;
Q[1]:=t2*T1a; mul+:=1;
Q[3]:=t1*t2; mul+:=1;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
return [Q[1],Q[2],Q[3],T1a,T1b],Fp2_ops;
end function;
/*
The ADD_core function on E. Takes Q in R3 and R in R2 and returns Q+R in R1. See Table 3.
*/
ADD_core:=function(Q,R,Fp2_ops)
mul:=0; sqr:=0; add:=0;
Z3:=Q[4]*R[4]; mul+:=1;
t1:=Q[3]*R[3]; mul+:=1;
X3:=Q[1]*R[1]; mul+:=1;
Y3:=Q[2]*R[2]; mul+:=1;
t2:=t1-Z3; add+:=1;
t1:=t1+Z3; add+:=1;
T3b:=X3-Y3; add+:=1;
T3a:=X3+Y3; add+:=1;
X3:=T3b*t2; mul+:=1;
Z3:=t1*t2; mul+:=1;
Y3:=T3a*t1; mul+:=1;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
return [X3,Y3,Z3,T3a,T3b],Fp2_ops;
end function;
/*
The ADD function on E. Takes Q in R1 and R in R2 and returns Q+R in R1. See Table 3.
*/
ADD:=function(Q,R,Fp2_ops)
Q,Fp2_ops:=R1toR3(Q,Fp2_ops);
return ADD_core(Q,R,Fp2_ops);
end function;
/*
This function is called every time an element from the lookup table is accessed.
In the actual C code we use masking to select between Q and -Q(=R), both in R2.
*/
negate_and_select:=function(Q,mask,Fp2_ops)
R:=[Q[2],Q[1],Q[3],-Q[4]];
Fp2_ops:=[Fp2_ops[1],Fp2_ops[2],Fp2_ops[3]+1];
if mask eq -1 then
return R,Fp2_ops;
else
return Q,Fp2_ops;
end if;
end function;
/*
This is just the generic scalar multiplication used for testing, and for cofactor
killing to make sure the input point is of order N.
*/
GenericScalarMult:=function(P,k)
Fp2_ops:=[0,0,0]; // Just for synching input/output
if k eq 0 then
return P;
else
bits:=IntegerToSequence(k,2);
Q:=[P[1],P[2],1,P[1],P[2]];
P:=R1toR2([P[1],P[2],1,P[1],P[2]],Fp2_ops);
for i:=#bits-1 to 1 by -1 do
Q,Fp2_ops:=DBL(Q,Fp2_ops);
if bits[i] eq 1 then
Q,Fp2_ops:=ADD(Q,P,Fp2_ops);
end if;
end for;
return Q;
end if;
end function;
/*
Generate a random point T of order N on E.
*/
RandomNTorstionPoint:=function()
_<Y>:=PolynomialRing(Fp2);
repeat X:=Random(Fp2);
until HasRoot(-X^2+Y^2-(1+d*X^2*Y^2));
_,Y:=HasRoot(-X^2+Y^2-(1+d*X^2*Y^2));
T:=GenericScalarMult(E![X,Y],392);
return T;
end function;
/*
THE MAPS: The four maps needed for our endomorphisms: tau, tau_dual, delphidel
and delpsidel.
*/
/*
tau: E -> Ehat
Input: P on E in homogeneous coordinates
Output: tau(P) on Ehat in homogeneous coordinates
*/
tau:=function(P,Fp2_ops)
Prune(~P); Prune(~P);
mul:=0; sqr:=0; add:=0;
t0:=P[1]^2; sqr+:=1;
t1:=P[2]^2; sqr+:=1;
P[1]:=P[1]*P[2]; mul+:=1;
P[2]:=P[3]^2; sqr+:=1;
P[3]:=t0+t1; add+:=1;
P[2]:=2*P[2]; add+:=1;
t0:=t0-t1; add+:=1;
P[2]:=-P[2]; add+:=1;
P[1]:=P[1]*t0; mul+:=1;
P[2]:=P[2]-t0; add+:=1;
P[1]:=ctau1*P[1]; mul+:=1;
P[2]:=P[2]*P[3]; mul+:=1;
P[3]:=t0*P[3]; mul+:=1;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
return P, Fp2_ops;
end function;
/*
tau_dual: Ehat -> E
Input: P on Ehat in homogeneous coordinates
Output: tau_dual(P) on E in homogeneous coordinates
*/
tau_dual:=function(P,Fp2_ops)
mul:=0; sqr:=0; add:=0;
t0:=P[1]^2; sqr+:=1;
Append(~P,P[3]^2); sqr+:=1;
t1:=P[2]^2; sqr+:=1;
P[3]:=2*P[4]; add+:=1;
P[4]:=t1-t0; add+:=1;
t0:=t0+t1; add+:=1;
P[1]:=P[1]*P[2]; mul+:=1;
P[3]:=P[3]-P[4]; add+:=1;
Append(~P,ctaudual1*P[1]); mul+:=1;
P[2]:=P[4]*P[3]; mul+:=1;
P[1]:=P[5]*t0; mul+:=1;
P[3]:=t0*P[3]; mul+:=1;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
return P, Fp2_ops;
end function;
/*
delphidel: Ehat -> Ehat
Input: P on Ehat
Output: delta(phi_W(delta_inv(P))) on Ehat, where delta: W->Ehat and
delta_inv: Ehat->W are isomorphisms and phi_W: W->W is the endomorphism on W.
*/
delphidel:=function(P,Fp2_ops)
mul:=0; sqr:=0; add:=0;
t4:=P[3]^2; sqr+:=1;
t3:=P[2]*P[3]; mul+:=1;
t0:=t4*cphi4; mul+:=1;
t2:=P[2]^2; sqr+:=1;
t0:=t0+t2; add+:=1;
t1:=t3*cphi3; mul+:=1;
t5:=t0-t1; add+:=1;
t0:=t1+t0; add+:=1;
t0:=t0*P[3]; mul+:=1;
t1:=t3*cphi1; mul+:=1;
t0:=t0*t5; mul+:=1;
t5:=t4*cphi2; mul+:=1;
t5:=t5+t2; add+:=1;
t6:=t1-t5; add+:=1;
t1:=t1+t5; add+:=1;
t6:=t6*t1; mul+:=1;
t6:=cphi0*t6; mul+:=1;
P[1]:=P[1]*t6; mul+:=1;
t6:=t2^2; sqr+:=1;
t2:=t3^2; sqr+:=1;
t3:=t4^2; sqr+:=1;
t1:=t2*cphi8; mul+:=1;
t5:=t3*cphi9; mul+:=1;
t1:=t1+t6; add+:=1;
t2:=t2*cphi6; mul+:=1;
t3:=t3*cphi7; mul+:=1;
t1:=t1+t5; add+:=1;
t2:=t2+t3; add+:=1;
t1:=P[2]*t1; mul+:=1;
P[2]:=t2+t6; add+:=1;
P[1]:=P[1]*t1; mul+:=1;
P[2]:=cphi5*P[2]; mul+:=1;
P[1]:=P[1]^p; add+:=1/2;
P[2]:=P[2]*P[3]; mul+:=1;
P[3]:=t0*t1; mul+:=1;
P[2]:=P[2]*t0; mul+:=1;
P[3]:=P[3]^p; add+:=1/2;
P[2]:=P[2]^p; add+:=1/2;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
return P, Fp2_ops;
end function;
/*
delpsidel: Ehat -> Ehat
Input: P on Ehat
Output: delta(psi_W(delta_inv(P))) on Ehat, where delta: W->Ehat and
delta_inv: Ehat->W are isomorphisms and psi_W: W->W is the endomorphism on W.
*/
delpsidel:=function(P,Fp2_ops)
mul:=0; sqr:=0; add:=0;
P[1]:=P[1]^p; add+:=1/2;
P[3]:=P[3]^p; add+:=1/2;
P[2]:=P[2]^p; add+:=1/2;
t2:=P[3]^2; sqr+:=1;
t0:=P[1]^2; sqr+:=1;
P[1]:=P[1]*t2; mul+:=1;
P[3]:=t2*cpsi2; mul+:=1;
t1:=t2*cpsi3; mul+:=1;
t2:=t2*cpsi4; mul+:=1;
P[3]:=t0+P[3]; add+:=1;
t2:=t0+t2; add+:=1;
t1:=t0+t1; add+:=1;
t2:=-t2; add+:=1;
P[3]:=P[2]*P[3]; mul+:=1;
P[1]:=P[1]*t2; mul+:=1;
P[2]:=P[3]*t1; mul+:=1;
P[1]:=P[1]*cpsi1; mul+:=1;
P[3]:=P[3]*t2; mul+:=1;
Fp2_ops:=[Fp2_ops[1]+mul,Fp2_ops[2]+sqr,Fp2_ops[3]+add];
return P, Fp2_ops;
end function;
/*
phi: E -> E
Input: P on E
Output: phi(P) on E
*/
phi:=function(P,Fp2_ops);
P,Fp2_ops:=tau(P,Fp2_ops);
P,Fp2_ops:=delphidel(P,Fp2_ops);
P,Fp2_ops:=tau_dual(P,Fp2_ops);
return P,Fp2_ops;
end function;
/*
psi: E -> E
Input: P on E
Output: psi(P) on E
*/
psi:=function(P,Fp2_ops);
P,Fp2_ops:=tau(P,Fp2_ops);
P,Fp2_ops:=delpsidel(P,Fp2_ops);
P,Fp2_ops:=tau_dual(P,Fp2_ops);
return P,Fp2_ops;
end function;
/*
The decomposition described in Proposition 5. The "if" and "while" statements
at the end of the function are for simplicity in Magma. In the C code the "if"
statement is turned into a constant-time masking and the "while" statements
are not necessary.
Input: the integer scalar m in [0,2^256)
Output: the multiscalar (a1,a2,a3,a4) described in Proposition 5.
*/
decomposition:=function(m)
alpha1:=Floor(ell1*m/mu);
alpha2:=Floor(ell2*m/mu);
alpha3:=Floor(ell3*m/mu);
alpha4:=Floor(ell4*m/mu);
t0:=alpha1*b11;
a1:=m-t0;
t0:=alpha2*b21;
a1:=a1-t0;
t0:=alpha3*b31;
a1:=a1-t0;
t0:=alpha4*b41;
a1:=a1-t0;
a2:=alpha1*b12;
a2:=a2+alpha2;
t0:=alpha3*b32;
a2:=a2-t0;
t0:=alpha4*b42;
a2:=a2-t0;
a3:=alpha1*b13;
a3:=a3+alpha2;
t0:=alpha3*b33;
a3:=t0-a3;
t0:=alpha4*b43;
a3:=a3+t0;
a4:=alpha1*b14;
t0:=alpha2*b24;
a4:=a4-t0;
t0:=alpha3*b34;
a4:=a4-t0;
t0:=alpha4*b44;
a4:=a4+t0;
a1:=a1+c1;
a2:=a2+c2;
a3:=a3+c3;
a4:=a4+c4;
a1hat:=a1+b41;
a2hat:=a2+b42;
a3hat:=a3-b43;
a4hat:=a4-b44;
if IsEven(a1) then
a1:=a1hat; a2:=a2hat; a3:=a3hat; a4:=a4hat;
end if;
a1:=IntegerToSequence(a1,2);
a2:=IntegerToSequence(a2,2);
a3:=IntegerToSequence(a3,2);
a4:=IntegerToSequence(a4,2);
// Padding
while #a1 ne 65 do Append(~a1,0); end while;
while #a2 ne 65 do Append(~a2,0); end while;
while #a3 ne 65 do Append(~a3,0); end while;
while #a4 ne 65 do Append(~a4,0); end while;
return a1,a2,a3,a4;
end function;
/*
The recoding described in Algorithm 1. The "if" statements are for
simplicity in Magma. In the C code the "if" statement are turned into constant-time maskings.
Input: the multiscalar (a1,a2,a3,a4) output from the decomposition function above.
Output: the indexes (d0,...,d64) and sign masks (m0,...,m64)
*/
recode:=function(a1,a2,a3,a4)
a:=[a1,a2,a3,a4];
b:=[[0: i in [1..65]]: j in [1..4]];
b[1][65]:=1;
for i:=1 to 65 do
if i ne 65 then
b[1][i]:=2*a[1][i+1]-1;
end if;
for j:=2 to 4 do
b[j][i]:=b[1][i]*a[j][1];
aj:=SequenceToInteger(a[j],2);
aj:=Floor(aj div 2)-Floor(b[j][i] div 2);
if aj ne 0 then
a[j]:=IntegerToSequence(aj,2);
else
a[j]:=[0];
end if;
end for;
end for;
m:=b[1];
d:=[];
for i:=1 to 65 do
Append(~d,SequenceToInteger([Abs(b[2][i]),Abs(b[3][i]),Abs(b[4][i])],2)+1);
end for;
return m,d;
end function;
/*
Building the lookup table as described in Section 5.2 and the proof of Theorem 1.
input: P, phi(P), psi(P) and psi(phi(P))
output: the lookup table of size 8
*/
lookup_table:=function(P,phiP,psiP,psiphiP,Fp2_ops)
T:=[];
Append(~T,[P[1],P[2],P[3],P[4]]); //T[1]
t0,Fp2_ops:=ADD_core(phiP,T[1],Fp2_ops);
t0,Fp2_ops:=R1toR2(t0,Fp2_ops);
Append(~T,t0); //T[2]
t0,Fp2_ops:=ADD_core(psiP,T[1],Fp2_ops);
t0,Fp2_ops:=R1toR2(t0,Fp2_ops);
Append(~T,t0); //T[3]
t0,Fp2_ops:=ADD_core(psiP,T[2],Fp2_ops);
t0,Fp2_ops:=R1toR2(t0,Fp2_ops);
Append(~T,t0); //T[4]
t0,Fp2_ops:=ADD_core(psiphiP,T[1],Fp2_ops);
t0,Fp2_ops:=R1toR2(t0,Fp2_ops);
Append(~T,t0); //T[5]
t0,Fp2_ops:=ADD_core(psiphiP,T[2],Fp2_ops);
t0,Fp2_ops:=R1toR2(t0,Fp2_ops);
Append(~T,t0); //T[6]
t0,Fp2_ops:=ADD_core(psiphiP,T[3],Fp2_ops);
t0,Fp2_ops:=R1toR2(t0,Fp2_ops);
Append(~T,t0); //T[7]
t0,Fp2_ops:=ADD_core(psiphiP,T[4],Fp2_ops);
t0,Fp2_ops:=R1toR2(t0,Fp2_ops);
Append(~T,t0); //T[8]
return T,Fp2_ops;
end function;
/*
The regular four-dimensional scalar multiplication described in Algorithm 2.
*/
scalar_multiplication:=function(P,m)
Fp2_ops:=[0,0,0];
// Step 1 - Compute endomorphisms:
phiP,Fp2_ops:=phi(P,Fp2_ops);
psiP,Fp2_ops:=psi(P,Fp2_ops);
psiphiP,Fp2_ops:=psi(phiP,Fp2_ops);
// Step 2 - Precompute lookup table:
P,Fp2_ops:=R1toR2(P,Fp2_ops);
phiP,Fp2_ops:=R1toR3(phiP,Fp2_ops);
psiP,Fp2_ops:=R1toR3(psiP,Fp2_ops);
psiphiP,Fp2_ops:=R1toR3(psiphiP,Fp2_ops);
T,Fp2_ops:=lookup_table(P,phiP,psiP,psiphiP,Fp2_ops);
// Step 3 - Scalar decomposition:
a1,a2,a3,a4:=decomposition(m);
// Step 4 - Scalar recoding:
masks,indexes:=recode(a1,a2,a3,a4);
// Step 5 - Initialize
Q:=T[indexes[65]];
Q,Fp2_ops:=negate_and_select(Q,masks[65],Fp2_ops);
Q,Fp2_ops:=R2toR4(Q,Fp2_ops);
// Steps 6,7,8 - Main loop:
for i:=64 to 1 by -1 do
Q,Fp2_ops:=DBL(Q,Fp2_ops);
Ti:=T[indexes[i]];
Ti,Fp2_ops:=negate_and_select(Ti,masks[i],Fp2_ops);
Q,Fp2_ops:=ADD(Q,Ti,Fp2_ops);
end for;
// Step 9 - Normalize output:
Q[3]:=1/Q[3];
Q[1]:=Q[1]*Q[3]; Fp2_ops[1]+:=1;
Q[2]:=Q[2]*Q[3]; Fp2_ops[1]+:=1;
return E![Q[1],Q[2]],Fp2_ops;
end function;
// Testing and illustrating the operation count in Theorem 1.
while true do
P:=RandomNTorstionPoint();
m:=Random(0,mu-1);
mP:=GenericScalarMult(E![P[1]/P[3],P[2]/P[3]],m);
compare:=E![mP[1]/mP[3],mP[2]/mP[3]];
Q,Fp2_ops:=scalar_multiplication(P,m);
if (Q eq compare) then
"PASSED: ", 1, "Fp2 invs", Fp2_ops[1], "Fp2 muls", Fp2_ops[2], "Fp2 sqrs", Fp2_ops[3], "Fp2 add";
else
"FAILED"; break;
end if;
end while;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

164
FourQ_ARM_NEON/FourQ.h Normal file
Просмотреть файл

@ -0,0 +1,164 @@
/*****************************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: main header file
*
* This code is based on the papers:
* [1] "FourQ: four-dimensional decompositions on a Q-curve over the Mersenne prime"
* by Craig Costello and Patrick Longa, ASIACRYPT2015 (http://eprint.iacr.org/2015/565).
* [2] "FourQNEON: Faster Elliptic Curve Scalar Multiplications on ARM Processors"
* by Patrick Longa, SAC2016 (http://eprint.iacr.org/2016/645).
******************************************************************************************/
#ifndef __FOURQ_H__
#define __FOURQ_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
// Definition of operating system
#define OS_LINUX 1
#if defined(__LINUX__) // Linux OS
#define OS_TARGET OS_LINUX
#else
#error -- "Unsupported OS"
#endif
// Definition of compiler
#define COMPILER_GCC 1
#define COMPILER_CLANG 2
#if defined(__GNUC__) // GNU GCC compiler
#define COMPILER COMPILER_GCC
#elif defined(__clang__) // Clang compiler
#define COMPILER COMPILER_CLANG
#else
#error -- "Unsupported COMPILER"
#endif
// Definition of the targeted architecture and basic data types
#define TARGET_ARM 1
#if defined(_ARM_)
#define TARGET TARGET_ARM
#define RADIX 32
typedef uint32_t digit_t; // Unsigned 32-bit digit
typedef int32_t sdigit_t; // Signed 32-bit digit
#define NWORDS_FIELD 4
#define NWORDS_ORDER 8
#else
#error -- "Unsupported ARCHITECTURE"
#endif
// Constants
#define RADIX64 64
#define NWORDS64_FIELD 2 // Number of 64-bit words of a field element
#define NWORDS64_ORDER 4 // Number of 64-bit words of an element in Z_r
// Definition of complementary cryptographic functions
#define RandomBytesFunction random_bytes
#define CryptoHashFunction crypto_sha512 // Use SHA-512 by default
// Detect if additional optimizationes are enabled
#if defined(_INTERLEAVE_)
#define INTERLEAVE // Interleaving of instructions
#endif
#if defined(_MIX_ARM_NEON_)
#define MIX_ARM_NEON // Mix ARM/NEON instructions
#endif
// Basic parameters for variable-base scalar multiplication (without using endomorphisms)
#define W_VARBASE 5
#define NBITS_ORDER_PLUS_ONE 246+1
// Basic parameters for fixed-base scalar multiplication
#define W_FIXEDBASE 5 // Memory requirement: 7.5KB (storage for 80 points).
#define V_FIXEDBASE 5
// Basic parameters for double scalar multiplication
#define WP_DOUBLEBASE 8 // Memory requirement: 24KB (storage for 256 points).
#define WQ_DOUBLEBASE 4
// FourQ's basic element definitions and point representations
typedef digit_t felm_t[NWORDS_FIELD]; // Datatype for representing 128-bit field elements
typedef felm_t f2elm_t[2]; // Datatype for representing quadratic extension field elements
typedef struct { f2elm_t x; f2elm_t y; } point_affine; // Point representation in affine coordinates.
typedef point_affine point_t[1];
// FourQ's vectorized element definitions and point representations
#define VWORDS_FIELD 5 // Number of 32-bit words of a vectorized field element
typedef uint32_t velm_t[VWORDS_FIELD]; // Datatype for representing 128-bit vectorized field elements
typedef uint32_t v2elm_t[2*VWORDS_FIELD]; // Datatype for representing vectorized quadratic extension field elements
typedef struct { v2elm_t x; v2elm_t y; } vpoint_affine; // Point representation in affine coordinates.
typedef vpoint_affine vpoint_t[1];
// Definitions of the error-handling type and error codes
typedef enum {
ECCRYPTO_ERROR, // 0x00
ECCRYPTO_SUCCESS, // 0x01
ECCRYPTO_ERROR_DURING_TEST, // 0x02
ECCRYPTO_ERROR_UNKNOWN, // 0x03
ECCRYPTO_ERROR_NOT_IMPLEMENTED, // 0x04
ECCRYPTO_ERROR_NO_MEMORY, // 0x05
ECCRYPTO_ERROR_INVALID_PARAMETER, // 0x06
ECCRYPTO_ERROR_SHARED_KEY, // 0x07
ECCRYPTO_ERROR_SIGNATURE_VERIFICATION, // 0x08
ECCRYPTO_ERROR_END_OF_LIST
} ECCRYPTO_STATUS;
#define ECCRYPTO_STATUS_TYPE_SIZE (ECCRYPTO_ERROR_END_OF_LIST)
// Error message definitions
#define ECCRYPTO_MSG_ERROR "ECCRYPTO_ERROR"
#define ECCRYPTO_MSG_SUCCESS "ECCRYPTO_SUCCESS"
#define ECCRYPTO_MSG_ERROR_DURING_TEST "ECCRYPTO_ERROR_DURING_TEST"
#define ECCRYPTO_MSG_ERROR_UNKNOWN "ECCRYPTO_ERROR_UNKNOWN"
#define ECCRYPTO_MSG_ERROR_NOT_IMPLEMENTED "ECCRYPTO_ERROR_NOT_IMPLEMENTED"
#define ECCRYPTO_MSG_ERROR_NO_MEMORY "ECCRYPTO_ERROR_NO_MEMORY"
#define ECCRYPTO_MSG_ERROR_INVALID_PARAMETER "ECCRYPTO_ERROR_INVALID_PARAMETER"
#define ECCRYPTO_MSG_ERROR_SHARED_KEY "ECCRYPTO_ERROR_SHARED_KEY"
#define ECCRYPTO_MSG_ERROR_SIGNATURE_VERIFICATION "ECCRYPTO_ERROR_SIGNATURE_VERIFICATION"
#ifdef __cplusplus
}
#endif
#endif

116
FourQ_ARM_NEON/FourQ_api.h Normal file
Просмотреть файл

@ -0,0 +1,116 @@
/*****************************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: API header file
*
* This code is based on the papers:
* [1] "FourQ: four-dimensional decompositions on a Q-curve over the Mersenne prime"
* by Craig Costello and Patrick Longa, ASIACRYPT2015 (http://eprint.iacr.org/2015/565).
* [2] "FourQNEON: Faster Elliptic Curve Scalar Multiplications on ARM Processors"
* by Patrick Longa, SAC2016 (http://eprint.iacr.org/2016/645).
******************************************************************************************/
#ifndef __FOURQ_API_H__
#define __FOURQ_API_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
#include "FourQ.h"
/**************** Public ECC API ****************/
// Set generator G = (x,y)
void eccset(point_t G);
// Variable-base scalar multiplication Q = k*P
bool ecc_mul(point_t P, digit_t* k, point_t Q, bool clear_cofactor);
// Fixed-base scalar multiplication Q = k*G, where G is the generator
bool ecc_mul_fixed(digit_t* k, point_t Q);
// Double scalar multiplication R = k*G + l*Q, where G is the generator
bool ecc_mul_double(digit_t* k, point_t Q, digit_t* l, point_t R);
/**************** Public API for SchnorrQ ****************/
// SchnorrQ public key generation
// It produces a public key PublicKey, which is the encoding of P = s*G, where G is the generator and
// s is the output of hashing SecretKey and taking the least significant 32 bytes of the result.
// Input: 32-byte SecretKey
// Output: 32-byte PublicKey
ECCRYPTO_STATUS SchnorrQ_KeyGeneration(const unsigned char* SecretKey, unsigned char* PublicKey);
// SchnorrQ keypair generation
// It produces a private key SecretKey and computes the public key PublicKey, which is the encoding of P = s*G,
// where G is the generator and s is the output of hashing SecretKey and taking the least significant 32 bytes of the result.
// Outputs: 32-byte SecretKey and 32-byte PublicKey
ECCRYPTO_STATUS SchnorrQ_FullKeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey);
// SchnorrQ signature generation
// It produces the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte SecretKey, 32-byte PublicKey, and Message of size SizeMessage in bytes
// Output: 64-byte Signature
ECCRYPTO_STATUS SchnorrQ_Sign(const unsigned char* SecretKey, const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, unsigned char* Signature);
// SchnorrQ signature verification
// It verifies the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte PublicKey, 64-byte Signature, and Message of size SizeMessage in bytes
// Output: true (valid signature) or false (invalid signature)
ECCRYPTO_STATUS SchnorrQ_Verify(const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, const unsigned char* Signature, unsigned int* valid);
/**************** Public API for co-factor ECDH key exchange with compressed, 32-byte public keys ****************/
// Compressed public key generation for key exchange
// It produces a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator).
// Input: 32-byte SecretKey
// Output: 32-byte PublicKey
ECCRYPTO_STATUS CompressedPublicKeyGeneration(const unsigned char* SecretKey, unsigned char* PublicKey);
// Keypair generation for key exchange. Public key is compressed to 32 bytes
// It produces a private key SecretKey and a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator).
// Outputs: 32-byte SecretKey and 32-byte PublicKey
ECCRYPTO_STATUS CompressedKeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey);
// Secret agreement computation for key exchange using a compressed, 32-byte public key
// The output is the y-coordinate of SecretKey*A, where A is the decoding of the public key PublicKey.
// Inputs: 32-byte SecretKey and 32-byte PublicKey
// Output: 32-byte SharedSecret
ECCRYPTO_STATUS CompressedSecretAgreement(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret);
/**************** Public API for co-factor ECDH key exchange with uncompressed, 64-byte public keys ****************/
// Public key generation for key exchange
// It produces the public key PublicKey = SecretKey*G, where G is the generator.
// Input: 32-byte SecretKey
// Output: 64-byte PublicKey
ECCRYPTO_STATUS PublicKeyGeneration(const unsigned char* SecretKey, unsigned char* PublicKey);
// Keypair generation for key exchange
// It produces a private key SecretKey and computes the public key PublicKey = SecretKey*G, where G is the generator.
// Outputs: 32-byte SecretKey and 64-byte PublicKey
ECCRYPTO_STATUS KeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey);
// Secret agreement computation for key exchange
// The output is the y-coordinate of SecretKey*PublicKey.
// Inputs: 32-byte SecretKey and 64-byte PublicKey
// Output: 32-byte SharedSecret
ECCRYPTO_STATUS SecretAgreement(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret);
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,360 @@
/*****************************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: internal header file
*
* This code is based on the papers:
* [1] "FourQ: four-dimensional decompositions on a Q-curve over the Mersenne prime"
* by Craig Costello and Patrick Longa, ASIACRYPT2015 (http://eprint.iacr.org/2015/565).
* [2] "FourQNEON: Faster Elliptic Curve Scalar Multiplications on ARM Processors"
* by Patrick Longa, SAC2016 (http://eprint.iacr.org/2016/645).
******************************************************************************************/
#ifndef __FOURQ_INTERNAL_H__
#define __FOURQ_INTERNAL_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
#include "FourQ_api.h"
// Basic parameters for variable-base scalar multiplication (without using endomorphisms)
#define NPOINTS_VARBASE (1 << (W_VARBASE-2))
#define t_VARBASE ((NBITS_ORDER_PLUS_ONE+W_VARBASE-2)/(W_VARBASE-1))
// Basic parameters for fixed-base scalar multiplication
#define E_FIXEDBASE (NBITS_ORDER_PLUS_ONE + W_FIXEDBASE*V_FIXEDBASE - 1)/(W_FIXEDBASE*V_FIXEDBASE)
#define D_FIXEDBASE E_FIXEDBASE*V_FIXEDBASE
#define L_FIXEDBASE D_FIXEDBASE*W_FIXEDBASE
#define NPOINTS_FIXEDBASE V_FIXEDBASE*(1 << (W_FIXEDBASE-1))
#define VPOINTS_FIXEDBASE (1 << (W_FIXEDBASE-1))
#if (NBITS_ORDER_PLUS_ONE-L_FIXEDBASE == 0) // This parameter selection is not supported
#error -- "Unsupported parameter selection for fixed-base scalar multiplication"
#endif
// Basic parameters for double scalar multiplication
#define NPOINTS_DOUBLEMUL_WP (1 << (WP_DOUBLEBASE-2))
#define NPOINTS_DOUBLEMUL_WQ (1 << (WQ_DOUBLEBASE-2))
// FourQ's point representations
typedef struct { f2elm_t x; f2elm_t y; f2elm_t z; f2elm_t ta; f2elm_t tb; } point_extproj; // Point representation in extended coordinates.
typedef point_extproj point_extproj_t[1];
typedef struct { f2elm_t xy; f2elm_t yx; f2elm_t z2; f2elm_t t2; } point_extproj_precomp; // Point representation in extended coordinates (for precomputed points).
typedef point_extproj_precomp point_extproj_precomp_t[1];
typedef struct { f2elm_t xy; f2elm_t yx; f2elm_t t2; } point_precomp; // Point representation in extended affine coordinates (for precomputed points).
typedef point_precomp point_precomp_t[1];
// FourQ's vectorized point representations
typedef struct { v2elm_t x; v2elm_t y; v2elm_t z; v2elm_t ta; v2elm_t tb; } vpoint_extproj; // Point representation in extended coordinates.
typedef vpoint_extproj vpoint_extproj_t[1];
typedef struct { v2elm_t xy; v2elm_t yx; v2elm_t z2; v2elm_t t2; } vpoint_extproj_precomp; // Point representation in extended coordinates (for precomputed points).
typedef vpoint_extproj_precomp vpoint_extproj_precomp_t[1];
typedef struct { v2elm_t xy; v2elm_t yx; v2elm_t t2; } vpoint_precomp; // Point representation in extended affine coordinates (for precomputed points).
typedef vpoint_precomp vpoint_precomp_t[1];
/********************** Constant-time unsigned comparisons ***********************/
// The following functions return 1 (TRUE) if condition is true, 0 (FALSE) otherwise
static __inline unsigned int is_digit_nonzero_ct(digit_t x)
{ // Is x != 0?
return (unsigned int)((x | (0-x)) >> (RADIX-1));
}
static __inline unsigned int is_digit_zero_ct(digit_t x)
{ // Is x = 0?
return (unsigned int)(1 ^ is_digit_nonzero_ct(x));
}
static __inline unsigned int is_digit_lessthan_ct(digit_t x, digit_t y)
{ // Is x < y?
return (unsigned int)((x ^ ((x ^ y) | ((x - y) ^ y))) >> (RADIX-1));
}
/********************** Macros for digit operations **********************/
// Digit addition with carry
#define ADDC(carryIn, addend1, addend2, carryOut, sumOut) \
{ digit_t tempReg = (addend1) + (digit_t)(carryIn); \
(sumOut) = (addend2) + tempReg; \
(carryOut) = (is_digit_lessthan_ct(tempReg, (digit_t)(carryIn)) | is_digit_lessthan_ct((sumOut), tempReg)); }
// Digit subtraction with borrow
#define SUBC(borrowIn, minuend, subtrahend, borrowOut, differenceOut) \
{ digit_t tempReg = (minuend) - (subtrahend); \
unsigned int borrowReg = (is_digit_lessthan_ct((minuend), (subtrahend)) | ((borrowIn) & is_digit_zero_ct(tempReg))); \
(differenceOut) = tempReg - (digit_t)(borrowIn); \
(borrowOut) = borrowReg; }
// Shift right with flexible datatype
#define SHIFTR(highIn, lowIn, shift, shiftOut, DigitSize) \
(shiftOut) = ((lowIn) >> (shift)) ^ ((highIn) << (DigitSize - (shift)));
/**************** Function prototypes ****************/
/************* Arithmetic functions modulo the curve order **************/
// Converting to Montgomery representation
void to_Montgomery(const digit_t* ma, digit_t* c);
// Converting from Montgomery to standard representation
void from_Montgomery(const digit_t* a, digit_t* mc);
// 256-bit Montgomery multiplication modulo the curve order
void Montgomery_multiply_mod_order(const digit_t* ma, const digit_t* mb, digit_t* mc);
// Addition modulo the curve order, c = a+b mod order
void add_mod_order(const digit_t* a, const digit_t* b, digit_t* c);
// Subtraction modulo the curve order, c = a-b mod order
void subtract_mod_order(const digit_t* a, const digit_t* b, digit_t* c);
// Reduction modulo the order using Montgomery arithmetic internally
void modulo_order(digit_t* a, digit_t* c);
/************* Multiprecision functions **************/
// Check if multiprecision element is zero
bool is_zero_ct(digit_t* a, unsigned int nwords);
// Multiprecision subtraction, c = a-b. Returns the borrow bit
unsigned int subtract(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords);
// Clear "nwords" integer-size digits from memory
extern void clear_words(void* mem, unsigned int nwords);
/************ Field arithmetic functions *************/
// Field negation, a = -a mod p
void vneg1271(velm_t a);
// Field negation over GF(2^127-1) of second element of a GF(p^2) element
void v2neg1271_felm(v2elm_t a);
// Modular correction, a = a mod p
void vmod1271(velm_t a, velm_t c);
// Field addition, c = a+b mod p
void vadd1271(velm_t a, velm_t b, velm_t c);
// Field subtraction, c = a-b mod p
void vsub1271(velm_t a, velm_t b, velm_t c);
// Field division by two, c = a/2 mod p
void vdiv1271(uint32_t* a);
// Field squaring, c = a^2 mod p
void vsqr1271(velm_t a, velm_t c);
void vsqr1271_a(uint32_t* a, uint32_t* c);
// Field multiplication, c = a*b mod p
void vmul1271(velm_t a, velm_t b, velm_t c);
void vmul1271_a(uint32_t* a, uint32_t* b, uint32_t* c);
// Field inversion, af = a^-1 = a^(p-2) mod p
void vinv1271(velm_t a);
// Exponentiation over GF(p), af = a^(125-1)
void vexp1251(velm_t a, velm_t af);
// Conversion functions
void from_std_to_ext(f2elm_t a, v2elm_t c);
void from_ext_to_std(v2elm_t a, f2elm_t c);
/************ Quadratic extension field arithmetic functions *************/
// Convert GF(p^2) element in 23/23/26/26/26/26/26/26/26/26-bit vector representation to
// two field elements in 23/26/26/26/26-bit vector representation
void from_v2_to_v(v2elm_t a, velm_t c0, velm_t c1);
// Convert two field elements in 23/26/26/26/26-bit vector representation to GF(p^2) element in
// 23/23/26/26/26/26/26/26/26/26-bit vector representation
void from_v_to_v2(velm_t a0, velm_t a1, v2elm_t c);
// Zeroing a quadratic extension field element, a=0
void v2zero1271(v2elm_t a);
// Copy quadratic extension field element, c = a
void fp2copy1271(f2elm_t a, f2elm_t c);
void v2copy1271(v2elm_t a, v2elm_t c);
// Quadratic extension field negation, a = -a in GF((2^127-1)^2)
void v2neg1271(v2elm_t a);
// Quadratic extension field addition, c = a+b in GF((2^127-1)^2)
void v2add1271(v2elm_t a, v2elm_t b, v2elm_t c);
void v2add1271_a(uint32_t* a, uint32_t* b, uint32_t* c);
// Quadratic extension field subtraction, c = a-b in GF((2^127-1)^2)
void v2sub1271(v2elm_t a, v2elm_t b, v2elm_t c);
void v2sub1271_a(uint32_t* a, uint32_t* b, uint32_t* c);
// Quadratic extension field addition followed by subtraction over GF(2^127-1)
void v2dblsub1271(v2elm_t a, v2elm_t b, v2elm_t c);
void v2dblsub1271_a(uint32_t* a, uint32_t* b, uint32_t* c);
// Quadratic extension field addition and subtraction over GF(2^127-1)
void v2addsub1271(v2elm_t a, v2elm_t b, v2elm_t c, v2elm_t d);
void v2addsub1271_a(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d);
// Modular correction over GF(p^2)
void v2mod1271(v2elm_t a, v2elm_t c);
// Quadratic extension field multiplication, c = a*b in GF((2^127-1)^2)
void v2mul1271(v2elm_t a, v2elm_t b, v2elm_t c);
void v2mul1271_a(uint32_t* a, uint32_t* b, uint32_t* c);
// Quadratic extension field squaring, c = a^2 in GF((2^127-1)^2)
void v2sqr1271(v2elm_t a, v2elm_t c);
void v2sqr1271_a(uint32_t* a, uint32_t* c);
// Vectorized GF(p^2) squaring/addition in GF((2^127-1)^2)
void v2sqradd1271(v2elm_t a, v2elm_t c, v2elm_t d, v2elm_t e, v2elm_t f);
void v2sqradd1271_a(uint32_t* a, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f);
// Vectorized GF(p^2) squaring/addition/subtraction in GF((2^127-1)^2)
void v2sqraddsub1271(v2elm_t a, v2elm_t c, v2elm_t d, v2elm_t e, v2elm_t f, v2elm_t g);
void v2sqraddsub1271_a(uint32_t* a, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f, uint32_t* g);
// Vectorized GF(p^2) multiplication/addition in GF((2^127-1)^2)
void v2muladd1271(v2elm_t a, v2elm_t b, v2elm_t c, v2elm_t d, v2elm_t e, v2elm_t f);
void v2muladd1271_a(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f);
// Vectorized GF(p^2) multiplication/subtraction in GF((2^127-1)^2)
void v2mulsub1271(v2elm_t a, v2elm_t b, v2elm_t c, v2elm_t d, v2elm_t e, v2elm_t f);
void v2mulsub1271_a(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f);
// Vectorized GF(p^2) multiplication/addition/subtraction in GF((2^127-1)^2)
void v2muladdsub1271(v2elm_t a, v2elm_t b, v2elm_t c, v2elm_t d, v2elm_t e, v2elm_t f, v2elm_t g);
void v2muladdsub1271_a(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f, uint32_t* g);
// Vectorized GF(p^2) multiplication/addition/subtraction in GF((2^127-1)^2)
void v2muldlbsub1271(v2elm_t a, v2elm_t b, v2elm_t c, v2elm_t d, v2elm_t e, v2elm_t f);
void v2muldblsub1271_a(uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d, uint32_t* e, uint32_t* f);
// Vectorized GF(p^2) inversion, af = a^-1 = a^(p-2) in GF((2^127-1)^2)
void v2inv1271(v2elm_t a);
/************ Curve and recoding functions *************/
// Normalize projective twisted Edwards point Q = (X,Y,Z) -> P = (x,y)
void eccnorm(vpoint_extproj_t P, vpoint_t Q);
// Conversion from representation (X,Y,Z,Ta,Tb) to (X+Y,Y-X,2Z,2dT), where T = Ta*Tb
void R1_to_R2(vpoint_extproj_t P, vpoint_extproj_precomp_t Q);
// Conversion from representation (X,Y,Z,Ta,Tb) to (X+Y,Y-X,Z,T), where T = Ta*Tb
void R1_to_R3(vpoint_extproj_t P, vpoint_extproj_precomp_t Q);
// Conversion from representation (X+Y,Y-X,2Z,2dT) to (2X,2Y,2Z,2dT)
void R2_to_R4(vpoint_extproj_precomp_t P, vpoint_extproj_t Q);
// Point doubling 2P
void eccdouble(vpoint_extproj_t P);
// Complete point addition P = P+Q or P = P+P
void eccadd(vpoint_extproj_precomp_t Q, vpoint_extproj_t P);
void eccadd_core(vpoint_extproj_precomp_t P, vpoint_extproj_precomp_t Q, vpoint_extproj_t R);
// Psi mapping of a point, P = psi(P)
void ecc_psi(vpoint_extproj_t P);
// Phi mapping of a point, P = phi(P)
void ecc_phi(vpoint_extproj_t P);
// Scalar decomposition
void decompose(uint64_t* k, uint64_t* scalars);
// 256-bit multiplication with truncation for the scalar decomposition
// Outputs 64-bit value c = (uint64_t)((a * b) >> 256)
void mul_truncate_a(uint32_t* a, uint32_t* b, uint32_t* c);
// Recoding sub-scalars for use in the variable-base scalar multiplication
void recode(uint64_t* scalars, unsigned int* digits, unsigned int* sign_masks);
// Convert scalar to odd if even using the prime subgroup order r
void conversion_to_odd(digit_t* k, digit_t* k_odd);
// Co-factor clearing
void cofactor_clearing(vpoint_extproj_t P);
// Reduction modulo the order using Montgomery arithmetic
void modulo_order(digit_t* a, digit_t* c);
// Precomputation function
void ecc_precomp(vpoint_extproj_t P, vpoint_extproj_precomp_t *T);
// Constant-time table lookup to extract an extended twisted Edwards point (X+Y:Y-X:2Z:2T) from the precomputed table
void table_lookup_1x8(vpoint_extproj_precomp_t* table, vpoint_extproj_precomp_t P, unsigned int digit, unsigned int sign_mask);
// Modular correction of input coordinates and conversion to representation (X,Y,Z,Ta,Tb)
void point_setup(point_t P, vpoint_extproj_t Q);
// Point validation: check if point lies on the curve
bool ecc_point_validate(vpoint_extproj_t P);
// Output error/success message for a given ECCRYPTO_STATUS
const char* FourQ_get_error_message(ECCRYPTO_STATUS Status);
// Constant-time table lookup to extract a point represented as (x+y,y-x,2t)
void table_lookup_fixed_base(vpoint_precomp_t* table, vpoint_precomp_t P, unsigned int digit, unsigned int sign);
// Computes the modified LSB-set representation of scalar
void mLSB_set_recode(uint64_t* scalar, unsigned int *digits);
// Generation of the precomputation table used internally by the double scalar multiplication function ecc_mul_double()
void ecc_precomp_double(vpoint_extproj_t P, vpoint_extproj_precomp_t* Table, unsigned int npoints);
// Computes wNAF recoding of a scalar
void wNAF_recode(uint64_t scalar, unsigned int w, int* digits);
// Encode point P
void encode(point_t P, unsigned char* Pencoded);
// Decode point P
ECCRYPTO_STATUS decode(const unsigned char* Pencoded, point_t P);
/************ Functions based on macros *************/
// Copy extended projective point Q = (X:Y:Z:Ta:Tb) to P
#define ecccopy(Q, P); v2copy1271((Q)->x, (P)->x); \
v2copy1271((Q)->y, (P)->y); \
v2copy1271((Q)->z, (P)->z); \
v2copy1271((Q)->ta, (P)->ta); \
v2copy1271((Q)->tb, (P)->tb);
// Copy extended affine point Q = (x+y,y-x,2dt) to P
#define ecccopy_precomp_fixed_base(Q, P); v2copy1271((Q)->xy, (P)->xy); \
v2copy1271((Q)->yx, (P)->yx); \
v2copy1271((Q)->t2, (P)->t2);
// Vectorize extended projective point Q = (X:Y:Z:Ta:Tb)
#define point_from_std_to_ext(Q, P); from_std_to_ext(Q->x, P->x); \
from_std_to_ext(Q->y, P->y); \
from_std_to_ext(Q->z, P->z); \
from_std_to_ext(Q->ta, P->ta); \
from_std_to_ext(Q->tb, P->tb);
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,36 @@
/******************************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: FourQ's curve parameters
*
* This code is based on the papers:
* [1] "FourQ: four-dimensional decompositions on a Q-curve over the Mersenne prime"
* by Craig Costello and Patrick Longa, ASIACRYPT2015 (http://eprint.iacr.org/2015/565).
* [2] "FourQNEON: Faster Elliptic Curve Scalar Multiplications on ARM Processors"
* by Patrick Longa, SAC2016 (http://eprint.iacr.org/2016/645).
*******************************************************************************************/
#ifndef __FOURQ_PARAMS_H__
#define __FOURQ_PARAMS_H__
#include "FourQ_internal.h"
// Encoding of field elements, elements over Z_r and elements over GF(p^2):
// -----------------------------------------------------------------------
// Elements over GF(p) and Z_r are encoded with the least significant digit located in the leftmost position (i.e., little endian format).
// Elements (a+b*i) over GF(p^2), where a and b are defined over GF(p), are encoded as a||b, with a in the least significant position.
// Parameter "d" is encoded as an interleaved vector using the representation b_4|a_4|...|b_0|a_0 <- 23|23|26|26|26|26|26|26|26|26-bit,
// where the 23-bit digits are the most significant digits. Digits are stored in 32-bit words.
static const uint32_t PARAMETER_d[10] = { 0x00000142, 0x01FC0C8D, 0x00000000, 0x0085223C, 0x000E4000, 0x020FCB38, 0x00000000, 0x0211995F, 0x00000000, 0x005E472F };
static const uint64_t GENERATOR_x[4] = { 0x286592AD7B3833AA, 0x1A3472237C2FB305, 0x96869FB360AC77F6, 0x1E1F553F2878AA9C };
static const uint64_t GENERATOR_y[4] = { 0xB924A2462BCBB287, 0x0E3FEE9BA120785A, 0x49A7C344844C8B5C, 0x6E1C4AF8630E0242 };
static const uint64_t curve_order[4] = { 0x2FB2540EC7768CE7, 0xDFBD004DFE0F7999, 0xF05397829CBC14E5, 0x0029CBC14E5E0A72 };
static const uint64_t Montgomery_Rprime[4] = { 0xC81DB8795FF3D621, 0x173EA5AAEA6B387D, 0x3D01B7C72136F61C, 0x0006A5F16AC8F9D3 };
static const uint64_t Montgomery_rprime[4] = { 0xE12FE5F079BC3929, 0xD75E78B8D1FCDCF3, 0xBCE409ED76B5DB21, 0xF32702FDAFC1C074 };
#endif

Просмотреть файл

@ -0,0 +1,369 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: precomputation tables
************************************************************************************/
#ifndef __TABLES_H__
#define __TABLES_H__
#include <stddef.h>
// The table below was generated using window width W = 5 and table parameter V = 5 (see http://eprint.iacr.org/2013/158).
// Number of point entries = 5 * 2^4 = 80 points, where each point (x,y) is represented using coordinates (x+y,y-x,2*d*t).
// Each coordinate a+b*i in GF(p^2) is encoded as an interleaved vector using the representation b_4|a_4|...|b_0|a_0 <- 23|23|
// 26|26|26|26|26|26|26|26-bit, where the 23-bit digits are the most significant digits. Digits are stored in 32-bit words.
// Table size = 80 * 3 * 320 = 9.375KB
static const uint32_t FIXED_BASE_TABLE[2400] = {
0x303E631, 0xF90353, 0x28D3CE9, 0x398BDF9, 0x2B5FE18, 0x2CDEE02, 0x2FC7540, 0xDE2E1A, 0x287460, 0xC3BA0, 0x937EDC, 0x3A01366, 0x3C3E62C, 0x48E448, 0x55590B, 0x17A5B32, 0x1E093C3, 0x2E4EA55, 0x740B7C, 0x4FFCF5, 0x3DA42BB, 0x330684C, 0x2BF32EA, 0x2268E4C, 0x17C6297, 0x1F27A81, 0xDD55B2, 0x1C828D0, 0x5948D1, 0xCAF2B,
0x1188787, 0x9F9B77, 0x2E8063F, 0xF30CF0, 0x12A83A8, 0x2049B0B, 0x2062374, 0x3E2E134, 0x554612, 0x1BAEEA, 0x1FAF900, 0x2556066, 0x1096984, 0x33C2684, 0x3789006, 0x36EB6DC, 0x4B869B, 0x3BAB39E, 0x18F7CD, 0x448E05, 0x12829B0, 0x3C03EE, 0x3CCDA27, 0xD4F6F7, 0x3DB4BF2, 0x25019F2, 0x32CA55E, 0x16EAFB, 0x6D911D, 0x6C543,
0x1AFA125, 0x1313EF2, 0x3D15C4F, 0x1DDC7E7, 0x364D2EA, 0x306961B, 0x1619228, 0x3E2FF8A, 0x729630, 0x4F41C7, 0x19790AC, 0xDD7487, 0x188EB96, 0x1A59927, 0xA42408, 0x2114FC5, 0x21910CC, 0x3839663, 0x4D3385, 0x74DF72, 0x13C110B, 0x2BFF3D9, 0x18C964, 0x679975, 0x30D8C9A, 0x3A08766, 0x457F92, 0x51F3B8, 0x76BD4, 0x249240,
0x965A73, 0x1F7A57B, 0x16E5852, 0x7014CA, 0x3706D69, 0x200E41F, 0x28A20A7, 0x3A27C0F, 0x28AAC8, 0x441CA9, 0x3F7241E, 0x25400C6, 0x28E2AE2, 0x2BE2E3E, 0x37F4E1A, 0x63ECAD, 0x2BF20CA, 0x18A13A, 0x58F28C, 0x34B6D1, 0x2F15097, 0x48E8BC, 0x2632ACE, 0x3DDAA05, 0x1C49F54, 0x200663B, 0x24005F6, 0x16FC8EB, 0x6DBE77, 0x637192,
0x1ED81FA, 0x975810, 0xB1C86F, 0x3366D6D, 0x16ABC5E, 0x1AA88F3, 0x3BB5A01, 0x64BC2A, 0x4EDE70, 0x4752FD, 0x3734414, 0x2B1A34E, 0x1E53AC7, 0xEC1BDC, 0x662318, 0x2770261, 0x34B211A, 0x2CDEAC1, 0x11DDF7, 0x465575, 0x2638D2B, 0x1B4F131, 0x26117E0, 0x2E4E940, 0x18CE40B, 0x32FBBED, 0x141E40A, 0x34A226, 0x488940, 0x4F356,
0x15B278B, 0x20C977E, 0x3761D44, 0x1307373, 0x58A457, 0x99692D, 0x395364A, 0x1061F5D, 0x56F25E, 0x78FCA, 0x2CC22A1, 0x1C2BAA2, 0x2CB7B5D, 0xDD9F2E, 0x2BF63BB, 0xA8F43F, 0x214F770, 0x9783AA, 0x117B28, 0x73079E, 0x215796D, 0x3372916, 0x1E64AD6, 0x2620D59, 0x2F92017, 0x176DBE0, 0x520367, 0x1ADEBDD, 0x2E7772, 0x258F17,
0x168391B, 0x3E85114, 0xCE3F58, 0x303F413, 0x13A4308, 0x2B51862, 0x17E69CD, 0x39D08EB, 0x728592, 0x53259E, 0x33B1A68, 0x1C928A7, 0xC6A12, 0x35505A3, 0x31FCFE0, 0x2A6A2DD, 0x1987E81, 0x6B7C65, 0x1A4F1D, 0x60185C, 0x6DA9B4, 0x1FA7E8D, 0x25C5F7, 0x3A9BE81, 0x3C03498, 0x8A0A41, 0x12D373F, 0x1BC9DC5, 0x606209, 0x4A4FE0,
0x29E80F0, 0x29A039E, 0x94EA7B, 0x8EF99A, 0x17337BB, 0x14BB843, 0x22F32C4, 0x2BA5CA0, 0x419A92, 0x1B2D1, 0x3051231, 0x22F22DD, 0x2216134, 0x241BF8F, 0x1DD7A75, 0x1A0F91D, 0x83325E, 0x25D7F7C, 0x54DF1E, 0x4E36E9, 0x3747634, 0x173BAA3, 0x21C5D1A, 0x2A025E5, 0x3433D81, 0x37C6E4D, 0x2EBBB84, 0x365F3F9, 0x3E5E31, 0x4B852A,
0x418B9E, 0x5C180B, 0x2CD19C5, 0xE74B79, 0x2F88E08, 0x15C8B73, 0x26CBF9B, 0x3BC474B, 0x283D71, 0x75ACFC, 0x561876, 0x2BAEE08, 0x1DDEA3, 0x38A1F59, 0xC4B8F4, 0x8BFB92, 0x1029C4D, 0x1401A86, 0xC54AC, 0x6F357E, 0x11E6971, 0x12F816E, 0xCC67B, 0x21AA47, 0x3D40C59, 0x2F7DDE4, 0x3BE476B, 0x3B6CECF, 0x747C45, 0x5DCB27,
0x21DD2EE, 0x1ED9BDC, 0x3711B3E, 0x14D3DD8, 0x249843F, 0x307FB54, 0x27DC259, 0x2CC1CFE, 0x51551F, 0x453455, 0x3CAB70B, 0x3EEE29, 0x1DCF8E0, 0x1FB7CA5, 0x34DFF24, 0xF66DA1, 0x179D633, 0x2E35B70, 0x679BE2, 0x3DC9E5, 0x13FB75B, 0x2C7213, 0x1432E90, 0x24090A0, 0x137F56A, 0x252E5FF, 0x16F16A1, 0x323D094, 0x1E6531, 0x73C9D8,
0x3198C8F, 0x2DD6902, 0xDEE18C, 0x4F9CB7, 0xF333C6, 0x33AFAD3, 0x2CFB505, 0x250737C, 0x534F84, 0x5ED57E, 0x257306E, 0x31C2BF3, 0x3F8074A, 0x2DC15C3, 0x13F95A6, 0x18DB39C, 0x3A8D11C, 0x3927C68, 0x73B63D, 0x2DF8C6, 0x37797E4, 0x959643, 0x2F0D259, 0xAA237A, 0x1062661, 0x1D515B5, 0x32EFAFA, 0xA04700, 0x501AE7, 0x37275,
0x1BB928, 0x1A02CF1, 0x315E88C, 0xFE908A, 0xFC6010, 0x1B29F88, 0x1C55555, 0x2E1435F, 0x378B31, 0x5F0047, 0x402DAA, 0xA443F5, 0x11EB8CA, 0x19766A2, 0x22BC4D2, 0x3089B4E, 0x9EA142, 0x1ACB5B6, 0xD0306, 0x6EC968, 0x2A1D987, 0x261BFB7, 0xB823F, 0x345EFBD, 0x3600DE2, 0x334C157, 0x34FCA35, 0xDB75D4, 0x5C64E1, 0x56392D,
0x119155C, 0x14E15E8, 0x11E362F, 0x2F802FE, 0x2AFDE25, 0x10C09BF, 0xB4F4CD, 0x269AB7C, 0x146D4F, 0x2B185A, 0x152AB7B, 0x7CC541, 0x149ECFB, 0x3D3FD25, 0x1E80926, 0x1A7AB58, 0x51CC40, 0x31FEB26, 0x67997E, 0x36F800, 0x456D9, 0x350D898, 0xB8C90, 0x132AED1, 0x297BD03, 0x3CBF914, 0xD902F1, 0x3EB2688, 0x4372E4, 0x75D25A,
0x255CBFE, 0x166D0C9, 0x1645D9D, 0x1EC8909, 0xB07794, 0x3B23705, 0x1985FF1, 0x1642105, 0x74DB21, 0x1D543B, 0x428783, 0x68AE72, 0xA02D11, 0xCF5AB0, 0x3EF19C, 0x19F4378, 0x3F62DB3, 0x688F00, 0x352309, 0x4EC067, 0x3D05BB5, 0x17EFB4A, 0x20DB868, 0x1AF0F39, 0x2FE39D9, 0x150A29, 0x37FC893, 0x1A0D685, 0x44FE1A, 0x2EFEC8,
0x3194BCA, 0x1C0B9E0, 0x67027E, 0x3FC85F2, 0x12062FE, 0x3CEE5BD, 0x34E54F3, 0x159606A, 0x18CC07, 0x671AA7, 0xF7D1A2, 0x1BABB83, 0x30CEB8A, 0xF4599, 0x23FEE1C, 0x1211515, 0x124DE82, 0xDB5622, 0x1B6F25, 0x74B956, 0x296F869, 0x2B93B13, 0x25EB93A, 0x393553E, 0x10BDBDB, 0x929796, 0x627894, 0x17C1658, 0x1507CE, 0x6A8176,
0x1A833ED, 0x3D52693, 0x1014879, 0x1DA5D7F, 0x36442E9, 0xED6BEA, 0xCAC917, 0x122E9B5, 0x3BDEA5, 0x64B948, 0xE33EC7, 0x35A8138, 0x14B4065, 0x1CEC7F6, 0x1F259DB, 0x1C22EDE, 0x369558E, 0xEDB18B, 0x71CF65, 0x12E4D1, 0x1185517, 0x2CD84E4, 0x26C3099, 0x37172AB, 0x3DD09D1, 0x12D11FE, 0x3495ED7, 0x5478D2, 0x77A011, 0x46844E,
0x4220DF, 0x335E22E, 0x8E8C64, 0x197BAB7, 0x30997A4, 0x195B1C6, 0x31D1FA3, 0x15BF115, 0x5B3165, 0x7802B5, 0x15BD2DE, 0x60C1E5, 0xB7BD00, 0x3DB4D48, 0x26AD85A, 0xE6A19C, 0x21E55C5, 0x346F902, 0x17F2AB, 0x122A7A, 0x5BF766, 0x3A28538, 0x26EF219, 0x9A89CA, 0x1ACF5B7, 0xBDE975, 0x275342B, 0x3A43508, 0x20FB00, 0x7041B4,
0xDAB057, 0x3CD4708, 0x44CD6, 0x1666680, 0x2433B3, 0x9691A, 0x19BC349, 0x27364E, 0x3D398B, 0x1EAE24, 0x36108C, 0x125DCFD, 0x35AD813, 0x2B5A45C, 0x196866D, 0x31CA57C, 0xDE2420, 0x2E25C13, 0x171308, 0x34B06C, 0x335ABF2, 0x3AF075B, 0x3FA39C7, 0x1D9D990, 0xDB9DCA, 0x2B6D628, 0x663551, 0x3955674, 0x698331, 0x200950,
0xDD9074, 0x1319356, 0x18FF0FB, 0xC201, 0x13A2D4F, 0x38BA96B, 0x1C50AB0, 0x380910D, 0x747331, 0x2C20FF, 0x26AC01A, 0x30BF8EA, 0x25446B4, 0x3F9B9C3, 0x3CF6488, 0x26D715F, 0x86665F, 0x2D29B42, 0x4EE327, 0x6B617F, 0x12F7324, 0x37E04B, 0x1B72871, 0x843132, 0x277491, 0x142CC24, 0x3C2191A, 0x13E4569, 0x3C8269, 0x4E480B,
0x27FE35E, 0xA407B9, 0x3BCEC26, 0xA79250, 0x4B2C5F, 0x25AB79F, 0x37913F6, 0xF29733, 0x31A501, 0xBA7E0, 0x274D8EA, 0xA1128A, 0x22C8162, 0x1C6B3A5, 0x1ADCA7A, 0x2811461, 0x204389B, 0x95256, 0x46F4C7, 0x44DB55, 0x3F18D5C, 0x31CFFAD, 0x2278692, 0x265D9AE, 0x6B27F8, 0x1ACA33A, 0xA90FCC, 0x164934E, 0x4D4F17, 0x625477,
0x225136E, 0x23F63BA, 0x148C3B0, 0x3A65A7D, 0x211DD85, 0x138212F, 0x341E364, 0x3725277, 0x1C544D, 0x69AF1, 0x3E5C256, 0x3B7DE06, 0x2F3D033, 0x425DE4, 0x3595305, 0x43EE45, 0x2492EEE, 0x3CE7F00, 0x63AE90, 0x9780C, 0x3798871, 0x2E055BA, 0x2BE39FA, 0x3C184CC, 0x3A37827, 0x292B79D, 0x1B1DD5D, 0x1EAAB3A, 0x3ACE8A, 0x561DC0,
0x20D2673, 0x2D8526B, 0x108B660, 0x146B077, 0x13487E4, 0x2BD1F1, 0x20F82BD, 0x39455C5, 0x6B85DF, 0x35EAD8, 0x3C79DD4, 0x27D5FA, 0x1BBDB0C, 0xDF4330, 0x3DE46DA, 0x331B910, 0x1349653, 0x401EC0, 0x5F2EA0, 0x53B540, 0x14BA5A3, 0x2ACF9E, 0x3C6628F, 0x2252B3B, 0x195810, 0x9CE32B, 0x966EA5, 0x187590D, 0x4463BD, 0x787117,
0x11FE211, 0x25E49DE, 0x2B86CFD, 0xDB4436, 0x2463253, 0x336A3A2, 0xFD4D6D, 0xA7084, 0x409E4B, 0x19D2B1, 0x2AADD90, 0x2828279, 0x17D010D, 0x244C61D, 0xB19283, 0x1F9CC18, 0x541464, 0x30F2A38, 0x942A3, 0x3AFE96, 0x1230693, 0x1D44C8E, 0x2006D24, 0x2D40D57, 0x10919F1, 0x280D9FA, 0x2E1897F, 0x369CA6C, 0x39E28D, 0x145155,
0x14D76D5, 0x354EA8A, 0x33E0407, 0x19B2132, 0x2C68D3C, 0x7733CC, 0x6A30AD, 0x38FD59B, 0x5A0FAA, 0x51052C, 0x1AE9FF5, 0x16BF15E, 0x3853799, 0x39E4722, 0x30243BE, 0x13D6089, 0x2280733, 0xB49876, 0x758611, 0x35FF02, 0x37D1CF9, 0x2DC41B4, 0x3384F63, 0x1A28918, 0x38F6CD3, 0x1D2951E, 0x23E56DE, 0xF08FDB, 0x4F1DE9, 0x61AD9E,
0xEBDB51, 0x1F336D5, 0x3FA9920, 0x3920FAB, 0x2CF3584, 0x296A9AF, 0x1CFE77, 0x32602C5, 0x5D52FE, 0x1DFA03, 0x3819A19, 0x2399419, 0x1CF51FF, 0x1201111, 0xED55F, 0x259FDED, 0x174D844, 0x119FF38, 0x697BF5, 0x618C94, 0x8EF50C, 0xDED5F6, 0x25FFC7C, 0x1632F1E, 0x33C0F25, 0x148FBB7, 0x2E63764, 0x1ABC4C, 0x7C935, 0x1E9A0D,
0x34CD4DB, 0x17605C3, 0x338515F, 0x2568F71, 0x994879, 0x27B1F50, 0x28658B5, 0xF69314, 0x28396C, 0x1E570F, 0x935787, 0xBC8633, 0x1A68E41, 0x2D637E2, 0x1CCE2AF, 0x15D1F77, 0x1DBF740, 0x146CBCE, 0x591EE3, 0x5464D6, 0x29A86AE, 0x29D3E08, 0x3025AC7, 0x2A0A34B, 0x2B28AFB, 0x26D03B3, 0x12FD96D, 0x7634B5, 0x6CE2DF, 0x638201,
0x13D193D, 0xAD15A9, 0x21F2993, 0x37D9F32, 0x16AF949, 0x1F928D5, 0x34EDB5, 0x262F16C, 0x50DDF7, 0x392080, 0x3D5A4FB, 0x3C789, 0x27D4837, 0x3E22A36, 0x3BA9CE9, 0x55E13, 0x21EE1A9, 0x2F7C880, 0x323BBC, 0x56FFDC, 0x324C72D, 0x2C46A13, 0x3C368C6, 0x1EDFD4E, 0xC163AF, 0x3BC276F, 0x1991830, 0x3FADC1D, 0x700115, 0x1C069B,
0x14A3C36, 0x17D6634, 0x1C64F28, 0x2CAF64C, 0x1E3D8F4, 0x1EC8634, 0x12BC223, 0xE2DDFC, 0x6D73E3, 0x5B4047, 0xA1CB1D, 0xEDA660, 0x3EAEDC7, 0x372B742, 0x2A46F34, 0x1EF1E8C, 0x32B2951, 0x2FE562F, 0x54ABB, 0x6971AB, 0x1DB4EAF, 0x3A26068, 0xE155F7, 0x1C11D33, 0x367C413, 0x2469D22, 0x216C1E6, 0xCACF3A, 0x1E1585, 0x53B36D,
0x543D08, 0x117ACD1, 0x148F05B, 0x3CFAF90, 0x314E011, 0x131ABAE, 0xB17DCC, 0x6A9C4E, 0x4668E9, 0x4037D, 0x390C68D, 0x329C032, 0x463938, 0x1FAA295, 0x157568E, 0x1AB2730, 0x1569130, 0x17FBBA6, 0x6B80CD, 0x5CC547, 0x14AC75, 0x588052, 0x1439093, 0x38AC6D4, 0x1CD8344, 0x2F8F62C, 0x1F976CF, 0x3153994, 0x3F0915, 0x27A899,
0x3C2A5ED, 0xA75958, 0x340E7CB, 0x34627A4, 0x3EEC0AC, 0x33A1C04, 0x3775604, 0x2F39C74, 0x4B4044, 0x242551, 0x1F87F05, 0x39483C5, 0x2BE5AD4, 0x3D97DCE, 0x1815D95, 0xB43B27, 0x83E027, 0x117D0D9, 0x29888, 0x2EF607, 0x34FB8B9, 0x39867A1, 0x1AF724F, 0x2F6B826, 0x3B8ACB6, 0x29AAF8E, 0x2D21D5A, 0x6139BF, 0x2B86C9, 0x441E70,
0xCC1289, 0xAE74BE, 0x94C0CC, 0xEDBE8C, 0x2992FDC, 0x19D58C0, 0x16A2D35, 0xF30EF6, 0x47D8D6, 0x1CA869, 0x18F2A6, 0x13AAB59, 0x3AC5444, 0x1C810CF, 0x3FF5699, 0x17FF361, 0x19367D3, 0x184B2E1, 0x3DA047, 0x2FA911, 0x2F1CAC, 0x15F0BC5, 0x15F6843, 0x1040834, 0x619A40, 0x1DAD423, 0x2E4CE97, 0x1411A82, 0x48A219, 0x73F889,
0x27421B8, 0x4E0DFF, 0x354C4B1, 0x1C69E79, 0x222E1BA, 0x31C28CC, 0x6CDA39, 0x391519F, 0x419477, 0x4B4564, 0x3E52093, 0x34EF798, 0x27C5AAB, 0x301A52A, 0x3EA9775, 0x130D2A1, 0x3735D7E, 0x1515110, 0x391B71, 0x23087, 0x3AA1AA1, 0x10B54B9, 0x2B87FF3, 0x11C0E2F, 0x21E74B7, 0x2E158DA, 0xCB5CCD, 0x1BFABB3, 0x64E26F, 0x148CFA,
0x1C2CC3D, 0x2BB2C43, 0x1B5351E, 0x322FBC9, 0x3DE375, 0x337FD82, 0x2A34C55, 0xCF49F, 0x25D44E, 0x2C2047, 0x3DAD260, 0x2A583F2, 0xCF660D, 0x1C75A5F, 0x3B7D5BD, 0x1BF2120, 0x5E8CE0, 0x9CA889, 0x779431, 0x3C7C41, 0x1F03AD3, 0x2EE75D1, 0x2EF7EBC, 0x38A14EE, 0x370492E, 0x3636CA6, 0x31A2D8, 0xD1DC68, 0x5D6103, 0x12404B,
0x2667E4F, 0x1C80F89, 0xF118C9, 0xFE32EB, 0x23B0BE1, 0xB4886E, 0x245BE6F, 0x2285E53, 0x2BD261, 0x74520D, 0x24CF97E, 0x399CDA1, 0x171D140, 0x223782B, 0x2B021E1, 0x62C8D0, 0x78794F, 0x2587302, 0x5CEE74, 0x625812, 0x1C0E934, 0x10E143, 0xD0DCC8, 0x1C7EFCF, 0x37A4431, 0x15B8ABA, 0x1A31093, 0x27C52A4, 0x60BBC7, 0x37B8EA,
0x213FF, 0x2F607A3, 0x1BB1971, 0x2DC6536, 0x45C8D9, 0x706BED, 0xA3FDDE, 0x1C45872, 0x74A088, 0x17E866, 0x24059CF, 0x31B3C47, 0x2E63814, 0xA5C6EB, 0x2F09ACE, 0x1B704CD, 0x3125245, 0x2F37788, 0x68552A, 0x68442E, 0x2867595, 0x2E393AD, 0xA6E303, 0x2D1783C, 0x247A196, 0x10C46FA, 0x34D8D7E, 0x3D3F3C1, 0x6A6955, 0x66DD3E,
0x1DC7DF1, 0x2FD411D, 0x2DEAF3F, 0x1E7E728, 0xF9CBB0, 0x200A1CF, 0x1D46C2F, 0x1CFFFC1, 0x14EB5B, 0x5C496F, 0x1426D70, 0x19B6D4F, 0x1236155, 0x3F6E1C3, 0x18A9496, 0x3633B57, 0x1A88C8B, 0x1482776, 0x46C101, 0x609EB6, 0x2DC82C5, 0x227A20, 0x3E459AF, 0xA5366C, 0x2F27E70, 0x3C8D79A, 0x2D722BE, 0x10444B6, 0x772FB5, 0x7F75B1,
0x2070020, 0x15F33FF, 0x71FE23, 0x94FAF8, 0x17B198D, 0xC45E28, 0x2AB1208, 0x3047985, 0x5953D0, 0x267D1D, 0x19E2246, 0x260BED0, 0x13D42AE, 0x356B01F, 0x1495BE6, 0x1B4D927, 0x1720BF9, 0x1B79AA8, 0x4EAAAB, 0x67D378, 0x36E2945, 0x26640AC, 0x258AFC3, 0x8A31F4, 0x2A9BA71, 0x35A1B34, 0x1128D7B, 0x34BACA3, 0x63D938, 0x169C38,
0x39DC22, 0x1D58C7, 0x25CACCD, 0x1B8497B, 0x1E144B7, 0x14F1522, 0x15F36A8, 0x25B9E3F, 0x714784, 0x669D87, 0x244A07F, 0x14FBD25, 0x3746AAA, 0x2E3A56D, 0x3ECF750, 0x364E006, 0x2D56BAE, 0x17407AC, 0x327C62, 0x2AB3F9, 0xD5E196, 0x139B5D, 0x3942030, 0x2CAD9D6, 0x2725FCB, 0x3A731D2, 0x35D695F, 0x2BE126D, 0x2A1B9B, 0x751CF4,
0x37D00A5, 0x1BE28F9, 0x29F4B8C, 0x2380D9B, 0x24BC164, 0x502349, 0x2932E0E, 0x245234A, 0xCEE3, 0x53D89, 0x2B0FB69, 0x13F915D, 0x1975932, 0x12EF52F, 0xE74016, 0x22BBBA4, 0x88235A, 0x3E45C84, 0x4A9913, 0x1D34B0, 0x1E8A9F3, 0x2F0F3E8, 0x5371CA, 0x2E3A48C, 0xB605D1, 0xF6228D, 0xF754CD, 0x6E0099, 0x8E7A4, 0x5CB7BE,
0x2508F23, 0x1D194BE, 0xB1E1E0, 0xB53B8B, 0x21B29AF, 0x28727FE, 0x333DF8E, 0x6CAE29, 0x336AE7, 0x573D2E, 0x3B2EA36, 0x2B3260D, 0xBA8CD8, 0x11F2301, 0x243333, 0x1C5E65C, 0xDD6C7D, 0x3294E65, 0x200BC1, 0x42021F, 0x3B19946, 0x3E0D70D, 0x39B3D26, 0x304ED8A, 0x2D2C2F7, 0x30DCC30, 0x1A88C65, 0x509C46, 0x311FBA, 0x61EEAC,
0x17D35D4, 0x129A510, 0x9A6596, 0x6CB42B, 0x21D7885, 0x394DA0F, 0x32F9AF4, 0x51CB06, 0x70169B, 0x2ADE53, 0x9873E7, 0x2F621E3, 0xC83706, 0x23114E9, 0x1B3811E, 0x36F7A0A, 0x253A173, 0x2D51497, 0x2D2A17, 0x4B06D5, 0x48EC1C, 0x10A5B4E, 0x2459A46, 0x18369CA, 0x730F42, 0x165FF8C, 0x155755E, 0xE687CD, 0x1D4216, 0x66DD9F,
0x3B474A0, 0x2E6BC89, 0x30A764D, 0x36B2A84, 0x1EE455A, 0x310918, 0x1E928DA, 0x2401947, 0x429196, 0x3D46E8, 0xE90B1, 0x8C51E6, 0x1550C28, 0x870CD2, 0xA39AF0, 0x3CD51A0, 0x3D5B697, 0x37D8FEE, 0x16F62B, 0xD64DA, 0x1BFEA7C, 0x39FA90C, 0x23B3967, 0x21516E2, 0x203A091, 0x19E61D8, 0x35F75D0, 0x3724231, 0x3B3319, 0x13B792,
0x3D0979, 0x26D8470, 0x364E6A7, 0x251FFFD, 0x31270A2, 0x3C995E5, 0x2FADD2F, 0x32BF49A, 0x321A5D, 0x22EC9E, 0x3B10536, 0x1485023, 0x1F2A0A4, 0x20DCCDD, 0x1846DE1, 0xB1C114, 0x3015677, 0x3F7DD12, 0x593F56, 0x23C6B0, 0x227804F, 0x235AC70, 0x2411162, 0x6C93CC, 0x2A70377, 0x385E35E, 0x2589C9B, 0x8127D3, 0x573E91, 0x51BA08,
0xD47194, 0x26E4E33, 0x1246058, 0x16252CF, 0x21DD4BC, 0x10FB7E1, 0x78CC23, 0xBD3CC7, 0x5D29A2, 0x50DBBD, 0x1A9C9DE, 0x2363BD2, 0x122F48D, 0x1C8CE94, 0x710EF2, 0x99F96C, 0x3486D8D, 0x2B66823, 0x3418AD, 0x7C8414, 0xE6C05C, 0x308FA1C, 0x2B2D295, 0x1F0F802, 0x179ABC6, 0x2A73062, 0x68464D, 0x3E785F0, 0x572902, 0x3D0B4F,
0x190317F, 0xE651F5, 0x1FA1D56, 0x203CB1B, 0x3E48D50, 0x2E4644A, 0x2CEF1EF, 0x3F06DC1, 0x75B27B, 0x7B9795, 0x1F9A640, 0x30889A0, 0x1D6F7BF, 0x2AC45A1, 0x3AA89DE, 0x2C6CCE0, 0x2AEAFF, 0x3F37567, 0x75ADE5, 0x6F3DDC, 0xDE0674, 0x884D61, 0x1A0CD62, 0x2394E19, 0x20736E3, 0xD76F8B, 0xA7A8A2, 0x3C6BA15, 0x291D11, 0x706EF8,
0x3753069, 0x376C7BA, 0x2A31960, 0x387FE0B, 0x3966137, 0x1C54E28, 0x731883, 0x2B38FA2, 0x1E45F, 0x36D29E, 0x30B49CB, 0x30CDA3E, 0x1E7C55F, 0x8F1141, 0x3937833, 0x2DE59B3, 0x278AEB2, 0xC6ADF8, 0x65E9C3, 0x16E02F, 0x35122B7, 0x21E57AC, 0x33CD198, 0x3D7E53A, 0x1E0953B, 0x34DF3A5, 0x1F5B0B, 0x3A343C2, 0x1FD7E2, 0xCBA06,
0x3A9C392, 0x239912B, 0x11030E1, 0x22E9B5C, 0x180070B, 0x2D14549, 0x10F7B87, 0x2805C60, 0x1E7DC1, 0x332870, 0x32D794C, 0x12BA79F, 0xC1BF19, 0x2DC8B23, 0x2B4E6BE, 0x327A109, 0x44916C, 0x3EA717D, 0x2C2CE2, 0x268520, 0xFE78EE, 0x210BF78, 0x2CC0149, 0x22B044C, 0x2698515, 0x1843460, 0x3B32EBA, 0x2467110, 0x736201, 0x32D8FD,
0xB8F2D8, 0x3A417F5, 0x15F86C1, 0x3D5616, 0x3459C95, 0x1304120, 0x3DE6371, 0x17CF9EB, 0x775437, 0x2E00EC, 0x3446288, 0x789B22, 0x1CF57CA, 0x1A91F02, 0x36E4FC8, 0x16BEC64, 0x24D8921, 0x3FA4958, 0x32270A, 0x2370D9, 0x1E671C4, 0x2417635, 0x2BE8D86, 0x137B0BC, 0x1FB2430, 0x258F3B8, 0x33AB07D, 0x2405F03, 0x156468, 0x31140E,
0x37443FA, 0x1B0FB84, 0x17E2332, 0x3FD121C, 0x24AC5C8, 0x36C3295, 0x1759361, 0x2EB4CC, 0xDA75F, 0x1B79E1, 0x12977B3, 0x112864E, 0x3E650B7, 0x1E28930, 0x1A23FFD, 0x8D0BA7, 0x2343E68, 0x25FC9B5, 0x4C1B19, 0x74F668, 0x27AB611, 0x1CB9165, 0x1701BA1, 0x2D3739D, 0x38B93FD, 0x1163F7D, 0xCFFDE1, 0x28267B1, 0x4B98CE, 0x11665A,
0x27118B9, 0xCE2C86, 0x263C5AB, 0x108C19A, 0x109A2A4, 0x33853DA, 0x36ED3AD, 0x2AACB8C, 0x265EC3, 0x36E62B, 0x1AB4478, 0x3022CE1, 0x1F529E, 0x307B24C, 0x875995, 0x466D7A, 0x3F1047A, 0x2B80CF4, 0x25BFB2, 0x23D341, 0x162BC00, 0x3922D4D, 0x16D197A, 0x3335EBF, 0x3180D29, 0x1514A03, 0x6E8B5C, 0x12378C0, 0x23D021, 0x1E7671,
0x94EFAB, 0x3D27A87, 0x6ACDAA, 0x2E5958A, 0x1E58C24, 0x3015CA3, 0x3CD0FF0, 0x8A1775, 0x1C9FC2, 0x53623E, 0x219420, 0x323592F, 0x1047C07, 0x4B6506, 0x2F9557, 0x1C06D33, 0x1DC25AD, 0x2870F14, 0x192655, 0x30A9A9, 0x26E8F79, 0x2DF6E36, 0x26C2CFA, 0x26C61B9, 0x3CB23D8, 0x1694C0A, 0x77171D, 0x160FC55, 0x7EAB75, 0x4F844D,
0x393DFFA, 0x1DF6E32, 0x608C9, 0x1203C4C, 0x54D419, 0x2417D55, 0x2DAF4E, 0x211AB8F, 0x2ADD44, 0x318CE3, 0x20984F4, 0x1E79790, 0x1418B46, 0x1D7F9CA, 0x39F6056, 0x24E7770, 0x18F4AFF, 0x1189322, 0x6EBAEC, 0xDD943, 0x3A9B062, 0x32C6344, 0x3C478B7, 0x85433D, 0x3364BF8, 0x28DC62C, 0x957BA2, 0x2034207, 0x1B17D8, 0x281068,
0x3EC91C1, 0xB9316F, 0x12BC377, 0x1E8E9CE, 0x1F2EF4A, 0x22EC72A, 0x1B25DF8, 0x1CA3138, 0x1A8F0E, 0x323716, 0x3A4AF3B, 0xB6C337, 0x1A4196, 0x352BEAA, 0x1367C14, 0xE751B, 0x922447, 0x26D44D0, 0x81514, 0x50E77A, 0x2822548, 0x1CAC17F, 0x146CA, 0x2C3BE90, 0x1CFC46C, 0x1675A06, 0x390697B, 0x2C06E71, 0x24886, 0x336A30,
0x2097626, 0x1A17B74, 0x2CB0432, 0xB254AE, 0x98174F, 0x303B690, 0x2A923A4, 0x2DAE488, 0x2B204C, 0x39C2E9, 0x597419, 0x2AE1427, 0x5AE6CF, 0xA5F57B, 0x1F76B92, 0x13077B1, 0x993C5, 0x2B7F86F, 0x6D9293, 0xF0744, 0x3E6A89D, 0x1DC772C, 0x15F8996, 0xE65718, 0x2C1033B, 0xFF53A0, 0x394CCD5, 0x17A24F7, 0x282FA2, 0x4F5D8F,
0x48023F, 0x29B8A2, 0x3249FBF, 0xF82BFB, 0x5AE4BF, 0x38423CB, 0x1075A9A, 0x344194, 0x596F22, 0x31018E, 0x575626, 0x26781A7, 0x3FA51, 0x3559993, 0x20112FD, 0x22CE970, 0x1C1260B, 0x2743CF7, 0x1241D8, 0x1B05F4, 0x3717E66, 0x3F1579A, 0x13FF7D8, 0x20B3B54, 0xE98A99, 0x2A4B8B0, 0x29DAEA2, 0x3EAD74A, 0x416374, 0x56781D,
0x65B318, 0x338E14E, 0x77BF46, 0x1BD2ED7, 0x1F7815, 0xB40E43, 0x2103582, 0x1042A5D, 0x64669B, 0x43D438, 0x266BE02, 0x1E3EA86, 0xB3ACF5, 0x251C6CE, 0x28E583, 0x1AE4697, 0x2786B86, 0x1872D2D, 0x6347D, 0x2CF2CF, 0x25A6EE4, 0x30D1FFC, 0x2CA7AB6, 0x2C44274, 0x1768B7A, 0xE5AE65, 0x2CA6B29, 0x335ACC8, 0x12E75C, 0x71F9BE,
0x247EED9, 0x254C1E5, 0xA24099, 0x2EFD48E, 0x58FDC8, 0x1491EA2, 0x143295, 0x2E78FB9, 0x31D62D, 0x602BF0, 0x380AD4B, 0x2A0470D, 0x29CD888, 0x17BF61A, 0x1F5825A, 0x354BDBC, 0xC9C77D, 0x92E310, 0x2B6B1E, 0x5353C, 0x1E06BCA, 0x2CE7CA1, 0x1F6CF3D, 0x14BD784, 0x25F7A3C, 0x3C7DD61, 0x23CAD3A, 0x2D0D99C, 0x288A1C, 0x59D4C1,
0x21FCB95, 0x1A4D9D1, 0x955394, 0x5BDACE, 0x14401E0, 0x2F62ABF, 0x3C902B, 0x72A530, 0x66D398, 0x7FEA35, 0x9163BA, 0x1A7C669, 0xADBCCE, 0x19100F3, 0x15EA3D6, 0x3193D5C, 0x13CB9E2, 0x243980, 0xFC6B4, 0x2E4099, 0x1FA4C2F, 0x25B331B, 0x303EBC5, 0x12B758E, 0x36399B5, 0x18795CE, 0x276384A, 0x1CDB131, 0x46295C, 0x5FA7BD,
0x3D1AEF2, 0x23C5299, 0xD1C511, 0x210DF66, 0x173947B, 0x27E8D58, 0x7088C9, 0x604B34, 0x28004C, 0x2AB19C, 0x37802, 0x2BC2139, 0x1C03DA0, 0x1FBCDBE, 0x2B363AE, 0x3D1D45B, 0x2002D08, 0x3FC8772, 0x1AD163, 0x44BCDE, 0x1E11C7B, 0x1C13849, 0x1B6885C, 0xA509D6, 0xC1441C, 0x50A485, 0x1E7DF13, 0x1BC42F8, 0x2C35EE, 0x6492D2,
0x50F0D9, 0x25E57A3, 0x153A623, 0x2601ACA, 0x181BA6F, 0x3D20F7D, 0x2DB7588, 0x36CEE94, 0x6A2DB2, 0x57526B, 0x100E650, 0x18DE970, 0x39B2C7D, 0x29B1A, 0x334517C, 0xB8EAA8, 0x2C10BE3, 0x166AF8B, 0x5D841, 0x4F4B5, 0x19CE49D, 0x1306204, 0x37F5C9, 0x496195, 0x3935C05, 0x305AB37, 0x2F7E536, 0x22C67E5, 0x213839, 0x7D323B,
0x2B6C618, 0x1B41872, 0x1140AC5, 0x1F038DB, 0x195B26D, 0x21D0F86, 0x1A6AA25, 0x361B1DB, 0x797170, 0x13D601, 0x31B7383, 0x310EBA0, 0x322C34C, 0x344F9CA, 0x752DF, 0x1B9505B, 0x3CF90BA, 0x1D243DE, 0x185472, 0x519A38, 0x3AD2500, 0x62426C, 0x2706CB4, 0x60655A, 0x37338D0, 0x1B09640, 0x174B3C3, 0x3D66FF8, 0x45DA4, 0x728D57,
0x1A2C585, 0x394FE0, 0x267E1E3, 0x180B315, 0xE10F9A, 0x28AE6DC, 0x798771, 0x1AD9FA7, 0x4FC483, 0x48456, 0x293809B, 0x2FE6C43, 0x33C11D2, 0x3EAF8D, 0x22BBC5F, 0xA7B40, 0xE963CF, 0xFABB93, 0x71C0C2, 0x614C2F, 0xE1C6C1, 0x2C2CB2B, 0x2A6034, 0x38727CE, 0x1DCC761, 0x341EEAD, 0x1F22221, 0x1EEBCBC, 0x1CE819, 0x471AD0,
0x301121B, 0x33262CA, 0x2A0DF1A, 0x1C0790B, 0xB59D67, 0x58052E, 0xA07D67, 0x1F7B394, 0x2A8E64, 0x19E0A2, 0x3BDA6AC, 0x3AE49EA, 0x24705E9, 0x555526, 0x31F2B56, 0x3AE5A68, 0xC46E77, 0x3768897, 0x43484C, 0x43A2C5, 0x1700EEF, 0x8C4DA9, 0x3A64ABB, 0x2E06879, 0x856FA5, 0x3BD648, 0x1588E46, 0x32F743, 0x58911F, 0x66E6E3,
0x29D266B, 0x20C3D2E, 0x2882705, 0x2D6AA86, 0x3685F3B, 0x11F1D1B, 0x188C111, 0x210F444, 0x20F7A8, 0x366C29, 0x1CC9013, 0x677464, 0x1E2D90B, 0x3AB2F29, 0x23FB06C, 0xCC18F8, 0x1938427, 0x6C7709, 0x27484A, 0xB6CB3, 0x18F0FA0, 0x14C5C69, 0x27213E2, 0x4A865F, 0x32A2DF6, 0x18D6C09, 0x1D12483, 0x1FDAA63, 0x2DD426, 0x489ADE,
0x3203E28, 0x16D7D67, 0x1DA7D1F, 0x24DBD2B, 0x2C97458, 0xFF83BB, 0x8FF016, 0x3FB53C0, 0x124F41, 0x330954, 0x2F90EAF, 0x6DFB83, 0x3994011, 0xC5CA96, 0x1EBDC2C, 0x3D962E9, 0x18B53E7, 0x18AD044, 0x7BF947, 0x3C7A60, 0x7F0D93, 0x3639BFA, 0x2C0E5C5, 0x399FFD9, 0x10345DD, 0x232374, 0x1BF1A0E, 0x846622, 0x8E359, 0x19021C,
0x1D55EFA, 0x174C84C, 0x3D7413F, 0x1E3A8EB, 0x3AA3002, 0x277DE56, 0x381E786, 0x209A962, 0x5B4C6, 0x1C42F7, 0x2CAFACD, 0xAEBB32, 0x119A2F4, 0x11A98DD, 0x261CE05, 0xEF4EDF, 0x34FB790, 0x164C73C, 0x237668, 0x31EC8C, 0x35B5825, 0x27D1EC0, 0x30BA570, 0x225DB90, 0x1603955, 0x3D13B7A, 0x3A9A096, 0x301C54A, 0x27D8B0, 0x6B6CC5,
0xB244CD, 0x293A7FD, 0x223C328, 0x12CE87D, 0x189703D, 0x2C96A84, 0x26A33FB, 0x32DEAF7, 0x1CAE, 0x676C9A, 0xCDBD33, 0x2FB2EFF, 0x2DAF578, 0x1F55D4D, 0x19B8631, 0x3059094, 0x3703377, 0x19438FA, 0x29F289, 0x1EB2CE, 0x28BF405, 0x270D6A6, 0x26CE903, 0x7B699E, 0x2E8D213, 0x4F6E06, 0x3ECE7D2, 0xCA3242, 0x4165ED, 0x2E3CC0,
0x56063F, 0x256D34B, 0x20CA7B4, 0x324BC5, 0x33D51EF, 0x29E0011, 0x33927A2, 0x1385C20, 0x6D4D01, 0x6DAD1C, 0xB477BE, 0x2B7D36D, 0x315B164, 0x2099363, 0x2935584, 0x29E600, 0x2B5497, 0x1526672, 0x597E5F, 0x3F5867, 0x1546A1D, 0x2F879A7, 0x3AA277D, 0x1E5A08B, 0x3643D7, 0x28723B0, 0x1F668FD, 0x2566098, 0x41754F, 0x1AB277,
0x3EF7923, 0x1DD5846, 0x1F27C2E, 0xB69702, 0x2097DC3, 0x145C4A7, 0x63B0D6, 0x187B72B, 0x256EC8, 0x51DF6C, 0x35CE819, 0x17B3A9E, 0x93F373, 0x1EF5969, 0x9F1AEF, 0xE4AE66, 0x2566B9A, 0x2468A2A, 0xBA6BB, 0x71FFD5, 0x3A7FADF, 0x12A09E4, 0xC97E94, 0x1D469B5, 0xF1306C, 0x74A3EF, 0x261ACB7, 0x10902E3, 0x6667F2, 0x517A10,
0x8183F5, 0x395933, 0x3377F63, 0x253F462, 0x7F1D08, 0x2F67FFF, 0x31C6E05, 0x164B443, 0x59237C, 0x538ACC, 0x3F0EB1D, 0x1BFE8B9, 0x738E1B, 0x3B68E65, 0x3E65AC5, 0x2341A17, 0x2045317, 0x23F7C16, 0x69D42B, 0x5DC6D9, 0xE8BE78, 0x380222A, 0x134DD7, 0xB60501, 0x3CAF23, 0x15C904D, 0x87B312, 0xAF8FB6, 0x31B585, 0x3DC18B,
0x2D70D2B, 0x2B7143B, 0x3858E7C, 0xF196E9, 0x38D0A48, 0x3A9D8AE, 0x29AF03C, 0x7E45E3, 0x4FFD54, 0x482EB4, 0x3AD4F1D, 0x275132, 0x2E2D3A1, 0x17DDF91, 0x2B40240, 0x2349C13, 0x1080167, 0x1A836AB, 0x6D8532, 0x626107, 0x42765C, 0x1177A75, 0x5AF6CE, 0x35DD2F5, 0x3D92353, 0x23B61C2, 0x2E8EA2F, 0x264591F, 0x246165, 0x45A2F,
0x14671A8, 0xA0F50F, 0x2D648D6, 0x25FF0D6, 0xDB5ED3, 0x2A91E82, 0x3696B35, 0x373CA54, 0x514FA, 0x7CD2BA, 0x29AC266, 0x293A390, 0x1144C3A, 0xADCA7F, 0x9790DA, 0x3CCBBB6, 0xF07853, 0x2BFDFD9, 0x26A0D4, 0x360357, 0x7C59E8, 0x3A3BD96, 0x120D747, 0x12F9A63, 0x70B3AD, 0x2FFCD7C, 0x3F61BE9, 0x3B0AB5D, 0x570DAF, 0x17E4BD,
0x2D7DC51, 0x680555, 0x393AA7A, 0x1331F99, 0x118E43C, 0x30B8E01, 0x3835929, 0x14F3898, 0x58BA7A, 0x3ABC9, 0x399BE57, 0x23B2FFD, 0x218831D, 0x23F7141, 0x2952A31, 0x2556DD8, 0x28BA136, 0x35E68EA, 0x2B258F, 0x17371D, 0x981299, 0xE54BD0, 0x2E0DD5E, 0xC18863, 0x2B2D927, 0x2235B45, 0x407642, 0x197FF6D, 0x554552, 0x59109B,
0x180A515, 0xB73878, 0xF83128, 0x306A937, 0x4F4866, 0x3517AE2, 0x3907198, 0xB1B01, 0x41467F, 0x19D3CB, 0x26745F1, 0x2F87DFA, 0x11F25FA, 0x4FB09A, 0x43CAA1, 0x3B25B92, 0x68C72B, 0x3A7D839, 0x70DAC7, 0x67F228, 0x38DF3DF, 0x3177544, 0x166E33D, 0x39707C8, 0x2FA3BFB, 0x1C90E1B, 0x24A9095, 0x6D912C, 0x366877, 0x786A9E,
0x3CA7F5B, 0x2631B6F, 0xBD1CE4, 0x2710C7E, 0x2B59417, 0xC6DBCD, 0x2D2E2AB, 0x2CBB727, 0x62AE5B, 0x1FBE20, 0xEE085, 0x1F7DBB6, 0x360A7EF, 0x1A23589, 0x1D595FD, 0x12D4B4B, 0x56B717, 0x3FB96FB, 0x241DD3, 0x595A82, 0x11880D, 0x3770A81, 0x14EB833, 0x1256D41, 0x2F76696, 0x731BB2, 0x3FBF100, 0x15D7ECD, 0x2B9E85, 0x5D20C,
0x2485AB2, 0xC04FF7, 0x3988D0D, 0x33FBD21, 0x3EBB9D9, 0x3FBE586, 0x25997CF, 0x3303AA, 0x27012A, 0x44A586, 0x3532E80, 0x3809678, 0x3F9B8BC, 0x3487CB2, 0x20FE6FB, 0x3ED21BE, 0x2EABCC8, 0x4ADFAB, 0x5ABEA, 0x2AA621, 0x210190B, 0xF96F6B, 0x220DF3D, 0x3A6CEA9, 0x18F8E29, 0xEF31EF, 0x2F3BE45, 0xA81A2C, 0x1EC8FB, 0x6A3B84,
0x3F827F7, 0x1F6D98, 0x352DF35, 0x2ED9067, 0x1C9792D, 0x3310139, 0x2EFCFF4, 0x3A65E36, 0x605175, 0x3A3AB2, 0x1D5DD0B, 0x1BB8126, 0x2565072, 0x1045692, 0x3CE0C5C, 0x36190D4, 0x18096CA, 0x3AC476B, 0x34C6C7, 0x7622CB, 0x24EF5AD, 0xCE6E5C, 0x2FFE4C5, 0x3C95713, 0x345D785, 0x2E3E117, 0x1F4D572, 0x22C3A6A, 0x719164, 0x581B44,
0x2225414, 0x3C6B96F, 0x13CF2CD, 0x19010ED, 0x68554A, 0x10B470, 0x314E6F1, 0x16CE8B0, 0x790180, 0x43CCCF, 0x14C3731, 0x1070B5A, 0x2FCEBF0, 0x30BB4ED, 0x25741DF, 0x3F6000B, 0xC6555C, 0x3758ECD, 0x1C368F, 0x332D8, 0x9BD8F0, 0x1C61E14, 0x12C6423, 0x16D2F6E, 0x39CE074, 0x2996BBA, 0x18A36B2, 0xA568D3, 0x2D258E, 0xBCA12,
0x32175D4, 0x1ABB5B0, 0x321319B, 0x253D5DF, 0x3E78059, 0x33E4DF3, 0x10E1E42, 0x398ECF0, 0x1A3BED, 0x304777, 0x2C5A6A, 0x3312959, 0xA753FA, 0x188C0C4, 0x37A459A, 0x3BB869E, 0x347A239, 0x2B633CA, 0x72E421, 0x2DA03A, 0x3ECB0B6, 0x29A8F63, 0x2361823, 0x26D9D74, 0x3A6285, 0x1886BA2, 0x39E9009, 0x293DBC5, 0x343099, 0x3D2028,
0x2047D0A, 0x385DA79, 0x238B4A1, 0x1D29648, 0xE20F06, 0x1CD9D18, 0x175B1DC, 0x14B0568, 0x14999B, 0x78AEB5, 0x3E9C06E, 0x29A7A06, 0x3733308, 0x3225BBF, 0x1745482, 0x1C13036, 0x27ED52D, 0x383461C, 0x7B18A1, 0x2F2C2C, 0x25492C7, 0x365E3CB, 0x366E7B5, 0x2D9BA9E, 0x10773B2, 0x303FCDA, 0x3942067, 0x10312AB, 0x649C7, 0x49B15B };
// The table below consists of four mini-tables each generated using window width W = 8.
// Number of point entries = 4 * 2^6 = 256 points, where each point (x,y) is represented using coordinates (x+y,y-x,2*d*t).
// Each coordinate a+b*i in GF(p^2) is encoded as an interleaved vector using the representation b_4|a_4|...|b_0|a_0 <- 23|23|
// 26|26|26|26|26|26|26|26-bit, where the 23-bit digits are the most significant digits. Digits are stored in 32-bit words.
// Table size = 256 * 3 * 320 = 30KB
static const uint32_t DOUBLE_SCALAR_TABLE[7680] = {
0x303E631, 0xF90353, 0x28D3CE9, 0x398BDF9, 0x2B5FE18, 0x2CDEE02, 0x2FC7540, 0xDE2E1A, 0x287460, 0xC3BA0, 0x937EDC, 0x3A01366, 0x3C3E62C, 0x48E448, 0x55590B, 0x17A5B32, 0x1E093C3, 0x2E4EA55, 0x740B7C, 0x4FFCF5, 0x3DA42BB, 0x330684C, 0x2BF32EA, 0x2268E4C, 0x17C6297, 0x1F27A81, 0xDD55B2, 0x1C828D0, 0x5948D1, 0xCAF2B,
0x3CF68C4, 0x1F89F9B, 0x1D5AC56, 0x296877A, 0x26BA892, 0x10F7340, 0x1F26294, 0x2BB9D7, 0x5742F7, 0x14EF68, 0x43A41F, 0x24DC0E2, 0x1DC3850, 0x1E479B7, 0x3C9584E, 0x1D2835B, 0x445B0C, 0x214635, 0x212C4, 0x5949DF, 0xED10DB, 0x2FDBA50, 0x38481D1, 0x62C562, 0x11D36A0, 0x20886F6, 0x33A110E, 0x1F91C38, 0x5A5183, 0x2CE203,
0x264BA3C, 0x355586B, 0x27E8526, 0x41415B, 0x4511F4, 0x1726030, 0x354659C, 0x155F63F, 0x5F9876, 0x20F1A, 0x6D86C8, 0x16A1B67, 0x32C5D6C, 0xCA529D, 0x390DF4, 0x38EC793, 0x2F9FF96, 0x2492D63, 0x694FBC, 0x9DBE9, 0x1F197B6, 0x2252367, 0x3D100F3, 0x191DDC4, 0xBA7590, 0x3096C49, 0x27F21E8, 0x1808BC6, 0x1C0796, 0x550897,
0x12E1775, 0x3E5DC5F, 0x28D8791, 0x39E4702, 0x38FBEFD, 0xB93B07, 0x332B320, 0x2D0632F, 0x7A0A0C, 0x24D9B6, 0x2117E03, 0x292612B, 0x25C3CF1, 0x161B39, 0x1595497, 0x39D68F8, 0x1632E5B, 0x369F937, 0x3986A1, 0x305CAF, 0x52914A, 0x364B099, 0x70B819, 0x196C7DC, 0x3079C1A, 0x1C6B3A7, 0x303AD60, 0x1B560A6, 0x7EF989, 0x4FEE23,
0x30E8419, 0x32B4210, 0x4257DD, 0xAE9C9A, 0x3C096F8, 0x78B2B7, 0x1ADCE5A, 0x74A407, 0x53BBD8, 0x625DDA, 0xCD2B3E, 0xFF50D7, 0x16F1EC6, 0x4917C8, 0x13320FF, 0x297E099, 0x231CD63, 0x397A466, 0x55659, 0xE7F58, 0x3758756, 0x34C7520, 0x1584DCE, 0xC18130, 0x198A5A0, 0x1BFAF92, 0x24FE1F0, 0x951D70, 0x6447BC, 0x6B2144,
0x27F9497, 0x64CFE4, 0x3798B5A, 0xE531F1, 0x93CE93, 0x21B3456, 0x2761BD1, 0x3FB0FD2, 0x212945, 0x612434, 0x4261F3, 0xA7E4E3, 0x247B77D, 0x3454C62, 0x23FF1ED, 0x110CD3F, 0x153E782, 0x2F7285A, 0xC6D38, 0x24691F, 0x3625C9D, 0x326D62B, 0x1D19735, 0x355D8E8, 0x19F4BE9, 0x20BA824, 0x34DCFDD, 0x2794368, 0x2AA61C, 0x1A0AE3,
0x2E4C3B9, 0x3BF95DA, 0x321207, 0x1C5C50B, 0x18C632D, 0x29C6E52, 0x427374, 0x7ED4B3, 0x6C3687, 0x67BFA4, 0xA01474, 0x103191E, 0x135A822, 0x3E3EAA4, 0x26264E2, 0x3062D67, 0x2B8FED, 0x3D6A9B4, 0x49A6CA, 0x674888, 0x2E85A99, 0x2728AC1, 0x1CE0930, 0x21EC6FA, 0x33144BA, 0x160EA70, 0x34634D6, 0x88C5EC, 0x406B2F, 0x11D2F2,
0x223A469, 0x1216BA, 0x11B801F, 0x27B86F7, 0x31A2F89, 0x2324530, 0x3EAEF38, 0x254E09E, 0x22A196, 0x240FE9, 0x3AEB5C7, 0x2CF61FB, 0x32E26D8, 0x61DB00, 0x31B0F9F, 0x148BB1F, 0x127B45A, 0x2BD84BE, 0x603B81, 0x4A5E32, 0x29A8813, 0x1E6C123, 0x246BB79, 0x1436C75, 0x3AA5FC4, 0x12CA5DA, 0x244DB94, 0x3DFF8B0, 0x1AD937, 0x2F4014,
0x285C3F5, 0x555F97, 0x19E475D, 0x1486BE6, 0x1A9BE4F, 0x1A7B0C0, 0x870DD1, 0xA54F2B, 0x4C2185, 0x1462A1, 0x2452C1B, 0x5DBC9C, 0xAAD8F5, 0x37BD4D8, 0x3B870BB, 0x2719737, 0xC7B262, 0x2E4C3A1, 0x5783C5, 0x49F982, 0x35211E3, 0x2EC9851, 0x59E432, 0xADCB7F, 0x299E75B, 0xC88106, 0x1D336EB, 0x27311A, 0x45AD65, 0x45029A,
0x3F3A1F2, 0x2F8A0A0, 0x90379D, 0xB5FBF0, 0x10EA532, 0x378EE0A, 0x7AAA6B, 0x148085, 0x17BD29, 0x3A7412, 0x2CC90DF, 0x300D6C6, 0x3EC25DA, 0x95E732, 0x31F3B0D, 0x9A3115, 0x2DA269E, 0xED8C61, 0x7FD603, 0x634074, 0x20CDA01, 0x181E75A, 0x291CA43, 0x975BF6, 0x2F0BEBA, 0x2F2A453, 0x29B54FF, 0x330E561, 0x143265, 0xE9780,
0x28628DD, 0x3B504B6, 0x1A3481E, 0x35DA692, 0x2841A4F, 0x292EF3B, 0x2D4624F, 0x18E5A4, 0x50D230, 0x55975C, 0x3B8756F, 0x35A1F0, 0x9EE897, 0x1FE9033, 0x31FD077, 0x18FCEF5, 0x33E3B5C, 0x1C21D08, 0x7FF86, 0x70753A, 0x2B973C, 0x1E44468, 0x255388D, 0x3A7A7FD, 0x1F86615, 0x3D233B8, 0x23C6967, 0x535828, 0x5AA9D6, 0x2E7491,
0x176DB4B, 0x31B6D27, 0x6E47B0, 0xE08C9E, 0x2E6D14A, 0x2AFDF42, 0x18F5A6A, 0x11D7EB2, 0x55F91A, 0x2ACF1F, 0x1B58968, 0x27AAAB6, 0x1A6D1E, 0x326AE62, 0x1F77FD9, 0x981A2A, 0x3971291, 0x14063D4, 0x3BAAF4, 0x5466CB, 0x1BA3205, 0x557393, 0x2E89DDC, 0x105AD7, 0x3BE43E6, 0xD7D000, 0x337A86E, 0x1056944, 0x31EA90, 0x464CB0,
0x2FF2BBF, 0x2CAAB0D, 0x21F481, 0x15B4E10, 0x2736D02, 0xA7B2B, 0x335FEAF, 0x2DDD9DC, 0x2B9C8E, 0x46EA0, 0x2317310, 0x10388BD, 0x29EA227, 0x36A53B5, 0x10CA113, 0x11543ED, 0x152FBDF, 0x3DD9E0E, 0x5992A3, 0x52661, 0x19E28E0, 0x335AB3D, 0x23B7DB8, 0xC85236, 0x4E54C2, 0xF55D7, 0x3CB4BD9, 0x52E0D6, 0x1D19C2, 0x680C47,
0x380CCEC, 0x19B45F2, 0x13CA0AE, 0x95DF56, 0x211CA37, 0x21B110D, 0x26F1DEB, 0x16E15DC, 0x789E60, 0x1C548B, 0x543FDF, 0x3E82082, 0x3A9C9AD, 0x18880ED, 0xED27BA, 0x2900D63, 0x244B46D, 0x8F4F1E, 0x3C1562, 0x1414E5, 0x1D23A9, 0xA9EF36, 0xD26547, 0x7AEF2B, 0xFB47CA, 0x180B798, 0x178F3A0, 0x396D6FE, 0x4DA426, 0x4EBAC9,
0x9CB5A4, 0x3D11CBD, 0xB0773D, 0x3BBFEAE, 0x340FABD, 0x1E8C202, 0x3F09718, 0x1F2CDA5, 0x3F54AC, 0x67216B, 0x23FC9F1, 0x111F85E, 0x32F3E6C, 0x15AFBE8, 0x3AFBFF7, 0x102C711, 0x37FDFE9, 0x237D48A, 0x2EEBEB, 0x1B8FD9, 0x2519791, 0x6967D5, 0x23AEB58, 0x5EF080, 0x18ED6B2, 0x30ADB46, 0x2583807, 0x1972CF7, 0x6CF0EA, 0x323DA0,
0x1E24D9C, 0x320527, 0x21F41D0, 0xFE1649, 0x3CC2316, 0x2D2B924, 0xAD4269, 0x3C075B9, 0x2DB8F, 0x68C360, 0x3D5306A, 0x3C4928F, 0x717A1D, 0x2594A0D, 0x33A9235, 0x39711B0, 0x3F21717, 0x155320F, 0x6F56CC, 0xB3337, 0xC783EC, 0xE2C6AC, 0xC6F8B3, 0x178D8D6, 0x64FE29, 0x11709F3, 0x252E823, 0xCEC003, 0x468296, 0x1474B3,
0x3C96640, 0x2FD9375, 0x1E49D5B, 0x3D6C496, 0xC5E24D, 0x258B7F, 0x27FBE1A, 0x1F81103, 0x618FDA, 0x778DD9, 0x2219627, 0x37B7BDC, 0x3CC5221, 0x2566A23, 0x2811FBF, 0x67221E, 0x3878A9F, 0x3AE30F2, 0x3417E1, 0x3508C2, 0x11C430F, 0x32F5746, 0x3B37784, 0x7E942A, 0x2134827, 0x18FAE0C, 0x27EC1EA, 0x2D3999, 0x21BCB1, 0x401E68,
0x13693CC, 0x381C3CC, 0x92EACC, 0x25D6DBE, 0x47A2CC, 0x17F7374, 0x4AE591, 0x3ECD138, 0x20541C, 0x52905E, 0x18B5F9E, 0x15BF4E4, 0x1726D5B, 0xE01F62, 0x23EC79C, 0x2B517EF, 0x1D74AE6, 0x1690811, 0x3390BF, 0x281416, 0x26FE158, 0x194D25, 0x33F424C, 0x235B6B3, 0x22EC7F8, 0x5E8567, 0x13D325D, 0x3EC29D5, 0x3232FB, 0x6F7CAF,
0x23E7963, 0x2062914, 0x2058DEC, 0x28C66B8, 0xEF5BD9, 0x285B10B, 0x1F2E228, 0x13E0A56, 0x691D7B, 0x6FB14, 0x3F62F8F, 0x1D10B1C, 0x18825DA, 0x2AA79D0, 0x16B480E, 0x69B800, 0x1C7B1CF, 0x22F4681, 0x2A4259, 0x230D7D, 0x28DFE8C, 0x3AF7B8, 0x2B38DD0, 0x3A549A5, 0x366765A, 0x1AE7CF0, 0xA5FD62, 0x16DD753, 0xFCAB5, 0x7D9091,
0x2259D6B, 0x287AEFD, 0x1691855, 0x2C3B4EA, 0x21B5745, 0x1D58F2F, 0x18DD333, 0x2BC3953, 0x29BCC0, 0x211A06, 0x23DE9BC, 0x14DFB18, 0x325715C, 0x18F9E13, 0xCA76C0, 0x1B307FD, 0x3B49402, 0x1366F07, 0x6299B6, 0x2CC93B, 0x5D13EA, 0x2215F79, 0x1F8B513, 0x38F7496, 0x11A0EBC, 0x16D349, 0x23534F4, 0x542CC1, 0x3278E1, 0x7EB2A7,
0x2A094CB, 0x96F009, 0xF5F57D, 0x3CE7A77, 0x140505F, 0x99208E, 0x35238CC, 0xDCE8D9, 0x2A3771, 0x12248, 0x1FD4D33, 0x22673B4, 0x23E4BF2, 0x25965, 0xA6CF75, 0x10548B0, 0x31B7F4F, 0xFAE676, 0x2339D8, 0x746FF4, 0x2422EFF, 0x21A42AE, 0x3370152, 0x3802B24, 0x3F0C47E, 0x18E622F, 0x32099ED, 0xF4C7F3, 0x33D8F7, 0x31E57F,
0x1C50869, 0x973EDF, 0x48C568, 0x75D298, 0x3BAFBB9, 0x5D7054, 0x2C3E9FA, 0xCD2CB, 0x4AC8CD, 0x723490, 0xADFA33, 0x6FDEB9, 0x1517DCC, 0x28F4017, 0x2C96F2E, 0x36B5FCB, 0x398F6D6, 0x3995664, 0x224E44, 0x2C93A4, 0x188D758, 0x32C0254, 0x1E835EB, 0x3BE26BA, 0x1CDD772, 0x2FB47B2, 0x859C6, 0x2DD1D62, 0x2E3310, 0x1F6DE5,
0x14FB321, 0x3A874D8, 0x22411C4, 0x24571C9, 0x180D6AE, 0x112F18E, 0x269BB1B, 0x2D7A742, 0x3D605E, 0x699088, 0x2056F10, 0xF4C891, 0xD11863, 0x230CF5C, 0x20B3AF9, 0x13C35EB, 0x37E0917, 0x3EC88AC, 0x1B9169, 0x1609DD, 0x1B366ED, 0x3C93968, 0x722174, 0x1D1E34B, 0x27B0813, 0x27F5D29, 0x27672C6, 0x15CE93A, 0x7BC3CF, 0x13CBB4,
0xD5986B, 0x3973C9E, 0x1ED7319, 0xD217C8, 0x35DCDD3, 0x11D7AC5, 0x35F606A, 0x174CCEE, 0x7ED3D1, 0x70567, 0x3186C1, 0x2717963, 0x17484F1, 0x3E22877, 0x1F14ADE, 0x3CE2A87, 0x15ED2FF, 0x82D466, 0x6A8BDF, 0x17F292, 0x395C610, 0x32813E1, 0xB5FEC3, 0xF0F625, 0xA7C7AF, 0x32C18E7, 0x248EC51, 0x10318B9, 0x28D1D3, 0x100B,
0x21F50DA, 0x34B285, 0x39EA07E, 0xD65BC2, 0x24484D, 0x29CEBCC, 0x3596276, 0x3582893, 0x4FA391, 0x4D4ACB, 0x1835A0D, 0x1B3D082, 0x2A62E30, 0x1CF465D, 0x1D0B97F, 0x148D60A, 0x238A640, 0x290C96E, 0x33ABCF, 0x60666A, 0x1284A39, 0x26A3872, 0x12B6DDA, 0x387FF2B, 0x1B28AD5, 0x18C4A1, 0x3444D82, 0x12F59FE, 0x227A98, 0x1E4EE4,
0x387D315, 0xBBB055, 0x131AED0, 0x54F89C, 0x7955A7, 0xA615CC, 0x302C6C6, 0x37C0371, 0x19428, 0x2B3CAB, 0x2924B57, 0x33389F5, 0x443009, 0x5A5E4C, 0x3217834, 0x2417471, 0x217CB67, 0x1A86080, 0x2D30E9, 0x53E3FD, 0x2E5864, 0x305B6D, 0x24F35E7, 0x2269FB2, 0x2E82B13, 0x337A869, 0xD79044, 0x13BB8A3, 0x58D929, 0x42A8FE,
0x1591901, 0x1687544, 0x84BBC0, 0x32F9B8F, 0x31B974E, 0x2FB67BB, 0x1E80E5E, 0x1C07426, 0x327791, 0xB8957, 0x503668, 0x22D0F4E, 0x2F23B9D, 0x115D4EE, 0x3486CF, 0x3D66570, 0x16B6A7E, 0xE19888, 0x48A992, 0x7D69CA, 0x117271F, 0x1EC35E, 0x153388A, 0x2B90B7E, 0x11DEC70, 0x3CC33A3, 0x3844CED, 0x3D0B51, 0x41BCE1, 0x7EAADA,
0x8A57CC, 0x2A0C732, 0x4E3C41, 0x657AC5, 0x1A8F13B, 0x34D27AF, 0x2F5FA45, 0x29E4758, 0x64F98A, 0x11BE81, 0x30F61B8, 0x3940AA6, 0x237D1D0, 0x1244DBE, 0x100497D, 0x2DBA3E9, 0x2CE049C, 0x1033655, 0x767C7, 0x3BDEE3, 0x11D2602, 0xD978CB, 0x3B13FE, 0x39D254C, 0x19DBB25, 0x1835AF5, 0x15351FD, 0x846753, 0x4CDE24, 0x5A8E2F,
0x20744DF, 0x1E4719C, 0x32D5096, 0xD7A0CB, 0x1055DF1, 0xD42C63, 0x29EFCD7, 0x1F82455, 0x3D3B08, 0x6EB8D9, 0x3D20DD9, 0xFA41C, 0x28FE378, 0x1AE037F, 0x33DA2F6, 0x17D7B4A, 0x3F49D88, 0x100EB3F, 0x13F23C, 0x58D876, 0x38E139B, 0x1ECA3C8, 0x10881E2, 0x9D6224, 0x94D2AD, 0x93809A, 0xAAEEBD, 0x3C45E2C, 0x73DBEE, 0x6EF9A9,
0xC637DA, 0x2F9FF1F, 0x3A7B2E4, 0x13A72D8, 0x1A7CFC7, 0x33D8C02, 0x17F042C, 0xEA92A8, 0x3A0434, 0x6C4F9C, 0x15AC1F0, 0xAC276, 0x35A656E, 0x19A8C5C, 0x3A1B049, 0x1905A14, 0x14655D8, 0x48E8C9, 0x224384, 0x600FB7, 0xD35A24, 0x12E221F, 0x2469928, 0x17796FF, 0x31089D3, 0x1B1E227, 0x1541907, 0x119658F, 0x3B093B, 0x25F5E7,
0x3E7FB84, 0x2EB0E48, 0x8041FD, 0x263467D, 0x1A8E3E2, 0x1FDAB41, 0xEF06E1, 0x1876B51, 0x6F06A2, 0x5DC117, 0x2B52A0D, 0x2C790BE, 0xF924A, 0x16DC33D, 0x3528BA3, 0x1A5CD3A, 0x31CF6A7, 0x3142067, 0x127C69, 0xD72B0, 0x2C2CDF7, 0x2F380EA, 0x3E4358B, 0x3020F54, 0x2DAF193, 0x3F4D7AE, 0x33F13D1, 0x36928A2, 0x67F7D0, 0x7C0A1D,
0x8CBA7, 0xF45F78, 0x3483F98, 0x74F6BB, 0x159546F, 0x30368FB, 0x2450457, 0x302539E, 0x7A588C, 0x851DA, 0x232A892, 0x21F9006, 0x29DB8A, 0x360791B, 0x1B2FCAE, 0x912B79, 0x4C8B77, 0x35E8926, 0x104F86, 0x1E4D28, 0x34B89BF, 0x265226F, 0x5D74E5, 0x1A20FA3, 0x15C2AF3, 0x2F0523F, 0x3E69A71, 0x35971B7, 0x613D00, 0x72F7E,
0x338E243, 0x24749AE, 0x3990EE, 0x1B459A7, 0x1B15669, 0x190C105, 0x29F2462, 0x29D063C, 0x1A81C4, 0x137F2, 0x2699D16, 0x1A88243, 0x649E5B, 0x21B451D, 0x237CED3, 0x316E78E, 0x2D170E2, 0x2B31256, 0x3ED76D, 0x45985A, 0x28F1030, 0xF7F26B, 0x1720823, 0xF4060B, 0x278247D, 0x2DBD08D, 0x1A2D343, 0x3385CBE, 0x6DBE5F, 0x64C375,
0x20C2875, 0x1F8E63E, 0x3DB6CE8, 0x150CFF7, 0x1250BA0, 0x2D9B031, 0x294C90, 0x1438DF6, 0x57E1D9, 0x333447, 0x269B016, 0x29D3DF5, 0x3034A2B, 0x12BAA19, 0x154762C, 0x14A9587, 0x3D8403, 0xFE0993, 0x435FE8, 0x3B9691, 0x31314B0, 0xB777AF, 0x19F5AE, 0x38AEF5A, 0xCCF738, 0x1D666F5, 0x9331BD, 0x1EEA58D, 0x48CCCF, 0x34C2C3,
0xFDBE5B, 0x11B73D7, 0x54D240, 0x104850D, 0x1D43D73, 0x25AE81B, 0x25EBF84, 0x2B446, 0x4E4F9D, 0x1D48D1, 0xE2B151, 0x3D45394, 0x3B9D98A, 0x2158683, 0x2FB82A4, 0x1AC0B5A, 0x24061DF, 0x3DB5735, 0x34902E, 0x44317A, 0x1068BAD, 0x12D0F2B, 0x3091A7A, 0x1DBBA08, 0x1022354, 0x1495FDA, 0x9D872B, 0x31B510D, 0x771FE, 0x76CDEE,
0x3E825FD, 0x3F466E7, 0x2615D6C, 0x31313EC, 0x3A1B55C, 0xBB0563, 0x17B575C, 0x2904CCE, 0x298332, 0x731B0F, 0x3A05240, 0x12AB28E, 0x1467295, 0x1F054F7, 0x3351DEB, 0x30B3EFB, 0x26D713D, 0x21977B8, 0x7A7E90, 0x11CA1C, 0x19D7DE1, 0x83AF7F, 0x32A0D23, 0x3262884, 0xF9A013, 0x2EE3464, 0x36BBBA3, 0x3617084, 0x575E0B, 0x683DDC,
0xD02019, 0x32E2ED3, 0x7C2AD3, 0x3B03BCF, 0x24C8117, 0x76C972, 0x71FD35, 0x3098469, 0x22C7E0, 0x623F83, 0x1AA25A1, 0x2A4D5F2, 0xFC5AFA, 0x3EEA151, 0xE0B99B, 0x6E35D5, 0x151A264, 0x24674A6, 0x2D3EBC, 0x4716E6, 0x3F5D6C, 0xF94F2B, 0xBCAF06, 0x31BCA9E, 0x14BE3AB, 0x24F5341, 0x34E4433, 0x2E2941, 0x5F6257, 0x6EE839,
0x3CA8E7, 0x30DFD59, 0x1902E6E, 0x335A36C, 0x3E3D9D8, 0x33F66F6, 0x349119A, 0x703E43, 0x33C5A, 0x52AA6B, 0x3403646, 0x35896DA, 0x2F35325, 0x212DDD5, 0x1FB0FE7, 0x2137245, 0x32582C1, 0x3AE4CB6, 0x11AB3F, 0x427F8D, 0x5306F0, 0x1B9CD3F, 0x28A32D4, 0x2AA6244, 0x20E928, 0x1145AAB, 0x1BFA18E, 0x2EA6536, 0x4AE91, 0x59E588,
0x2EE9E9F, 0x137B146, 0x3C6BEAF, 0x3D4F3A6, 0x3F8E9B8, 0x448E9C, 0x3BCD1DB, 0x2A00549, 0x4FFC7, 0x73FE42, 0x3BBAAAD, 0x345726B, 0x2F68F3C, 0x3BAB520, 0x4A4224, 0x36D28E6, 0x15B5662, 0xDB505C, 0x5FA850, 0x92309, 0x1AD6BE7, 0x60E24B, 0x27AD634, 0x23AD49E, 0x1EAFE67, 0x3278968, 0x26D4C2C, 0xB6BE6B, 0x8BB75, 0x13704D,
0x3906F14, 0x29E61EB, 0x1CEB1C6, 0x223866E, 0x1EB5D92, 0x1699B77, 0x3EEF503, 0x3707176, 0x57EE05, 0x7967B6, 0x30127C0, 0x14D1B07, 0x10FF08, 0x1ECA103, 0x119C36E, 0x2A3FC01, 0x262ECB5, 0x1227DD5, 0x2A7165, 0x1D3BFA, 0x318D36, 0x1F89084, 0x1CEAFC9, 0x269F250, 0x225D4AD, 0x22FCB21, 0x3D4F849, 0x1EA3D1D, 0x1915E6, 0x228008,
0x3D1B4E7, 0x22CE2E1, 0xA00D17, 0x18E9E1F, 0x3D798EB, 0x3885C9E, 0x3B95DCB, 0x2B6F6A4, 0x55B8D4, 0x685741, 0x1A3B491, 0x2629078, 0x20C2AC4, 0x2BA89C6, 0x2428FFB, 0x2639C03, 0x87E4D5, 0xCA4C28, 0x7E8911, 0x71C459, 0x3F81795, 0x27A63D7, 0x3C64A9A, 0x36D56A2, 0x2DF1E7D, 0x33C06D, 0x23C60EA, 0x21D8FCC, 0x704AEE, 0x52556D,
0x30C33A7, 0xC27B9B, 0x2D1631B, 0x2B95D69, 0x395AB76, 0x2DFD365, 0x21F0D8A, 0x44158A, 0x28666B, 0x36EF35, 0x127F9C7, 0x3F988C1, 0x1577636, 0x382F13B, 0x2C9E899, 0x946762, 0x1F5A961, 0x2D2D6B9, 0x526E78, 0x6C9523, 0xCFE95F, 0x258520F, 0x2A425A2, 0x522E9E, 0x2DA3E90, 0x11CFBEE, 0x322CFFE, 0x1F615CF, 0x658A7D, 0x681900,
0x1BE9C5, 0x330E894, 0xED7B05, 0xBEA6E2, 0x3C2775D, 0x2CBF119, 0x2B98D3C, 0xF87424, 0x4BC236, 0x4129D4, 0xBBEA45, 0x155ECD4, 0x301A156, 0x1E85E68, 0x2534FCA, 0x172F537, 0x21EE045, 0x795515, 0x513E8D, 0x6C9353, 0x9AAD91, 0xBA172A, 0x37E06E8, 0xC82C76, 0x2250727, 0x9B150, 0xE76F25, 0x17D8286, 0x75271, 0x2281E8,
0xEBA6AF, 0x2AEBE78, 0x12DF549, 0x3785F58, 0xCA8716, 0x10DE90, 0x58FFA9, 0x2E8A301, 0x50D387, 0x6AB369, 0x295D138, 0x101B92, 0x1F8C56, 0x28136EF, 0x3EFD17D, 0x1B0EB87, 0xD4914F, 0x3EDD5FA, 0x58B496, 0x40A8F0, 0x16E64D1, 0x6B563E, 0x22D229A, 0x9FA7CE, 0x17D7214, 0x23C5179, 0xE8D430, 0x351078F, 0x4E004A, 0x29DA9C,
0x3417213, 0x453DF1, 0x34B70D5, 0xDEBD52, 0x2644883, 0x393B53A, 0xFFDE18, 0x2CF0C02, 0x2E9465, 0x4475D, 0x15E7204, 0x34D97CD, 0x17E9360, 0x1CD3033, 0x3CCD2D6, 0x11221FD, 0x2DD30B0, 0x30417DB, 0x231A2D, 0x32D255, 0x1EB07B0, 0x2A97072, 0x13F6480, 0x2990E6F, 0x2F60BB7, 0xBC1FB9, 0x7206B1, 0x1F6E737, 0x12E33F, 0x52E14B,
0x2E374CB, 0x24B7D33, 0x2B06A46, 0x21B1429, 0x224637, 0x1893EB7, 0x30D6B72, 0x29C8CA9, 0x1C8622, 0x362823, 0x8D472A, 0x3F4BCF1, 0x36BF29A, 0x2125EFF, 0x37C4F22, 0x1B7F97B, 0x3808DF, 0x2C9EA71, 0x18598F, 0x7ABF4C, 0x33D95D3, 0x1F902C8, 0x1F1138E, 0xDA069B, 0x3A43EA4, 0x1E797FD, 0x38F8609, 0x2F7104F, 0x58728F, 0x6DB1DB,
0x2C3007F, 0x3D2519A, 0x3BFFB46, 0x166D3E2, 0x3CABBC4, 0x1DBE65, 0x11D1221, 0x316C309, 0x7F31A5, 0x18A78E, 0x15D2030, 0x1116B47, 0x40A16C, 0x2DBC837, 0xFF4F6E, 0x733134, 0x3A8866A, 0x36F2266, 0x5C1323, 0x5D0ABD, 0x302E151, 0x21815E6, 0x264E4E1, 0xED2FB6, 0x2D5DA3C, 0x2FDC8CF, 0x2D253DA, 0x8C0230, 0xAB6AE, 0x546CE3,
0x38DBE39, 0x117D806, 0x3AD69A9, 0x332F8C5, 0x3DA4A10, 0x162C026, 0x2A2E115, 0x12E04BD, 0x26D2E8, 0x2A3517, 0x17A374D, 0x101062C, 0x1C12677, 0x2C9457E, 0x5E557D, 0x377490, 0x146B34F, 0x39F0C57, 0x3368F9, 0x316109, 0x29535CF, 0x4D5E0F, 0x83AE95, 0x2025B71, 0x170932E, 0x3B0557, 0xE7599F, 0xB39CE4, 0x496A8C, 0x608A16,
0xB37CAB, 0x2602455, 0x399614B, 0x212CC20, 0x9A96B2, 0xB947AC, 0xB9BB58, 0x2D653A1, 0x75B09A, 0x7690CB, 0x11973FB, 0x1D5883E, 0x176B654, 0xCFF24E, 0x6D0FC8, 0x9F4832, 0x2C23240, 0x22D76CF, 0x738A74, 0x7FBFC0, 0x35F7749, 0x1CC656F, 0x3924FE, 0x3C0B982, 0x37C181A, 0x3CEC234, 0x3DF9A69, 0x2E587C, 0x2C255E, 0x5960CF,
0x3B1F17A, 0xD8B0C6, 0xA5008D, 0x2824380, 0x6ACAC7, 0x73ECA6, 0x228A751, 0x900079, 0x434E03, 0x1F1AAD, 0x33399FE, 0x1BBF5DF, 0x12DB704, 0x242CFC9, 0x6076D6, 0xE11CA5, 0x107A775, 0x1E2C363, 0x899BA, 0x572179, 0x26DE9AC, 0x1A7757F, 0x132C4F6, 0x3EF541D, 0x375DD6B, 0x2161649, 0x33D593, 0x2E43F9C, 0x3C8852, 0x3F2593,
0x1DCC9A8, 0xAA855C, 0x3B94FA4, 0xE5A25E, 0xA92E1B, 0x3D73EF8, 0x373931D, 0x2060ED4, 0x10069, 0x6CD884, 0xE403EB, 0x19850E2, 0x37D6584, 0xC44B31, 0xA7F0B3, 0x330CCC2, 0x3511860, 0x2D9C28D, 0x713225, 0x105796, 0x22FA4CF, 0x285F560, 0x1FD3B1E, 0x1D157, 0x3253A14, 0x1D604E7, 0x1CB5D6, 0x1A9DC7F, 0x32DA1F, 0x76A537,
0xC699F7, 0x372546F, 0x2D3EAF7, 0x19BCAEA, 0x2D9647E, 0xDEC360, 0x18CD31B, 0x19564FB, 0x4E45DB, 0x4F480, 0x3BB5601, 0x3B4DBD, 0x3009E4F, 0x3D9BFE, 0x25263FE, 0x3F1C21D, 0x189AD92, 0x3B7991, 0x122F74, 0x137061, 0x8172C9, 0x5C93F5, 0x20890AE, 0x326810E, 0x1ADE57B, 0xA6C5E9, 0x2B7F719, 0x2794952, 0x527DCB, 0x64D1CF,
0x65C994, 0x251095, 0x1CCCDE, 0x8A3B1, 0x1615BA0, 0x308DF84, 0x13942F3, 0x204AA63, 0x633EE1, 0x49BB96, 0x2F96678, 0x12AE863, 0x15F4108, 0x43329D, 0x20E182F, 0x3E38339, 0xEFFF9F, 0x1F19821, 0x6D7E4, 0x4D46E, 0x27017C3, 0x2CD6164, 0x24D7105, 0x258913C, 0x9ACF14, 0x24DBA61, 0x3D1340F, 0x339453E, 0x3F22E2, 0x15A2B4,
0x2BBD0C4, 0xA673C0, 0x681312, 0x160F061, 0x219D519, 0x33E7FEF, 0x183B322, 0x29F1D0, 0xE7633, 0x75C2F3, 0x3C7C099, 0x2BEC2D4, 0x1E95551, 0x199BE79, 0x3A83E94, 0x1AC867A, 0x3913DB9, 0x8BE991, 0x245C7A, 0x5DE0B9, 0xB72E22, 0x23AC231, 0x2CF9297, 0x3ADA3A1, 0x3A8EDD9, 0x2DA0A7F, 0x3215EB6, 0x3BE23B0, 0x139C2, 0x501381,
0xF40B01, 0x2D65714, 0x231A91C, 0x2410529, 0x3062B2B, 0x1F0C4CE, 0x2F6E0D8, 0x1497467, 0x51D65, 0x1E510B, 0x1374CF6, 0x10F9AA2, 0x39C8FD7, 0x1167AF1, 0x21F0569, 0x1E32AE7, 0x3F4E3F7, 0x2C5C37F, 0x4BFE02, 0xF7E2C, 0x27407CB, 0x285C3C8, 0x3688C9A, 0x2CD3217, 0x18423C3, 0x333362A, 0x2A17FF4, 0x1912ECD, 0xCFC50, 0x22B4D9,
0x7C2D98, 0xBEFC0C, 0xC4ECF6, 0xF447E9, 0x133F57D, 0x312E616, 0x72E924, 0x48BF77, 0x4F432C, 0x1AB94E, 0x2FC85A8, 0x145C810, 0x324D62B, 0x3B5BFC8, 0x9B1FB7, 0x2D00CF8, 0x23E0765, 0x300864C, 0x5B2006, 0x5794AF, 0x36E35D5, 0x23EA1D7, 0x261EB66, 0x3C7FB52, 0x203E5C8, 0x27BF794, 0x2E0DBF6, 0xA37AC3, 0x6BB1F4, 0xCF6D1,
0x1878CF5, 0x1E77B71, 0x30F8719, 0x3645C14, 0x200E54E, 0x1E7F382, 0x1D8EE88, 0x2F404EA, 0x2811, 0x49E00C, 0xCF019C, 0x1EDFC1F, 0x15DBA69, 0x85A245, 0x333ACCF, 0x1685F77, 0xA1E5C0, 0x3B2991E, 0x4B4A66, 0x278EB5, 0x341CF06, 0x1F2FE75, 0x1722E73, 0x3846622, 0x39DB8A9, 0x18D4478, 0x31E09B4, 0x6646F6, 0x6E58C9, 0x73ECD2,
0x3BB9502, 0x38BB5C5, 0x1D47FA7, 0x1A3E5BB, 0x2E9526E, 0x2004216, 0x1C6C18C, 0x2794F26, 0x29825B, 0x2F2A89, 0x345CE8, 0x36FE9A5, 0xCA4BB5, 0x2B2A712, 0x1DEC280, 0x16713AA, 0x1571F19, 0x33B6A2F, 0x727310, 0x6228D3, 0x3C48EAF, 0x2C8D766, 0x38B17BF, 0x2784125, 0x1AC9773, 0x30F960, 0x2783FAA, 0x3E6CC0B, 0x17AB1, 0x121E89,
0x3E96480, 0x2CD4E52, 0x1F40282, 0x15BE51F, 0x1BAB4E8, 0xF5BC67, 0x5C2EA7, 0x2EEF334, 0x9BD8D, 0x2C9E40, 0x1FD812E, 0x16E77C1, 0x16DDD9A, 0x177E674, 0xD9E42A, 0x2509EE5, 0x160EC20, 0x1717BFC, 0x66ABA9, 0x4CC00C, 0x2B7C16B, 0x2DCEF54, 0x1357882, 0x17A40D1, 0x3EFB8C8, 0x3B72B29, 0x258613F, 0x28E770, 0xAE5C, 0x5D1BDA,
0x9B5EF2, 0x2C433C1, 0x24B5CAA, 0x33EDCA9, 0x2C0E75F, 0x36048A1, 0x2327FE6, 0x752759, 0x259D99, 0x23F5B7, 0x14F62EF, 0x2488C4A, 0x363CC24, 0xB3A6F1, 0x2CA9478, 0x3E2E4DA, 0x4D4863, 0x3F4D4A0, 0x8FE61, 0x15F1EA, 0x42EA0F, 0x3BDEEB2, 0xAF8FAF, 0x26414B9, 0x2902C2D, 0x290CA1E, 0x14E75BB, 0xC7B1E0, 0x2A5216, 0x3A8F26,
0x2BFBFE4, 0x2221F75, 0x1462A0B, 0x14B5646, 0x3DDCB71, 0x3D926EF, 0x1C711BA, 0x136DA99, 0x247006, 0x479461, 0xBAB607, 0xDB3B29, 0x3D723B9, 0x1564EFA, 0x35D5761, 0x22601A4, 0x23C8D86, 0x197AC45, 0x31D9DD, 0x7F06C3, 0x12EB65B, 0x14ADB75, 0x1699B9, 0x13F4A05, 0x2C189D3, 0x1742EF3, 0x2D584FA, 0x15D4EE7, 0x5EDCFC, 0x790F80,
0x1DFB797, 0x2815528, 0x356B095, 0x21B17BE, 0x8DB6EC, 0x1887C1C, 0x36D766A, 0xCEE967, 0xCBE14, 0x2C6361, 0x1F52297, 0xDE6903, 0x350B0B6, 0x1F37DE4, 0x2BD3C75, 0x230A32E, 0x30878B, 0x260DF4F, 0x4BD354, 0x1AAE3C, 0x1436F09, 0x19797A5, 0xA3927, 0x51561F, 0x2D1CEED, 0x7B6E0, 0x8D47BF, 0x133BA69, 0x779AE1, 0x25156E,
0x2C57119, 0x3241611, 0x3F60BCA, 0x30363EC, 0x2ED2AC2, 0x145AEAC, 0x1BC7460, 0x1974B5D, 0x7F8C02, 0x5968DB, 0x1121DBE, 0x1B66C01, 0x9611AC, 0x3FA6FB2, 0x39CF7D5, 0xEFA471, 0x35EE00C, 0x15FC49A, 0x57949F, 0x5C2700, 0x3F656E, 0x206B312, 0x24918C2, 0x2CAEF2A, 0x2CF9CE0, 0x3416B7C, 0x737218, 0x1AF6218, 0x16E824, 0x3C2593,
0x4A3827, 0x1A6AC6A, 0x232A59B, 0x3400AE5, 0x263E19B, 0x29971DF, 0x2B7F487, 0x1FDB663, 0x1AE43B, 0x4708E2, 0x31AC7D, 0x63960C, 0x358C8B7, 0x2A8BA95, 0x1550B5F, 0x254F025, 0x36685B7, 0x31E8F3E, 0x53BAF4, 0x5B5B33, 0x2E96B90, 0xC154B, 0xA1E19B, 0xFB016A, 0x1C4FDBA, 0x3B96233, 0x3CFCE9B, 0x1756E67, 0x4748C1, 0x4A4774,
0x26ECDED, 0x12FC35A, 0x156C18A, 0x2FD80F4, 0x3170449, 0x26736, 0x3AA4057, 0x2F294E2, 0x7791FE, 0x2632AD, 0x1697C4F, 0x1A56406, 0x3931238, 0x1010A83, 0x232D956, 0x3353A58, 0x3FA1803, 0x3D2FD15, 0x4EE9AD, 0x34A3D7, 0x176FAB, 0x1F340A4, 0x3F53F80, 0x1C07BE0, 0x1F4E8D4, 0xBA8670, 0x3A15650, 0x1862BB4, 0x15321E, 0xC7D7C,
0x1BFD9D6, 0x2E8B991, 0x20C4C76, 0x33EEF2A, 0x2C65732, 0xAC6466, 0xE78C6E, 0x138611E, 0x34935A, 0x250DD5, 0x240DE4F, 0xB877C, 0x391B147, 0x13620C2, 0xE04659, 0x4F7FE6, 0x53FB14, 0x2ED9A23, 0x618EA0, 0x572CAB, 0x2834146, 0x336A849, 0x205D24E, 0x382DC5C, 0x120A2C, 0x13C4E3D, 0x121D8DE, 0x146476D, 0x6CD73, 0x36942F,
0x2BF4D88, 0x38A5B4F, 0x26B7D9A, 0x27FBF2D, 0x3A96A3F, 0xBABFE4, 0x12E021F, 0x2185A4A, 0x2A9A14, 0x1BE40A, 0x121F7AA, 0x242380E, 0x24065D5, 0x3C0212E, 0x351007A, 0x7374DB, 0x29A0DA4, 0x256E463, 0x1FC66E, 0x1F3744, 0x380A00A, 0x6312C1, 0x11A55A8, 0x2D5A275, 0x2A07B83, 0x1316B4D, 0x1D9BF36, 0xC9D370, 0x1346F4, 0x775E7F,
0x32341C0, 0x1E9C5E4, 0x2620A3C, 0x3181338, 0x6DF078, 0x87370B, 0x28CECFA, 0x3780088, 0x144390, 0x127652, 0x1F50D45, 0x18214E2, 0x12F19A7, 0x293FF4C, 0x21F4287, 0x17453BF, 0x2145405, 0x1859416, 0x236F45, 0x7CC92A, 0x10EF72A, 0xD1D447, 0x383A482, 0x300C25D, 0xC3B2FA, 0x6E7220, 0x356713F, 0x21FA61A, 0x26676B, 0x664558,
0x760DDC, 0x371CADE, 0x12E3936, 0x10B1B24, 0x2B63416, 0x20B9D9B, 0x1BE103F, 0x33BB305, 0x5517A8, 0x3A7F03, 0xAE366C, 0x3A0E82B, 0x21B593, 0x3BF34A9, 0x2533DD4, 0x131E144, 0x30C9E10, 0x972843, 0x1B6290, 0x166219, 0xE208F1, 0x749D99, 0x3344C46, 0x11CCC72, 0x54EA9D, 0xB5580C, 0x1FB72C7, 0xD5A6A0, 0x5A90F9, 0x6F061A,
0x22A15C5, 0x1C9B47F, 0x2AFD867, 0x2C4261, 0x5F40F6, 0x3410586, 0x2604889, 0xDE7857, 0x29106C, 0x4F379A, 0x28E1678, 0x12A6A3A, 0x1BD177D, 0x1EA8025, 0x283C2DD, 0x136523B, 0x19EB66C, 0x9A9031, 0x2C4751, 0x5532BC, 0x196CE22, 0x173E67F, 0x2A2F8D, 0x3A10EAA, 0x256FA5C, 0x3854944, 0x1EA6BBE, 0x3516BA1, 0x4FA312, 0x3C7727,
0x1117EA4, 0x26F88E5, 0x28B399D, 0x10E791C, 0x3B9C48F, 0x2286D57, 0x12B4EE, 0x29A80EC, 0x7BCA8E, 0x3337D3, 0x2005953, 0x2D7C6B4, 0x185CA40, 0x3E24D3B, 0xA1B0B, 0x375EF97, 0x19CD39B, 0x33B9FC6, 0x514BD7, 0xABE13, 0x20E54A7, 0x1B94097, 0x2041E84, 0x1314C42, 0x11DF6C8, 0x373A504, 0x1B5E9B8, 0x319548A, 0x634F96, 0x68D49F,
0x444666, 0x35DA76F, 0xA57363, 0x3E25062, 0x222469E, 0x2CB413F, 0x17F6666, 0x1E1AA1F, 0x542C4C, 0x7133FA, 0x16402B4, 0xC71590, 0x2024991, 0x3C3484C, 0xDCC2F1, 0x18266EA, 0x29E4C71, 0x28BB08C, 0x52DDAD, 0x14EC2, 0x3B34DD6, 0x2D01099, 0x16D8510, 0xBD2E12, 0x3219AC0, 0xEB8E4E, 0x3EAC462, 0x1368A68, 0x157ACB, 0xABF4A,
0x19EAB1F, 0x3790A15, 0x14AE16D, 0x19764A1, 0x29ED5F8, 0xA00CE5, 0x311C9A1, 0x10AF3D6, 0x1BD259, 0x17A484, 0x381363B, 0x714CB2, 0x1465488, 0x2FCBEF7, 0x207A01E, 0x38A9CFE, 0x1E9C436, 0x11D308E, 0x2336D0, 0x2F7A51, 0xE3716C, 0x1401AE4, 0x2CA81F5, 0xD8F39B, 0x180677D, 0x32FD644, 0x34B4282, 0x3811C05, 0x40E8D8, 0x53F9CA,
0x1DADC53, 0x439CE2, 0x25BB363, 0x282485, 0x169658D, 0x3E566F4, 0x13CF5B, 0x1C48DB0, 0x150282, 0x738C53, 0x28BF9FC, 0x321E376, 0x21FB9E8, 0x2A57D2F, 0xFEE64F, 0x16BCD0A, 0x1126A04, 0x90A0E1, 0x4F1899, 0x6170CC, 0x364FF75, 0x22CE087, 0x31249F5, 0x34D9958, 0x20129DF, 0x285EADD, 0x158FE8B, 0x3A81E94, 0x227EA1, 0x473D3B,
0x12B0EB2, 0x4FD508, 0x261BB83, 0x36FCC28, 0x18EDC0B, 0x2DBBD5A, 0x31D0374, 0x16AD66F, 0x78E584, 0x1C6AED, 0x1DB5BA1, 0x18144FA, 0x17F32F, 0x3D8D0FF, 0x231925D, 0x7E5DB2, 0x1ACFE25, 0x379B56C, 0x4A58FB, 0x46A445, 0x3E9E1DA, 0x20A2A0C, 0x2819A13, 0xE65020, 0x1C9FF67, 0x1AB5504, 0x1648EC5, 0x2C9BC13, 0x57B251, 0x62F4B9,
0x1B033D, 0x7ED39A, 0x3A98074, 0x2FFCBE4, 0x3FFBE79, 0x1400333, 0x5DBC43, 0x27989B7, 0x9BC6, 0x253D0A, 0xBEF06A, 0x124CC9A, 0x2EFB73F, 0x3ED18A8, 0x342D7A9, 0x1CB0BAD, 0x1E96CE4, 0x2760B05, 0x2D1B6A, 0x2E8CDE, 0x2F1B2A1, 0xCBD304, 0x3E06F35, 0x1B4F6CE, 0x12947C3, 0x3553FA3, 0x23E901D, 0xD10A20, 0x4CB0B, 0x59FEF9,
0xB9342E, 0x2293ECE, 0x20A9D07, 0x2D3B096, 0x1982919, 0x30A4530, 0x2B05EC0, 0x2B67E83, 0x7B9D63, 0x611069, 0x256A79D, 0x25D4E50, 0x18A966D, 0x3F5D906, 0x15B07A2, 0x111C2C2, 0x3D35B40, 0x1C1632, 0x6FE6F8, 0x24B0C5, 0x2FE45AE, 0x178B8C, 0x220B924, 0x32AABE5, 0x2761834, 0x3D010EA, 0x6C4D0C, 0x24C01B5, 0x68D0B0, 0x123E3A,
0x37FF33C, 0x2E45654, 0xBF9A4D, 0x31116C7, 0x184BECF, 0x1A932AD, 0x2AD1021, 0x734742, 0x4FC960, 0x498968, 0x3E9E3B6, 0x2391B25, 0x25666B, 0xA167F5, 0x1C15795, 0x2D272ED, 0x2FBBA18, 0x8A26DA, 0x7F6FFB, 0x5E8BD5, 0x3CE7C79, 0x27D373B, 0x24A02B6, 0x15CC533, 0xD54C94, 0xEF27F9, 0x3A197C3, 0x292EAC2, 0x510999, 0x4B2C0E,
0x5A8DB, 0x2C55B8, 0x33022D7, 0x12E8D46, 0x36972D7, 0x21E6E20, 0x3A88D41, 0xFF7BD, 0x4609A0, 0x5E4D59, 0x26598B, 0x1E5A0F3, 0xE10BCA, 0x6865E, 0x2179FE6, 0x3BA2D2F, 0x34EAD8A, 0x2F758DF, 0x782A3F, 0xFB4C6, 0x20C350, 0x1A2E55, 0x3D30648, 0x35EA227, 0x23C0FBF, 0x12CB65E, 0x230F48, 0x3D20FE8, 0x148590, 0x1D78DA,
0x1BC09CA, 0x5B63A7, 0x13446C0, 0x948C44, 0x25155B5, 0x1A99897, 0x15CDCC1, 0xE52B73, 0x54FDE7, 0x712D1F, 0x1ABEFAB, 0x1995549, 0x1001BBA, 0x8ACE8C, 0x1381B55, 0x122F98D, 0x1EEF531, 0x379AD5C, 0x4DD8F, 0x637A53, 0x92DA63, 0x23D7B7C, 0x1F5A6D3, 0x15426BD, 0xDF6836, 0x25F8B26, 0x2545094, 0xDAF12D, 0x236F2A, 0x8522E,
0x2CE8301, 0x30E5F0A, 0x39C9404, 0x2160E15, 0xCE9ABA, 0x2B6C331, 0x1C65EA6, 0x1EB1053, 0x493B25, 0x65F547, 0x699753, 0x1BDC53D, 0xA8DA15, 0x921046, 0x3DB3D00, 0x2E1E3B3, 0x2D365BB, 0x3026A3E, 0x2BE693, 0x55691A, 0x14C047F, 0xD6AB37, 0x278E514, 0x1BD918E, 0x171F024, 0x118F116, 0x3242DE0, 0x2932D4B, 0x765674, 0x746ADB,
0x1DA6CDA, 0x2D96CC2, 0xA4D94F, 0x1F10B42, 0xB6893E, 0xA7465C, 0x354BAFC, 0x38472BF, 0x5D004E, 0x3350DB, 0x2FEF67, 0x9AA471, 0x233EA25, 0x2D89799, 0x1164C63, 0x386D9E1, 0x3FF16B0, 0x340F4BA, 0xFF2DF, 0x13A219, 0x2F9F7F9, 0x1F7E5C6, 0xA167AE, 0x433FA6, 0x1ABCDB9, 0x170D25C, 0x2463DF5, 0x2D4FE40, 0x645C50, 0x13D858,
0x2B1E7A6, 0x111CDA8, 0x962C4E, 0x21FEA15, 0x3FC4DDB, 0x2F7A9EF, 0x127D384, 0x134ED34, 0x4849FF, 0x48C50D, 0x7C9AC, 0x1B4EC3B, 0x2108B20, 0x632C59, 0x34916C9, 0x3DAA56B, 0x39968F4, 0x3E78FF0, 0x3FDD72, 0x6E2C6D, 0x1DC97A4, 0x24D0A0, 0x2D6AA63, 0x23D7B7D, 0x3795F6D, 0x193642F, 0x20BCFE, 0x9A584E, 0x423FD4, 0x1A091C,
0x3B2D58A, 0x2FAB685, 0x70AEEC, 0x3DF447D, 0x1099316, 0x1A4B45E, 0x27AC3EE, 0x1A36CF, 0x2E8D33, 0x7F222A, 0x2549A7C, 0x31AF02E, 0x25BE5D0, 0x23A06C4, 0x81C9AF, 0x2CEEDE9, 0x3CC773B, 0x8A91D2, 0x55370D, 0x58BD06, 0x2882E0D, 0x2DA77FD, 0x103E9F2, 0x13AD1E6, 0x24108AB, 0xA7D475, 0x255957C, 0xDF5BF2, 0x5B4DB1, 0x67A8A4,
0x30C9D58, 0x7B57D9, 0x2095293, 0x2C37808, 0x618988, 0x2AA7587, 0x20EFB43, 0x2FB2C25, 0x3232BA, 0x20DF6, 0x229A8AB, 0x23EE086, 0x390414A, 0x33A5524, 0x1A69EF9, 0x2887167, 0x3B9C285, 0x265B077, 0x4AE671, 0x6878C3, 0xAC097E, 0x6D8D29, 0x31C4524, 0x1E5AE9, 0x1144B29, 0x3B65059, 0x27095DF, 0x32352BA, 0x1CF41A, 0x1C2E6D,
0x9B4CB9, 0x1BE57D, 0x2413E2B, 0x8BD210, 0x29E7BFB, 0x132F5A4, 0xB1E191, 0x371DF5B, 0x4EA174, 0xBE0AF, 0x2C738D3, 0xDF7DF6, 0x1D972E8, 0x22B8310, 0x89D5E8, 0x16D5928, 0x1D41668, 0x25DC568, 0x7DAD04, 0x51C65F, 0x6FF9D4, 0x204E41F, 0x57531E, 0x3D19A11, 0x9EFA96, 0xEFC1C1, 0xFB006, 0x3559F6C, 0x507FFE, 0x282FE9,
0x1FB8178, 0x39ED71, 0x39FE0E0, 0x1A51D0D, 0xD57EBE, 0x5ECF35, 0x117082, 0x28DCFAF, 0x5BD4B6, 0x7CDDD5, 0x28E3B5F, 0x1489131, 0x37CCF31, 0x20752FF, 0xDF3A58, 0x28C1EA8, 0x13D7172, 0x2D2470, 0x40E671, 0x6B3640, 0xB6303B, 0x394CE3, 0x1D73D65, 0x161EB4D, 0x254AD44, 0x2275A0B, 0x3771CB9, 0x18053E1, 0x5B630C, 0x3EA3BA,
0x120EEEE, 0x1D7EC00, 0x3AB0497, 0x2E8FEB1, 0x33BBC3D, 0x223CEE6, 0x210428A, 0xCCDEAA, 0x2EF356, 0x5FABCB, 0x17889A, 0x362BF51, 0x84B9EE, 0x32950F5, 0x11D16B1, 0x1D0617, 0x216A6F9, 0x329A52C, 0xB37D2, 0x896B4, 0x277A1FB, 0x36CF430, 0x3765C60, 0x2E3DFA4, 0x865E3A, 0xB90904, 0x1F751E1, 0x3C82C91, 0x553DEE, 0x5B6A78,
0x14B9BFA, 0x37E7654, 0x21DB0A4, 0x3A86D52, 0x29F4A2B, 0x3660B04, 0x14BA765, 0x2CE5273, 0x704DE9, 0x5D307B, 0x1049D17, 0x286F656, 0x1308FAF, 0x210CAE0, 0x1063CEE, 0x16E500B, 0xEEC40C, 0x21A8588, 0x7A8829, 0x260A9C, 0x29D8686, 0x19B2928, 0x39B998, 0x3C3DDB3, 0x2000D14, 0x3DD4536, 0x3FD5806, 0x308EA08, 0x296011, 0x267409,
0x17F8423, 0x2098EA, 0x10410DE, 0x277FBA8, 0x2CA90F0, 0x20C52E6, 0x981658, 0x3BBB34E, 0x3DA610, 0x427E7E, 0x190793D, 0x1F3C326, 0x3E97A29, 0x786E2E, 0x3C9175E, 0x2E911AA, 0x37DB7F7, 0x260FF3, 0x1F5841, 0x7BD5B, 0x1C48939, 0x113764F, 0x25082FA, 0xCC3FFC, 0x23DD16, 0x6C79BB, 0x13C2EE4, 0x2C33F89, 0x794033, 0x674FF1,
0x129CBAB, 0x1E883A3, 0x20FE35C, 0x10469F5, 0x904E20, 0x15909BE, 0x38F6701, 0x1939F09, 0x7E6223, 0x726426, 0x412322, 0x3FDE271, 0x3DE0ED7, 0x18FBABB, 0x280BBB1, 0x3B9FA3, 0x23F5CDC, 0x4C7F0B, 0x46716E, 0x6C256C, 0x32CE1D8, 0x119DA19, 0x166AFF2, 0x1F23494, 0x2708132, 0x995FAA, 0x15BA5AA, 0x10E3A7E, 0x53B965, 0x5019F,
0x24F1EE, 0x3A10158, 0x7556A5, 0x2113A65, 0x3F0905E, 0xCA5E9D, 0x139B0BC, 0x347A528, 0x63E8E1, 0x51904E, 0x36BC6CC, 0x147187A, 0x118B537, 0x10E1211, 0x2691B09, 0x1DD43F8, 0x239885C, 0x2365CE7, 0x2EE530, 0x62B92B, 0x39F083C, 0x2296979, 0x152AD74, 0x2C3F59F, 0x8D43CA, 0xBB77CA, 0x181228A, 0x1E0E58B, 0x25B333, 0x58BA2E,
0x38F3515, 0x1128F01, 0x23C686, 0x11107DE, 0x3BDD778, 0x35E3758, 0x27B9C54, 0x101BD44, 0x290C21, 0x442DB, 0x30A9D, 0x33ADDE0, 0x7794BB, 0x130A9C5, 0x36B2E74, 0xD0CBD6, 0x159619D, 0x1B48222, 0x374697, 0x2280B6, 0x2DB0FB2, 0x7FDD97, 0x2D4F2D2, 0x1AA579F, 0x5BEDD1, 0x2D9553B, 0x10E5311, 0x1BD4125, 0x397496, 0x6EACDC,
0x38A5BB3, 0x104962E, 0x3413015, 0x3405C71, 0x9C8178, 0x95EFE0, 0x17D4857, 0x152C881, 0xD171A, 0x4EECE, 0x1DB67AA, 0x1686AD7, 0x3451400, 0x2B98B66, 0x20AFAC4, 0xD89CDD, 0x19A5885, 0x12348C, 0x6577C4, 0x7A053A, 0x205A880, 0x13AAB89, 0x26A839, 0x2BDEC2D, 0x232F1FF, 0x378CFBD, 0x9BCD54, 0x2E7AC37, 0x5D2604, 0x5EEF31,
0x3276288, 0xA44B01, 0x21F95AD, 0x39292F0, 0xD06FB7, 0x2E33415, 0x2A1F58C, 0x7DC762, 0x4DCCCB, 0xF0A98, 0x18A1502, 0x3EBE037, 0x2EDE1BE, 0x1890185, 0x628E0E, 0x2B5B8D3, 0xF39C37, 0x3874800, 0xEA4AA, 0x2D20C0, 0x1A30282, 0x26B63B, 0x3E2A904, 0x237FE2B, 0x2C4C336, 0x9BCE46, 0x1F605E3, 0x2F5FC47, 0x1D87C6, 0x266086,
0xD829F8, 0x68394, 0x3FBB720, 0x36E4C9F, 0x335505C, 0xC38413, 0x280A774, 0xDE47D9, 0x146902, 0x55FA41, 0x21BF9D, 0x1CC21BF, 0xE57040, 0x2B9A163, 0xE45E06, 0x18F79E7, 0x1A33DE7, 0x2FA5ED5, 0x18D662, 0x3AD51D, 0x2EEF43C, 0x223E935, 0x24B1D1E, 0x3F28E52, 0x2BB7067, 0x1126AA, 0x1E085C2, 0x36636D9, 0x27EC9B, 0x18F7CB,
0x36EDBFA, 0x1B35467, 0x11B39AC, 0x26387D1, 0x2A23341, 0x1412684, 0x3AADF33, 0x68EDC7, 0x1DCFB4, 0x1B20D7, 0x2602E3E, 0xCAFE8A, 0x1D7F253, 0xC9B407, 0x2C2B7A8, 0x666B52, 0x291255D, 0x1CC935C, 0x78C15F, 0x3F53F5, 0x1BCEBAA, 0x1F2306F, 0x20DB8E, 0x3B5CF7B, 0x884383, 0xF745DF, 0x1CF740B, 0x22DB3D5, 0x27A30C, 0x75EE4A,
0x11A8E3E, 0x1169E7D, 0x3327161, 0x2E87F8B, 0x1F2D97E, 0x3BD3F7B, 0x5A430F, 0x120429D, 0x496B58, 0x4B0618, 0x103C7BD, 0x11F1EC6, 0x1B590EE, 0x11F86B1, 0x106D40E, 0xDCF92F, 0xED45DA, 0x1314F30, 0x3C90F6, 0x70C245, 0x653B4E, 0x1D0F4A3, 0x1D7491B, 0x2D1311C, 0x30DFB5A, 0x1977CAF, 0x29082A2, 0x3A4AEF9, 0x7E5173, 0x69A3A4,
0x1FEB424, 0x2FE9979, 0x24C60F3, 0x2FBE99C, 0x213026E, 0x1BF9669, 0x2D5BE9F, 0x1A9FBD9, 0x1E0489, 0xF8AEA, 0x16B51FF, 0x301C9BE, 0x2E20FAA, 0x1E800A5, 0x867FF0, 0x3D63688, 0x1D8F0F2, 0x335C321, 0x31A668, 0x545644, 0x39410E0, 0x3F22468, 0x2DBEDF6, 0x6D35C7, 0x33B9537, 0x29F9C7D, 0x3C408A6, 0x34EC815, 0x6CA227, 0x522058,
0x251FB62, 0x25857B, 0x2FF604E, 0x3F6DA16, 0x24A15F4, 0xBF96D, 0x28E9090, 0x2205514, 0x105B94, 0x14D985, 0x7A9404, 0x1BC821C, 0x2E0D453, 0x275FA57, 0x2F37B4D, 0x2BD3122, 0x26215BE, 0x5E8BDC, 0x67AAF9, 0x7E617A, 0x222695A, 0xDF7538, 0x1336E9C, 0xB0266A, 0x3EAFE96, 0x21AD7F8, 0x3310281, 0x1D7B256, 0x677619, 0x2A2191,
0x11FF3DC, 0x350278D, 0x2B051ED, 0x352A48F, 0x23EC755, 0x120A6D8, 0x14BE1A0, 0x2B26300, 0x4A87F6, 0x4BB952, 0x31E482C, 0x208D16D, 0x315E9A8, 0x176DAB1, 0x1653968, 0x39C63F0, 0x5207F5, 0x1D1B841, 0x855A1, 0x33F9E5, 0x51F53A, 0x1875DDF, 0x11638FB, 0x2CB8B6D, 0xF811F3, 0x35E03C0, 0x20DB3B3, 0x498B2E, 0x4AE3FC, 0x42336A,
0x2DC3868, 0x72E53A, 0x14514F2, 0x2CC424A, 0x22DEE36, 0x1C37D4C, 0x3F5BA02, 0x126846A, 0x25081C, 0x16CA93, 0x11CB675, 0x3D0CA1, 0xEB9103, 0x39AA113, 0x16A4B1D, 0x3023475, 0x3B2F32F, 0x37B6FC1, 0x41B2D6, 0x2CD0E0, 0x3002A6E, 0x1A3276C, 0x3511B76, 0x1E4E1FA, 0x60985A, 0xB109E7, 0x1506699, 0x18EA502, 0x72A06E, 0x414A81,
0x391333E, 0x94F121, 0x1ED4F05, 0x2CD1AC, 0x183825C, 0x2C9DBF2, 0x242D0B3, 0x2EA66C1, 0x3EA571, 0x47570C, 0x6CB5F2, 0x2243975, 0x340721D, 0x25A43, 0x28EFE6B, 0x3DA2B22, 0x2313025, 0x3929590, 0x3C0B0B, 0x251737, 0x2B89DEA, 0x2FFEA7B, 0x352448E, 0x1D19A17, 0x5A63CD, 0x3A29563, 0x3478F31, 0x721BAC, 0x68748C, 0x4E4C5B,
0x2D32070, 0x1E30288, 0x2805D45, 0x19A831F, 0x13A3E1B, 0xF1DBC, 0x28312EA, 0x15A83DC, 0x5CDD35, 0x221071, 0x2C0F647, 0x178CCED, 0x1A4116A, 0x36CE7DB, 0xBC00FB, 0x3892266, 0x25D8F42, 0x21F1C0C, 0x111DCB, 0x2A325, 0x22A4B19, 0x377AC7, 0x325339A, 0x1161302, 0x296F76F, 0x34C00C4, 0x3C4BF3E, 0x3D0C503, 0x474DB0, 0x5F435B,
0xEEF7A3, 0x2A39450, 0x1070C05, 0x3D5AEDB, 0x3F04B97, 0x2B10EAD, 0x8ED4DB, 0x1B86995, 0x54596C, 0x32F24F, 0x1F54E3F, 0xBF9928, 0x8B9375, 0x18BFF74, 0x607214, 0xAA7F6F, 0x1E14D98, 0x24C0057, 0xD6AD5, 0x72569C, 0x31B9216, 0xBE0E05, 0x24D5E64, 0xF88018, 0x27EF42, 0x29A4622, 0x1015F9A, 0x3A5A77E, 0x49D6A, 0x20D91A,
0x56D47A, 0x3BC9BF8, 0x46CD15, 0x5EC9A, 0x2A0F026, 0x2359E6B, 0x4F46F7, 0x3CF5950, 0x601DD4, 0x63399F, 0x5A9764, 0x20535CE, 0x3F88941, 0xB56943, 0x1BEBDBD, 0xAF1C65, 0xCD1992, 0x158E713, 0x10ACD9, 0x49EFBD, 0x304DE65, 0x2715261, 0x176F628, 0x20CDF57, 0x1BE865A, 0x7E25DB, 0x3B43A19, 0x1D525A0, 0x8DDEB, 0x34CF4C,
0x244B56A, 0x1C9568, 0x31D05B, 0x3F9B7CB, 0x3151D84, 0x22B136F, 0x34A0B62, 0x22DB4C6, 0x10FD30, 0x66D8A3, 0x1984774, 0xF0EC9E, 0x2B4EA98, 0x2517B8, 0x3D9001F, 0xF37272, 0x361ECC0, 0x31FAA13, 0x412A9F, 0xC91B4, 0x15832F0, 0x1ED3342, 0x18BC97F, 0x1F4930C, 0x1842984, 0x1FD8ECC, 0x1E31243, 0x1A65145, 0x6F4CD5, 0x580AB9,
0x465B3E, 0x15B774A, 0x2A5FB66, 0x9A9395, 0xAE36D8, 0x3568506, 0x3004242, 0x396A2A6, 0x16995D, 0x82636, 0x23B413, 0x2F9F9DD, 0x10D7312, 0x8DB739, 0x34E7A99, 0x2ADC114, 0xF443BF, 0x312EF82, 0x41FC42, 0x6C3995, 0x135753D, 0xCC292E, 0x8B25D6, 0x36AB0CB, 0x2A78F3F, 0x15AADBA, 0x9FB7B0, 0x1BE28DE, 0x6B1B3F, 0x385603,
0x2C01D73, 0x1C184A3, 0x5532AB, 0x32527CE, 0x349B947, 0x10C8C50, 0x1CF8FC3, 0x21A14D7, 0xA22E5, 0x2AADD0, 0x3992446, 0x26308F9, 0x316EF97, 0x438DE, 0xE9022B, 0x307038, 0x37F28EB, 0x3635C60, 0x15D36A, 0x161B06, 0x2F8D056, 0x18EF392, 0x3D38EAF, 0x1751338, 0x16BACFB, 0x1E646A1, 0x3FA71DA, 0x2700DA7, 0x2A1765, 0x540523,
0xF58E29, 0x1322520, 0x2F68484, 0x3F7CA1D, 0x30355FA, 0x547A29, 0xE5D2CD, 0x3A17B6B, 0x40CBB0, 0x3B32AC, 0x1679DF8, 0x2CCC95A, 0x324AD07, 0x3197016, 0x2F0C0F0, 0x3221B5F, 0x351E9F4, 0x29C18DB, 0x7F07EC, 0xE8B1D, 0xE8A846, 0x2F689ED, 0x2F44C7D, 0x3CF503F, 0x3391B2E, 0x1582AA2, 0x12AE95F, 0x57F797, 0x7DF51E, 0xEE1E1,
0x2240AE6, 0x205E565, 0x96D0B, 0x3FF2BFC, 0x2AF2F7D, 0x2E1E7C5, 0x3BFAD49, 0x3621038, 0x29FC1B, 0x4CF4D0, 0xAD0FF6, 0x2A8D08C, 0x34604, 0x23F47BB, 0x15FFB8B, 0x1C4F86A, 0x1A1AEA4, 0x2B73DBB, 0x44D3AF, 0x3EB300, 0x3588186, 0xCCC170, 0xF099A, 0xEE8983, 0x28818DB, 0xC77BA8, 0x34C07A5, 0x151B3AC, 0x289D0F, 0x26EE69,
0x2C4EA05, 0x2664A0B, 0x2762FE4, 0x2640B96, 0x37D1110, 0x3B714BD, 0xD99C64, 0x3B513F6, 0x33AA0, 0x42BD48, 0x3A9622D, 0x3643859, 0x27864D5, 0x37AECC8, 0x222F735, 0x366EC24, 0xA1576B, 0x3878645, 0xD6EE9, 0x4C60FE, 0x1FAA328, 0x2710909, 0x2BB03A6, 0x2278318, 0x1B0A3BE, 0x2CE17FE, 0x385C271, 0x34EB139, 0x56C2A, 0x7E3B5C,
0x7370A4, 0x3C3197F, 0x1921AB, 0x2943882, 0x1429E9D, 0x300B11, 0x18BA67E, 0xF0976B, 0x4B1A8C, 0x75EC51, 0x1466DCA, 0x1B99943, 0x3F4192C, 0x3B8FEDF, 0x308CFB9, 0x2A44CA3, 0x33F3964, 0x3A4C3EB, 0x290379, 0x2AF7A3, 0x105E35B, 0x31D4CFE, 0x2539B45, 0x215C020, 0x1F0D2, 0x90E902, 0x2146078, 0x41741B, 0x7D5345, 0x419F25,
0x3828172, 0x4D4A6A, 0x79E7D7, 0x20554FA, 0x27985F7, 0x173DA09, 0xA90CC9, 0x1064E1, 0x2921E, 0x220C82, 0x320C927, 0x1ED2828, 0x2D6DE3B, 0x91FF66, 0x2DDBFD2, 0x90CFB1, 0x3718472, 0xE7DC92, 0x3C99A2, 0x4B3A37, 0x12D1017, 0xA6B5C3, 0x17A8B5F, 0x1448E88, 0x987777, 0x161F82E, 0x2D6EA2B, 0x262AA08, 0x3AB07C, 0x449650,
0x1AC4C0C, 0x1FFEDAB, 0x1231DFA, 0x13D014B, 0x157D209, 0x327FC8F, 0x12AC850, 0x30BBD1B, 0x521E93, 0x1DA963, 0x12FA2E0, 0x1DE4BAE, 0x1D8C788, 0x20FB4E1, 0x184E3BE, 0x30D9B44, 0x2234690, 0x37A0F4A, 0xD188E, 0x4FFADF, 0x2938608, 0x6F3A5D, 0x2F66946, 0x110134, 0x30E8ACE, 0x2D37857, 0x324C0A, 0x1E98689, 0x40968C, 0x3E9F47,
0x3D18D12, 0x35C8CAF, 0x7BF1F2, 0x1A917A2, 0xB041DA, 0x35CC755, 0x11EE7CB, 0x2DDC8EC, 0x4FB87A, 0x7F6991, 0x132635F, 0x667C21, 0x4285A5, 0x11770ED, 0x152F3FA, 0x1BAFE6B, 0x735CAF, 0x352EFCE, 0x15E61B, 0x45CF3B, 0x29D63F9, 0x3CEC018, 0xEC18DA, 0x398468F, 0x1567734, 0x392D331, 0x3126B12, 0x1611D5A, 0x457551, 0x7D19E2,
0x59655, 0x1458870, 0x1477C5D, 0xDC487F, 0x3337789, 0x3C3CB3E, 0x225A9E4, 0x2C686FA, 0x573CD, 0x3CC032, 0x24D5A41, 0x1A224ED, 0x7741B4, 0x2A14305, 0x1FFA257, 0x6D46CD, 0x3B12A8A, 0x3B8B5D6, 0x17382, 0x6AF59B, 0x3F80EE9, 0x20490D5, 0x34F1009, 0x3CC9F17, 0xF25287, 0x2DFBF29, 0x2E79475, 0x3E4FD0F, 0x6AA570, 0xFB62,
0x313277, 0x1A589A, 0x1B980B7, 0x18604C1, 0x39E7B0, 0x31EC5BB, 0x239C8EC, 0x4FBBDF, 0x5D8DC9, 0x2A4C9F, 0x3BABA6F, 0x16BBC8D, 0x27B72D2, 0x2B8A8BF, 0x4AD943, 0x2FF087, 0x12539DE, 0x2E906BB, 0x27F4D, 0x230F37, 0x2AAC09C, 0x982A, 0x1DB90F6, 0x135433C, 0x1BE3638, 0x2A75D35, 0x2B9B85F, 0x2849CEB, 0x28ABD7, 0x1DD774,
0x14B0902, 0x9628C5, 0x19624C3, 0x301EE6B, 0x23D7243, 0x39CC22B, 0x8E8B69, 0x35A2AA4, 0xDF507, 0x134123, 0xD450E2, 0x1610565, 0x13B8B3C, 0x39D0711, 0x1ED14E8, 0x3E19D06, 0x36F52AA, 0x3E5BCBD, 0x53A8C6, 0x608DA7, 0x2A0243C, 0x2914182, 0x1FF27F9, 0x477A0D, 0x2B3D59B, 0x31E409A, 0x2D1BF47, 0x3302E5B, 0xDA36B, 0x3BECC1,
0x171C17F, 0x1523C28, 0x2E2932B, 0x1FF6AB8, 0x43C820, 0x2FB1F6F, 0x340812A, 0x325879, 0x2A425D, 0x5FB74C, 0x37845A2, 0x2A5934F, 0x1B83DCA, 0xB4D737, 0x27780C7, 0x1D5D7A2, 0x5E51B3, 0x6C9099, 0x273DB1, 0x73AEEB, 0x2E4392D, 0x1EFBF2F, 0x2986154, 0x3DAADE0, 0x1923938, 0x1354F32, 0x16FADB0, 0x1711DB8, 0x605021, 0x2E4ECE,
0x3812356, 0x23BCE54, 0x1296584, 0x3EFE561, 0x33FDF2A, 0x27A62FF, 0x3680624, 0x270C607, 0x555185, 0x72644F, 0x1E3D624, 0x150FBAD, 0x1AC7542, 0x25D84F5, 0x17D098C, 0x3923DD1, 0x1CC24E7, 0x3E87EB2, 0x5BDDD5, 0x7671FA, 0xC5B802, 0x2FD8871, 0x2ED8452, 0x1D6D311, 0x3BD13D, 0x38700B1, 0x31CF337, 0x3AC002A, 0x616BC5, 0x498A1E,
0x3802521, 0x3DD52B0, 0x3C728B5, 0x30CF1C9, 0x3E5AA49, 0x1749F1B, 0x1B33802, 0x3CC48BF, 0x690634, 0x5D005F, 0x3C622E7, 0x3FFF3B9, 0x62B575, 0x3E8848F, 0x2E82513, 0x6E588D, 0x1B45791, 0x3F38F2B, 0x50F93D, 0x3848E6, 0x3EA4F5E, 0x259A7E2, 0x3F0C68C, 0x2500B, 0x144F6CE, 0x712EE2, 0x3713978, 0x3F6E1BD, 0xCC5E7, 0x257679,
0xB17E83, 0x11E6AAD, 0x1A254F6, 0x2E3A79, 0x20704CF, 0x24F6400, 0x305B38, 0x2B3407C, 0x710F97, 0x5AF48D, 0x3FCC916, 0xD990D2, 0x19E7574, 0x35EAE91, 0x232209, 0x1A62D6, 0x375F2FA, 0x3CB52CB, 0xA3538, 0x46C718, 0x378233C, 0x3B77EEE, 0xF5E668, 0xBC12B2, 0x27A0995, 0x1B2D991, 0x3D29A0B, 0x1E6865, 0x4F4E80, 0x317432,
0x1C11E3B, 0x3F750EA, 0x33369A8, 0x36C5D9C, 0x3BE2ACC, 0x9B6016, 0x205F43C, 0x668900, 0x3FD895, 0x635FC6, 0x30DA1E7, 0x18508D0, 0x11EACCD, 0x16B1C0F, 0x221B84, 0x1CB55F3, 0x2866AFD, 0xC9352B, 0x6C893A, 0x13533D, 0x2CE8512, 0x3BF6A04, 0x40DC37, 0x3583C, 0xF4B846, 0x54318F, 0x9BE69C, 0x22C83BE, 0x2223F1, 0x174BD7,
0x1698189, 0xE4BC6, 0x1E6F1A8, 0x148D0AF, 0x1302EB1, 0x1E85983, 0x1298805, 0x1030552, 0x732BF4, 0x53F66, 0x17C7CE8, 0x6CDB97, 0x3BA2C0E, 0x3E832CA, 0x227B65E, 0x3BF236F, 0x3CE7CBE, 0x3B13259, 0x790451, 0x46D07C, 0x868412, 0x273E57F, 0x126B38C, 0x1E1523C, 0x34997C8, 0x1EF08AB, 0x274CE7B, 0x2F62DFD, 0x6DEE23, 0x1C5BE,
0x2EAE93B, 0xA565C9, 0x397C10, 0x1749B09, 0x3DB6E44, 0x302FE6D, 0x15FF815, 0x2829AB5, 0x65583F, 0x6B3B87, 0x17B8E64, 0x20F9BFA, 0x1754CC4, 0x3546643, 0x1F89D3F, 0x10A4F1B, 0x3436A4B, 0x3B076F3, 0x4ADDB9, 0x30C624, 0x27023A0, 0x13DD8C7, 0x3CBC036, 0x36F52FF, 0x34E4AFA, 0x92E93B, 0xCAD515, 0x3B84CB2, 0x3086E1, 0x690976,
0x124D198, 0x164F568, 0x30471E5, 0x22ECE15, 0x73486F, 0x116B5B7, 0x198B80B, 0x3D575F3, 0xF6B95, 0x55C9B3, 0x2D1C07F, 0x257B3D6, 0xC590D2, 0x34895FA, 0x12DEDF1, 0x439A1F, 0x34FF7CC, 0x2AF92D5, 0x93D67, 0x4B5B18, 0x1D796B2, 0x1E68AE4, 0xA3D6D6, 0xDD4C99, 0x1EA466C, 0x2D6FB9D, 0x1B990BF, 0x35B7EC0, 0x7BAFFE, 0x40903B,
0x32D6BC8, 0x721AEF, 0x2563535, 0x32A16F2, 0x1DD3357, 0x32255A9, 0x37A9196, 0x2780F26, 0x179330, 0x209F0, 0x933495, 0x2A6B951, 0x3CBA5CE, 0xF25AD9, 0x10C5C0B, 0x1358274, 0x135C579, 0x222835B, 0x5E0DDE, 0x6AF961, 0xF2A709, 0x12177, 0xF1CA08, 0x4FD4C9, 0x19A0B2F, 0x3ACEF0B, 0x350CC9F, 0x3D3DD06, 0x5E9B8F, 0x7ABDEA,
0x11471F7, 0x13AFA2, 0x18924D, 0x2BC720F, 0x2D6C6F0, 0x135BE09, 0x2473FA7, 0x2235779, 0x3204EB, 0x6D70ED, 0x22FAA1F, 0x3A1CE1D, 0x221CF46, 0x2ED01E8, 0x33DA207, 0x2A8541B, 0x36E365B, 0xBED53B, 0x5C73BE, 0x7A40EC, 0x1D722E3, 0xC0EA05, 0x15A72E7, 0x1876063, 0x3B6AD6D, 0x4E227C, 0x1E01649, 0x327D664, 0x10ACF6, 0x57B175,
0x2B5A60D, 0x2A720E, 0x2D02F24, 0x1375573, 0x389A4F7, 0x1A1CCD8, 0x191ED1A, 0x25C0202, 0x51431F, 0x6B3605, 0x20E9A0F, 0x28FEE2B, 0xF97741, 0x96C37A, 0x37D478E, 0x206DC99, 0x6851B1, 0x1812C5A, 0x630C0C, 0x4728F0, 0x35B2318, 0x23211DB, 0x41418, 0x3B4A894, 0x309BB46, 0x3A5BBE2, 0xA06191, 0x3FC8F74, 0x2484F7, 0x6425D4,
0x17AEF5E, 0x17F87E9, 0x1A30240, 0x76D27C, 0x15EEF08, 0x1727A63, 0x386B71B, 0x33B5535, 0x2733D1, 0x36D753, 0x4AF537, 0x13E549B, 0x345FEDB, 0x2378323, 0x1B04451, 0x2C3D0BB, 0x1847755, 0x49C564, 0x1DCC4D, 0x2FB2CA, 0x3C31CED, 0x30277E3, 0x1E453FE, 0x37596A5, 0xD10D87, 0x1FA44B, 0x2865941, 0x19E2D2C, 0x190809, 0x13195C,
0x384D41F, 0x30E1C9B, 0x2906953, 0xB4BF1B, 0x508E69, 0x152AECA, 0x1C15979, 0x203895C, 0x61C7C8, 0x7F0654, 0x28873B0, 0x29DA7A2, 0x2A7DF0E, 0x29E409B, 0x324AFAA, 0x39D9969, 0x236D628, 0x16BCCA2, 0x43FCDB, 0x4EAB13, 0x3F85F7C, 0xD27CBC, 0x2AABFA1, 0x1FDB1AD, 0x2F32B38, 0x39E7560, 0x3F869AD, 0x2FA9DD3, 0x69EBA4, 0x273072,
0xD51DB0, 0xFE70DA, 0x5278F2, 0x2987C86, 0xBFA3C1, 0x36BB765, 0x350CF0A, 0x1017C80, 0x161F8C, 0x442B5D, 0x564CC1, 0x2AF395C, 0x1E409C7, 0x28E2D11, 0x95696F, 0xCE6621, 0xCD4173, 0x2D16EDC, 0x3D5DBB, 0x2DA978, 0x1A49388, 0xB7BE24, 0x2B29C47, 0x2D15357, 0x2DF8755, 0x2D12FC5, 0xF957A1, 0x35A363D, 0x46F2E3, 0x67DF47,
0x3898AAD, 0x3D460D9, 0x3889224, 0x1A79358, 0x113E7A1, 0xAD26C9, 0x272270B, 0x177E2D8, 0x40021, 0x4DF64D, 0x1FF89ED, 0x96ADB6, 0x3B41691, 0x3EF0F7C, 0x34EF1FE, 0x1C9697F, 0x1679A12, 0x1F9D958, 0x290C4B, 0x4AC603, 0x15E51B1, 0x3AC596C, 0x100A644, 0x157E2DA, 0x21BE1BC, 0x217843F, 0x28765AA, 0x180C206, 0x7169E0, 0x1CC6A0,
0x3C925D0, 0x20AF1B5, 0x34B6DA6, 0x7AC90B, 0x29318E1, 0x2D7C3AD, 0x3BB5474, 0x54BF35, 0x6FFB86, 0x338198, 0x1F13943, 0x27EEC81, 0xE0525B, 0x5D4437, 0xB02C1F, 0x12B8396, 0xBF8718, 0x16B1DAC, 0x5D924, 0x24D8BA, 0x2548483, 0x1BD1235, 0x3ACB6E7, 0x27E424E, 0x13F0280, 0x1AA6B2A, 0x1ECEA2A, 0x21B0E7E, 0x6C5131, 0x2DA9DE,
0x3127B97, 0x31E9DA7, 0x1245C40, 0x275C0F4, 0x21697F5, 0xA4EC96, 0x16B4C9D, 0xEEEC7E, 0x7BE2BE, 0x500DF, 0x1795917, 0x1AABE35, 0x171DDA1, 0x1FE378B, 0x1345EA0, 0x35CBD56, 0x2A64B42, 0xD6A380, 0x49575, 0x383FAD, 0x3D43D56, 0x1BEC03E, 0x14FACAE, 0x12F351B, 0xC5AB93, 0x279CF9E, 0xC88618, 0x2D29ECC, 0x52B395, 0x4B0DB0,
0x1FF80C0, 0x39C4236, 0x17DADB8, 0x23AC96C, 0x22158CC, 0x29FCD00, 0x1192D54, 0x2ECBD0A, 0x1BD2CE, 0x3B4CE5, 0x1153D9D, 0xED5A53, 0x925A07, 0x740872, 0x5B9E1F, 0x4958A1, 0x2C52F13, 0x2C962FB, 0x3E022C, 0x560D3F, 0x5A6012, 0x27CE0C3, 0x16149C, 0x303D8EE, 0x2FD3F44, 0x1BBAD93, 0x34AC6CF, 0x32CFA4F, 0x5C8BCC, 0x337798,
0xC8E88, 0x3BDB4A9, 0x3DA33E0, 0x1075B37, 0x3CCE7A9, 0x274E7DD, 0x1A27CFA, 0x31386C, 0x579AFE, 0x380241, 0xF0DB02, 0x2D1952E, 0x1075DC3, 0xFF60D7, 0x1E23642, 0x237BF3C, 0xCF1D2F, 0x2228F3B, 0x2F7C81, 0x741B1D, 0x283C68F, 0x3E47C24, 0x6B9911, 0x135D07C, 0x11E174E, 0x1252398, 0x2783DEA, 0x1EDA8E7, 0xC80DD, 0x4B3EB9,
0x1A9A195, 0xDDEA30, 0x26E5043, 0x3F5794F, 0x3B4132E, 0xE05F92, 0x37013B0, 0x1562783, 0x11D09F, 0x296E09, 0x283B696, 0xAD0033, 0x8030E8, 0x300E5E4, 0x332C4E3, 0x84ED3, 0x2E913B2, 0x982D7B, 0x7E33FB, 0x5C8EBB, 0x39D2E9D, 0x10D8D49, 0x1D156ED, 0x17DAED3, 0x3155A66, 0x180B3AA, 0x2753D6E, 0x3B5C197, 0x12FBEC, 0xCA652,
0x11C6F83, 0x3C38F7D, 0xE1D4F5, 0x8F5358, 0x39F2B79, 0x1282842, 0x306980B, 0x12E2E4C, 0x41644A, 0x71057B, 0x25F47B5, 0x26C2DAD, 0x3E80545, 0x4F2905, 0x201D39, 0x511BE7, 0x28670CF, 0x30AD066, 0x7536C8, 0x456C98, 0xB44658, 0x1A27957, 0xFC9787, 0x3B5B878, 0x1BA7479, 0x2BDB9F9, 0x73F868, 0x380A109, 0x1D002F, 0x95DEC,
0x1001D6, 0x1C02AA5, 0x34D04BF, 0x1ADAE83, 0x1E99E57, 0x683C75, 0x28366C9, 0x1F5E7B5, 0x481C63, 0x24AF04, 0x3B68275, 0x3900CE, 0x2B0404C, 0x1E37BC3, 0x2012E37, 0x1740875, 0x395C200, 0x248EE32, 0x418B45, 0x7C5661, 0x1DA7366, 0x9E4D32, 0x2AC29BF, 0x14A390B, 0x2B3C5F4, 0x1DE8308, 0x209793, 0x1E64CF7, 0xAC610, 0x436E59,
0x3352222, 0x38C9273, 0x1BAF848, 0x31577FC, 0x3DC70CD, 0x11D96C, 0x2291BCC, 0x369C501, 0x63D176, 0x474438, 0x1CF6402, 0x3391F0E, 0x12E26E0, 0x11C8105, 0x1050A18, 0xCBA3BD, 0x28EA99D, 0x2166A38, 0x6BF820, 0x3F2B8F, 0x125DA29, 0x1B0A9FD, 0x149586C, 0x1C3431F, 0x97DED9, 0xA6CC3F, 0x31D0594, 0x29224A5, 0x7EB1A, 0x5AB896,
0x20018D, 0x24C7464, 0x18225D7, 0x1BA63F0, 0x456D4B, 0x1E42F76, 0xE7C974, 0x2748A4, 0x6243B0, 0x20035C, 0x3462524, 0xFA9BF6, 0x396D7BA, 0x2636639, 0x657CC0, 0x24D443A, 0x15417E4, 0x3106209, 0x24BCBA, 0x3B621E, 0x35C812C, 0x3F5D0BD, 0x11CBF88, 0x2036DF5, 0x2D23633, 0xF947B, 0x1128CC5, 0x3D598DE, 0x31A208, 0x22D482,
0x2142020, 0x2657645, 0x89F714, 0x29BB8C2, 0x137E4DF, 0x2433CB4, 0x1892FC, 0x36ED6B6, 0x25076D, 0xCE469, 0x25B9C5B, 0x1EC4B97, 0x18947D, 0x2932073, 0x3538FDB, 0x1D0D98F, 0x1D2A3A3, 0x346AED8, 0x44F822, 0xCCD61, 0xC5AB54, 0x1BA5722, 0x30DC4D1, 0x3207CDA, 0x3919B9D, 0x24DA67F, 0x333E397, 0x286BD80, 0x35DCD9, 0x121B5A,
0x3B1F1FA, 0xE40104, 0x6C5AC3, 0x61F3C4, 0x5BE0B, 0x2CD905C, 0x35B4EC6, 0x31D0F6A, 0x4DC688, 0x71AF39, 0x2ACF4B3, 0x3DE616B, 0x7A5FE0, 0xEBC4DF, 0x3F5BE69, 0x27F6B06, 0x16E490E, 0xA87781, 0xC4630, 0x4E26E7, 0x2221004, 0x2EFFEFC, 0x399B406, 0x1434DEC, 0x10B161F, 0x2A5D4FF, 0x9033A9, 0x2AC2E26, 0x172FE9, 0x6BE02,
0x17AF213, 0x89326D, 0x2AAE59C, 0xAAA596, 0x3FFCDD4, 0x17A4781, 0x156D629, 0x3D83591, 0x323225, 0x1BD608, 0x199E141, 0x3814855, 0x2DAD13A, 0x11A7F0C, 0x28A82C7, 0x1586D95, 0x2A1E15A, 0xDBDAFF, 0x113A86, 0x4A18DC, 0x3854FD3, 0x1F8DCC, 0x1AD82F6, 0x3DF3F39, 0x3A90070, 0x2AE824E, 0x1A15943, 0xF98CB7, 0x4DC356, 0x19049C,
0x3138A89, 0x2A362D2, 0x2938A2D, 0x1273719, 0x7E25C9, 0x2C85EBF, 0x2F07942, 0x57995D, 0xF0B7D, 0x19E4B8, 0x3B6063D, 0x3986795, 0x18147B8, 0x240D37B, 0x28E4189, 0x35E8400, 0x10614A9, 0x3FCE6D2, 0x9ECC7, 0x36B440, 0x28AF1CB, 0x3AE5F2D, 0x991FB8, 0x62B977, 0x33A89BC, 0x855C20, 0x277454A, 0x3CC0027, 0x62613C, 0x29CE5E,
0x21D2B1C, 0x553D3, 0x14D562C, 0x10DCC9, 0x9360B6, 0x2310483, 0x1747DD, 0x26216A0, 0x45E2C5, 0x52856, 0x3924181, 0x7D28A, 0x3500B8C, 0x242B9F8, 0x1555A90, 0x2E37288, 0x3708F2E, 0x2DAC7AE, 0x5E610E, 0x7E5132, 0x94CB1B, 0x1730534, 0x94BADF, 0x2B02D0C, 0x36720D5, 0x25B999F, 0x3A87F6E, 0x358EE4C, 0x308DDA, 0x77D54E,
0x2C6EC3F, 0xB08A35, 0x11EF2DD, 0xAD7B0C, 0x2D864D6, 0x2B5C4B2, 0x8BB0B2, 0xED48C9, 0xE968B, 0x3B31DF, 0x2C3105D, 0x2F2CF2A, 0x13D8E36, 0x2DA5165, 0x3ED3BE8, 0x20AA7A8, 0x3C4CFB2, 0x305745B, 0x7DB085, 0x67B2E6, 0x173011D, 0x1743987, 0x22C82FC, 0x3CFCF36, 0x3864480, 0x1DF3F67, 0x2FEF99B, 0x3A2585F, 0x25D5FB, 0x654250,
0x20A88C0, 0x1256902, 0x69F82E, 0x2709E8B, 0x350AF5A, 0x17DD266, 0x205E66A, 0x20384BF, 0x3616C7, 0x3A8EC3, 0x2418E30, 0x35A4133, 0xD87D12, 0x74EDD4, 0x3645A25, 0x3BDF60F, 0x748C, 0x284B971, 0x2942F3, 0x14DEAA, 0x10C8D6F, 0x370567D, 0x27EFB38, 0x28C2FEE, 0x3D008, 0x3FB365A, 0x4DD5F2, 0x2BD0268, 0x4BF7C3, 0x4FED47,
0x1D3DAF5, 0x29AE02F, 0x15F761D, 0x3D90F4C, 0x9BB075, 0x3CB0A21, 0x8E038F, 0x11D0CE2, 0x36C49C, 0x6CF6F7, 0x20F3012, 0x35E79CD, 0x3DE04DA, 0x1BF32F9, 0x29D4B5D, 0x3B7D4D8, 0x37CB803, 0x3820B40, 0x31FB2, 0x23F890, 0x10A8262, 0x6090D5, 0x1A87FED, 0x2F8D47E, 0x3302571, 0x13646A1, 0x2A9B3C, 0x3F04CD2, 0x199B5, 0x36095E,
0xE46920, 0x3156A6, 0x1D4AFA3, 0x3B957F4, 0x2F65FFE, 0x9F6320, 0xD02D94, 0x1149E10, 0x65047A, 0x5AF6AA, 0x1CF3850, 0x318F680, 0x2BCA0EC, 0x3D9E49A, 0x2F96A6C, 0x1A4A750, 0x23D841C, 0xA49F48, 0x4E3A98, 0x9FC3F, 0x2CE1169, 0x23774F2, 0x224F0BC, 0x49565C, 0x3E75914, 0x54A6CB, 0x19C486C, 0x30A9C38, 0x4D15B3, 0x3EE5B8,
0x184D2D7, 0x1842A05, 0x26CD463, 0x342412B, 0x3A587DD, 0x1845E1B, 0x1694FD5, 0xA7269, 0x147D5A, 0x3A0F3B, 0x1410074, 0x1F28AF9, 0xF00C98, 0x33D72DE, 0xC17715, 0x39F4EBE, 0x19CDC16, 0x261C309, 0x4E203D, 0x574B88, 0x1F444A4, 0x6275B2, 0xC5EC01, 0x3C87371, 0xB1E326, 0x24E07C5, 0x112CD3D, 0x2E7B893, 0x7480DA, 0x210494,
0xAA4EAD, 0x3A566CA, 0x3DB287D, 0x22A119C, 0x19403CB, 0x1A219E, 0xB32FFB, 0x5A6410, 0x6BF387, 0x61A80E, 0x39B3824, 0x29F9AF0, 0x380A79F, 0x38DB525, 0x2BD3EA2, 0x799F60, 0x21197C3, 0x6014C7, 0x576229, 0xB826, 0xF3C61D, 0x2A5CBA3, 0x83B257, 0x11F3FD1, 0x7D0171, 0x226BB0D, 0x35B7A17, 0x35FB7, 0x47196C, 0x292714,
0x116B894, 0x1C0DB5F, 0x2420D4D, 0x177BB79, 0x2C8E835, 0x9FB2EC, 0x2307BB7, 0x22B129A, 0x4BC57F, 0x7B9FC4, 0xFC10E5, 0x2A531F9, 0x339B7A2, 0x847F13, 0x23D6F82, 0x203E88A, 0x29C380E, 0x396462A, 0x6C5D84, 0x7D5583, 0x2FB8F39, 0xCACB4, 0xB5C1D9, 0x261CAE0, 0x318ABDF, 0x22D6D6A, 0x1F9CD2A, 0x35487F4, 0x592649, 0x757C1C,
0x3EC4BC0, 0x2D3D4EB, 0x142C304, 0x239E3F3, 0x299A22D, 0x216995C, 0x34D2857, 0x27056F, 0x288A77, 0x45ECE1, 0x132128, 0x2E7741E, 0x3BC98B4, 0x3150974, 0x39D6878, 0x1C65E3F, 0x27F6624, 0x39C7D66, 0x48110E, 0x50CA6, 0x19FE375, 0x3229A54, 0x3E5D817, 0x1287041, 0x10E4E02, 0x1FEFD3, 0x26FFB90, 0x3372F5, 0x2AF48B, 0x43DC6F,
0x1CC562B, 0x1D32810, 0x13ADF59, 0x21D847B, 0x124815B, 0x1D7F2B0, 0x374FA4, 0x1377382, 0x369A7B, 0x116B23, 0x290D2B0, 0x242B600, 0xF2BA3, 0x1E4DCE4, 0x2038CDB, 0x12A1081, 0x561D59, 0x398CF35, 0x4017D5, 0x5086E8, 0x1CB8087, 0x2DF2068, 0x36BB855, 0x16A82B2, 0x27E9F5D, 0x288236E, 0x2D83566, 0xA06C64, 0x773311, 0x7126A4,
0x37ECEF8, 0x2740C25, 0x437D53, 0x7ADB0F, 0x3F6754A, 0x32DEAC3, 0x3EEDB8C, 0x12103FA, 0x3CD7D2, 0x517DB5, 0x3CE27A2, 0x385A2DA, 0x32C9A6C, 0x21F07CB, 0x19E7F17, 0x1B01FC8, 0x3347732, 0x1096ED5, 0x4A8FE, 0x280DA7, 0x16A5A53, 0x2587F71, 0x3DCBD49, 0xFF9EE9, 0x3465A1A, 0x3335C20, 0x27F1167, 0x7DDE93, 0x71DA83, 0x8A420,
0x3014D96, 0x3E3997F, 0x27A95A0, 0x2B05A30, 0x1AE26CB, 0xF7AB55, 0x1DADAD4, 0x8DCF5E, 0x5DA170, 0x41B9A3, 0x600A50, 0x3D66D0C, 0x1600CEE, 0x2220DC1, 0x16CC96F, 0x226F0FF, 0xFB2765, 0xD5114, 0x6EBFBA, 0x2F562B, 0x3D368C7, 0x24083A6, 0x23F0056, 0x3C0DA70, 0x227E238, 0x1AAA301, 0xB389FD, 0x3DB6A35, 0x2B7D80, 0x77E139,
0x3FCE43C, 0xE26585, 0x215D1A5, 0x1801CCE, 0x21B69F7, 0x2FF1AD, 0x2515950, 0x17ACD70, 0x2726C, 0x6134CC, 0xDCD1E1, 0x1ED2E10, 0x39CE727, 0xE49B73, 0x3A1377A, 0x3B7397D, 0x10C8CF1, 0x1F8533A, 0x4E965, 0x6BCDFF, 0x2489774, 0xD9784E, 0x1AB8ACC, 0x142F644, 0x2F8D9C4, 0xAD7B03, 0x26811CE, 0x34F8859, 0x4A97B, 0x448212,
0x1F5E995, 0x2AF20, 0x19380D4, 0x15354D0, 0x28D6F34, 0x2AEB868, 0x92CEB7, 0x3F977A4, 0x68AB4D, 0x613F7F, 0x8A370A, 0x2BD3680, 0x16D3D18, 0x3B14E12, 0x2688B38, 0xFD8C31, 0x3B2F1BC, 0x1068800, 0x220DCC, 0x25A828, 0x694236, 0xD99176, 0x3908941, 0x21947B7, 0x1F5D19, 0x1C76080, 0x135505E, 0x88F50A, 0xBC112, 0x41B81F,
0x2CC80C6, 0x327119, 0x372C998, 0xABB63E, 0x1F741A6, 0x23406F0, 0x2C3BC34, 0x1DB3312, 0xB101F, 0x5B4C51, 0x16EE8ED, 0x2DD1341, 0x3BF4803, 0x3FB287E, 0x7498FC, 0x16CE1E, 0x1CA1FD1, 0x627724, 0x54812, 0xE74BC, 0x346CB12, 0x32497D1, 0x11C0D4F, 0xDA1BC7, 0x90CE90, 0x1086950, 0xD156F2, 0x2DDCCFC, 0x69513D, 0x280A0B,
0xA91DEA, 0x3DBCEB1, 0x17E664C, 0xCB1953, 0x387814E, 0xECF46E, 0x212C0F0, 0x208AECB, 0x7840AD, 0x7E88D2, 0x3F8661D, 0x474A10, 0x22A2BB5, 0x1BC5CCF, 0x1804D7, 0x4EF97B, 0x105BBD0, 0x3F131C2, 0x70EB17, 0x3D0D27, 0x1EE0D71, 0x2F1611, 0x3D83DA8, 0x22BCCDD, 0x1302730, 0x22EDA1E, 0x22174F6, 0x3B04A60, 0x7BF6E3, 0x73B798,
0x642A70, 0x298CBD7, 0x1A6EC25, 0x63807E, 0x4A40F6, 0x14510DB, 0x379E27F, 0x1D9D2F8, 0x142927, 0x6AE4D3, 0x38B4B74, 0x4DB879, 0x17A63C5, 0x47494B, 0x2C6C717, 0x1AAEB72, 0xC66F14, 0x3E3CFB4, 0x40534E, 0x1A7651, 0x150CC97, 0x35B3839, 0x290E4CB, 0x35DD5D7, 0x3599C9, 0x64A327, 0xADC807, 0x39E10C6, 0x630B23, 0x5F0E19,
0x30A3BB6, 0x4BD764, 0x2C02D94, 0x1DE779D, 0x3857BFB, 0x11E1759, 0x18365FD, 0x18C5DDE, 0x19BA9D, 0x5FACBE, 0x16A3B61, 0x7AF492, 0x3A94471, 0x252D4, 0x31DC74, 0x2B37CD2, 0x3A1020F, 0x301F24A, 0x1D8909, 0x2EF1B9, 0x494FC9, 0x3175D73, 0x3B67BE, 0x236F20D, 0x1FA1843, 0x10221FB, 0x39B7D6C, 0x2D60023, 0x3F9170, 0x65B961,
0x2864B6F, 0x161EF84, 0x2BEDA05, 0x773583, 0x31E97E1, 0x1298C0A, 0xB14D21, 0x3A64B10, 0x54C4B9, 0x4390F0, 0x3C27348, 0x4A89FC, 0x138B22D, 0xBEF643, 0x308C1E5, 0x209DEE4, 0x68BB0, 0x1FE35F1, 0x7A987E, 0x1ED8C7, 0x19A3346, 0x39FD03C, 0x37B6B2A, 0x1548A8E, 0x34ED569, 0x2BFBC91, 0x39827FB, 0x2C919D1, 0xEB471, 0x726453,
0x1C5FA4B, 0x1FAC3, 0xF2B94F, 0x37E7C1, 0x2EF64ED, 0x2E2F085, 0x2CD2E7F, 0xF2C908, 0x1BF1E4, 0xA58D3, 0x3ECFC29, 0xD9BCAF, 0x25FE580, 0x324CC4, 0x32E3D1, 0x33F96C, 0x36E8731, 0x1162F8B, 0x45E46E, 0x18DE3A, 0x12A49A, 0x5710B3, 0x19796F3, 0xECBC07, 0x3187C9E, 0x2C4A53B, 0x17C08E6, 0x3D5F38B, 0x71A534, 0x438350,
0x20391DB, 0x33117FD, 0x34DA29D, 0x2B5D7B5, 0x1FE2DBB, 0x2E8C297, 0x237FB0A, 0x3552C41, 0x403363, 0x269C08, 0x38B4218, 0x1CF5FA7, 0xF93F48, 0x1454C45, 0xAAAA4E, 0x374A957, 0x32C2482, 0x3C21DBE, 0x1F48A1, 0x59FEEF, 0x3368710, 0x707C39, 0x36D2BDB, 0x35AEED3, 0x34D4FDE, 0x3BB1689, 0x39E7E99, 0x526415, 0x79BE1F, 0x394A45,
0x1FC43B3, 0x334BD13, 0x1F53EC8, 0x2DDA512, 0x23BF588, 0xB36C66, 0x3F12D70, 0x2A2916F, 0x37628D, 0x6E97F0, 0x1EDBBDD, 0x3CD9037, 0x1AC404E, 0x16365DD, 0x18333AC, 0x2537F87, 0x11AD9D1, 0x23C09A4, 0x313F48, 0x2FDC9, 0x3F833A5, 0x2D8C9EE, 0x27CE07F, 0x3D2281D, 0x105C9E7, 0x3B31E9, 0x1A3126C, 0x327FA55, 0x25AC5D, 0x788C85,
0x3B3B778, 0x2FDDD25, 0x3A9476C, 0x24B0AA0, 0xDB2776, 0x29763C3, 0x10156D9, 0xEFA3B, 0x7C4, 0x650002, 0x37C50AB, 0x18B8282, 0x6599AA, 0x2BDE5C4, 0x2D39EA1, 0xD3AC4A, 0x3A3E0, 0x354E0B8, 0x528B27, 0x55E5A7, 0x9F1039, 0x1622435, 0x202C8BA, 0x18C1D43, 0x7A015A, 0x35B28D5, 0x1652C49, 0x2331B7B, 0x199F68, 0x2687F4,
0x1EAFAEE, 0x2679D9F, 0x2C30096, 0x2F3CD33, 0x195AA16, 0x3C87E31, 0x20D3A4D, 0x20A7BB8, 0x7AEB10, 0x4E2C19, 0xA35C9D, 0x298389C, 0x21A72E3, 0x23B299B, 0x4EBA46, 0x2740A08, 0x4F0214, 0x3C3DC98, 0x3CD353, 0x44C562, 0x47523A, 0xF2E0AD, 0x2E28A3D, 0xB175B4, 0x3576D3E, 0xC61031, 0x166FF8D, 0x3C34585, 0x43A0E0, 0x5F30AA,
0x182B0AA, 0x27925E6, 0x269E9B8, 0x26ED7BB, 0x296B6F0, 0x2FE3659, 0x3486A08, 0x1163730, 0x575DB3, 0x93F89, 0x151FC84, 0x75A4F6, 0x12BDE14, 0x1BE3E4C, 0x148070C, 0x1C6D0E6, 0x3146779, 0x898CE9, 0x1230C0, 0x5DE4A1, 0x1ECE1B6, 0x359C447, 0x273E0FE, 0x39A79A3, 0x1617DB9, 0x3C164DF, 0x1284F7B, 0x3DDC568, 0x1C3ACD, 0x482BA1,
0x1EA8FD, 0x3DF322B, 0x3B4A9F2, 0x31D2B3E, 0x172FEFE, 0x2FBF78B, 0x3ADC4E9, 0x33A3AE1, 0x4E089E, 0x4B4951, 0x2C6714D, 0x1E9E3A2, 0x3EDAD1A, 0x22FDBF3, 0x14040EA, 0x2D62B49, 0x34427DF, 0x20FBD77, 0x72913E, 0x3C08A2, 0x248B346, 0x1DF44AC, 0x27D64E, 0x3A10FB9, 0x9809AF, 0x2151A78, 0x1074035, 0x35082A1, 0x7ED524, 0x25DB12,
0x1D049E0, 0x1DA882C, 0x1039FA2, 0x1771549, 0x16CCEC8, 0x27DD87, 0x3A4A2FE, 0xBF095A, 0x5A34CB, 0x2AF444, 0x2EF5A5D, 0xC240DA, 0x3ED0A30, 0x1CA0955, 0x3D9C089, 0x2BC96F5, 0x3382028, 0x299C1ED, 0xB573A, 0x425CED, 0x1E824FB, 0x5C1EB7, 0x16A30F7, 0xA48647, 0x1DA994B, 0x1533ADF, 0x1A9116D, 0x20BE939, 0x264F6F, 0x5E302E,
0x237F35, 0x1C71B75, 0x1C4BF11, 0x24B2D36, 0x2E66F51, 0x295B103, 0xB10B95, 0x3FA115E, 0x2B0AF6, 0x4D7E08, 0x4534BF, 0xBA79E9, 0x2E7B3AC, 0x290FF6D, 0x21E5210, 0x1E87667, 0x71F623, 0x109DBB, 0x73329D, 0x3435EC, 0x278B098, 0x2754041, 0x2150286, 0x3A8D45C, 0x3B7838B, 0x3DAC447, 0x1B99E4E, 0x1D0B630, 0x4F6C26, 0x109D7B,
0x2A4F6F7, 0x245BAB5, 0x32AD174, 0x2CE7595, 0x3D2AE3C, 0x2AA730, 0x2DCFCEE, 0x34BE0CE, 0x59040B, 0x5C61AE, 0x3CF83E1, 0x310E2F7, 0x850F78, 0x1208A2C, 0xF9A99, 0x333A546, 0x2E226DC, 0x14BB83D, 0x13455C, 0x5B8377, 0x1EA0DD9, 0x3D94258, 0xE9B039, 0x30816E3, 0x29A2392, 0x2CD5A34, 0x7F272, 0xA682D, 0x5EBEBD, 0x7D1A10,
0x1A46527, 0x27240B6, 0xF00890, 0x21BFD72, 0x3C626C8, 0x1CD926F, 0x175AF87, 0x79F765, 0x4127C8, 0x216739, 0x78CAEF, 0x5CF574, 0x9D41AB, 0x1149990, 0x2A0F792, 0x3AE1077, 0x66E20C, 0x1FD5C4, 0x1A2CF9, 0x38095A, 0xA3E7E7, 0x4A4822, 0x3AAE617, 0x9FAF9, 0x1639E5E, 0x1F0991, 0x3BADCD3, 0x3ED37A7, 0x6A5DD9, 0x311085,
0x66C3B5, 0x32BAC13, 0xD87884, 0xD17154, 0x288F33F, 0x31B5376, 0x34B7F21, 0x23E6424, 0x550091, 0xAA089, 0x1D3226E, 0x33850C, 0x3CCD1B9, 0x30AB98D, 0x2AFCEA2, 0x2F52AC7, 0x2ADE1DD, 0xEB6843, 0x208790, 0x3C5C37, 0x34CDE6A, 0x536294, 0x6D000F, 0x187F4FA, 0x178196C, 0x10666C9, 0x311D702, 0x18FF035, 0x4546A9, 0x43F36E,
0x2167F4, 0x1CE9617, 0x1807631, 0x289F84, 0x71B296, 0x24EEDB0, 0x30E1595, 0x206DF9F, 0x241C1F, 0x603811, 0x1AC4D52, 0xC43E0B, 0x1DADD8D, 0x23DA6FB, 0x1A38C10, 0xB17523, 0x3FEE37, 0x8055C2, 0x16601, 0x63303A, 0x3B22591, 0x3F1A7B3, 0x2B6CB96, 0x2AC06AA, 0x131DE8B, 0x126F236, 0x38862D8, 0x69A290, 0x3A10A4, 0x1CE8A5,
0x2A87928, 0x36BF79B, 0x1DD78A8, 0xF0AF85, 0x30159E, 0x6600B4, 0x3AD2DCE, 0x3ED909, 0x770B48, 0x195785, 0xB0AB2A, 0x2183F6B, 0x157B87B, 0x23D8B2D, 0x34F0444, 0x15DB019, 0x2845BBB, 0x23ABCB5, 0x620CEA, 0x3274F7, 0xF7ED5F, 0x1942722, 0x2939183, 0x39BD16C, 0x2F43D2B, 0x3B58CBA, 0x1EF02D9, 0x11CE451, 0x19CFC1, 0x5D93E4,
0x28FC597, 0x3083464, 0x602E74, 0x19CD1DF, 0x1A46D07, 0x26C2ED2, 0x86CBA9, 0x3BB315F, 0x35372B, 0x7A9EBE, 0x1A6B314, 0x110DD05, 0x36646A0, 0x878825, 0x1E58B51, 0x138045F, 0x3D3B5B, 0x9C5723, 0x35E7D9, 0x446FFD, 0x36D3E76, 0x1508738, 0x2D71EA6, 0x72122F, 0x12E6E69, 0x3FF6C16, 0x27EE5A4, 0x127633, 0x1379E7, 0x22264A,
0x37EF7B3, 0x1D764E7, 0x869A3F, 0x23196EA, 0x3333323, 0xF51C0, 0x331616, 0x24FE4BC, 0x57B0E5, 0x5534C7, 0x2FE6FE4, 0x2DD3FF2, 0x33B65FA, 0x317E3F2, 0x199C7A1, 0x653618, 0x1CE4809, 0x2CF9952, 0x6B8933, 0x2A8719, 0x200F0C, 0x21ACCD, 0x2A7B171, 0x2C8ADD4, 0x1A58346, 0x2465844, 0x340343B, 0x167F17, 0x7A36B8, 0x769737,
0x19F266, 0x24B6FF3, 0x2E9A6D4, 0x3446B49, 0x1AC1DB1, 0x3053491, 0x8C176E, 0x37F15E8, 0x177724, 0x136198, 0x1EB7176, 0x1BE386D, 0x33191D0, 0x1199FDC, 0x36504A6, 0x2B5E6B6, 0x325FF25, 0x2B7C067, 0x14E811, 0x3286FC, 0x18E10A0, 0x100DCF2, 0x1647D12, 0x23B1FB8, 0x67B3F2, 0x32A4BAE, 0x30CB7DE, 0x288298D, 0x674FA7, 0x3B2C0,
0x1E24474, 0x28F514D, 0x35DAD1C, 0xAF6CBF, 0x216B4C8, 0x33F5C67, 0x29EE28C, 0x14F66BF, 0x421FB6, 0x202AF6, 0x226953E, 0xF70479, 0x17E03E5, 0x2392070, 0x2FFC05E, 0x362B99D, 0x28F3350, 0x1D1B48C, 0x7B721F, 0x54C31, 0x30E8025, 0x2B347E3, 0x3CB8810, 0x1C061D3, 0x20C2FBE, 0x37A6161, 0x3C0B9DC, 0x3A432ED, 0x60E1E3, 0x363924,
0x23A1A6A, 0x35447F0, 0x3D7B861, 0x1E619B8, 0x1FE2180, 0x1636446, 0x11BFDE, 0x375CF83, 0x2F79C0, 0x1C64C6, 0x341469D, 0x36952A5, 0x5D5598, 0x21D13E5, 0x1E871D8, 0xC8A8F4, 0x2596E2E, 0x348F6E5, 0x5BA634, 0x744F28, 0x232DA34, 0x66EF89, 0x3A12C7C, 0x24F15BA, 0x2E8CD15, 0x2B03146, 0x1EA8E2F, 0x2683E07, 0x556F3D, 0x1564FB,
0x22B483F, 0x23B3E45, 0x3BB55BE, 0x3C4A2B2, 0x1957E97, 0x13A9AE8, 0x6BAF4, 0x16E8ABF, 0x6D3F7E, 0x3D41E8, 0x36D8328, 0xD6E91A, 0x3921792, 0x2803815, 0x98EE4F, 0x1006E96, 0x130FA60, 0x89CE33, 0x65C49B, 0x394A21, 0x3D90785, 0x3A148AC, 0x3328F7F, 0x3711E8C, 0x965715, 0x3D556DC, 0x3785624, 0x35B6F86, 0x7BC3DC, 0x435DB9,
0x3D89C27, 0x2C5189A, 0x3535B83, 0x1049EE9, 0x553D74, 0x139CBE5, 0x3DA94E0, 0xF0F986, 0x25E727, 0x65C87D, 0x2809E2E, 0x1758661, 0x29B448A, 0x22DB9C0, 0x2AFAC34, 0x2046B8F, 0x21FC25F, 0x2FE5C10, 0x7DE6B7, 0x10705F, 0x1A2D44F, 0x249C60, 0x58539B, 0x2630694, 0x70F159, 0x23029AD, 0x1BB1BAC, 0x113592C, 0x7C74F2, 0x6E1BBD,
0x7790F9, 0x1AE0DAE, 0x33B9D81, 0x39E6B9D, 0x3690937, 0x3556332, 0x31C2FAB, 0x587424, 0x5B4CCB, 0x2E6394, 0x36849F0, 0x273F2A4, 0x1E2FDA3, 0x10C7878, 0x272D4B3, 0x24FD8BB, 0x2833AEE, 0x202EF80, 0x6C419F, 0x357CEC, 0x22F11A9, 0x3C49E13, 0x1BA44E5, 0x242D76A, 0x371883A, 0x172AB66, 0xB8948, 0x964DD6, 0x7808DF, 0x6CEF23,
0x1E551FC, 0x19E3E1F, 0x2B1D9ED, 0x248F788, 0x3D36D18, 0x1CFE6F7, 0x3776C56, 0x2236E6D, 0x5A0BA1, 0x3EC235, 0x83BBE0, 0x110218E, 0x308F50B, 0x16DB95C, 0x18CDA4F, 0x77FA29, 0x1DA19, 0x2C7457D, 0x21581A, 0x3E7BBA, 0x30D0635, 0x38CBEB8, 0x1B00F4F, 0x299D2AE, 0x3B5226, 0x3390AA1, 0x22A56F8, 0x2954EB8, 0x4174F0, 0x6BDF6B,
0x38545E2, 0x3A69F65, 0x7E0918, 0x294F632, 0x1E538A3, 0x2316148, 0x283C3BB, 0x3A05B65, 0x2A9E37, 0x64C587, 0x3E97E93, 0x22FA665, 0x280A291, 0xE2D121, 0x2E0E777, 0x35F6131, 0x11AFBEC, 0xE2A1DD, 0x13728E, 0xFCA8C, 0x1D067FA, 0xC2F728, 0x12F5603, 0x2E9B6E0, 0x102ECC4, 0x37F9AB3, 0x190B88B, 0xB8B496, 0x40F2F7, 0x5068AA,
0x22923FF, 0x1460A84, 0x2A10B02, 0x32E7FD5, 0x1965A8, 0x25188F5, 0x228401B, 0x829066, 0x67C39E, 0x2E735C, 0x3DC2DA4, 0xE1608F, 0x3B8FF2F, 0x3384C3A, 0x12BD0C6, 0x28E85E4, 0x182A1EE, 0x2CF9400, 0x5BF6ED, 0x932CE, 0x38CBFB8, 0x35060DE, 0x33E2814, 0x29E590B, 0x37BD793, 0x16CAA, 0x30062FA, 0x29344FC, 0x4E89E2, 0x542A38,
0x663E55, 0x24119FE, 0x3F66AB, 0x3A0BD96, 0xE4A1B, 0x1FC4060, 0x7DECCF, 0x1A6854A, 0x5158BF, 0x323470, 0x27480D5, 0x36C7013, 0x1BBDA44, 0x230E4BA, 0x2FFE5C9, 0xA79DBE, 0x84D37D, 0x22C38ED, 0x409A90, 0x73F2C4, 0x37E2DFF, 0xFD49A7, 0x14182E4, 0x3F8A6B9, 0x11D9DDF, 0x1F29F47, 0x49E18, 0x3F9D54E, 0x1534F9, 0x7A2C0B,
0x30FE7FB, 0x1DF4AC3, 0x1346CA, 0x25C3092, 0x350E19E, 0x36855C8, 0x2F60606, 0x33A3B79, 0x56381E, 0x8ACAE, 0xA0D20B, 0x5A0C95, 0x3C69C6B, 0x1A9F962, 0x2C3AC44, 0x116E549, 0x2364B92, 0xDCC56C, 0x623EDC, 0x20A9BA, 0x1F5B55D, 0x3724573, 0x161CE02, 0x25B6487, 0x2FF5376, 0x29EB56A, 0x10BAFBC, 0x16DCAE2, 0x23C44C, 0x321781,
0x350A489, 0x12CE34D, 0x6D0BD4, 0x2972313, 0x70B2CC, 0x2EAC504, 0x1BA16E3, 0x9ACDE1, 0x31F0B3, 0x1AF8EA, 0x3AFD62F, 0x8EFB27, 0x31789B5, 0x3599DAA, 0x3F9A69B, 0x2FD46E6, 0x341091E, 0x2E7FA69, 0x21E399, 0x476212, 0x4168DE, 0x1D81C29, 0x3ED94A, 0x1B0C9E7, 0x1408074, 0x2D6D016, 0x2F9979A, 0x2401F13, 0x5F7570, 0x656548,
0x35219C9, 0x1C1198B, 0x2D6F4DE, 0x98E6D4, 0x10F7BAF, 0x28110D2, 0x27CB88, 0x3CEF8F7, 0x2517, 0xF3C0D, 0x3374EEF, 0x157A00C, 0x984AF8, 0x3C7078D, 0x20AA355, 0x2614CB9, 0x10C63FE, 0x3D77A2D, 0x83474, 0x20C359, 0xD05268, 0xD911A6, 0x2520A8D, 0xDB08BA, 0x35D7D31, 0x7E1CA3, 0x1C6D1AD, 0x1C019E9, 0x421657, 0x4D072F,
0x1555E9E, 0x44817, 0xB1BC40, 0x2042CB6, 0x1697902, 0x9C1629, 0x2BDF30B, 0x3006C1B, 0x4C8C7E, 0x25110B, 0x39EAFF7, 0xB62068, 0x2701AFC, 0x1CE9A85, 0x34E81BF, 0x382176B, 0x547D4A, 0x372276C, 0x6CC36F, 0x47DCB0, 0x3670F41, 0x133C1A, 0x37FAB0B, 0x3245E4C, 0x417FE9, 0x3B2B5F8, 0x24EE5CF, 0xF8264A, 0x625B5C, 0x6BD35F,
0x1409E5E, 0x2A23CB6, 0x14E46A1, 0x172028C, 0x276703B, 0x2DC3DB4, 0x3F458D8, 0x1FBD22C, 0x7981D8, 0x67356A, 0x301ADAF, 0x69727E, 0x248DBA7, 0x189C667, 0x2BD6618, 0x1453D, 0x153940C, 0x1058F3B, 0x7A1E9, 0x25D67E, 0x3A80738, 0x1643F04, 0x1EEDA98, 0x2B5B4E0, 0x3C7418E, 0x334DAD9, 0x132D772, 0x32FAAED, 0x3112BE, 0x116112,
0x166FF07, 0x497808, 0x8EAF8B, 0x3419B01, 0x36DE326, 0x27009BE, 0x20890, 0x2CE73A1, 0x4D7803, 0x40DB29, 0x5602A5, 0x3A18394, 0x397ACE0, 0xB13065, 0x340D6E5, 0x30BC51C, 0x3CAC6E6, 0x108FB89, 0x52F227, 0x6D8BCA, 0x3B07F72, 0x20B17CC, 0x1833FA3, 0x3A9ED66, 0xC6D6E, 0x172966A, 0xE5C3E5, 0x2C00583, 0x7DD66C, 0x75FCF8,
0x32402B5, 0x31B6631, 0x317A8E6, 0x777CB2, 0x2DD5BED, 0x176AADC, 0x1097FB, 0xF8EABA, 0xDC360, 0x205EE9, 0x3C98498, 0x1599FE, 0x32D38CC, 0xE6F06D, 0x72C7A2, 0x14278E3, 0x1DDB55A, 0x294FEB2, 0x7D12EB, 0x4600F0, 0x2F14304, 0x2A35739, 0x274E8DC, 0x1E5889C, 0x3742104, 0x30C4D56, 0x82C8B6, 0x22C4457, 0x7B54E0, 0x27A117,
0x1C35E1B, 0x34FFFEA, 0x2CE7586, 0x173BDFE, 0x14866CF, 0x21D1AF4, 0x346A767, 0x2CAEA4C, 0x5CB96F, 0x4A73D7, 0xBE86AC, 0x72F372, 0x11AD2A0, 0x344279D, 0x373444B, 0x15B6AB5, 0x15E7A3, 0x2872FA6, 0x2769B5, 0x2BCCFB, 0x332F6A3, 0xD90DD9, 0x98454, 0x1571823, 0x1C53C00, 0x2E13215, 0x1F68558, 0x2CA1E36, 0x7ACB28, 0x7731D1,
0x1A0649, 0x19CE66F, 0x8AFD7B, 0x2F86D6B, 0x467321, 0x19D876, 0x28603B2, 0x316ECD2, 0x592B5F, 0x484C1C, 0x330B06C, 0x187AEFF, 0x1331096, 0x2095912, 0x22CE08E, 0x16A6D90, 0x17C3934, 0x331FF11, 0x276606, 0x3A835F, 0x806D69, 0x1F1E74F, 0x20074B3, 0x3AA7F40, 0x3839F4D, 0x11CBF2D, 0x3B32957, 0x25D1888, 0x41D767, 0x74D01B,
0x29F80CC, 0x862CD9, 0x38A02B4, 0x195680F, 0x3231E43, 0xC79E8D, 0x29A40A6, 0x2D6343A, 0x5CDF66, 0x388E38, 0xFF83A2, 0x12109EA, 0x2AA9212, 0x1B736A4, 0x3E745D9, 0x3541042, 0x3B935B2, 0x335D752, 0x14D6FB, 0x1BB7B9, 0x39B8505, 0x1A6473A, 0x301412C, 0x1E4F58D, 0x367A3A3, 0x2034678, 0x220ACC4, 0x1F88080, 0x35A3C5, 0x66ABCA,
0x1300021, 0x369095D, 0x3FC76B, 0x1B4E6E3, 0x26844A9, 0xCC8203, 0xD95134, 0x1591746, 0x18F290, 0x36490F, 0x2D3562E, 0x253E40B, 0x135CDA2, 0x2C395B5, 0x87E941, 0x37BB93D, 0x2811561, 0x3AA5814, 0x7F8108, 0x3F413, 0x37267EF, 0x2060A49, 0x1C5EDDF, 0xC6370D, 0x3305984, 0x239E725, 0x29297B9, 0x3E39E68, 0x6C5D9D, 0x274397,
0x95BAB0, 0x32D6733, 0x1E596D0, 0x3EDA819, 0x26E3BDA, 0x2859451, 0x14171E1, 0x3D0090A, 0x6292B2, 0x37C560, 0x18F1423, 0x25C75E1, 0x395BAE0, 0x17FE1CE, 0x2EE1151, 0x396A927, 0x21BC308, 0x1CD28CA, 0x634519, 0x178CDC, 0x244AACC, 0x1071219, 0x2B6EC90, 0x3072320, 0x2DDCFF7, 0x26DC161, 0x2837F65, 0x130428F, 0x76518A, 0x584D4,
0x1E9ACAB, 0x21C0E6D, 0x1CA0A82, 0xF41672, 0xEBD272, 0x2BC6032, 0x270D145, 0x2E1F749, 0x1298E4, 0x6072C8, 0xD36F26, 0x39546A7, 0x328AACA, 0x1F50E82, 0x2A2A36E, 0x1D29F15, 0x2D6AB93, 0x3C3B598, 0x2A977C, 0x4D60A, 0x26E4402, 0xF07A40, 0x3042004, 0xDE5C9E, 0x117134B, 0x20ACBD1, 0x2688562, 0x3C2D5FC, 0x7677EF, 0x32C0DA,
0x366DC2E, 0x339DC8A, 0xFF46E0, 0x12168FC, 0x30ECBC8, 0x3E8BF35, 0x21B1399, 0x217C891, 0x6CD072, 0x6E7E92, 0x1943BAE, 0x3242FE, 0x674E82, 0x4E6281, 0x12A6A9D, 0xBE9F91, 0x25FBB61, 0x32C4C4B, 0x43FA51, 0x4A100D, 0x110A692, 0x12D578F, 0x3F61AFA, 0x2A62C6A, 0x3937BE2, 0xA7EDB5, 0xA4DA35, 0xF86C37, 0x614FD8, 0x46F1D2,
0x2813F36, 0x28F5C7F, 0x1319C97, 0x1940EB8, 0xE918BF, 0xCE5FF5, 0x1E04A7, 0x139085E, 0x68BC89, 0x2B6E0F, 0x65895B, 0x158A0A0, 0x33651FB, 0x2BCCB7C, 0x36C9A97, 0x3713EBB, 0x198A03F, 0x2B00AE, 0x7AA90B, 0x6A748D, 0x1E83397, 0x2B32881, 0x26D7586, 0x615486, 0x1B69DF7, 0x20C9E75, 0x11FD921, 0x9DA9D1, 0x169349, 0x20791E,
0x2C70BC9, 0x13711DE, 0x3100F88, 0x35725C7, 0x21D3D25, 0x232C45D, 0x146399B, 0x1A8C2F8, 0xBF079, 0x66BD2C, 0x29E53CA, 0x20F1D39, 0x20A796C, 0xE1627A, 0x8A2607, 0x3C5C3FD, 0x139C770, 0x487CDF, 0x30ED41, 0x5A881A, 0x987A4F, 0xF33EA0, 0x24E50DA, 0x3ADD420, 0x2E2D27B, 0x2BBDC6F, 0x1784EBE, 0x14BD17B, 0x321FE4, 0x2166D,
0xCD2FC9, 0x3C676C9, 0x9A86C3, 0x37D81B, 0x3D6D150, 0x38C4FD2, 0x24F56F0, 0x1AC02B5, 0x1141BE, 0x4059E2, 0x2C6B505, 0x1DF0CFC, 0x26D0273, 0x35DF47D, 0x38E5070, 0x2FF1875, 0x3A2B3D1, 0x1DCD458, 0x68F020, 0x66EB37, 0x17A32AE, 0x99ECDB, 0x120AAD0, 0x3FC3368, 0x3935860, 0x38E7A07, 0x11F6884, 0x5DEB8A, 0x21175F, 0x26AE5F,
0x120EAF7, 0x1FA2A7A, 0x1C3A94, 0x3C4DFC, 0x3F81A9A, 0x2C6249E, 0x3AE9CE0, 0x1473F47, 0x2581FE, 0x7FE93C, 0x3777F7E, 0x1D77A2E, 0x136F729, 0x2D3E182, 0x23FF2D7, 0xEC8543, 0x2E9D3A0, 0x84BC8D, 0x562DA2, 0x3A0F65, 0x270EBC6, 0x26A8576, 0xB8FFA8, 0x5621EA, 0x1E11F84, 0x29A3808, 0xB1A8A2, 0x14F0FF8, 0x452432, 0x46F49D,
0x1B0D388, 0x3654AD9, 0x24F3B7F, 0x33558DC, 0x2D2BBCC, 0x115F1F2, 0x1DBBC2, 0x25C00D3, 0x4DB312, 0x4C6446, 0x1D7130C, 0x3AF1B1A, 0xB36FF5, 0x252DCB, 0x2AE534D, 0x8F7736, 0x340F6C, 0x1AA7C96, 0x619895, 0x1F6CA4, 0x259772A, 0x14F6D6F, 0x2C0F58, 0x38D032, 0x23A8CBA, 0x466709, 0xF635AF, 0x1FB953A, 0x24E5A2, 0x287BA2,
0x2D607F0, 0x3F6BA4A, 0x832208, 0x3026182, 0x3171873, 0xC0AF35, 0x94277, 0xC3BDDF, 0x44FD58, 0x6CF531, 0xB48CE4, 0x298D33D, 0x459E80, 0x95A0FB, 0xB48AA8, 0x21A659A, 0x1DD6C36, 0x1F441, 0x649F4C, 0x651479, 0x36E16DA, 0x162458A, 0x121D047, 0x7C4D10, 0xBF2155, 0x1368C23, 0x191D501, 0x18CFDF7, 0x411D03, 0x4F36B7,
0x27A89A4, 0x1ED45, 0x3770293, 0x3ED22C4, 0x1542A98, 0x2B95C3, 0x369BAB3, 0x332BE9C, 0x55D8A5, 0x5C7785, 0x16AFB79, 0x327B6F, 0xDA7F48, 0x3D20C6F, 0x669A64, 0x82D755, 0x3C43A50, 0x1F5C7C6, 0x1F405E, 0x2BC1B6, 0x17777D0, 0x1C9DB39, 0x2C573FB, 0x6DD5C0, 0x13268EA, 0x3621081, 0x3560366, 0x32D4BDE, 0x517370, 0x234D84,
0x1DAE49C, 0x35E7008, 0x313EF77, 0x83DAB5, 0x1E1970, 0x3345B07, 0x1091D79, 0x314612F, 0x3BA8D8, 0x275CD5, 0xD3796A, 0x12B5F4D, 0x260CE22, 0x1523F82, 0x2F35EB, 0x3CC9946, 0x37F7847, 0x2D43C98, 0x1B3A42, 0x119917, 0x20A3F82, 0x150372A, 0x37A5568, 0x8C04E0, 0x3FF4622, 0x36A7C79, 0x28E9831, 0x2546379, 0x6A552E, 0x18083B,
0x13B5455, 0x2356271, 0x2DD375F, 0x129CCD7, 0x33455F, 0x31D2599, 0x269C3FE, 0x3D810C3, 0x523EEA, 0x3BB011, 0x1D6EA7C, 0x1EBF07, 0x10D32E8, 0x14105D5, 0x17801EC, 0x383046C, 0x2583FAD, 0x3EFE748, 0x69B632, 0x1470B, 0x9BC5CC, 0x1E83A38, 0x147D301, 0x28EA450, 0x28EDE95, 0x127B09C, 0xE3CD7B, 0xF9D044, 0x1C1246, 0x44DAAF,
0x2FCD10, 0x341E833, 0x11C5EDB, 0x2B1B208, 0x114B0E5, 0x672528, 0x1AC9B56, 0x267507D, 0x518AB4, 0x2247FA, 0xF327A2, 0xE86B3, 0xC31970, 0x3BF5A53, 0x21B4ABE, 0xE4E35D, 0x4ADDF, 0x42FF98, 0x3AC74E, 0x7C382E, 0x2B8461C, 0xF7B7B1, 0x38E0A65, 0x3C59E21, 0x1E1AF37, 0x643AC8, 0x714D8C, 0x1AAC693, 0x4D4748, 0x5AE1BB,
0x29DF80, 0xE09807, 0x2C09642, 0x3890BC7, 0x3FA163E, 0x3D2B6E1, 0x218A9E4, 0xC2ABB3, 0x623126, 0x7BF961, 0xBFF70A, 0x14D30AB, 0x17A7A84, 0x1C3B916, 0x126EEDC, 0x353E70C, 0x8CEE53, 0x1B22044, 0x66B548, 0x79B000, 0x1710C1F, 0x1E3779C, 0x9E4B24, 0x257B9DA, 0x3539435, 0x2DCDFC9, 0x14606A7, 0x1B2E773, 0xC7BF1, 0x44871C,
0x9A046B, 0x75FB94, 0x202EFCB, 0x2CC8E1A, 0xCD90D1, 0xF35DEF, 0x2631174, 0x14D5598, 0x5445C5, 0x5B0D23, 0x33A7973, 0x2D77504, 0x37AA096, 0x3D7A1FE, 0x2147BE1, 0x169448A, 0x31386EF, 0x32529F7, 0x10658E, 0x55F5D3, 0xAD6BA2, 0x10AEBC, 0xF9C18B, 0x359485C, 0x2A31A9A, 0x3598C4B, 0x38FE783, 0x3F22E7E, 0x36C0A7, 0x1D031D,
0x113889E, 0x3785FD7, 0x870410, 0x316E281, 0x2477E36, 0xADA124, 0x3B879A9, 0x3C60623, 0x774B77, 0x5A6C0D, 0x272D7BE, 0x3E4A4D0, 0x3735517, 0x32F8D7, 0x2966F4A, 0x175210, 0x3FED9AE, 0xB7C14B, 0x38100F, 0x4489BE, 0x326899F, 0x2795EAA, 0x288900E, 0x3EFEE00, 0x3928A03, 0x253289D, 0x283FB04, 0x2713B3C, 0x5AE4A0, 0x34917E,
0x20CBBB3, 0x1EE34E1, 0x24D9D31, 0x8FD9BC, 0x71D64B, 0x1E48A7, 0x1418CD3, 0x37D23C5, 0x25C098, 0x3A960A, 0x1E440BB, 0xB25496, 0x3CE19A5, 0x1066C3D, 0x15E6659, 0x65B8EF, 0x2FDBA02, 0x28C2E79, 0x577A0F, 0x44176, 0x2013E6F, 0x38EFFD7, 0x21C177C, 0x3A45EE5, 0x1CE77A9, 0x2C7F309, 0x120EAA5, 0x16FFA50, 0x77D0B2, 0x8F1E5,
0xD613C8, 0x2E4F9FA, 0x1058A6E, 0x267DA8F, 0x149FFC2, 0x33B5388, 0xD735A2, 0x3374C03, 0x140F2E, 0x7ABC8E, 0x1D23EAF, 0x20EC5C4, 0x2B48D41, 0x12998ED, 0x2C7CD3D, 0x2EC9564, 0x24DDAC, 0x22BF87A, 0x75E73F, 0x511ADE, 0x1ABCA89, 0xD28C8, 0x17F938, 0x299962E, 0x1F6CBB0, 0x1EC800, 0x1CEC328, 0x1872459, 0x2838DE, 0x48AABA,
0x304D4E2, 0x1F69D03, 0x1D672AD, 0x38738D0, 0x3ECA222, 0x2E10A1C, 0x3033A16, 0x43A393, 0x106DD3, 0x1651B2, 0x133E136, 0x7B02AF, 0xA6979C, 0x32E95A5, 0x27B9473, 0x1B4809D, 0x11F724D, 0x45E049, 0x58C02F, 0x435C25, 0xCD9315, 0x331F32D, 0x25E68FC, 0x83D401, 0x3DDBD56, 0xB5D239, 0x29908AB, 0x8E08CB, 0x2F02B0, 0xAB833,
0xBB60DB, 0xD5282E, 0xF46FEC, 0x39B9685, 0x2EC2A7B, 0x224BAC5, 0x280F1BA, 0x77710A, 0x2342C2, 0x5B9A42, 0x143E056, 0x3DB1CED, 0x1419051, 0x2FDC7B4, 0x14E6018, 0x9794F8, 0x1F02125, 0x3056AC4, 0x6D7C37, 0x5150DB, 0x33A7FBF, 0x25B7911, 0x14286CD, 0x16FFA5B, 0x70500B, 0x3F3E500, 0x30F4C91, 0x156EC4C, 0x140BE5, 0x77CEA5,
0x3A973C6, 0x323C9C3, 0x786A75, 0x3DD1D92, 0x28D32AB, 0x17CD9E0, 0x260C525, 0x2EB9066, 0x3897AC, 0x2E5ECB, 0xF12433, 0x36BB343, 0xBA9592, 0xDB00F0, 0x269C43E, 0xE4317D, 0x392023, 0x14D207, 0x3A515A, 0x44CEBD, 0x21B0D76, 0x8A0E83, 0x2195B0, 0x8FE408, 0x1BE6890, 0x2A732E2, 0x3F2E402, 0x353BF4D, 0x2F8513, 0x3828C2,
0x1A8527D, 0x7DC5EF, 0x1F593E2, 0x2F1C917, 0x151DBF1, 0x15EC7D7, 0xAE5958, 0xA832DA, 0x59EBB4, 0x191B68, 0x19F9ADD, 0x3002DD1, 0x45CBEB, 0xCBE729, 0x3DCF893, 0x18B5769, 0x2EEACBA, 0x123E163, 0x239B6C, 0xC1405, 0x3741EA5, 0x7436FE, 0x2B7F773, 0xD6897E, 0x25676C7, 0xAE0C51, 0x2E78B86, 0x3B2DF74, 0x3B39C4, 0x690D8F,
0xDA10C2, 0x3C955A4, 0xA9863B, 0x207DC6E, 0x3832D78, 0x239835A, 0x2CC4D33, 0x3B592B9, 0x4F2A84, 0x457F88, 0x1479985, 0x275EB11, 0x3ADC70C, 0xBA5E16, 0x2B32C27, 0x2D36A5F, 0x215A6A, 0x266E0DF, 0x4AE918, 0x619CB1, 0x1484E40, 0x12B039D, 0x39644AE, 0x9DE70B, 0xAF00E7, 0x61A49A, 0x3A1FF6F, 0x381FD24, 0x3B5831, 0x3D4B81,
0x222B55C, 0x1DD7637, 0x66C3E8, 0x34A3946, 0x14E2AA1, 0x24B26B4, 0x46D0BF, 0x2403796, 0x265C1B, 0x3D2DA7, 0x1F21D63, 0x32F8C92, 0x1961AD, 0x79D4E4, 0x2E1899B, 0x3834B67, 0x3679A87, 0x874261, 0x4CE62B, 0x390B78, 0x3F1FC2F, 0x11E7533, 0x3DF1CF0, 0xECD7F8, 0x3AF91AD, 0x3FD7AEE, 0x2A14529, 0x249E3DB, 0x78C636, 0x7FBD19,
0x23D77DE, 0x39A981C, 0x2AEFD0D, 0x192877F, 0x3F6A41A, 0x3F9ADA2, 0x3C62E5A, 0x214C302, 0x1B27FD, 0x36EFC0, 0x1830854, 0x364FDCF, 0x2218A97, 0xCC9316, 0x26CB5BD, 0x265F452, 0x17995B, 0xDD88E1, 0x23D7C9, 0x36627F, 0x6D5EA4, 0x3B009B, 0x3D4E497, 0x36D4A95, 0x3022564, 0x194BF90, 0x21A8644, 0x3247E2E, 0x17C7CC, 0x15192D,
0x39EC6E2, 0xF1824, 0x3E8F069, 0x1A8EE63, 0x2ECC80B, 0x1E22FEE, 0x3AA65DC, 0x15806E0, 0x48FCA8, 0x46A8C7, 0x895FCC, 0x5971D7, 0xF100AA, 0x3BF9E3A, 0x1CE22CB, 0xB2C1A, 0x27010C1, 0x20EAD6A, 0x1D1DFF, 0x79C6A0, 0x1BF2518, 0x25F470E, 0x31EF297, 0x10B273E, 0xA02379, 0x459C9C, 0x22626CF, 0x33A46C5, 0x241935, 0x4481C2,
0x226DECA, 0xFA4F26, 0x137A87A, 0x331AF36, 0x21016B0, 0xFBDE36, 0x3BB8342, 0x25C65D9, 0x26EE3C, 0x4D1470, 0x31FEF52, 0x64CF3B, 0x1CA9C1B, 0x392C12A, 0x2EC1E05, 0x77332A, 0x1A688FC, 0x2A46E51, 0xF75FB, 0xB6373, 0x3D088AF, 0x3C51433, 0x3CAF082, 0x1AC2528, 0x17471A8, 0x1C7A0E, 0x16B3900, 0x8F09A3, 0x586B0D, 0x1752A1,
0x1770EA1, 0xCC6B3F, 0x30AA4ED, 0x2C14974, 0x2B43643, 0x2FC36BF, 0x346DC7B, 0x3BB0EB7, 0x536CB9, 0x1F4DCF, 0xBF57F0, 0x3AD7A1, 0x5A774, 0x3681A1C, 0x144928A, 0x203DBBC, 0x2A8828D, 0x20A0F07, 0x1336C9, 0x5E3347, 0x18FDAF2, 0x1695613, 0x25DCCF4, 0x1C30535, 0x3867F19, 0x256F799, 0x1E85EE, 0x10BA114, 0x789AF5, 0x794523,
0x226A018, 0xB30929, 0xBE4D9E, 0x39B77C9, 0x1FBE6C1, 0x755720, 0x723E73, 0x78F951, 0x11BEDA, 0x7706E9, 0x26C9059, 0x1D2BB07, 0xE074E, 0x10D5698, 0x424446, 0x29E2602, 0x1B0D9E3, 0x75E721, 0x7E0191, 0x68BAE0, 0x5DF659, 0x3266467, 0x32F3FCA, 0x3C1E305, 0x933F21, 0x2103CE0, 0x1ABAD5F, 0x36D45C2, 0x2F7EE, 0x39B4F,
0x1A4AE1B, 0x210DED9, 0x383FB18, 0x139039A, 0x695D5D, 0x3213EA6, 0x54A9DE, 0x10DCEF6, 0x33D37A, 0x1F1D39, 0x359FD14, 0x376F4A1, 0x1662DBB, 0x2A43862, 0x2283F63, 0x1DAEE39, 0x370EB94, 0x3AF662A, 0x57922A, 0x27F3DB, 0x3804B3, 0x32F3225, 0x1E77670, 0x7DB492, 0x2D73181, 0x197F88E, 0x30644B8, 0x267370A, 0x511D72, 0x560099,
0x3D82FE4, 0x3F13BD7, 0x37E5DED, 0x3EB3F0E, 0x2226DA6, 0xE180B5, 0x2EE98F6, 0x13D9BC, 0x76F746, 0x4A31EB, 0x3CFE28F, 0x3400317, 0x39CF579, 0x25E7F9C, 0x20B18AC, 0x3C9FA91, 0x6F0C30, 0x1C68271, 0x19AA73, 0x6795CE, 0x33700BA, 0x1EDCA71, 0x1554064, 0x316AF22, 0x114D93D, 0x25EF450, 0x3C22C7F, 0x2122F7E, 0x3850EA, 0x1BE5DB,
0x3CF082B, 0x3E0ED6D, 0x19F4FD3, 0xB04A97, 0x3C45776, 0x3ED16F2, 0x1B12092, 0x1C8AD77, 0x673B6E, 0x6EE6, 0x28D0C62, 0x1D3AB58, 0x284F051, 0x1AD54EA, 0x26E4B47, 0x3CFD0BC, 0x1E68DE3, 0x1E79137, 0x405648, 0x21761C, 0x31050FB, 0xDBF2AD, 0xDBB4FA, 0x113129A, 0x1D366F, 0x39C487, 0x4C4B74, 0xADB5B8, 0x2E67DF, 0x784496,
0x378B65F, 0x38C2E2B, 0x2D59D74, 0x29599F5, 0x1DF0E07, 0x1E2A320, 0x2A8F4B0, 0x365B769, 0x336262, 0x4F668D, 0x7B8470, 0x32206B6, 0x1559E57, 0x14C8451, 0x2BB1E21, 0x3A39AEE, 0x16CBBE0, 0x1FFB835, 0x306190, 0x1F8737, 0x3B1A0C7, 0xA3990F, 0x16314A8, 0x3FB1175, 0x3FFDDAC, 0x22C2FDF, 0x3813C35, 0x3DE78AB, 0x6E3C4C, 0x4B5340,
0x3D1F332, 0x1057F1E, 0x1F22DEC, 0xDB439B, 0x2E1A053, 0x33D7423, 0x112B8D7, 0x2799172, 0x552927, 0x5AC40E, 0x5E46C7, 0x3AF4F35, 0x3DEDFE1, 0x2B3D88A, 0x3150848, 0x27BB891, 0x19CDBBF, 0x273CE59, 0x74BDA8, 0x14BCEF, 0x331B9B3, 0x662ED0, 0x4D5365, 0xA6A384, 0x259F9AA, 0x37A71A8, 0x2864A57, 0x3E7B110, 0x27E855, 0x3BBC43,
0x1DE5341, 0x1F25A48, 0x2A2C72C, 0x201F690, 0x15498BF, 0x2552E3D, 0x201A34D, 0x738BBF, 0x343277, 0x1BB6EE, 0x3D3AFFC, 0x22F8939, 0x26F7B42, 0x37F5E55, 0x17A808D, 0x211FDA8, 0x14A66A4, 0x39A1A18, 0x290F1C, 0x1BF7AA, 0x860765, 0x439B94, 0x1B6BE6F, 0x1BEAADF, 0xA0B2AB, 0xBDA874, 0xBC3AD6, 0x1DD42EE, 0x7BEF6E, 0x17EA8,
0x39C9A7C, 0x1F1606, 0x3FAC888, 0x2A52B18, 0x3A13F8D, 0x176768A, 0x34A21EC, 0xFE2E98, 0x35CEC0, 0x747055, 0x1EAC410, 0x1A2FE94, 0x253E472, 0x23643CA, 0x3732378, 0x23A53F, 0x3AE0CDF, 0x22BB1A4, 0x55B22A, 0xAEC06, 0x16182EE, 0x12DF3C8, 0x1858AB, 0x35C2552, 0x1475405, 0x3521968, 0x3C6B079, 0x18657D9, 0x6A327F, 0x3F93F4,
0x170D546, 0x2B6F8B3, 0xEF28A2, 0x2C04C99, 0x13C2498, 0x369FF42, 0xC4A5AD, 0x212DA8, 0x2716B9, 0x76F29B, 0x2216249, 0x2B8F954, 0x21D2488, 0x199A5FA, 0x2CFD8E2, 0xCE50EE, 0x34E9B06, 0xA3FB03, 0x4F2FA1, 0x37C33E, 0x2FD1DD1, 0x1E5C7E6, 0x10678AE, 0x1AAEF0, 0xDAA7D0, 0x32A95EC, 0x10A66E5, 0x18183B5, 0x1F04D, 0x3A24C6,
0x3960F26, 0x6D9149, 0x1D93857, 0x3098237, 0x1C3A0DB, 0x3518F3D, 0x357567E, 0x1186DCB, 0x1D5973, 0x1D80E0, 0x1C8B09C, 0x31FC2AD, 0x1373352, 0x38E21C6, 0xD5E226, 0xBD32D6, 0x28918CD, 0x2B93CA1, 0x1F03E7, 0x418588, 0x3E1AFA2, 0x1CC4A76, 0x2C1C6EB, 0x9CC88B, 0x18DC3EF, 0xB23A6B, 0x3202F7, 0x22B229, 0x799BA, 0x13859F,
0x23C5ACB, 0x6F8CC1, 0x12B3099, 0x155543C, 0x2DF6019, 0x2A751B0, 0x16F42EF, 0x3519667, 0x459FA5, 0x9E5FA, 0x32958A3, 0x210F594, 0x245BBDD, 0x140F8D9, 0x24316B3, 0x23B98E1, 0x306024E, 0x1412289, 0x4AAAA5, 0x620EF5, 0xB8ECBC, 0x19CFEA9, 0x2258F23, 0xE581BD, 0x15A5A2, 0x28B167E, 0x2C6DD03, 0x38DDDF2, 0x6AEE46, 0x13A579,
0xBB8DE3, 0x2379578, 0x364BD87, 0x18D51B7, 0xEAB45A, 0x8609B1, 0x690918, 0x29F3B35, 0x53068A, 0x7BF38, 0x1282DE1, 0x15F6D45, 0x31DC0C7, 0xF7480A, 0xFFCF84, 0x2ECDFB8, 0x18E67DE, 0x15CD034, 0x402AED, 0x3702E2, 0x39B97C8, 0x13017DB, 0x2CB62E5, 0x3D89E0C, 0xC51B8D, 0x1D92D86, 0x34A942C, 0x37B157E, 0x617526, 0x2F35EE,
0x117973B, 0x39F63D, 0x2DA524D, 0x31B6A3B, 0x309AEEC, 0x3746B82, 0x1D382EB, 0x18C4A0C, 0x7A111A, 0x421707, 0x1DA88D9, 0x13D6CBB, 0x1B447CF, 0x26D8B42, 0x28875D3, 0x28FD982, 0x2CD83CA, 0xBDBB7C, 0x7BAEBC, 0x10F17A, 0x3F40626, 0x3960895, 0x3BE90D4, 0x159E209, 0xE34FE3, 0x355C618, 0x197046, 0x293D318, 0x731CA3, 0x7F906,
0x2657142, 0x104B69A, 0x3673443, 0x77C17, 0x21CE361, 0xDBA3E, 0x114B761, 0x2F133F3, 0x2B5F5D, 0x533723, 0x1BBCCB5, 0x1E13646, 0xE12BE8, 0x369420E, 0xDFD820, 0x29680F8, 0x1056576, 0x15CE965, 0x4E67E9, 0x6887A0, 0x2CE7343, 0x8074C1, 0x37477D6, 0xBE1526, 0x16C8E93, 0xB60BA, 0x3CA3B3E, 0x529069, 0xD4076, 0x5EB2A3,
0x276B27E, 0xD7DA95, 0x3DB49E9, 0x7E69D4, 0x114E49F, 0x2B5CC17, 0x102B354, 0x2247DE7, 0x15F7CA, 0x3BEDBE, 0x3F74FF, 0x260C4A9, 0x10EF3AE, 0x2531F82, 0x1A4C5B6, 0x3151DE2, 0x3CEA8CC, 0x3F20482, 0x88B1A, 0xA0770, 0x7C1937, 0x28CC49, 0x2DD5E83, 0x38FB6CB, 0x1C88F09, 0x122C051, 0x300FBF6, 0x3B16B14, 0x34B797, 0x66DB34,
0x3DC8CBF, 0x310F89D, 0x37834F4, 0x11B465D, 0x18CF95F, 0x9C51FD, 0x3204860, 0x1600FE0, 0x797897, 0x533A50, 0x9FD211, 0x8CF5A5, 0x3C70243, 0x30FFE93, 0x1D82B60, 0x21F4BF, 0x1E6BD72, 0x2984C1A, 0x4A7C34, 0x6949F4, 0x27ABCDC, 0x10895E0, 0x1325271, 0x191BDAF, 0x23C4D81, 0x145A9DE, 0xCC59A1, 0x1126951, 0x419A5E, 0x497CC1,
0x3E126F2, 0x178127D, 0x2CC491F, 0x36D34F, 0x347769E, 0x380C52E, 0x8CE59F, 0x2239EE4, 0x323C83, 0x42A0E1, 0x2E34E7E, 0x308FA4D, 0x2C04711, 0x1C28975, 0x34AA3A6, 0xDC8942, 0x22AA682, 0x632F27, 0x79F416, 0x2BB286, 0x606819, 0x2D0AF10, 0x391AEC1, 0x2E4B431, 0x2982741, 0x14126DB, 0x14BECB3, 0x2B8187A, 0x2790C, 0x32AA96,
0xD98EAA, 0x9AFF20, 0x19C0324, 0x1FE3BBE, 0x3136137, 0x2E37B39, 0x1943029, 0x128106E, 0x4D1DFE, 0x4836AC, 0xA02B8, 0x16B7E7B, 0x3041DAA, 0x3C985ED, 0x3A37F37, 0x1A5D498, 0x28919EC, 0x2536E16, 0xD063F, 0x65EF11, 0x28FFCB6, 0x9B15B, 0x3897574, 0x3A0ACEC, 0x83D1F, 0xBFC6B7, 0x3D25167, 0x17BC7F3, 0x228EE6, 0x713B18,
0x360C298, 0x30816C2, 0x11A3C7F, 0x1AB643F, 0x1614552, 0x2E58A8, 0x1740946, 0x24A12F4, 0x2B7BA6, 0x7BF924, 0x34C2D10, 0x3DEA766, 0x2315B91, 0x2DE741E, 0x540300, 0x151F15F, 0x2DDFE01, 0x31EE6C2, 0x171473, 0x66AC67, 0x2D2F652, 0x315C19C, 0x32856ED, 0x16B88DD, 0x217B34B, 0x3EF2C51, 0x349A1F5, 0x19D97EF, 0x13C63D, 0xE543C,
0x156FB5E, 0x394E113, 0x3203EBC, 0x2EA8990, 0x22B8668, 0x19CF89E, 0xECF665, 0x873C59, 0x1E2E9E, 0x322ADD, 0x3619F8E, 0x17E092F, 0x1B899CC, 0x3BCA0DF, 0x7F0F9E, 0x101179A, 0x22DE485, 0x164A42D, 0x723BFC, 0x1AA61C, 0x2499CD3, 0x1A8676B, 0x16B95DA, 0x133E866, 0x20DA995, 0x285FB86, 0x1A96873, 0x7C4200, 0x2C3D6E, 0x4961A2,
0x39D997B, 0x14CFCC5, 0x38612B7, 0x1D19DC2, 0x2725828, 0x105BE69, 0x2A5F9F3, 0x1DCE518, 0xC84BD, 0x4EC8CD, 0x15FB5C6, 0x139C03D, 0x1A06F32, 0x1D8A3F7, 0x3269A48, 0x18429B9, 0x3E3DE97, 0x387C67C, 0x6ADE87, 0x3BDE0E, 0x17C0CA1, 0x38A57E5, 0x2323EC4, 0x17D0D6D, 0x29BF4EF, 0xF9CC8F, 0x3E341F7, 0x2A186EF, 0x769BF8, 0x79987A,
0xB02022, 0x33EB70B, 0x3155C81, 0x187BC02, 0x29D17F6, 0x3B39F0C, 0x644471, 0x1446FED, 0x119BD8, 0x4317F0, 0x4D608E, 0x5F1775, 0xAE513A, 0x2FD1C42, 0x29CB36A, 0x19AD37D, 0x18B68CD, 0x7841D0, 0x1C1A38, 0x383575, 0x307A3FE, 0x154F23E, 0x2C3212E, 0x3F4832D, 0x13A004A, 0x15B715F, 0x3EF1F7C, 0x110AC54, 0x63758B, 0x1FF11C,
0x3937186, 0x352A761, 0xDDFC6F, 0x39F3EB8, 0x38F8171, 0x1502321, 0x20AE0D4, 0x9F5C90, 0x615EFE, 0x7AF024, 0x2CC559F, 0xBFDAC9, 0x11B91FC, 0x362A96E, 0x1D75865, 0x623C95, 0x2805D96, 0x32DA264, 0x65A1D8, 0x1E887, 0x26BCC3D, 0xC16B35, 0x23BA311, 0x2068D20, 0x108FF1F, 0x8CDD2B, 0x13CAE8E, 0xFAAFDC, 0x40CE5E, 0x51625D,
0x105739, 0x1E8F732, 0x1DC2884, 0x13246F4, 0x18A044D, 0x2460FBE, 0x12808A5, 0x32C4D61, 0x7F1DE7, 0x204FBA, 0x22E3CF8, 0x141909, 0x1E425F5, 0x2D1E467, 0x311497D, 0x1ECFFDF, 0x16464D2, 0x394913F, 0x541AD5, 0x354926, 0x2E994B0, 0x2371E7, 0x6C2838, 0x26F950C, 0x3D1629, 0x1CD818, 0x1A74E9B, 0x177C6A2, 0x2B9A9A, 0x3645C6,
0x1E3877B, 0x146B6B0, 0x1183D11, 0x397DDA3, 0x126EDF0, 0x14E60C2, 0x3714B43, 0x36A9F17, 0x7EA384, 0x1F6E62, 0x32343EE, 0x2731517, 0x9ACCE, 0x1746DAD, 0x372CF8B, 0xD60BD4, 0x321D9F4, 0xA1F11C, 0x2B7183, 0x4DDB3D, 0x263ECE2, 0x109B455, 0x76E900, 0x326341F, 0x45F103, 0x37F58CB, 0x2835964, 0xA28AF2, 0x4E737F, 0x34A351 };
#endif

73
FourQ_ARM_NEON/README.txt Normal file
Просмотреть файл

@ -0,0 +1,73 @@
FourQlib v3.0 (C Edition)
=========================
Optimized implementation for 32-bit ARM using NEON
==================================================
1. CONTENTS:
--------
The "FourQ_ARM_NEON" folder contains:
makefile - Makefile for compilation on ARM processors with NEON support using
GNU GCC or clang on Linux.
*.c, *.h - Library and header files. Public API for ECC scalar multiplication, key
exchange and signatures is located in FourQ_api.h
ARM/ - Folder with library files implementing low-level arithmetic for ARM.
tests/ - Test files.
README.txt - This readme file.
2. SUPPORTED PLATFORMS:
-------------------
This implementation is supported on 32-bit ARM platforms that contain the SIMD engine called NEON and run Linux.
For example, platforms with a NEON engine include many cores with the ARMv7 architecture. The implementation
has been optimized for ARM Cortex-A7, Cortex-A8, Cortex-A9 and Cortex-A15 based processors.
See instructions below to choose an implementation option and compile on one of the supported platforms.
3. COMPLEMENTARY CRYPTO FUNCTIONS:
------------------------------
Random values are generated with /dev/urandom.
The library includes an implementation of SHA-512 which is used by default by SchnorrQ signatures.
Users can experiment with different options by replacing functions in the folders "random" and "sha512" and
applying the corresponding changes to the settings in FourQ.h.
4. INSTRUCTIONS TO BUILD THE LIBRARY AND EXECUTE THE TESTS WITH GNU GCC OR CLANG:
---------------------------------------------------------------------------
To compile on Linux using the GNU GCC compiler or the clang compiler, execute the following command from the
command prompt:
make CC=[gcc/clang] USE_ENDO=[TRUE/FALSE] EXTENDED_SET=[TRUE/FALSE] INTERLEAVE=[TRUE/FALSE]
MIX_ARM_NEON=[TRUE/FALSE]
After compilation, run fp_tests, ecc_tests or crypto_tests.
By default GNU GCC is used, as well as endomorphisms and extended settings.
There are two special optimizations that can be exploited. INTERLEAVE improves performance on some platforms
by interleaving load/store instructions with other non-memory instructions. This optimization is recommended
for Cortex-A7, Cortex-A8 and Cortex-A9. MIX_ARM_NEON improves performance on some platforms by mixing ARM and
NEON instructions. This optimization is recommended for Cortex-A7, Cortex-A9 and Cortex-A15.
By default, INTERLEAVE is turned off and MIX_ARM_NEON is turned on.
For example, to compile using GNU GCC with the efficient endomorphisms on an ARM Cortex-A15 device, execute:
make
As another example, to compile using clang with the efficient endomorphisms on an ARM Cortex-A8 device,
execute:
make CC=clang INTERLEAVE=TRUE MIX_ARM_NEON=FALSE
By default EXTENDED_SET is enabled, which sets the following compilation flags: -fwrapv -fomit-frame-pointer
-funroll-loops. To disable this, use EXTENDED_SET=FALSE.
Users are encouraged to experiment with the different flag options.

Просмотреть файл

@ -0,0 +1,177 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: crypto utility functions
************************************************************************************/
#include "FourQ_internal.h"
#include "FourQ_params.h"
#include <string.h>
static digit_t mask4000 = (digit_t)1 << (sizeof(digit_t)*8 - 2);
static digit_t mask7fff = (digit_t)(-1) >> 1;
bool is_zero_ct(digit_t* a, unsigned int nwords)
{ // Check if multiprecision element is zero
digit_t x;
unsigned int i;
x = a[0];
for (i = 1; i < nwords; i++) {
x |= a[i];
}
return (bool)(1 ^ ((x | (0-x)) >> (RADIX-1)));
}
void encode(point_t P, unsigned char* Pencoded)
{ // Encode point P
// SECURITY NOTE: this function does not run in constant time.
digit_t temp1 = (P->x[1][NWORDS_FIELD-1] & mask4000) << 1;
digit_t temp2 = (P->x[0][NWORDS_FIELD-1] & mask4000) << 1;
memmove(Pencoded, P->y, 32);
if (is_zero_ct((digit_t*)P->x, NWORDS_FIELD) == true) {
((digit_t*)Pencoded)[2*NWORDS_FIELD-1] |= temp1;
} else {
((digit_t*)Pencoded)[2*NWORDS_FIELD-1] |= temp2;
}
}
ECCRYPTO_STATUS decode(const unsigned char* Pencoded, point_t P)
{ // Decode point P
// SECURITY NOTE: this function does not run in constant time.
velm_t r, t, t0, t1, t2, t3, t4, VPx0, VPx1;
v2elm_t u, v, u2, v2, one = {0};
digit_t sign_dec;
vpoint_extproj_t R;
vpoint_t VP;
unsigned int i, sign;
one[0] = 1;
memmove((unsigned char*)P->y, Pencoded, 32); // Decoding y-coordinate and sign
sign = (unsigned int)(Pencoded[31] >> 7);
P->y[1][NWORDS_FIELD-1] &= mask7fff;
from_std_to_ext(P->y, VP->y);
v2sqr1271(VP->y, u2);
v2mul1271(u2, (uint32_t*)&PARAMETER_d, v2);
v2sub1271(u2, one, u2);
v2add1271(v2, one, v2);
from_v2_to_v(u2, &u[0], &u[VWORDS_FIELD]);
from_v2_to_v(v2, &v[0], &v[VWORDS_FIELD]);
vsqr1271(&v[0], t0); // t0 = v0^2
vsqr1271(&v[VWORDS_FIELD], t1); // t1 = v1^2
vadd1271(t0, t1, t0); // t0 = t0+t1
vmul1271(&u[0], &v[0], t1); // t1 = u0*v0
vmul1271(&u[VWORDS_FIELD], &v[VWORDS_FIELD], t2); // t2 = u1*v1
vadd1271(t1, t2, t1); // t1 = t1+t2
vmul1271(&u[VWORDS_FIELD], &v[0], t2); // t2 = u1*v0
vmul1271(&u[0], &v[VWORDS_FIELD], t3); // t3 = u0*v1
vsub1271(t2, t3, t2); // t2 = t2-t3
vsqr1271(t1, t3); // t3 = t1^2
vsqr1271(t2, t4); // t4 = t2^2
vadd1271(t3, t4, t3); // t3 = t3+t4
for (i = 0; i < 125; i++) { // t3 = t3^(2^125)
vsqr1271(t3, t3);
}
vadd1271(t1, t3, t); // t = t1+t3
vmod1271(t, t);
if (is_zero_ct(t, VWORDS_FIELD) == true) {
vsub1271(t1, t3, t); // t = t1-t3
}
vadd1271(t, t, t); // t = 2*t
vsqr1271(t0, t3); // t3 = t0^2
vmul1271(t0, t3, t3); // t3 = t3*t0
vmul1271(t, t3, t3); // t3 = t3*t
vexp1251(t3, r); // r = t3^(2^125-1)
vmul1271(t0, r, t3); // t3 = t0*r
vmul1271(t, t3, VPx0); // x0 = t*t3
vsqr1271(VPx0, t1);
vmul1271(t0, t1, t1); // t1 = t0*x0^2
vdiv1271(VPx0); // x0 = x0/2
vmul1271(t2, t3, VPx1); // x1 = t3*t2
vsub1271(t, t1, t);
vmod1271(t, t);
if (is_zero_ct(t, VWORDS_FIELD) == false) { // If t != t1 then swap x0 and x1
memmove((unsigned char*)t0, (unsigned char*)VPx0, 20);
memmove((unsigned char*)VPx0, (unsigned char*)VPx1, 20);
memmove((unsigned char*)VPx1, t0, 20);
}
from_v_to_v2(VPx0, VPx1, VP->x);
v2mod1271(VP->x, VP->x);
if (is_zero_ct(VP->x, VWORDS_FIELD) == true) {
sign_dec = VP->x[2*VWORDS_FIELD-1] >> 22;
} else {
sign_dec = VP->x[2*VWORDS_FIELD-2] >> 22;
}
if (sign != (unsigned int)sign_dec) { // If sign of x-coordinate decoded != input sign bit, then negate x-coordinate
v2neg1271(VP->x);
}
v2mod1271(VP->x, R->x);
v2mod1271(VP->y, R->y);
if (ecc_point_validate(R) == false) {
v2neg1271_felm(R->x);
if (ecc_point_validate(R) == false) { // Final point validation
return ECCRYPTO_ERROR;
}
}
v2mod1271(R->x, R->x);
from_ext_to_std(R->x, P->x);
from_ext_to_std(R->y, P->y);
return ECCRYPTO_SUCCESS;
}
void to_Montgomery(const digit_t* ma, digit_t* c)
{ // Converting to Montgomery representation
Montgomery_multiply_mod_order(ma, (digit_t*)&Montgomery_Rprime, c);
}
void from_Montgomery(const digit_t* a, digit_t* mc)
{ // Converting from Montgomery to standard representation
digit_t one[NWORDS_ORDER] = {0};
one[0] = 1;
Montgomery_multiply_mod_order(a, one, mc);
}
const char* FourQ_get_error_message(ECCRYPTO_STATUS Status)
{ // Output error/success message for a given ECCRYPTO_STATUS
struct error_mapping {
unsigned int index;
char* string;
} mapping[ECCRYPTO_STATUS_TYPE_SIZE] = {
{ECCRYPTO_ERROR, ECCRYPTO_MSG_ERROR},
{ECCRYPTO_SUCCESS, ECCRYPTO_MSG_SUCCESS},
{ECCRYPTO_ERROR_DURING_TEST, ECCRYPTO_MSG_ERROR_DURING_TEST},
{ECCRYPTO_ERROR_UNKNOWN, ECCRYPTO_MSG_ERROR_UNKNOWN},
{ECCRYPTO_ERROR_NOT_IMPLEMENTED, ECCRYPTO_MSG_ERROR_NOT_IMPLEMENTED},
{ECCRYPTO_ERROR_NO_MEMORY, ECCRYPTO_MSG_ERROR_NO_MEMORY},
{ECCRYPTO_ERROR_INVALID_PARAMETER, ECCRYPTO_MSG_ERROR_INVALID_PARAMETER},
{ECCRYPTO_ERROR_SHARED_KEY, ECCRYPTO_MSG_ERROR_SHARED_KEY},
{ECCRYPTO_ERROR_SIGNATURE_VERIFICATION, ECCRYPTO_MSG_ERROR_SIGNATURE_VERIFICATION},
};
if (Status >= ECCRYPTO_STATUS_TYPE_SIZE || mapping[Status].string == NULL) {
return "Unrecognized ECCRYPTO_STATUS";
} else {
return mapping[Status].string;
}
};

1117
FourQ_ARM_NEON/eccp2.c Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,159 @@
/****************************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
*
* Abstract: ECC operations over GF(p^2) without exploiting endomorphisms
*
* This code is based on the papers:
* [1] "FourQ: four-dimensional decompositions on a Q-curve over the Mersenne prime"
* by Craig Costello and Patrick Longa, ASIACRYPT2015 (http://eprint.iacr.org/2015/565).
* [2] "FourQNEON: Faster Elliptic Curve Scalar Multiplications on ARM Processors"
* by Patrick Longa, SAC2016 (http://eprint.iacr.org/2016/645).
******************************************************************************************/
#include "FourQ_internal.h"
#if (USE_ENDO == false)
/***********************************************/
/********** CURVE/SCALAR FUNCTIONS ***********/
void fixed_window_recode(uint64_t* scalar, unsigned int* digits, unsigned int* sign_masks)
{ // Converting scalar to the fixed window representation used by the variable-base scalar multiplication
// Inputs: scalar in [0, order-1], where the order of FourQ's subgroup is 246 bits.
// Outputs: "digits" array with (t_VARBASE+1) nonzero entries. Each entry is in the range [0, 7], corresponding to one entry in the precomputed table.
// where t_VARBASE+1 = ((bitlength(order)+w-1)/(w-1))+1 represents the fixed length of the recoded scalar using window width w.
// The value of w is fixed to W_VARBASE = 5, which corresponds to a precomputed table with 2^(W_VARBASE-2) = 8 entries (see FourQ.h)
// used by the variable base scalar multiplication ecc_mul().
// "sign_masks" array with (t_VARBASE+1) entries storing the signs for their corresponding digits in "digits".
// Notation: if the corresponding digit > 0 then sign_mask = 0xFF...FF, else if digit < 0 then sign_mask = 0.
unsigned int val1, val2, i, j;
uint64_t res, borrow;
int64_t temp;
val1 = (1 << W_VARBASE) - 1;
val2 = (1 << (W_VARBASE-1));
for (i = 0; i < t_VARBASE; i++)
{
temp = (scalar[0] & val1) - val2; // ki = (k mod 2^w)/2^(w-1)
sign_masks[i] = ~((unsigned int)(temp >> (RADIX64-1)));
digits[i] = ((sign_masks[i] & (unsigned int)(temp ^ -temp)) ^ (unsigned int)-temp) >> 1;
res = scalar[0] - temp; // k = (k - ki) / 2^(w-1)
borrow = ((temp >> (RADIX64-1)) - 1) & (uint64_t)is_digit_lessthan_ct((digit_t)scalar[0], (digit_t)temp);
scalar[0] = res;
for (j = 1; j < NWORDS64_ORDER; j++)
{
res = scalar[j];
scalar[j] = res - borrow;
borrow = (uint64_t)is_digit_lessthan_ct((digit_t)res, (digit_t)borrow);
}
for (j = 0; j < (NWORDS64_ORDER-1); j++) {
SHIFTR(scalar[j+1], scalar[j], (W_VARBASE-1), scalar[j], RADIX64);
}
scalar[NWORDS64_ORDER-1] = scalar[NWORDS64_ORDER-1] >> (W_VARBASE-1);
}
sign_masks[t_VARBASE] = ~((unsigned int)(scalar[0] >> (RADIX64-1)));
digits[t_VARBASE] = ((sign_masks[t_VARBASE] & (unsigned int)(scalar[0] ^ (0-scalar[0]))) ^ (unsigned int)(0-scalar[0])) >> 1; // kt = k (t_VARBASE+1 digits)
}
void ecc_precomp(vpoint_extproj_t P, vpoint_extproj_precomp_t *T)
{ // Generation of the precomputation table used by the variable-base scalar multiplication ecc_mul().
// Input: P = (X1,Y1,Z1,Ta,Tb), where T1 = Ta*Tb, corresponding to (X1:Y1:Z1:T1) in extended twisted Edwards coordinates.
// Output: table T containing NPOINTS_VARBASE points: P, 3P, 5P, ... , (2*NPOINTS_VARBASE-1)P. NPOINTS_VARBASE is fixed to 8 (see FourQ.h).
// Precomputed points use the representation (X+Y,Y-X,2Z,2dT) corresponding to (X:Y:Z:T) in extended twisted Edwards coordinates.
vpoint_extproj_precomp_t P2;
vpoint_extproj_t Q;
unsigned int i;
// Generating P2 = 2(X1,Y1,Z1,T1a,T1b) = (XP2+YP2,Y2P-X2P,ZP2,TP2) and T[0] = P = (X1+Y1,Y1-X1,2*Z1,2*d*T1)
ecccopy(P, Q);
R1_to_R2(P, T[0]);
eccdouble(Q);
R1_to_R3(Q, P2);
for (i = 1; i < NPOINTS_VARBASE; i++) {
// T[i] = 2P+T[i-1] = (2*i+1)P = (XP2+YP2,Y2P-X2P,ZP2,TP2) + (X_(2*i-1)+Y_(2*i-1), Y_(2*i-1)-X_(2*i-1), 2Z_(2*i-1), 2T_(2*i-1)) = (X_(2*i+1)+Y_(2*i+1), Y_(2*i+1)-X_(2*i+1), 2Z_(2*i+1), 2dT_(2*i+1))
eccadd_core(P2, T[i-1], Q);
R1_to_R2(Q, T[i]);
}
}
void cofactor_clearing(vpoint_extproj_t P)
{ // Co-factor clearing
// Input: P = (X1,Y1,Z1,Ta,Tb), where T1 = Ta*Tb, corresponding to (X1:Y1:Z1:T1) in extended twisted Edwards coordinates
// Output: P = 392*P = (Xfinal,Yfinal,Zfinal,Tafinal,Tbfinal), where Tfinal = Tafinal*Tbfinal,
// corresponding to (Xfinal:Yfinal:Zfinal:Tfinal) in extended twisted Edwards coordinates
vpoint_extproj_precomp_t Q;
R1_to_R2(P, Q); // Converting from (X,Y,Z,Ta,Tb) to (X+Y,Y-X,2Z,2dT)
eccdouble(P); // P = 2*P using representations (X,Y,Z,Ta,Tb) <- 2*(X,Y,Z)
eccadd(Q, P); // P = P+Q using representations (X,Y,Z,Ta,Tb) <- (X,Y,Z,Ta,Tb) + (X+Y,Y-X,2Z,2dT)
eccdouble(P);
eccdouble(P);
eccdouble(P);
eccdouble(P);
eccadd(Q, P);
eccdouble(P);
eccdouble(P);
eccdouble(P);
}
bool ecc_mul(point_t P, digit_t* k, point_t Q, bool clear_cofactor)
{ // Scalar multiplication Q = k*P
// Inputs: scalar "k" in [0, 2^256-1],
// point P = (x,y) in affine coordinates,
// clear_cofactor = 1 (TRUE) or 0 (FALSE) whether cofactor clearing is required or not, respectively.
// Output: Q = k*P in affine coordinates (x,y).
// This function performs point validation and (if selected) cofactor clearing.
vpoint_t A;
vpoint_extproj_t R;
vpoint_extproj_precomp_t S, Table[NPOINTS_VARBASE];
unsigned int digits[t_VARBASE+1] = {0}, sign_masks[t_VARBASE+1] = {0};
digit_t k_odd[NWORDS_ORDER];
int i;
point_setup(P, R); // Convert to representation (X,Y,1,Ta,Tb)
if (ecc_point_validate(R) == false) { // Check if point lies on the curve
return false;
}
if (clear_cofactor == true) {
cofactor_clearing(R);
}
modulo_order(k, k_odd); // k_odd = k mod (order)
conversion_to_odd(k_odd, k_odd); // Converting scalar to odd using the prime subgroup order
ecc_precomp(R, Table); // Precomputation of points T[0],...,T[npoints-1]
fixed_window_recode((uint64_t*)k_odd, digits, sign_masks); // Scalar recoding
table_lookup_1x8(Table, S, digits[t_VARBASE], sign_masks[t_VARBASE]);
R2_to_R4(S, R); // Conversion to representation (2X,2Y,2Z)
for (i = (t_VARBASE-1); i >= 0; i--)
{
eccdouble(R);
table_lookup_1x8(Table, S, digits[i], sign_masks[i]); // Extract point in (X+Y,Y-X,2Z,2dT) representation
eccdouble(R);
eccdouble(R);
eccdouble(R); // P = 2*P using representations (X,Y,Z,Ta,Tb) <- 2*(X,Y,Z)
eccadd(S, R); // P = P+S using representations (X,Y,Z,Ta,Tb) <- (X,Y,Z,Ta,Tb) + (X+Y,Y-X,2Z,2dT)
}
eccnorm(R, A); // Conversion to affine coordinates (x,y) and modular correction.
from_ext_to_std(A->x, Q->x);
from_ext_to_std(A->y, Q->y);
return true;
}
#endif

181
FourQ_ARM_NEON/kex.c Normal file
Просмотреть файл

@ -0,0 +1,181 @@
/********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: Diffie-Hellman key exchange based on FourQ
* option 1: co-factor ecdh using compressed 32-byte public keys,
* (see https://datatracker.ietf.org/doc/draft-ladd-cfrg-4q/).
* option 2: co-factor ecdh using uncompressed, 64-byte public keys.
*********************************************************************************/
#include "FourQ_internal.h"
#include "FourQ_params.h"
#include "../random/random.h"
#include <string.h>
static __inline bool is_neutral_point(point_t P)
{ // Is P the neutral point (0,1)?
// SECURITY NOTE: this function does not run in constant time (input point P is assumed to be public).
if (is_zero_ct((digit_t*)P->x, 2*NWORDS_FIELD) && is_zero_ct(&((digit_t*)P->y)[1], 2*NWORDS_FIELD-1) && is_digit_zero_ct(P->y[0][0] - 1)) {
return true;
}
return false;
}
/*************** ECDH USING COMPRESSED, 32-BYTE PUBLIC KEYS ***************/
ECCRYPTO_STATUS CompressedPublicKeyGeneration(const unsigned char* SecretKey, unsigned char* PublicKey)
{ // Compressed public key generation for key exchange
// It produces a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator).
// Input: 32-byte SecretKey
// Output: 32-byte PublicKey
point_t P;
ecc_mul_fixed((digit_t*)SecretKey, P); // Compute public key
encode(P, PublicKey); // Encode public key
return ECCRYPTO_SUCCESS;
}
ECCRYPTO_STATUS CompressedKeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey)
{ // Keypair generation for key exchange. Public key is compressed to 32 bytes
// It produces a private key SecretKey and a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator).
// Outputs: 32-byte SecretKey and 32-byte PublicKey
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretKey, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = CompressedPublicKeyGeneration(SecretKey, PublicKey);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretKey, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 256/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS CompressedSecretAgreement(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret)
{ // Secret agreement computation for key exchange using a compressed, 32-byte public key
// The output is the y-coordinate of SecretKey*A, where A is the decoding of the public key PublicKey.
// Inputs: 32-byte SecretKey and 32-byte PublicKey
// Output: 32-byte SharedSecret
point_t A;
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
if ((PublicKey[15] & 0x80) != 0) { // Is bit128(PublicKey) = 0?
Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
goto cleanup;
}
Status = decode(PublicKey, A); // Also verifies that A is on the curve. If it is not, it fails
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = ecc_mul(A, (digit_t*)SecretKey, A, true);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
if (is_neutral_point(A)) { // Is output = neutral point (0,1)?
Status = ECCRYPTO_ERROR_SHARED_KEY;
goto cleanup;
}
memmove(SharedSecret, (unsigned char*)A->y, 32);
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SharedSecret, 256/(sizeof(unsigned int)*8));
return Status;
}
/*************** ECDH USING UNCOMPRESSED PUBLIC KEYS ***************/
ECCRYPTO_STATUS PublicKeyGeneration(const unsigned char* SecretKey, unsigned char* PublicKey)
{ // Public key generation for key exchange
// It produces the public key PublicKey = SecretKey*G, where G is the generator.
// Input: 32-byte SecretKey
// Output: 64-byte PublicKey
ecc_mul_fixed((digit_t*)SecretKey, (point_affine*)PublicKey); // Compute public key
return ECCRYPTO_SUCCESS;
}
ECCRYPTO_STATUS KeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey)
{ // Keypair generation for key exchange
// It produces a private key SecretKey and computes the public key PublicKey = SecretKey*G, where G is the generator.
// Outputs: 32-byte SecretKey and 64-byte PublicKey
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretKey, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = PublicKeyGeneration(SecretKey, PublicKey);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretKey, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 512/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS SecretAgreement(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret)
{ // Secret agreement computation for key exchange
// The output is the y-coordinate of SecretKey*PublicKey.
// Inputs: 32-byte SecretKey and 64-byte PublicKey
// Output: 32-byte SharedSecret
point_t A;
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
if (((PublicKey[15] & 0x80) != 0) || ((PublicKey[31] & 0x80) != 0) || ((PublicKey[47] & 0x80) != 0) || ((PublicKey[63] & 0x80) != 0)) { // Are PublicKey_x[i] and PublicKey_y[i] < 2^127?
Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
goto cleanup;
}
Status = ecc_mul((point_affine*)PublicKey, (digit_t*)SecretKey, A, true); // Also verifies that PublicKey is a point on the curve. If it is not, it fails
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
if (is_neutral_point(A)) { // Is output = neutral point (0,1)?
Status = ECCRYPTO_ERROR_SHARED_KEY;
goto cleanup;
}
memmove(SharedSecret, (unsigned char*)A->y, 32);
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SharedSecret, 256/(sizeof(unsigned int)*8));
return Status;
}

95
FourQ_ARM_NEON/makefile Normal file
Просмотреть файл

@ -0,0 +1,95 @@
#### Makefile for compilation using GNU GCC or clang on ARM-based processors with NEON support ####
OPT=-O3 # Optimization option by default
CC=gcc
ifeq "$(CC)" "gcc"
COMPILER=gcc
else ifeq "$(CC)" "clang"
COMPILER=clang
endif
ADDITIONAL_SETTINGS=-fwrapv -fomit-frame-pointer -funroll-loops
ifeq "$(EXTENDED_SET)" "FALSE"
ADDITIONAL_SETTINGS=
endif
USE_ENDOMORPHISMS=-D USE_ENDO
ifeq "$(USE_ENDO)" "FALSE"
USE_ENDOMORPHISMS=
endif
INLINING_SETTINGS=
ifeq "$(CC)" "gcc"
INLINING_SETTINGS=-finline-functions -finline-limit=300
endif
ifeq "$(INTERLEAVE)" "TRUE"
USE_INTERLEAVING=-D _INTERLEAVE_
endif
USE_ARM_NEON_MIX=-D _MIX_ARM_NEON_
ifeq "$(MIX_ARM_NEON)" "FALSE"
USE_ARM_NEON_MIX=
endif
CFLAGS=-c $(OPT) $(ADDITIONAL_SETTINGS) -D _ARM_ -D __LINUX__ -mfloat-abi=hard -mfpu=neon $(USE_ENDOMORPHISMS) $(USE_INTERLEAVING) $(USE_ARM_NEON_MIX) $(INLINING_SETTINGS)
LDFLAGS=
OBJECTS=eccp2.o fp2_1271_NEON.o eccp2_no_endo.o crypto_util.o schnorrq.o kex.o sha512.o random.o
OBJECTS_ECC_TEST=ecc_tests.o test_extras.o $(OBJECTS)
OBJECTS_FP_TEST=$(OBJECTS) fp_tests.o test_extras.o
OBJECTS_CRYPTO_TEST=crypto_tests.o $(OBJECTS) test_extras.o
OBJECTS_ALL=$(OBJECTS) $(OBJECTS_ECC_TEST) $(OBJECTS_FP_TEST) $(OBJECTS_CRYPTO_TEST)
all: crypto_test ecc_test fp_test
crypto_test: $(OBJECTS_CRYPTO_TEST)
$(CC) -o crypto_test $(OBJECTS_CRYPTO_TEST) -lrt
ecc_test: $(OBJECTS_ECC_TEST)
$(CC) -o ecc_test $(OBJECTS_ECC_TEST) -lrt
fp_test: $(OBJECTS_FP_TEST)
$(CC) -o fp_test $(OBJECTS_FP_TEST) -lrt
eccp2.o: eccp2.c
$(CC) $(CFLAGS) eccp2.c
eccp2_no_endo.o: eccp2_no_endo.c
$(CC) $(CFLAGS) eccp2_no_endo.c
fp2_1271_NEON.o: ARM/fp2_1271_NEON.c
$(CC) $(CFLAGS) ARM/fp2_1271_NEON.c
schnorrq.o: schnorrq.c
$(CC) $(CFLAGS) schnorrq.c
kex.o: kex.c
$(CC) $(CFLAGS) kex.c
crypto_util.o: crypto_util.c
$(CC) $(CFLAGS) crypto_util.c
sha512.o: ../sha512/sha512.c
$(CC) $(CFLAGS) ../sha512/sha512.c
random.o: ../random/random.c
$(CC) $(CFLAGS) ../random/random.c
test_extras.o: tests/test_extras.c
$(CC) $(CFLAGS) tests/test_extras.c
crypto_tests.o: tests/crypto_tests.c
$(CC) $(CFLAGS) tests/crypto_tests.c
ecc_tests.o: tests/ecc_tests.c
$(CC) $(CFLAGS) tests/ecc_tests.c
fp_tests.o: tests/fp_tests.c
$(CC) $(CFLAGS) tests/fp_tests.c
.PHONY: clean
clean:
rm -f crypto_test ecc_test fp_test fp2_1271_NEON.o $(OBJECTS_ALL)

190
FourQ_ARM_NEON/schnorrq.c Normal file
Просмотреть файл

@ -0,0 +1,190 @@
/**********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: digital signature SchnorrQ
*
* See "SchnorrQ: Schnorr signatures on FourQ" by Craig Costello and Patrick Longa,
* MSR Technical Report, 2016. Available at:
* https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/SchnorrQ.pdf.
***********************************************************************************/
#include "FourQ_internal.h"
#include "FourQ_params.h"
#include "../random/random.h"
#include "../sha512/sha512.h"
#include <malloc.h>
#include <string.h>
ECCRYPTO_STATUS SchnorrQ_KeyGeneration(const unsigned char* SecretKey, unsigned char* PublicKey)
{ // SchnorrQ public key generation
// It produces a public key PublicKey, which is the encoding of P = s*G, where G is the generator and
// s is the output of hashing SecretKey and taking the least significant 32 bytes of the result.
// Input: 32-byte SecretKey
// Output: 32-byte PublicKey
point_t P;
unsigned char k[64];
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
if (CryptoHashFunction(SecretKey, 32, k) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
ecc_mul_fixed((digit_t*)k, P); // Compute public key
encode(P, PublicKey); // Encode public key
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)k, 512/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 256/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS SchnorrQ_FullKeyGeneration(unsigned char* SecretKey, unsigned char* PublicKey)
{ // SchnorrQ keypair generation
// It produces a private key SecretKey and computes the public key PublicKey, which is the encoding of P = s*G,
// where G is the generator and s is the output of hashing SecretKey and taking the least significant 32 bytes of the result.
// Outputs: 32-byte SecretKey and 32-byte PublicKey
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretKey, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = SchnorrQ_KeyGeneration(SecretKey, PublicKey);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretKey, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 256/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS SchnorrQ_Sign(const unsigned char* SecretKey, const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, unsigned char* Signature)
{ // SchnorrQ signature generation
// It produces the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte SecretKey, 32-byte PublicKey, and Message of size SizeMessage in bytes
// Output: 64-byte Signature
point_t R;
unsigned char k[64], r[64], h[64], *temp = NULL;
digit_t* H = (digit_t*)h;
digit_t* S = (digit_t*)(Signature+32);
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
if (CryptoHashFunction(SecretKey, 32, k) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
temp = (unsigned char*)calloc(1, SizeMessage+64);
if (temp == NULL) {
Status = ECCRYPTO_ERROR_NO_MEMORY;
goto cleanup;
}
memmove(temp+32, k+32, 32);
memmove(temp+64, Message, SizeMessage);
if (CryptoHashFunction(temp+32, SizeMessage+32, r) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
ecc_mul_fixed((digit_t*)r, R);
encode(R, Signature); // Encode lowest 32 bytes of signature
memmove(temp, Signature, 32);
memmove(temp+32, PublicKey, 32);
if (CryptoHashFunction(temp, SizeMessage+64, h) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
modulo_order((digit_t*)r, (digit_t*)r);
modulo_order(H, H);
to_Montgomery((digit_t*)k, S); // Converting to Montgomery representation
to_Montgomery(H, H); // Converting to Montgomery representation
Montgomery_multiply_mod_order(S, H, S);
from_Montgomery(S, S); // Converting back to standard representation
subtract_mod_order((digit_t*)r, S, S);
Status = ECCRYPTO_SUCCESS;
cleanup:
if (temp != NULL)
free(temp);
clear_words((unsigned int*)k, 512/(sizeof(unsigned int)*8));
clear_words((unsigned int*)r, 512/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS SchnorrQ_Verify(const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, const unsigned char* Signature, unsigned int* valid)
{ // SchnorrQ signature verification
// It verifies the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte PublicKey, 64-byte Signature, and Message of size SizeMessage in bytes
// Output: true (valid signature) or false (invalid signature)
point_t A;
unsigned char *temp, h[64];
unsigned int i;
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
*valid = false;
temp = (unsigned char*)calloc(1, SizeMessage+64);
if (temp == NULL) {
Status = ECCRYPTO_ERROR_NO_MEMORY;
goto cleanup;
}
if (((PublicKey[15] & 0x80) != 0) || ((Signature[15] & 0x80) != 0) || (Signature[63] != 0) || ((Signature[62] & 0xC0) != 0)) { // Are bit128(PublicKey) = bit128(Signature) = 0 and Signature+32 < 2^246?
Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
goto cleanup;
}
Status = decode(PublicKey, A); // Also verifies that A is on the curve. If it is not, it fails
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
memmove(temp, Signature, 32);
memmove(temp+32, PublicKey, 32);
memmove(temp+64, Message, SizeMessage);
if (CryptoHashFunction(temp, SizeMessage+64, h) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
Status = ecc_mul_double((digit_t*)(Signature+32), A, (digit_t*)h, A);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
encode(A, (unsigned char*)A);
for (i = 0; i < NWORDS_ORDER; i++) {
if (((digit_t*)A)[i] != ((digit_t*)Signature)[i]) {
goto cleanup;
}
}
*valid = true;
cleanup:
if (temp != NULL)
free(temp);
return Status;
}

Просмотреть файл

@ -0,0 +1,657 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: testing code for FourQ's curve arithmetic
************************************************************************************/
#include "../FourQ_api.h"
#include "../FourQ_params.h"
#include "../FourQ_tables.h"
#include "test_extras.h"
#include <stdio.h>
// Benchmark and test parameters
#define BENCH_LOOPS 1000 // Number of iterations per bench
#define SHORT_BENCH_LOOPS 100 // Number of iterations per bench (for expensive operations)
#define TEST_LOOPS 1000 // Number of iterations per test
bool ecc_test()
{
bool clear_cofactor, OK = true;
unsigned int n;
int passed;
point_t A;
vpoint_t VA;
vpoint_extproj_t VP;
vpoint_extproj_precomp_t VQ;
v2elm_t t1;
uint64_t scalar[4], res_x[4], res_y[4];
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing FourQ's curve arithmetic: \n\n");
// Point doubling
passed = 1;
eccset(A);
point_setup(A, VP);
for (n=0; n<TEST_LOOPS; n++)
{
eccdouble(VP); // 2*P
}
eccnorm(VP, VA);
from_ext_to_std(VA->x, A->x);
from_ext_to_std(VA->y, A->y);
// Result
res_x[0] = 0xC9099C54855859D6; res_x[1] = 0x2C3FD8822C82270F; res_x[2] = 0xA7B3F6E2043E8E68; res_x[3] = 0x4DA5B9E83AA7A1B2;
res_y[0] = 0x3EE089F0EB49AA14; res_y[1] = 0x2001EB3A57688396; res_y[2] = 0x1FEE5617A7E954CD; res_y[3] = 0x0FFDB0D761421F50;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Point doubling tests .................................................................... PASSED");
else { printf(" Point doubling tests ... FAILED"); printf("\n"); return false; }
printf("\n");
// Point addition
eccset(A);
point_setup(A, VP);
for (n=0; n<TEST_LOOPS; n++)
{
v2mul1271((uint32_t*)&PARAMETER_d, VP->ta, t1); // d*ta
v2add1271(t1, t1, t1); // 2*d*ta
v2mul1271(t1, VP->tb, VQ->t2); // 2*d*t
v2add1271(VP->x, VP->y, VQ->xy); // x+y
v2sub1271(VP->y, VP->x, VQ->yx); // y-x
v2copy1271(VP->z, VQ->z2);
v2add1271(VQ->z2, VQ->z2, VQ->z2); // 2*z
eccadd(VQ, VP); // 2*P
}
eccnorm(VP, VA);
from_ext_to_std(VA->x, A->x);
from_ext_to_std(VA->y, A->y);
// Result
res_x[0] = 0xC9099C54855859D6; res_x[1] = 0x2C3FD8822C82270F; res_x[2] = 0xA7B3F6E2043E8E68; res_x[3] = 0x4DA5B9E83AA7A1B2;
res_y[0] = 0x3EE089F0EB49AA14; res_y[1] = 0x2001EB3A57688396; res_y[2] = 0x1FEE5617A7E954CD; res_y[3] = 0x0FFDB0D761421F50;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
eccset(A);
point_setup(A, VP);
v2mul1271((uint32_t*)&PARAMETER_d, VP->x, t1); // d*x
v2add1271(t1, t1, t1); // 2*d*x
v2mul1271(t1, VP->y, VQ->t2); // 2*d*t
v2add1271(VP->x, VP->y, VQ->xy); // x+y
v2sub1271(VP->y, VP->x, VQ->yx); // y-x
v2zero1271(VQ->z2); VQ->z2[0] = 2; // 2*z
eccdouble(VP); // P = 2P
for (n=0; n<TEST_LOOPS; n++)
{
eccadd(VQ, VP); // P = P+Q
}
eccnorm(VP, VA);
from_ext_to_std(VA->x, A->x);
from_ext_to_std(VA->y, A->y);
// Result
res_x[0] = 0x6480B1EF0A151DB0; res_x[1] = 0x3E243958590C4D90; res_x[2] = 0xAA270F644A65D473; res_x[3] = 0x5327AF7D84238CD0;
res_y[0] = 0x5E06003D73C43EB1; res_y[1] = 0x3EF69A49CB7E0237; res_y[2] = 0x4E752648AC2EF0AB; res_y[3] = 0x293EB1E26DD23B4E;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Point addition tests .................................................................... PASSED");
else { printf(" Point addition tests ... FAILED"); printf("\n"); return false; }
printf("\n");
#if (USE_ENDO == true)
// Psi endomorphism
eccset(A);
point_setup(A, VP);
for (n=0; n<TEST_LOOPS; n++)
{
ecc_psi(VP); // P = Psi(P)
}
eccnorm(VP, VA);
from_ext_to_std(VA->x, A->x);
from_ext_to_std(VA->y, A->y);
// Result
res_x[0] = 0xD8F3C8C24A2BC7E2; res_x[1] = 0x75AF54EDB41A2B93; res_x[2] = 0x4DE2466701F009A9; res_x[3] = 0x065249F9EDE0C798;
res_y[0] = 0x1C6E119ADD608104; res_y[1] = 0x06DBB85BFFB7C21E; res_y[2] = 0xFD234D6C4CFA3EC1; res_y[3] = 0x060A30903424BF13;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Psi endomorphism tests .................................................................. PASSED");
else { printf(" Psi endomorphism tests ... FAILED"); printf("\n"); return false; }
printf("\n");
// Phi endomorphism
eccset(A);
point_setup(A, VP);
for (n=0; n<TEST_LOOPS; n++)
{
ecc_phi(VP); // P = Phi(P)
eccnorm(VP, VA);
from_ext_to_std(VA->x, A->x);
from_ext_to_std(VA->y, A->y);
point_setup(A, VP);
}
// Result
res_x[0] = 0xD5B5A3061287DB16; res_x[1] = 0x5550AAB9E7A620EE; res_x[2] = 0xEC321E6CF33610FC; res_x[3] = 0x3E61EBB9A1CB0210;
res_y[0] = 0x7E2851D5A8E83FB9; res_y[1] = 0x5474BF8EC55603AE; res_y[2] = 0xA5077613491788D5; res_y[3] = 0x5476093DBF8BF6BF;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Phi endomorphism tests .................................................................. PASSED");
else { printf(" Phi endomorphism tests ... FAILED"); printf("\n"); return false; }
printf("\n");
// Scalar decomposition and recoding
{
uint64_t acc1, acc2, acc3, acc4, scalars[4];
unsigned int digits[65], sign_masks[65];
uint64_t k[4];
int i;
for (n=0; n<TEST_LOOPS*10; n++)
{
random_scalar_test(k);
decompose(k, scalars);
fp2copy1271((felm_t*)scalars, (felm_t*)scalar);
recode(scalars, digits, sign_masks);
acc1 = acc2 = acc3 = acc4 = 0;
for (i = 64; i >= 0; i--)
{
acc1 = 2*acc1; acc2 = 2*acc2; acc3 = 2*acc3; acc4 = 2*acc4;
if (sign_masks[i] == (unsigned int)-1) {
acc1 += 1;
acc2 += (digits[i] & 1);
acc3 += ((digits[i] >> 1) & 1);
acc4 += ((digits[i] >> 2) & 1);
} else if (sign_masks[i] == 0) {
acc1 -= 1;
acc2 -= (digits[i] & 1);
acc3 -= ((digits[i] >> 1) & 1);
acc4 -= ((digits[i] >> 2) & 1);
}
}
if (scalar[0] != acc1 || scalar[1] != acc2 || scalar[2] != acc3 || scalar[3] != acc4) { passed=0; break; }
}
if (passed==1) printf(" Recoding and decomposition tests ........................................................ PASSED");
else { printf(" Recoding and decomposition tests ... FAILED"); printf("\n"); return false; }
printf("\n");
}
#endif
// Scalar multiplication
eccset(A);
clear_cofactor = false;
scalar[0] = 0x3AD457AB55456230; scalar[1] = 0x3A8B3C2C6FD86E0C; scalar[2] = 0x7E38F7C9CFBB9166; scalar[3] = 0x0028FD6CBDA458F0;
for (n=0; n<TEST_LOOPS; n++)
{
scalar[1] = scalar[2];
scalar[2] += scalar[0];
ecc_mul(A, (digit_t*)scalar, A, clear_cofactor);
}
res_x[0] = 0xDFD2B477BD494BEF; res_x[1] = 0x257C122BBFC94A1B; res_x[2] = 0x769593547237C459; res_x[3] = 0x469BF80CB5B11F01;
res_y[0] = 0x281C5067996F3344; res_y[1] = 0x0901B3817C0E936C; res_y[2] = 0x4FE8C429915F1245; res_y[3] = 0x570B948EACACE210;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
eccset(A);
clear_cofactor = true;
scalar[0] = 0x3AD457AB55456230; scalar[1] = 0x3A8B3C2C6FD86E0C; scalar[2] = 0x7E38F7C9CFBB9166; scalar[3] = 0x0028FD6CBDA458F0;
for (n=0; n<TEST_LOOPS; n++)
{
scalar[1] = scalar[2];
scalar[2] += scalar[0];
ecc_mul(A, (digit_t*)scalar, A, clear_cofactor);
}
res_x[0] = 0x85CF54A3BEE3FD23; res_x[1] = 0x7A7EC43976FAAD92; res_x[2] = 0x7697567B785E2327; res_x[3] = 0x4CBDAB448B1539F2;
res_y[0] = 0xE9193B41CDDF94D0; res_y[1] = 0x5AA6C859ECC810D5; res_y[2] = 0xAA876E760AA8B331; res_y[3] = 0x320C53F02230094A;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Scalar multiplication tests ............................................................. PASSED");
else { printf(" Scalar multiplication tests ... FAILED"); printf("\n"); return false; }
printf("\n");
{
point_t A, B, C;
vpoint_extproj_t VS;
unsigned int i, j, w, v, e, d;
uint64_t k[4];
unsigned int digits_fixed[NBITS_ORDER_PLUS_ONE+(W_FIXEDBASE*V_FIXEDBASE)-1] = {0};
// Scalar recoding using the mLSB-set representation
w = W_FIXEDBASE;
v = V_FIXEDBASE;
e = E_FIXEDBASE;
d = D_FIXEDBASE;
for (n=0; n<TEST_LOOPS; n++)
{
random_scalar_test(scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar); // k = k mod (order)
conversion_to_odd((digit_t*)scalar, (digit_t*)k);
for (j = 0; j < NWORDS64_ORDER; j++) scalar[j] = k[j];
mLSB_set_recode(k, digits_fixed);
if (verify_mLSB_recoding(scalar, (int*)digits_fixed)==false) { passed=0; break; }
}
if (passed==1) printf(" mLSB-set recoding tests ................................................................. PASSED");
else { printf(" mLSB-set recoding tests ... FAILED"); printf("\n"); return false; }
printf("\n");
// Fixed-base scalar multiplication
eccset(A);
for (n=0; n<TEST_LOOPS; n++)
{
random_scalar_test(scalar);
ecc_mul_fixed((digit_t*)scalar, B);
ecc_mul(A, (digit_t*)scalar, C, false);
if (fp2compare64((uint64_t*)B->x,(uint64_t*)C->x)!=0 || fp2compare64((uint64_t*)B->y,(uint64_t*)C->y)!=0) { passed=0; break; }
}
if (passed==1) printf(" Fixed-base scalar multiplication tests .................................................. PASSED");
else { printf(" Fixed-base scalar multiplication tests ... FAILED"); printf("\n"); return false; }
printf("\n");
}
{
point_t PP, QQ, RR, UU, TT;
vpoint_extproj_t VS, VT;
vpoint_extproj_precomp_t VR;
uint64_t k[4], l[4], scalar[4];
// Double scalar multiplication
eccset(QQ);
eccset(PP);
for (n=0; n<TEST_LOOPS; n++)
{
random_scalar_test(scalar);
ecc_mul(QQ, (digit_t*)scalar, QQ, false);
random_scalar_test(k);
random_scalar_test(l);
ecc_mul_double((digit_t*)k, QQ, (digit_t*)l, RR);
ecc_mul(PP, (digit_t*)k, UU, false);
ecc_mul(QQ, (digit_t*)l, TT, false);
point_setup(UU, VS);
from_std_to_ext(TT->x, VT->x);
from_std_to_ext(TT->y, VT->y);
v2add1271(VT->x, VT->y, VR->xy);
v2sub1271(VT->y, VT->x, VR->yx);
v2zero1271(VR->z2); VR->z2[0] = 2;
v2mul1271(VT->x, VT->y, VR->t2);
v2add1271(VR->t2, VR->t2, VR->t2);
v2mul1271(VR->t2, (digit_t*)&PARAMETER_d, VR->t2);
eccadd(VR, VS);
eccnorm(VS, VA);
from_ext_to_std(VA->x, A->x);
from_ext_to_std(VA->y, A->y);
if (fp2compare64((uint64_t*)A->x,(uint64_t*)RR->x)!=0 || fp2compare64((uint64_t*)A->y,(uint64_t*)RR->y)!=0) { passed=0; break; }
}
if (passed==1) printf(" Double scalar multiplication tests ...................................................... PASSED");
else { printf(" Double scalar multiplication tests ... FAILED"); printf("\n"); return false; }
printf("\n");
}
return OK;
}
bool ecc_run()
{
bool OK = true;
unsigned int n, i, sign_mask=-1, digit=1;
unsigned long long nsec, nsec1, nsec2;
point_t A, B;
vpoint_extproj_t VP;
vpoint_extproj_precomp_t VQ, Table[8];
v2elm_t t1;
uint64_t scalar[4];
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking FourQ's curve arithmetic \n\n");
// Point doubling
eccset(A);
point_setup(A, VP);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
eccdouble(VP);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Point doubling runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Point addition
eccset(A);
point_setup(A, VP);
v2mul1271((digit_t*)&PARAMETER_d, VP->x, t1); // d*x
v2add1271(t1, t1, t1); // 2*d*x
v2mul1271(t1, VP->y, VQ->t2); // 2*d*t
v2add1271(VP->x, VP->y, VQ->xy); // x+y
v2sub1271(VP->y, VP->x, VQ->yx); // y-x
v2zero1271(VQ->z2); VQ->z2[0] = 2; // 2*z
eccdouble(VP); // P = 2P
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
eccadd(VQ, VP);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Point addition runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
#if (USE_ENDO == true)
// Psi endomorphism
eccset(A);
point_setup(A, VP);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
ecc_psi(VP);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Psi mapping runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Phi endomorphism
eccset(A);
point_setup(A, VP);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
ecc_phi(VP);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Phi mapping runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Scalar decomposition
{
uint64_t scalars[4];
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
decompose(scalar, scalars);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Scalar decomposition runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
}
// Scalar recoding
{
unsigned int digits[65], sign_masks[65];
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
recode(scalar, digits, sign_masks);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Scalar recoding runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
}
#endif
// Precomputation
eccset(A);
point_setup(A, VP);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 100; i++) {
ecc_precomp(VP, Table);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Precomputation runs in ... %8lld nsec", nsec/(BENCH_LOOPS*100));
printf("\n");
// Table lookup
eccset(A);
point_setup(A, VP);
ecc_precomp(VP, Table);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
table_lookup_1x8(Table, VQ, digit, sign_mask);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Table lookup runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Scalar multiplication
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
eccset(A);
nsec1 = cpu_nseconds();
for (i = 0; i < 100; i++) {
ecc_mul(A, (digit_t*)scalar, B, false);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Scalar multiplication (without clearing cofactor) runs in ...... %8lld nsec", nsec/(SHORT_BENCH_LOOPS*100));
printf("\n");
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
eccset(A);
nsec1 = cpu_nseconds();
ecc_mul(A, (digit_t*)scalar, B, true);
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Scalar multiplication (including clearing cofactor) runs in .... %8lld nsec", nsec/SHORT_BENCH_LOOPS);
printf("\n");
{
vpoint_precomp_t T;
unsigned int digits_fixed[256+(W_FIXEDBASE*V_FIXEDBASE)-1] = {0};
// Reduction modulo the order
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
modulo_order((digit_t*)scalar, (digit_t*)scalar);
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Reduction modulo the order runs in ... %8lld nsec", nsec/(BENCH_LOOPS*10));
printf("\n");
// Scalar recoding using the mLSB-set representation
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
mLSB_set_recode(scalar, digits_fixed);
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Fixed-base recoding runs in ... %8lld nsec", nsec/(SHORT_BENCH_LOOPS*10));
printf("\n");
// Table lookup for fixed-base scalar multiplication
eccset(A);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 1, 0);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 2, (unsigned int)-1);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 1, 0);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 2, (unsigned int)-1);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 1, 0);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 2, (unsigned int)-1);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 1, 0);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 2, (unsigned int)-1);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 1, 0);
table_lookup_fixed_base((vpoint_precomp_t*)&FIXED_BASE_TABLE, T, 2, (unsigned int)-1);
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Fixed-base table lookup runs in ... %8lld nsec", nsec/(BENCH_LOOPS*10));
printf("\n");
// Fixed-base scalar multiplication
eccset(A);
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
random_scalar_test(scalar);
nsec1 = cpu_nseconds();
ecc_mul_fixed((digit_t*)scalar, B);
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Fixed-base scalar mul runs in ... %8lld nsec with w=%d and v=%d", nsec/SHORT_BENCH_LOOPS, W_FIXEDBASE, V_FIXEDBASE);
printf("\n");
}
{
point_t PP, QQ, RR;
uint64_t k[4], l[4], scalar[4];
// Double scalar multiplication
eccset(QQ);
eccset(PP);
random_scalar_test(scalar);
ecc_mul(QQ, (digit_t*)scalar, QQ, false);
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
random_scalar_test(k);
random_scalar_test(l);
nsec1 = cpu_nseconds();
ecc_mul_double((digit_t*)k, QQ, (digit_t*)l, RR);
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Double scalar mul runs in ... %8lld nsec with wP=%d and wQ=%d", nsec/SHORT_BENCH_LOOPS, WP_DOUBLEBASE, WQ_DOUBLEBASE);
printf("\n");
}
return OK;
}
int main()
{
bool OK = true;
OK = OK && ecc_test(); // Test FourQ's curve functions
OK = OK && ecc_run(); // Benchmark FourQ's curve functions
return OK;
}

Просмотреть файл

@ -0,0 +1,174 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: utility functions for tests
************************************************************************************/
#include "../FourQ_internal.h"
#include "test_extras.h"
#if (OS_TARGET == OS_LINUX) && (TARGET == TARGET_ARM)
#include <time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int64_t cpu_nseconds(void)
{ // Access system counter for benchmarking
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return (int64_t)(time.tv_sec*1e9 + time.tv_nsec);
}
int fpcompare64(uint64_t* a, uint64_t* b)
{ // Comparing uint64_t digits of two field elements, a=b? : (0) equal, (1) unequal
// NOTE: this function does not have constant-time execution. TO BE USED FOR TESTING ONLY.
unsigned int i;
for (i = 0; i < (NWORDS64_FIELD); i++) {
if (a[i] != b[i]) return 1;
}
return 0;
}
int fp2compare64(uint64_t* a, uint64_t* b)
{ // Comparing uint64_t digits of two quadratic extension field elements, ai=bi? : (0) equal, (1) unequal
// NOTE: this function does not have constant-time execution. TO BE USED FOR TESTING ONLY.
unsigned int i;
for (i = 0; i < (2*NWORDS64_FIELD); i++) {
if (a[i] != b[i]) return 1;
}
return 0;
}
void random_scalar_test(uint64_t* a)
{ // Generating a pseudo-random scalar value in [0, 2^256-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
unsigned char* string = (unsigned char*)&a[0];
unsigned int i;
for (i = 0; i < (sizeof(uint64_t)*NWORDS64_ORDER); i++) {
string[i] = (unsigned char)rand();
}
}
void fp2random1271_test(f2elm_t a)
{ // Generating a pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
digit_t mask_7fff = (digit_t)-1 >> 1;
random_scalar_test((uint64_t*)&a[0]);
a[0][NWORDS_FIELD-1] &= mask_7fff;
a[1][NWORDS_FIELD-1] &= mask_7fff;
}
void vrandom1271_test(velm_t a)
{ // Generating a vectorized pseudo-random GF(p) element in [0, 2^127-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
v2elm_t temp;
velm_t b;
v2random1271_test(temp);
from_v2_to_v(temp, a, b);
}
void v2random1271_test(v2elm_t a)
{ // Generating a vectorized pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
digit_t mask_7fff = (digit_t)-1 >> 1;
f2elm_t temp;
random_scalar_test((uint64_t*)&temp[0]);
temp[0][NWORDS_FIELD-1] &= mask_7fff;
temp[1][NWORDS_FIELD-1] &= mask_7fff;
from_std_to_ext(temp, a);
}
bool verify_mLSB_recoding(uint64_t* scalar, int* digits)
{ // Verification of the mLSB-set's recoding algorithm used in fixed-base scalar multiplication
unsigned int j, l = L_FIXEDBASE, d = D_FIXEDBASE;
uint64_t temp, temp2, carry, borrow, generated_scalar[NWORDS64_ORDER] = {0};
int i, digit;
for (i = (l-1); i >= 0; i--)
{
// Shift generated scalar to the left by 1 (multiply by 2)
temp = ((generated_scalar[0] >> (RADIX64-1)) & 1) ;
generated_scalar[0] = generated_scalar[0] << 1;
for (j = 1; j < NWORDS64_ORDER; j++) {
temp2 = ((generated_scalar[j] >> (RADIX64-1)) & 1) ;
generated_scalar[j] = (generated_scalar[j] << 1) | temp;
temp = temp2;
}
// generated scalar + digit_i
if (i < (int)d) {
digit = digits[i] | 1;
if (digit >= 0) {
generated_scalar[0] = generated_scalar[0] + digit;
carry = (generated_scalar[0] < (unsigned int)digit);
for (j = 1; j < NWORDS64_ORDER; j++)
{
generated_scalar[j] = generated_scalar[j] + carry;
carry = (generated_scalar[j] < carry);
}
} else {
borrow = 0;
temp = (uint64_t)(-digit);
for (j = 0; j < NWORDS64_ORDER; j++)
{
temp2 = generated_scalar[j] - temp;
carry = (generated_scalar[j] < temp);
generated_scalar[j] = temp2 - borrow;
borrow = carry || (temp2 < borrow);
temp = 0;
}
}
} else {
digit = digits[i]*(digits[i-(i/d)*d] | 1);
if (digit >= 0) {
generated_scalar[0] = generated_scalar[0] + digit;
carry = (generated_scalar[0] < (unsigned int)digit);
for (j = 1; j < NWORDS64_ORDER; j++)
{
generated_scalar[j] = generated_scalar[j] + carry;
carry = (generated_scalar[j] < carry);
}
} else {
borrow = 0;
temp = (uint64_t)(-digit);
for (j = 0; j < NWORDS64_ORDER; j++)
{
temp2 = generated_scalar[j] - temp;
carry = (generated_scalar[j] < temp);
generated_scalar[j] = temp2 - borrow;
borrow = carry || (temp2 < borrow);
temp = 0;
}
}
}
}
for (j = 0; j < NWORDS64_ORDER; j++)
{
if (scalar[j] != generated_scalar[j])
return false;
}
return true;
}

Просмотреть файл

@ -0,0 +1,49 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: utility header file for tests
************************************************************************************/
#ifndef __TEST_EXTRAS_H__
#define __TEST_EXTRAS_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
// Access system counter for benchmarking
int64_t cpu_nseconds(void);
// Comparing uint64_t digits of two field elements, a=b? : (0) equal, (1) unequal
int fpcompare64(uint64_t* a, uint64_t* b);
// Comparing uint64_t digits of two quadratic extension field elements, ai=bi? : (0) equal, (1) unequal
int fp2compare64(uint64_t* a, uint64_t* b);
// Generating a pseudo-random scalar value in [0, 2^256-1]
void random_scalar_test(uint64_t* a);
// Generating a vectorized pseudo-random GF(p) element in [0, 2^127-1]
void vrandom1271_test(velm_t a);
// Generating a pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
void fp2random1271_test(f2elm_t a);
// Generating a vectorized pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
void v2random1271_test(v2elm_t a);
// Verification of the mLSB-set's recoding algorithm used in fixed-base scalar multiplication
bool verify_mLSB_recoding(uint64_t* scalar, int* digits);
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,644 @@
//***********************************************************************************
// FourQlib: a high-performance crypto library based on the elliptic curve FourQ
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Abstract: arithmetic over GF(p^2) using ARM assembly for Linux
//***********************************************************************************
.text
.align 4
//***********************************************************************
// Multiplication over GF(p^2)
// Operation: c [reg_p3] = a [reg_p1] * b [reg_p2]
// Restriction : b != c
//***********************************************************************
.global fp2mul1271_a
.type fp2mul1271_a, %function
fp2mul1271_a:
push {r4-r12}
sub r13, r13, #44 // Allocating space in the stack
// T0 = a0 * b0
ldm r0!, {r3-r6}
ldr r7, [r1]
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #4]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #8]
str r8, [r13], #4 // Store in stack
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #12]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
// T1 = a1 * b1
ldm r0!, {r3-r6}
ldr r7, [r1, #16]
stmia r13!, {r8-r12} // Store in stack
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #20]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #24]
str r8, [r13], #4 // Store in stack
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #28]
str r9, [r13], #4 // Store in stack
mov r9, #0
sub r13, r13, #52
stmia r13!, {r0-r1}
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
// c0 = T0 - T1 = a0*b0 - a1*b1
ldmia r13!, {r3-r6}
ldr r0, [r13, #16]
ldr r1, [r13, #20]
ldr r7, [r13, #24]
subs r3, r3, r0
sbcs r4, r4, r1
sbcs r5, r5, r7
sbcs r6, r6, r8
ldmia r13!, {r7-r8}
ldmia r13!, {r0-r1}
sbcs r7, r7, r9
sbcs r8, r8, r10
sbcs r9, r0, r11
sbcs r10, r1, r12
sub r13, #40
pop {r0-r1}
// Reducing and storing c0
lsl r10, r10, #1
orr r10, r10, r9, lsr #31
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
lsl r7, r7, #1
orr r7, r7, r6, lsr #31
and r6, r6, #0x7FFFFFFF
subs r7, r7, r10, lsr #31
sbcs r8, r8, #0
sbcs r9, r9, #0
sbcs r10, r10, #0
and r10, r10, #0x7FFFFFFF
adds r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r7, #0
stmia r13!, {r3-r6}
// T2 = a0 * b1
sub r0, r0, #32
ldm r0!, {r3-r6}
ldr r7, [r1, #16]
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #20]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #24]
str r8, [r13], #4 // Store in stack
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #28]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
str r8, [r13], #4
sub r13, r13, #32
ldm r13, {r3-r6}
stmia r13!, {r9-r12} // Store in stack
ldr r7, [r1]
stmia r2!, {r3-r6} // Storing c0
// T3 = a1 * b0
add r13, r13, #16
ldm r0!, {r3-r6}
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #4]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #8]
str r8, [r13], #4 // Store in stack
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #12]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
// c1 = T2 + T3 = a0*b1 + a1*b0
sub r13, r13, #28
ldmia r13!, {r3-r6}
ldmia r13, {r0-r1,r7}
sub r13, r13, #32
adds r3, r3, r0
adcs r4, r4, r1
adcs r5, r5, r7
adcs r6, r6, r8
ldmia r13!, {r7-r8}
ldmia r13!, {r0-r1}
adcs r7, r7, r9
adcs r8, r8, r10
adcs r9, r0, r11
adcs r10, r1, r12
// Reducing and storing c1
lsl r10, r10, #1
orr r10, r10, r9, lsr #31
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
lsl r7, r7, #1
orr r7, r7, r6, lsr #31
and r6, r6, #0x7FFFFFFF
lsls r10, r10, #1
adcs r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10, lsr #1
and r7, r6, #0x7FFFFFFF
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r7, #0
stmia r2!, {r3-r6} // Storing c1
add r13, r13, #28 // Restoring stack
pop {r4-r12}
bx lr
//***********************************************************************
// Squaring over GF(p^2)
// Operation: c [reg_p2] = a^2 [reg_p1]
//***********************************************************************
.global fp2sqr1271_a
.type fp2sqr1271_a, %function
fp2sqr1271_a:
push {r4-r12}
sub r13, r13, #16 // Allocating space in the stack
// t0 = a0 + a1
ldm r0, {r2-r9}
adds r2, r2, r6
adcs r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
stm r13, {r2-r5} // Store in stack
// t1 = a0 - a1
ldm r0, {r2-r5}
subs r2, r2, r6
sbcs r3, r3, r7
sbcs r4, r4, r8
sbcs r5, r5, r9
and r6, r5, #0x7FFFFFFF
subs r2, r2, r5, lsr #31
sbcs r3, r3, #0
sbcs r4, r4, #0
sbcs r5, r6, #0
// T0 = t0 * t1 = (a0 + a1)*(a0 - a1)
ldr r12, [r13]
mov r9, #0
mov r10, #0
mov r11, #0
umull r6, r7, r12, r2
umlal r7, r9, r12, r3
umlal r9, r10, r12, r4
umlal r10, r11, r12, r5
ldr r12, [r13, #4]
str r6, [r13] // Store in stack
mov r6, #0
umlal r7, r6, r12, r2
umaal r6, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
ldr r12, [r13, #8]
str r7, [r13, #4] // Store in stack
mov r7, #0
umlal r6, r7, r12, r2
umaal r7, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
ldr r12, [r13, #12]
mov r8, #0
umlal r7, r8, r12, r2
umaal r8, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
// Reduction
lsl r11, r11, #1
orr r11, r11, r10, lsr #31
lsl r10, r10, #1
orr r10, r10, r9, lsr #31
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
ldm r13, {r4,r5}
and r7, r7, #0x7FFFFFFF
lsls r11, r11, #1
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
adcs r7, r7, r11, lsr #1
and r8, r7, #0x7FFFFFFF
adds r9, r4, r7, lsr #31
adcs r10, r5, #0
ldm r0, {r2-r5}
adcs r11, r6, #0
adcs r12, r8, #0
// t0 = 2*a0
adds r2, r2, r2
adcs r3, r3, r3
adcs r4, r4, r4
adcs r5, r5, r5
stmia r1!, {r9-r12} // Storing c0
// T1 = 2a0 * a1
ldr r12, [r0, #16]
mov r9, #0
mov r10, #0
mov r11, #0
umull r6, r7, r12, r2
umlal r7, r9, r12, r3
umlal r9, r10, r12, r4
umlal r10, r11, r12, r5
ldr r12, [r0, #20]
str r6, [r13] // Store in stack
mov r6, #0
umlal r7, r6, r12, r2
umaal r6, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
ldr r12, [r0, #24]
str r7, [r13, #4] // Store in stack
mov r7, #0
umlal r6, r7, r12, r2
umaal r7, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
ldr r12, [r0, #28]
mov r8, #0
umlal r7, r8, r12, r2
umaal r8, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
// Reduction
lsl r11, r11, #1
orr r11, r11, r10, lsr #31
lsl r10, r10, #1
orr r10, r10, r9, lsr #31
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
ldm r13, {r4,r5}
and r7, r7, #0x7FFFFFFF
lsls r11, r11, #1
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
adcs r7, r7, r11, lsr #1
and r8, r7, #0x7FFFFFFF
adds r4, r4, r7, lsr #31
adcs r5, r5, #0
adcs r6, r6, #0
adcs r7, r8, #0
stmia r1!, {r4-r7} // Storing c1
add r13, r13, #16 // Restoring stack
pop {r4-r12}
bx lr
//***********************************************************************
// Addition over GF(p^2)
// Operation: c [reg_p3] = a [reg_p1] + b [reg_p2] mod p, p = 2^127-1
//***********************************************************************
.global fp2add1271_a
.type fp2add1271_a, %function
fp2add1271_a:
push {r4-r10}
ldm r0!, {r3-r4}
ldm r1!, {r7-r8}
ldm r0!, {r5-r6}
ldm r1!, {r9-r10}
adds r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
ldm r1!, {r7-r10}
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r6, #0
and r6, r6, #0x7FFFFFFF
stmia r2!, {r3-r4}
ldm r0!, {r3-r4}
stmia r2!, {r5-r6}
ldm r0!, {r5-r6}
adds r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r7, #0
stmia r2!, {r3-r6}
pop {r4-r10}
bx lr
//***********************************************************************
// Subtraction over GF(p^2)
// Operation: c [reg_p3] = a [reg_p1] - b [reg_p2] mod p, p = 2^127-1
//***********************************************************************
.global fp2sub1271_a
.type fp2sub1271_a, %function
fp2sub1271_a:
push {r4-r10}
ldm r0!, {r3-r4}
ldm r1!, {r7-r8}
ldm r0!, {r5-r6}
ldm r1!, {r9-r10}
subs r3, r3, r7
sbcs r4, r4, r8
sbcs r5, r5, r9
sbcs r6, r6, r10
ldm r1!, {r7-r10}
subs r3, r3, r6, lsr #31
sbcs r4, r4, #0
sbcs r5, r5, #0
sbcs r6, r6, #0
and r6, r6, #0x7FFFFFFF
stmia r2!, {r3-r4}
ldm r0!, {r3-r4}
stmia r2!, {r5-r6}
ldm r0!, {r5-r6}
subs r3, r3, r7
sbcs r4, r4, r8
sbcs r5, r5, r9
sbcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
subs r3, r3, r6, lsr #31
sbcs r4, r4, #0
sbcs r5, r5, #0
sbcs r6, r7, #0
stmia r2!, {r3-r6}
pop {r4-r10}
bx lr
//***********************************************************************
// Integer multiplication
// Operation: c [reg_p3] = a [reg_p1] * b [reg_p2]
// Restriction : b != c
//***********************************************************************
.global mul1271_a
.type mul1271_a, %function
mul1271_a:
push {r4-r12}
ldm r0!, {r3-r6}
ldr r7, [r1]
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #4]
str r9, [r2], #4
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #8]
str r8, [r2], #4
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #12]
str r9, [r2], #4
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
stmia r2!, {r8-r12}
pop {r4-r12}
bx lr
//***********************************************************************
// Modular reduction
// Operation: c [reg_p3] = a [reg_p1] mod p, p = 2^127-1
//***********************************************************************
.global mod1271_a
.type mod1271_a, %function
mod1271_a:
push {r4-r9}
ldm r0!, {r2-r9}
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
lsl r7, r7, #1
orr r7, r7, r6, lsr #31
lsl r6, r6, #1
orr r6, r6, r5, lsr #31
and r5, r5, #0x7FFFFFFF
adds r2, r2, r6
adcs r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
and r6, r5, #0x7FFFFFFF
adds r2, r2, r5, lsr #31
adcs r3, r3, #0
adcs r4, r4, #0
adcs r5, r6, #0
stmia r1!, {r2-r5}
pop {r4-r9}
bx lr
//***********************************************************************
// Field addition
// Operation: c [reg_p3] = a [reg_p1] + b [reg_p2] mod p, p = 2^127-1
//***********************************************************************
.global fpadd1271_a
.type fpadd1271_a, %function
fpadd1271_a:
push {r4-r10}
ldm r0!, {r3-r4}
ldm r1!, {r7-r8}
ldm r0!, {r5-r6}
ldm r1!, {r9-r10}
adds r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r7, #0
stmia r2!, {r3-r6}
pop {r4-r10}
bx lr
//***********************************************************************
// Field subtraction
// Operation: c [reg_p3] = a [reg_p1] - b [reg_p2] mod p, p = 2^127-1
//***********************************************************************
.global fpsub1271_a
.type fpsub1271_a, %function
fpsub1271_a:
push {r4-r10}
ldm r0!, {r3-r4}
ldm r1!, {r7-r8}
ldm r0!, {r5-r6}
ldm r1!, {r9-r10}
subs r3, r3, r7
sbcs r4, r4, r8
sbcs r5, r5, r9
sbcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
subs r3, r3, r6, lsr #31
sbcs r4, r4, #0
sbcs r5, r5, #0
sbcs r6, r7, #0
stmia r2!, {r3-r6}
pop {r4-r10}
bx lr

Просмотреть файл

@ -0,0 +1,637 @@
//***********************************************************************************
// FourQlib: a high-performance crypto library based on the elliptic curve FourQ
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// Abstract: arithmetic over GF(p^2) using ARMv7-M assembly (Cortex-M4) for Linux
//***********************************************************************************
.syntax unified
.cpu cortex-m4
.thumb
.text
.align 4
//***********************************************************************
// Multiplication over GF(p^2)
// Operation: c [reg_p3] = a [reg_p1] * b [reg_p2]
// Restriction : b != c
//***********************************************************************
.global fp2mul1271_a
.type fp2mul1271_a, %function
fp2mul1271_a:
push {r4-r12}
sub r13, r13, #44 // Allocating space in the stack
// T0 = a0 * b0
ldm r0!, {r3-r6}
ldr r7, [r1]
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #4]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #8]
str r8, [r13], #4 // Store in stack
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #12]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
// T1 = a1 * b1
ldm r0!, {r3-r6}
ldr r7, [r1, #16]
stmia r13!, {r8-r12} // Store in stack
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #20]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #24]
str r8, [r13], #4 // Store in stack
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #28]
str r9, [r13], #4 // Store in stack
mov r9, #0
sub r13, r13, #52
str r0, [r13], #4
str r1, [r13], #4
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
// c0 = T0 - T1 = a0*b0 - a1*b1
ldmia r13!, {r3-r6}
ldr r0, [r13, #16]
ldr r1, [r13, #20]
ldr r7, [r13, #24]
subs r3, r3, r0
sbcs r4, r4, r1
sbcs r5, r5, r7
sbcs r6, r6, r8
ldmia r13!, {r7-r8}
ldmia r13!, {r0-r1}
sbcs r7, r7, r9
sbcs r8, r8, r10
sbcs r9, r0, r11
sbcs r10, r1, r12
sub r13, #40
pop {r0-r1}
// Reducing and storing c0
lsl r10, r10, #1
orr r10, r10, r9, lsr #31
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
lsl r7, r7, #1
orr r7, r7, r6, lsr #31
and r6, r6, #0x7FFFFFFF
subs r7, r7, r10, lsr #31
sbcs r8, r8, #0
sbcs r9, r9, #0
sbcs r10, r10, #0
and r10, r10, #0x7FFFFFFF
adds r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r7, #0
stm r13, {r3-r6}
add r13, r13, #16
// T2 = a0 * b1
sub r0, r0, #32
ldm r0!, {r3-r6}
ldr r7, [r1, #16]
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #20]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #24]
str r8, [r13], #4 // Store in stack
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #28]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
str r8, [r13], #4
sub r13, r13, #32
ldm r13, {r3-r6}
stmia r13!, {r9-r12} // Store in stack
ldr r7, [r1]
stmia r2!, {r3-r6} // Storing c0
// T3 = a1 * b0
add r13, r13, #16
ldm r0!, {r3-r6}
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #4]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #8]
str r8, [r13], #4 // Store in stack
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #12]
str r9, [r13], #4 // Store in stack
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
// c1 = T2 + T3 = a0*b1 + a1*b0
sub r13, r13, #28
ldmia r13!, {r3-r6}
ldm r13, {r0-r1,r7}
sub r13, r13, #32
adds r3, r3, r0
adcs r4, r4, r1
adcs r5, r5, r7
adcs r6, r6, r8
ldmia r13!, {r7-r8}
ldmia r13!, {r0-r1}
adcs r7, r7, r9
adcs r8, r8, r10
adcs r9, r0, r11
adcs r10, r1, r12
// Reducing and storing c1
lsl r10, r10, #1
orr r10, r10, r9, lsr #31
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
lsl r7, r7, #1
orr r7, r7, r6, lsr #31
and r6, r6, #0x7FFFFFFF
lsls r10, r10, #1
adcs r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10, lsr #1
and r7, r6, #0x7FFFFFFF
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r7, #0
stmia r2!, {r3-r6} // Storing c1
add r13, r13, #28 // Restoring stack
pop {r4-r12}
bx lr
//***********************************************************************
// Squaring over GF(p^2)
// Operation: c [reg_p2] = a^2 [reg_p1]
//***********************************************************************
.global fp2sqr1271_a
.type fp2sqr1271_a, %function
fp2sqr1271_a:
push {r4-r12}
sub r13, r13, #16 // Allocating space in the stack
// t0 = a0 + a1
ldm r0, {r2-r9}
adds r2, r2, r6
adcs r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
stm r13, {r2-r5} // Store in stack
// t1 = a0 - a1
ldm r0, {r2-r5}
subs r2, r2, r6
sbcs r3, r3, r7
sbcs r4, r4, r8
sbcs r5, r5, r9
and r6, r5, #0x7FFFFFFF
subs r2, r2, r5, lsr #31
sbcs r3, r3, #0
sbcs r4, r4, #0
sbcs r5, r6, #0
// T0 = t0 * t1 = (a0 + a1)*(a0 - a1)
ldr r12, [r13]
mov r9, #0
mov r10, #0
mov r11, #0
umull r6, r7, r12, r2
umlal r7, r9, r12, r3
umlal r9, r10, r12, r4
umlal r10, r11, r12, r5
ldr r12, [r13, #4]
str r6, [r13] // Store in stack
mov r6, #0
umlal r7, r6, r12, r2
umaal r6, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
ldr r12, [r13, #8]
str r7, [r13, #4] // Store in stack
mov r7, #0
umlal r6, r7, r12, r2
umaal r7, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
ldr r12, [r13, #12]
mov r8, #0
umlal r7, r8, r12, r2
umaal r8, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
// Reduction
lsl r11, r11, #1
orr r11, r11, r10, lsr #31
lsl r10, r10, #1
orr r10, r10, r9, lsr #31
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
ldm r13, {r4,r5}
and r7, r7, #0x7FFFFFFF
lsls r11, r11, #1
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
adcs r7, r7, r11, lsr #1
and r8, r7, #0x7FFFFFFF
adds r9, r4, r7, lsr #31
adcs r10, r5, #0
ldm r0, {r2-r5}
adcs r11, r6, #0
adcs r12, r8, #0
// t0 = 2*a0
adds r2, r2, r2
adcs r3, r3, r3
adcs r4, r4, r4
adcs r5, r5, r5
stmia r1!, {r9-r12} // Storing c0
// T1 = 2a0 * a1
ldr r12, [r0, #16]
mov r9, #0
mov r10, #0
mov r11, #0
umull r6, r7, r12, r2
umlal r7, r9, r12, r3
umlal r9, r10, r12, r4
umlal r10, r11, r12, r5
ldr r12, [r0, #20]
str r6, [r13] // Store in stack
mov r6, #0
umlal r7, r6, r12, r2
umaal r6, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
ldr r12, [r0, #24]
str r7, [r13, #4] // Store in stack
mov r7, #0
umlal r6, r7, r12, r2
umaal r7, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
ldr r12, [r0, #28]
mov r8, #0
umlal r7, r8, r12, r2
umaal r8, r9, r12, r3
umaal r9, r10, r12, r4
umaal r10, r11, r12, r5
// Reduction
lsl r11, r11, #1
orr r11, r11, r10, lsr #31
lsl r10, r10, #1
orr r10, r10, r9, lsr #31
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
ldm r13, {r4,r5}
and r7, r7, #0x7FFFFFFF
lsls r11, r11, #1
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
adcs r7, r7, r11, lsr #1
and r8, r7, #0x7FFFFFFF
adds r4, r4, r7, lsr #31
adcs r5, r5, #0
adcs r6, r6, #0
adcs r7, r8, #0
stmia r1!, {r4-r7} // Storing c1
add r13, r13, #16 // Restoring stack
pop {r4-r12}
bx lr
//***********************************************************************
// Addition over GF(p^2)
// Operation: c [reg_p3] = a [reg_p1] + b [reg_p2] mod p, p = 2^127-1
//***********************************************************************
.global fp2add1271_a
.type fp2add1271_a, %function
fp2add1271_a:
push {r4-r10}
ldm r0!, {r3-r6}
ldm r1!, {r7-r10}
adds r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
ldm r1!, {r7-r10}
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r6, #0
and r6, r6, #0x7FFFFFFF
stmia r2!, {r3-r6}
ldm r0!, {r3-r6}
adds r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r7, #0
stmia r2!, {r3-r6}
pop {r4-r10}
bx lr
//***********************************************************************
// Subtraction over GF(p^2)
// Operation: c [reg_p3] = a [reg_p1] - b [reg_p2] mod p, p = 2^127-1
//***********************************************************************
.global fp2sub1271_a
.type fp2sub1271_a, %function
fp2sub1271_a:
push {r4-r10}
ldm r0!, {r3-r6}
ldm r1!, {r7-r10}
subs r3, r3, r7
sbcs r4, r4, r8
sbcs r5, r5, r9
sbcs r6, r6, r10
ldm r1!, {r7-r10}
subs r3, r3, r6, lsr #31
sbcs r4, r4, #0
sbcs r5, r5, #0
sbcs r6, r6, #0
and r6, r6, #0x7FFFFFFF
stmia r2!, {r3-r6}
ldm r0!, {r3-r6}
subs r3, r3, r7
sbcs r4, r4, r8
sbcs r5, r5, r9
sbcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
subs r3, r3, r6, lsr #31
sbcs r4, r4, #0
sbcs r5, r5, #0
sbcs r6, r7, #0
stmia r2!, {r3-r6}
pop {r4-r10}
bx lr
//***********************************************************************
// Integer multiplication
// Operation: c [reg_p3] = a [reg_p1] * b [reg_p2]
// Restriction : b != c
//***********************************************************************
.global mul1271_a
.type mul1271_a, %function
mul1271_a:
push {r4-r12}
ldm r0!, {r3-r6}
ldr r7, [r1]
mov r10, #0
mov r11, #0
mov r12, #0
umull r9, r8, r7, r3
umlal r8, r10, r7, r4
umlal r10, r11, r7, r5
umlal r11, r12, r7, r6
ldr r7, [r1, #4]
str r9, [r2], #4
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #8]
str r8, [r2], #4
mov r8, #0
umlal r9, r8, r7, r3
umaal r8, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
ldr r7, [r1, #12]
str r9, [r2], #4
mov r9, #0
umlal r8, r9, r7, r3
umaal r9, r10, r7, r4
umaal r10, r11, r7, r5
umaal r11, r12, r7, r6
stmia r2!, {r8-r12}
pop {r4-r12}
bx lr
//***********************************************************************
// Modular reduction
// Operation: c [reg_p3] = a [reg_p1] mod p, p = 2^127-1
//***********************************************************************
.global mod1271_a
.type mod1271_a, %function
mod1271_a:
push {r4-r9}
ldm r0!, {r2-r9}
lsl r9, r9, #1
orr r9, r9, r8, lsr #31
lsl r8, r8, #1
orr r8, r8, r7, lsr #31
lsl r7, r7, #1
orr r7, r7, r6, lsr #31
lsl r6, r6, #1
orr r6, r6, r5, lsr #31
and r5, r5, #0x7FFFFFFF
adds r2, r2, r6
adcs r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
and r6, r5, #0x7FFFFFFF
adds r2, r2, r5, lsr #31
adcs r3, r3, #0
adcs r4, r4, #0
adcs r5, r6, #0
stmia r1!, {r2-r5}
pop {r4-r9}
bx lr
//***********************************************************************
// Field addition
// Operation: c [reg_p3] = a [reg_p1] + b [reg_p2] mod p, p = 2^127-1
//***********************************************************************
.global fpadd1271_a
.type fpadd1271_a, %function
fpadd1271_a:
push {r4-r10}
ldm r0!, {r3-r6}
ldm r1!, {r7-r10}
adds r3, r3, r7
adcs r4, r4, r8
adcs r5, r5, r9
adcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
adds r3, r3, r6, lsr #31
adcs r4, r4, #0
adcs r5, r5, #0
adcs r6, r7, #0
stmia r2!, {r3-r6}
pop {r4-r10}
bx lr
//***********************************************************************
// Field subtraction
// Operation: c [reg_p3] = a [reg_p1] - b [reg_p2] mod p, p = 2^127-1
//***********************************************************************
.global fpsub1271_a
.type fpsub1271_a, %function
fpsub1271_a:
push {r4-r10}
ldm r0!, {r3-r6}
ldm r1!, {r7-r10}
subs r3, r3, r7
sbcs r4, r4, r8
sbcs r5, r5, r9
sbcs r6, r6, r10
and r7, r6, #0x7FFFFFFF
subs r3, r3, r6, lsr #31
sbcs r4, r4, #0
sbcs r5, r5, #0
sbcs r6, r7, #0
stmia r2!, {r3-r6}
pop {r4-r10}
bx lr

Просмотреть файл

@ -0,0 +1,363 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: modular arithmetic and other low-level operations for ARM processors
************************************************************************************/
#ifndef __FP_ARM_H__
#define __FP_ARM_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
#include "../table_lookup.h"
const digit_t mask_7fff = (digit_t)(-1) >> 1;
const digit_t prime1271_0 = (digit_t)(-1);
#define prime1271_1 mask_7fff
void digit_x_digit(digit_t a, digit_t b, digit_t* c)
{ // Digit multiplication, digit * digit -> 2-digit result
register digit_t al, ah, bl, bh, temp;
digit_t albl, albh, ahbl, ahbh, res1, res2, res3, carry;
digit_t mask_low = (digit_t)(-1) >> (sizeof(digit_t)*4), mask_high = (digit_t)(-1) << (sizeof(digit_t)*4);
al = a & mask_low; // Low part
ah = a >> (sizeof(digit_t) * 4); // High part
bl = b & mask_low;
bh = b >> (sizeof(digit_t) * 4);
albl = al*bl;
albh = al*bh;
ahbl = ah*bl;
ahbh = ah*bh;
c[0] = albl & mask_low; // C00
res1 = albl >> (sizeof(digit_t) * 4);
res2 = ahbl & mask_low;
res3 = albh & mask_low;
temp = res1 + res2 + res3;
carry = temp >> (sizeof(digit_t) * 4);
c[0] ^= temp << (sizeof(digit_t) * 4); // C01
res1 = ahbl >> (sizeof(digit_t) * 4);
res2 = albh >> (sizeof(digit_t) * 4);
res3 = ahbh & mask_low;
temp = res1 + res2 + res3 + carry;
c[1] = temp & mask_low; // C10
carry = temp & mask_high;
c[1] ^= (ahbh & mask_high) + carry; // C11
}
__inline void fpcopy1271(felm_t a, felm_t c)
{ // Copy of a field element, c = a
unsigned int i;
for (i = 0; i < NWORDS_FIELD; i++)
c[i] = a[i];
}
static __inline void fpzero1271(felm_t a)
{ // Zeroing a field element, a = 0
unsigned int i;
for (i = 0; i < NWORDS_FIELD; i++)
a[i] = 0;
}
__inline void fpadd1271(felm_t a, felm_t b, felm_t c)
{ // Field addition, c = a+b mod p
fpadd1271_a(a, b, c);
}
__inline void fpsub1271(felm_t a, felm_t b, felm_t c)
{ // Field subtraction, c = a-b mod p
fpsub1271_a(a, b, c);
}
__inline void fpneg1271(felm_t a)
{ // Field negation, a = -a mod p
unsigned int i;
unsigned int borrow = 0;
for (i = 0; i < (NWORDS_FIELD-1); i++) {
SUBC(borrow, prime1271_0, a[i], borrow, a[i]);
}
a[NWORDS_FIELD-1] = prime1271_1 - a[NWORDS_FIELD-1];
}
void fpmul1271(felm_t a, felm_t b, felm_t c)
{ // Field multiplication using schoolbook method, c = a*b mod p
digit_t t[2*NWORDS_FIELD] = {0};
mul1271_a(a, b, t);
mod1271_a(t, c);
}
void fpsqr1271(felm_t a, felm_t c)
{ // Field squaring using schoolbook method, c = a^2 mod p
fpmul1271(a, a, c);
}
void mod1271(felm_t a)
{ // Modular correction, a = a mod (2^127-1)
digit_t mask;
unsigned int i;
unsigned int borrow = 0;
for (i = 0; i < (NWORDS_FIELD-1); i++) {
SUBC(borrow, a[i], prime1271_0, borrow, a[i]);
}
SUBC(borrow, a[NWORDS_FIELD-1], prime1271_1, borrow, a[NWORDS_FIELD-1]);
mask = 0 - (digit_t)borrow; // If result < 0 then mask = 0xFF...F else sign = 0x00...0
borrow = 0;
for (i = 0; i < (NWORDS_FIELD-1); i++) {
ADDC(borrow, a[i], mask, borrow, a[i]);
}
ADDC(borrow, a[NWORDS_FIELD-1], (mask >> 1), borrow, a[NWORDS_FIELD-1]);
}
void mp_mul(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords)
{ // Schoolbook multiprecision multiply, c = a*b
unsigned int i, j;
digit_t u, v, UV[2];
unsigned int carry = 0;
for (i = 0; i < (2*nwords); i++) c[i] = 0;
for (i = 0; i < nwords; i++) {
u = 0;
for (j = 0; j < nwords; j++) {
MUL(a[i], b[j], UV+1, UV[0]);
ADDC(0, UV[0], u, carry, v);
u = UV[1] + carry;
ADDC(0, c[i+j], v, carry, v);
u = u + carry;
c[i+j] = v;
}
c[nwords+i] = u;
}
}
unsigned int mp_add(digit_t* a, digit_t* b, digit_t* c, unsigned int nwords)
{ // Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit
unsigned int i, carry = 0;
for (i = 0; i < nwords; i++) {
ADDC(carry, a[i], b[i], carry, c[i]);
}
return carry;
}
__inline void fpexp1251(felm_t a, felm_t af)
{ // Exponentiation over GF(p), af = a^(125-1)
int i;
felm_t t1, t2, t3, t4, t5;
fpsqr1271(a, t2);
fpmul1271(a, t2, t2);
fpsqr1271(t2, t3);
fpsqr1271(t3, t3);
fpmul1271(t2, t3, t3);
fpsqr1271(t3, t4);
fpsqr1271(t4, t4);
fpsqr1271(t4, t4);
fpsqr1271(t4, t4);
fpmul1271(t3, t4, t4);
fpsqr1271(t4, t5);
for (i = 0; i<7; i++) fpsqr1271(t5, t5);
fpmul1271(t4, t5, t5);
fpsqr1271(t5, t2);
for (i = 0; i<15; i++) fpsqr1271(t2, t2);
fpmul1271(t5, t2, t2);
fpsqr1271(t2, t1);
for (i = 0; i<31; i++) fpsqr1271(t1, t1);
fpmul1271(t2, t1, t1);
for (i = 0; i<32; i++) fpsqr1271(t1, t1);
fpmul1271(t1, t2, t1);
for (i = 0; i<16; i++) fpsqr1271(t1, t1);
fpmul1271(t5, t1, t1);
for (i = 0; i<8; i++) fpsqr1271(t1, t1);
fpmul1271(t4, t1, t1);
for (i = 0; i<4; i++) fpsqr1271(t1, t1);
fpmul1271(t3, t1, t1);
fpsqr1271(t1, t1);
fpmul1271(a, t1, af);
}
void fpinv1271(felm_t a)
{ // Field inversion, af = a^-1 = a^(p-2) mod p
// Hardcoded for p = 2^127-1
felm_t t;
fpexp1251(a, t);
fpsqr1271(t, t);
fpsqr1271(t, t);
fpmul1271(a, t, a);
}
static __inline void multiply(const digit_t* a, const digit_t* b, digit_t* c)
{ // Schoolbook multiprecision multiply, c = a*b
mp_mul(a, b, c, NWORDS_ORDER);
}
static __inline unsigned int add(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords)
{ // Multiprecision addition, c = a+b, where lng(a) = lng(b) = nwords. Returns the carry bit
return mp_add((digit_t*)a, (digit_t*)b, c, (unsigned int)nwords);
}
unsigned int subtract(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords)
{ // Multiprecision subtraction, c = a-b, where lng(a) = lng(b) = nwords. Returns the borrow bit
unsigned int i;
unsigned int borrow = 0;
for (i = 0; i < nwords; i++) {
SUBC(borrow, a[i], b[i], borrow, c[i]);
}
return borrow;
}
void subtract_mod_order(const digit_t* a, const digit_t* b, digit_t* c)
{ // Subtraction modulo the curve order, c = a-b mod order
digit_t mask, carry = 0;
digit_t* order = (digit_t*)curve_order;
unsigned int i, bout;
bout = subtract(a, b, c, NWORDS_ORDER); // (bout, c) = a - b
mask = 0 - (digit_t)bout; // if bout = 0 then mask = 0x00..0, else if bout = 1 then mask = 0xFF..F
for (i = 0; i < NWORDS_ORDER; i++) { // c = c + (mask & order)
ADDC(carry, c[i], mask & order[i], carry, c[i]);
}
}
void add_mod_order(const digit_t* a, const digit_t* b, digit_t* c)
{ // Addition modulo the curve order, c = a+b mod order
add(a, b, c, NWORDS_ORDER); // c = a + b
subtract_mod_order(c, (digit_t*)&curve_order, c); // if c >= order then c = c - order
}
void Montgomery_multiply_mod_order(const digit_t* ma, const digit_t* mb, digit_t* mc)
{ // 256-bit Montgomery multiplication modulo the curve order, mc = ma*mb*r' mod order, where ma,mb,mc in [0, order-1]
// ma, mb and mc are assumed to be in Montgomery representation
// The Montgomery constant r' = -r^(-1) mod 2^(log_2(r)) is the global value "Montgomery_rprime", where r is the order
unsigned int i;
digit_t mask, P[2*NWORDS_ORDER], Q[2*NWORDS_ORDER], temp[2*NWORDS_ORDER];
digit_t* order = (digit_t*)curve_order;
unsigned int cout = 0, bout = 0;
multiply(ma, mb, P); // P = ma * mb
multiply(P, (digit_t*)&Montgomery_rprime, Q); // Q = P * r' mod 2^(log_2(r))
multiply(Q, (digit_t*)&curve_order, temp); // temp = Q * r
cout = add(P, temp, temp, 2*NWORDS_ORDER); // (cout, temp) = P + Q * r
for (i = 0; i < NWORDS_ORDER; i++) { // (cout, mc) = (P + Q * r)/2^(log_2(r))
mc[i] = temp[NWORDS_ORDER + i];
}
// Final, constant-time subtraction
bout = subtract(mc, (digit_t*)&curve_order, mc, NWORDS_ORDER); // (cout, mc) = (cout, mc) - r
mask = (digit_t)cout - (digit_t)bout; // if (cout, mc) >= 0 then mask = 0x00..0, else if (cout, mc) < 0 then mask = 0xFF..F
for (i = 0; i < NWORDS_ORDER; i++) { // temp = mask & r
temp[i] = (order[i] & mask);
}
add(mc, temp, mc, NWORDS_ORDER); // mc = mc + (mask & r)
return;
}
void modulo_order(digit_t* a, digit_t* c)
{ // Reduction modulo the order using Montgomery arithmetic
// ma = a*Montgomery_Rprime mod r, where a,ma in [0, r-1], a,ma,r < 2^256
// c = ma*1*Montgomery_Rprime^(-1) mod r, where ma,c in [0, r-1], ma,c,r < 2^256
digit_t ma[NWORDS_ORDER], one[NWORDS_ORDER] = {0};
one[0] = 1;
Montgomery_multiply_mod_order(a, (digit_t*)&Montgomery_Rprime, ma);
Montgomery_multiply_mod_order(ma, one, c);
}
void conversion_to_odd(digit_t* k, digit_t* k_odd)
{// Convert scalar to odd if even using the prime subgroup order r
digit_t i, mask;
digit_t* order = (digit_t*)curve_order;
unsigned int carry = 0;
mask = ~(0 - (k[0] & 1));
for (i = 0; i < NWORDS_ORDER; i++) { // If (k is odd) then k_odd = k else k_odd = k + r
ADDC(carry, order[i] & mask, k[i], carry, k_odd[i]);
}
}
__inline void fpdiv1271(felm_t a)
{ // Field division by two, c = a/2 mod p
digit_t mask;
unsigned int carry = 0;
unsigned int i;
mask = 0 - (a[0] & 1); // if a is odd then mask = 0xFF...FF, else mask = 0
for (i = 0; i < (NWORDS_FIELD-1); i++) {
ADDC(carry, mask, a[i], carry, a[i]);
}
ADDC(carry, (mask >> 1), a[NWORDS_FIELD-1], carry, a[NWORDS_FIELD-1]);
for (i = 0; i < (NWORDS_FIELD-1); i++) {
SHIFTR(a[i+1], a[i], 1, a[i], RADIX);
}
a[NWORDS_FIELD-1] = (a[NWORDS_FIELD-1] >> 1);
}
void fp2div1271(f2elm_t a)
{ // GF(p^2) division by two c = a/2 mod p
fpdiv1271(a[0]);
fpdiv1271(a[1]);
}
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,140 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: main header file
*
* This code is based on the paper "FourQ: four-dimensional decompositions on a
* Q-curve over the Mersenne prime" by Craig Costello and Patrick Longa, in Advances
* in Cryptology - ASIACRYPT, 2015.
* Preprint available at http://eprint.iacr.org/2015/565.
************************************************************************************/
#ifndef __FOURQ_H__
#define __FOURQ_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
// Definition of operating system
#define OS_LINUX 1
#if defined(__LINUX__) // Linux OS
#define OS_TARGET OS_LINUX
#else
#error -- "Unsupported OS"
#endif
// Definition of compiler
#define COMPILER_GCC 1
#define COMPILER_CLANG 2
#if defined(__GNUC__) // GNU GCC compiler
#define COMPILER COMPILER_GCC
#elif defined(__clang__) // Clang compiler
#define COMPILER COMPILER_CLANG
#else
#error -- "Unsupported COMPILER"
#endif
// Definition of the targeted architecture and basic data types
#define TARGET_ARM 1
#if defined(_ARM_)
#define TARGET TARGET_ARM
#define RADIX 32
typedef uint32_t digit_t; // Unsigned 32-bit digit
typedef int32_t sdigit_t; // Signed 32-bit digit
#define NWORDS_FIELD 4
#define NWORDS_ORDER 8
#else
#error -- "Unsupported ARCHITECTURE"
#endif
// Constants
#define RADIX64 64
#define NWORDS64_FIELD 2 // Number of 64-bit words of a field element
#define NWORDS64_ORDER 4 // Number of 64-bit words of an element in Z_r
// Definition of complementary cryptographic functions
#define RandomBytesFunction random_bytes
#define CryptoHashFunction crypto_sha512 // Use SHA-512 by default
// Basic parameters for fixed-base scalar multiplication
#define W_FIXEDBASE 5 // Memory requirement: 7.5KB (storage for 80 points).
#define V_FIXEDBASE 5
// Basic parameters for double scalar multiplication
#define WP_DOUBLEBASE 8 // Memory requirement: 24KB (storage for 256 points).
#define WQ_DOUBLEBASE 4
// Full table randomization selection for additional protection against side-channel attacks
//#define FULL_TABLE_RANDOMIZATION
// FourQ's basic element definitions and point representations
typedef digit_t felm_t[NWORDS_FIELD]; // Datatype for representing 128-bit field elements
typedef felm_t f2elm_t[2]; // Datatype for representing quadratic extension field elements
typedef struct { f2elm_t x; f2elm_t y; } point_affine; // Point representation in affine coordinates.
typedef point_affine point_t[1];
// Definitions of the error-handling type and error codes
typedef enum {
ECCRYPTO_ERROR, // 0x00
ECCRYPTO_SUCCESS, // 0x01
ECCRYPTO_ERROR_DURING_TEST, // 0x02
ECCRYPTO_ERROR_UNKNOWN, // 0x03
ECCRYPTO_ERROR_NOT_IMPLEMENTED, // 0x04
ECCRYPTO_ERROR_NO_MEMORY, // 0x05
ECCRYPTO_ERROR_INVALID_PARAMETER, // 0x06
ECCRYPTO_ERROR_SHARED_KEY, // 0x07
ECCRYPTO_ERROR_SIGNATURE_VERIFICATION, // 0x08
ECCRYPTO_ERROR_END_OF_LIST
} ECCRYPTO_STATUS;
#define ECCRYPTO_STATUS_TYPE_SIZE (ECCRYPTO_ERROR_END_OF_LIST)
// Error message definitions
#define ECCRYPTO_MSG_ERROR "ECCRYPTO_ERROR"
#define ECCRYPTO_MSG_SUCCESS "ECCRYPTO_SUCCESS"
#define ECCRYPTO_MSG_ERROR_DURING_TEST "ECCRYPTO_ERROR_DURING_TEST"
#define ECCRYPTO_MSG_ERROR_UNKNOWN "ECCRYPTO_ERROR_UNKNOWN"
#define ECCRYPTO_MSG_ERROR_NOT_IMPLEMENTED "ECCRYPTO_ERROR_NOT_IMPLEMENTED"
#define ECCRYPTO_MSG_ERROR_NO_MEMORY "ECCRYPTO_ERROR_NO_MEMORY"
#define ECCRYPTO_MSG_ERROR_INVALID_PARAMETER "ECCRYPTO_ERROR_INVALID_PARAMETER"
#define ECCRYPTO_MSG_ERROR_SHARED_KEY "ECCRYPTO_ERROR_SHARED_KEY"
#define ECCRYPTO_MSG_ERROR_SIGNATURE_VERIFICATION "ECCRYPTO_ERROR_SIGNATURE_VERIFICATION"
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,112 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: API header file
*
* This code is based on the paper "FourQ: four-dimensional decompositions on a
* Q-curve over the Mersenne prime" by Craig Costello and Patrick Longa, in Advances
* in Cryptology - ASIACRYPT, 2015.
* Preprint available at http://eprint.iacr.org/2015/565.
************************************************************************************/
#ifndef __FOURQ_API_H__
#define __FOURQ_API_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
#include "FourQ.h"
/**************** Public ECC API ****************/
// Set generator G = (x,y)
void eccset(point_t G);
// Variable-base scalar multiplication Q = k*P using a 4-dimensional decomposition and protected against side-channel attacks
bool ecc_mul_SCA_secure(point_t P, point_t R, digit_t* k, point_t Q, bool clear_cofactor);
// Double scalar multiplication R = k*G + l*Q, where G is the generator
bool ecc_mul_double(digit_t* k, point_t Q, digit_t* l, point_t R);
/**************** Public API for SchnorrQ ****************/
// SchnorrQ public key generation
// It produces a blinding point BlindingPoint and a public key PublicKey, which is the encoding of P = s*G, where G is the generator and
// s is the output of hashing SecretKey and taking the least significant 32 bytes of the result.
// Input: 32-byte SecretKey
// Output: 32-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS SchnorrQ_KeyGeneration_SCA_secure(const unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint);
// SchnorrQ keypair generation
// It produces a blinding point BlindingPoint, a private key SecretKey and computes the public key PublicKey, which is the encoding of P = s*G,
// where G is the generator and s is the output of hashing SecretKey and taking the least significant 32 bytes of the result.
// Outputs: 32-byte SecretKey, 32-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS SchnorrQ_FullKeyGeneration_SCA_secure(unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint);
// SchnorrQ signature generation
// It produces the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte SecretKey, 32-byte PublicKey, Message of size SizeMessage in bytes, and 64-byte BlindingPoint
// Output: 64-byte Signature
ECCRYPTO_STATUS SchnorrQ_Sign_SCA_secure(const unsigned char* SecretKey, const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, unsigned char* Signature, unsigned char* BlindingPoint);
// SchnorrQ signature verification
// It verifies the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte PublicKey, 64-byte Signature, and Message of size SizeMessage in bytes
// Output: true (valid signature) or false (invalid signature)
ECCRYPTO_STATUS SchnorrQ_Verify(const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, const unsigned char* Signature, unsigned int* valid);
/**************** Public API for co-factor ECDH key exchange with compressed, 32-byte public keys ****************/
// Compressed public key generation for key exchange
// It produces a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator), and a blinding point BlindingPoint.
// Input: 32-byte SecretKey
// Output: 32-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS CompressedPublicKeyGeneration_SCA_secure(const unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint);
// Keypair generation for key exchange. Public key is compressed to 32 bytes
// It produces a private key SecretKey, a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator), and a blinding point BlindingPoint.
// Outputs: 32-byte SecretKey, 32-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS CompressedKeyGeneration_SCA_secure(unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint);
// Secret agreement computation for key exchange using a compressed, 32-byte public key
// The output is the y-coordinate of SecretKey*A, where A is the decoding of the public key PublicKey.
// Inputs: 32-byte SecretKey, 32-byte PublicKey and 64-byte BlindingPoint
// Output: 32-byte SharedSecret
ECCRYPTO_STATUS CompressedSecretAgreement_SCA_secure(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret, unsigned char* BlindingPoint);
/**************** Public API for co-factor ECDH key exchange with uncompressed, 64-byte public keys ****************/
// Public key generation for key exchange
// It produces the public key PublicKey = SecretKey*G, where G is the generator, and a blinding point BlindingPoint.
// Input: 32-byte SecretKey
// Output: 64-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS PublicKeyGeneration_SCA_secure(const unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint);
// Keypair generation for key exchange
// It produces a private key SecretKey, the public key PublicKey = SecretKey*G, where G is the generator, and a blinding point BlindingPoint.
// Outputs: 32-byte SecretKey, 64-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS KeyGeneration_SCA_secure(unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint);
// Secret agreement computation for key exchange
// The output is the y-coordinate of SecretKey*PublicKey.
// Inputs: 32-byte SecretKey, 64-byte PublicKey and 64-byte BlindingPoint
// Output: 32-byte SharedSecret
ECCRYPTO_STATUS SecretAgreement_SCA_secure(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret, unsigned char* BlindingPoint);
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,331 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: internal header file
*
* This code is based on the paper "FourQ: four-dimensional decompositions on a
* Q-curve over the Mersenne prime" by Craig Costello and Patrick Longa, in Advances
* in Cryptology - ASIACRYPT, 2015.
* Preprint available at http://eprint.iacr.org/2015/565.
************************************************************************************/
#ifndef __FOURQ_INTERNAL_H__
#define __FOURQ_INTERNAL_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
#include "FourQ_api.h"
// Extended datatype definition
typedef uint64_t uint128_t[2];
// Basic parameters for fixed-base scalar multiplication
#define NBITS_ORDER_PLUS_ONE 246+1
#define E_FIXEDBASE (NBITS_ORDER_PLUS_ONE + W_FIXEDBASE*V_FIXEDBASE - 1)/(W_FIXEDBASE*V_FIXEDBASE)
#define D_FIXEDBASE E_FIXEDBASE*V_FIXEDBASE
#define L_FIXEDBASE D_FIXEDBASE*W_FIXEDBASE
#define NPOINTS_FIXEDBASE V_FIXEDBASE*(1 << (W_FIXEDBASE-1))
#define VPOINTS_FIXEDBASE (1 << (W_FIXEDBASE-1))
#if (NBITS_ORDER_PLUS_ONE-L_FIXEDBASE == 0) // This parameter selection is not supported
#error -- "Unsupported parameter selection for fixed-base scalar multiplication"
#endif
// Basic parameters for double scalar multiplication
#define NPOINTS_DOUBLEMUL_WP (1 << (WP_DOUBLEBASE-2))
#define NPOINTS_DOUBLEMUL_WQ (1 << (WQ_DOUBLEBASE-2))
// FourQ's point representations
typedef struct { f2elm_t x; f2elm_t y; f2elm_t z; f2elm_t t; } point_extedwards; // Point representation in extended twisted Edwards coordinates.
typedef point_extedwards point_extedwards_t[1];
typedef struct { f2elm_t x; f2elm_t y; f2elm_t z; f2elm_t ta; f2elm_t tb; } point_extproj; // Point representation in extended coordinates.
typedef point_extproj point_extproj_t[1];
typedef struct { f2elm_t xy; f2elm_t yx; f2elm_t z2; f2elm_t t2; } point_extproj_precomp; // Point representation in extended coordinates (for precomputed points).
typedef point_extproj_precomp point_extproj_precomp_t[1];
typedef struct { f2elm_t xy; f2elm_t yx; f2elm_t t2; } point_precomp; // Point representation in extended affine coordinates (for precomputed points).
typedef point_precomp point_precomp_t[1];
/********************** Constant-time unsigned comparisons ***********************/
// The following functions return 1 (TRUE) if condition is true, 0 (FALSE) otherwise
static __inline unsigned int is_digit_nonzero_ct(digit_t x)
{ // Is x != 0?
return (unsigned int)((x | (0-x)) >> (RADIX-1));
}
static __inline unsigned int is_digit_zero_ct(digit_t x)
{ // Is x = 0?
return (unsigned int)(1 ^ is_digit_nonzero_ct(x));
}
static __inline unsigned int is_digit_lessthan_ct(digit_t x, digit_t y)
{ // Is x < y?
return (unsigned int)((x ^ ((x ^ y) | ((x - y) ^ y))) >> (RADIX-1));
}
/********************** Macros for digit operations **********************/
// Digit multiplication
#define MUL(multiplier, multiplicand, hi, lo) \
digit_x_digit((multiplier), (multiplicand), &(lo));
// Digit addition with carry
#define ADDC(carryIn, addend1, addend2, carryOut, sumOut) \
{ digit_t tempReg = (addend1) + (digit_t)(carryIn); \
(sumOut) = (addend2) + tempReg; \
(carryOut) = (is_digit_lessthan_ct(tempReg, (digit_t)(carryIn)) | is_digit_lessthan_ct((sumOut), tempReg)); }
// Digit subtraction with borrow
#define SUBC(borrowIn, minuend, subtrahend, borrowOut, differenceOut) \
{ digit_t tempReg = (minuend) - (subtrahend); \
unsigned int borrowReg = (is_digit_lessthan_ct((minuend), (subtrahend)) | ((borrowIn) & is_digit_zero_ct(tempReg))); \
(differenceOut) = tempReg - (digit_t)(borrowIn); \
(borrowOut) = borrowReg; }
// Shift right with flexible datatype
#define SHIFTR(highIn, lowIn, shift, shiftOut, DigitSize) \
(shiftOut) = ((lowIn) >> (shift)) ^ ((highIn) << (DigitSize - (shift)));
// 64x64-bit multiplication
#define MUL128(multiplier, multiplicand, product) \
mp_mul((digit_t*)&(multiplier), (digit_t*)&(multiplicand), (digit_t*)&(product), NWORDS_FIELD/2);
// 128-bit addition, inputs < 2^127
#define ADD128(addend1, addend2, addition) \
mp_add((digit_t*)(addend1), (digit_t*)(addend2), (digit_t*)(addition), NWORDS_FIELD);
// 128-bit addition with output carry
#define ADC128(addend1, addend2, carry, addition) \
(carry) = mp_add((digit_t*)(addend1), (digit_t*)(addend2), (digit_t*)(addition), NWORDS_FIELD);
/**************** Function prototypes ****************/
/************* Arithmetic functions modulo the curve order **************/
// Converting to Montgomery representation
void to_Montgomery(const digit_t* ma, digit_t* c);
// Converting from Montgomery to standard representation
void from_Montgomery(const digit_t* a, digit_t* mc);
// 256-bit Montgomery multiplication modulo the curve order
void Montgomery_multiply_mod_order(const digit_t* ma, const digit_t* mb, digit_t* mc);
// Addition modulo the curve order, c = a+b mod order
void add_mod_order(const digit_t* a, const digit_t* b, digit_t* c);
// Subtraction modulo the curve order, c = a-b mod order
void subtract_mod_order(const digit_t* a, const digit_t* b, digit_t* c);
// Reduction modulo the order using Montgomery arithmetic internally
void modulo_order(digit_t* a, digit_t* c);
/************* Multiprecision functions **************/
// Check if multiprecision element is zero
bool is_zero_ct(digit_t* a, unsigned int nwords);
// Multiprecision addition, c = a+b. Returns the carry bit
unsigned int mp_add(digit_t* a, digit_t* b, digit_t* c, unsigned int nwords);
// Schoolbook multiprecision multiply, c = a*b
void mp_mul(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords);
// Multiprecision subtraction, c = a-b. Returns the borrow bit
unsigned int subtract(const digit_t* a, const digit_t* b, digit_t* c, const unsigned int nwords);
// Clear "nwords" integer-size digits from memory
extern void clear_words(void* mem, unsigned int nwords);
/************ Field arithmetic functions *************/
// Copy of a field element, c = a
void fpcopy1271(felm_t a, felm_t c);
// Field negation, a = -a mod p
void fpneg1271(felm_t a);
// Integer multiplication, c = a*b
void mul1271_a(felm_t a, felm_t b, felm_t c);
// Modular correction, a = a mod p
void mod1271(felm_t a);
void mod1271_a(felm_t a, felm_t c);
// Field addition, c = a+b mod p
void fpadd1271(felm_t a, felm_t b, felm_t c);
void fpadd1271_a(felm_t a, felm_t b, felm_t c);
// Field subtraction, c = a-b mod p
void fpsub1271(felm_t a, felm_t b, felm_t c);
void fpsub1271_a(felm_t a, felm_t b, felm_t c);
// Field division by two, c = a/2 mod p
void fpdiv1271(felm_t a);
// Field multiplication, c = a*b mod p
void fpmul1271(felm_t a, felm_t b, felm_t c);
// Field squaring, c = a^2 mod p
void fpsqr1271(felm_t a, felm_t c);
// Field inversion, af = a^-1 = a^(p-2) mod p
void fpinv1271(felm_t a);
// Exponentiation over GF(p), af = a^(125-1)
void fpexp1251(felm_t a, felm_t af);
/************ Quadratic extension field arithmetic functions *************/
// Zeroing a quadratic extension field element, a=0
void fp2zero1271(f2elm_t a);
// Copy quadratic extension field element, c = a
void fp2copy1271(f2elm_t a, f2elm_t c);
// Quadratic extension field negation, a = -a in GF((2^127-1)^2)
void fp2neg1271(f2elm_t a);
// Quadratic extension field addition, c = a+b in GF((2^127-1)^2)
void fp2add1271(f2elm_t a, f2elm_t b, f2elm_t c);
void fp2add1271_a(f2elm_t a, f2elm_t b, f2elm_t c);
// Quadratic extension field subtraction, c = a-b in GF((2^127-1)^2)
void fp2sub1271(f2elm_t a, f2elm_t b, f2elm_t c);
void fp2sub1271_a(f2elm_t a, f2elm_t b, f2elm_t c);
// Quadratic extension field multiplication, c = a*b in GF((2^127-1)^2)
void fp2mul1271(f2elm_t a, f2elm_t b, f2elm_t c);
void fp2mul1271_a(f2elm_t a, f2elm_t b, f2elm_t c);
// Quadratic extension field squaring, c = a^2 in GF((2^127-1)^2)
void fp2sqr1271(f2elm_t a, f2elm_t c);
void fp2sqr1271_a(f2elm_t a, f2elm_t c);
// Quadratic extension field inversion, af = a^-1 = a^(p-2) in GF((2^127-1)^2)
void fp2inv1271(f2elm_t a);
/************ Curve and recoding functions *************/
// Normalize projective twisted Edwards point Q = (X,Y,Z) -> P = (x,y)
void eccnorm(point_extedwards_t P, point_t Q);
// Normalize two projective points, including full reduction
void eccnorm2(point_extedwards_t P, point_t Q, point_extedwards_t R, point_t S);
// Conversion from representation (X,Y,Z,Ta,Tb) to (X+Y,Y-X,2Z,2dT), where T = Ta*Tb
void R1_to_R2(point_extproj_t P, point_extproj_precomp_t Q);
// Point doubling 2P
void eccdouble(point_extedwards_t P);
// Complete point addition P = P+Q or P = P+P
void eccadd(point_extedwards_t P, point_extedwards_t Q, point_extedwards_t R);
void eccadd_core(point_extedwards_t P, point_extedwards_t Q, point_extedwards_t R, f2elm_t Ta, f2elm_t Tb);
// Psi mapping of a point, P = psi(P)
void ecc_psi(point_extedwards_t P);
// Phi mapping of a point, P = phi(P)
void ecc_phi(point_extedwards_t P);
// Scalar decomposition
void decompose(uint64_t* k, uint64_t* scalars);
// Generate random field element in [0, 2^127-1]
void random_felmt(felm_t random);
// Scalar randomization for variable-base scalar multiplication
void randomize(uint64_t* scalars, unsigned char* r, uint128_t* random_scalars);
// Randomization of point coordinates using a random field element
void felmt_randomize_point(point_extedwards_t P, felm_t random);
// Randomization of all the point coordinates in the precomputed table using a random element in GF(p^2)
void randomize_table(point_extedwards_t* Table, felm_t random);
// Recoding sub-scalars for use in the variable-base scalar multiplication
void recode(uint128_t* scalars, unsigned int* digits);
// Computes the fixed window representation of scalar
void fixed_window_recode(uint64_t* scalar, unsigned int* digits, unsigned int* sign_masks);
// Convert scalar to odd if even using the prime subgroup order r
void conversion_to_odd(digit_t* k, digit_t* k_odd);
// Co-factor clearing
void cofactor_clearing(point_extedwards_t P);
// Reduction modulo the order using Montgomery arithmetic
void modulo_order(digit_t* a, digit_t* c);
// Generation of the precomputation table used by the variable-base scalar multiplication ecc_mul_SCA_secure()
void ecc_precomp(point_extedwards_t P, point_extedwards_t R, point_extedwards_t *Table);
// Constant-time table lookup to extract an extended twisted Edwards point (X:Y:Z:T) from the precomputed table
void table_lookup_1x16(point_extedwards_t* table, point_extedwards_t P, unsigned int digit);
// Modular correction of input coordinates and conversion to representation (X,Y,Z,Ta,Tb)
void point_setup(point_t P, point_extedwards_t Q);
// Point validation: check if point lies on the curve
bool ecc_point_validate(point_extedwards_t P);
// Output error/success message for a given ECCRYPTO_STATUS
const char* FourQ_get_error_message(ECCRYPTO_STATUS Status);
// Generation of the precomputation table used internally by the double scalar multiplication function ecc_mul_double()
void ecc_precomp_double(point_extedwards_t P, point_extedwards_t* Table, unsigned int npoints);
// Computes wNAF recoding of a scalar
void wNAF_recode(uint64_t scalar, unsigned int w, int* digits);
// Encode point P
void encode(point_t P, unsigned char* Pencoded);
// Decode point P
ECCRYPTO_STATUS decode(const unsigned char* Pencoded, point_t P);
/************ Functions based on macros *************/
// Copy extended projective point Q = (X:Y:Z:T) to P
#define ecccopy(Q, P); fp2copy1271((Q)->x, (P)->x); \
fp2copy1271((Q)->y, (P)->y); \
fp2copy1271((Q)->z, (P)->z); \
fp2copy1271((Q)->t, (P)->t);
// Copy extended projective point Q = (X+Y,Y-X,2Z,2dT) to P
#define ecccopy_precomp(Q, P); fp2copy1271((Q)->xy, (P)->xy); \
fp2copy1271((Q)->yx, (P)->yx); \
fp2copy1271((Q)->z2, (P)->z2); \
fp2copy1271((Q)->t2, (P)->t2);
// Copy extended affine point Q = (x+y,y-x,2dt) to P
#define ecccopy_precomp_fixed_base(Q, P); fp2copy1271((Q)->xy, (P)->xy); \
fp2copy1271((Q)->yx, (P)->yx); \
fp2copy1271((Q)->t2, (P)->t2);
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,33 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: FourQ's curve parameters
*
* This code is based on the paper "FourQ: four-dimensional decompositions on a
* Q-curve over the Mersenne prime" by Craig Costello and Patrick Longa, in Advances
* in Cryptology - ASIACRYPT, 2015.
* Preprint available at http://eprint.iacr.org/2015/565.
************************************************************************************/
#ifndef __FOURQ_PARAMS_H__
#define __FOURQ_PARAMS_H__
#include "FourQ_internal.h"
// Encoding of field elements, elements over Z_r and elements over GF(p^2):
// -----------------------------------------------------------------------
// Elements over GF(p) and Z_r are encoded with the least significant digit located in the leftmost position (i.e., little endian format).
// Elements (a+b*i) over GF(p^2), where a and b are defined over GF(p), are encoded as a||b, with a in the least significant position.
static const uint64_t PARAMETER_d[4] = { 0x0000000000000142, 0x00000000000000E4, 0xB3821488F1FC0C8D, 0x5E472F846657E0FC };
static const uint64_t GENERATOR_x[4] = { 0x286592AD7B3833AA, 0x1A3472237C2FB305, 0x96869FB360AC77F6, 0x1E1F553F2878AA9C };
static const uint64_t GENERATOR_y[4] = { 0xB924A2462BCBB287, 0x0E3FEE9BA120785A, 0x49A7C344844C8B5C, 0x6E1C4AF8630E0242 };
static const uint64_t curve_order[4] = { 0x2FB2540EC7768CE7, 0xDFBD004DFE0F7999, 0xF05397829CBC14E5, 0x0029CBC14E5E0A72 };
static const uint64_t Montgomery_Rprime[4] = { 0xC81DB8795FF3D621, 0x173EA5AAEA6B387D, 0x3D01B7C72136F61C, 0x0006A5F16AC8F9D3 };
static const uint64_t Montgomery_rprime[4] = { 0xE12FE5F079BC3929, 0xD75E78B8D1FCDCF3, 0xBCE409ED76B5DB21, 0xF32702FDAFC1C074 };
#endif

Просмотреть файл

@ -0,0 +1,278 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: precomputation tables
************************************************************************************/
#ifndef __TABLES_H__
#define __TABLES_H__
#include <stddef.h>
// The table below consists of four mini-tables each generated using window width W = 8.
// Number of point entries = 4 * 2^6 = 256 points, where each point (x,y) is represented using coordinates (x+y,y-x,2*d*t).
// Table size = 256 * 3 * 256 = 24KB
static const uint64_t DOUBLE_SCALAR_TABLE[3072] = {
0xe18a34f3a703e631, 0x287460bf1d502b5f, 0xe02e62f7e4f90353, 0x0c3ba0378b86acde, 0x90bf0f98b0937edc, 0x740b7c7824f0c555, 0xb321239123a01366, 0x4ffcf5b93a9557a5, 0x297afccbabda42bb, 0x5948d137556c97c6, 0xa8189a393330684c, 0x0caf2b720a341f27
, 0x892756b15bcf68c4, 0x5742f77c98a526ba, 0x340a5a1de9f89f9b, 0x14ef680aee75d0f7, 0x84e770e14043a41f, 0x0212c41116c33c95, 0x35b791e6de4dc0e2, 0x5949df08518d5d28, 0x6a0e120744ed10db, 0x5a5183ce844391d3, 0x6f618b158afdba50, 0x2ce2037e470e2088
, 0x1f49fa149a64ba3c, 0x5f9876d519670451, 0x030105056f55586b, 0x020f1a557d8fd726, 0xdf4cb175b06d86c8, 0x694fbcbe7fe58390, 0x7933294a756a1b67, 0x09dbe9924b58f8ec, 0x590f4403cdf197b6, 0x1c07969fc87a0ba7, 0xc496477712252367, 0x5508976022f1b096
, 0xefda361e452e1775, 0x7a0a0cccacc838fb, 0xb07e791c0be5dc5f, 0x24d9b6b418cbcb93, 0x497970f3c6117e03, 0x3986a158cb96d595, 0x8f80586ce692612b, 0x305cafda7e4df9d6, 0xc1a1c2e06452914a, 0x7ef989c0eb583079, 0x3a765b1f7364b099, 0x4fee236d58299c6b
, 0x6f81095f770e8419, 0x53bbd86b7396bc09, 0x2b72ba726b2b4210, 0x625dda1d2901c78b, 0x0ff5bc7b18cd2b3e, 0x0556598c7358d332, 0x0991245f20ff50d7, 0x0e7f58e5e919a97e, 0x5a0561373b758756, 0x6447bc93f87c198a, 0xf9230604c34c7520, 0x6b214425475c1bfa
, 0xe93de62d6a7f9497, 0x2129459d86f4493c, 0x456394c7c464cfe4, 0x612434fec3f4a1b3, 0x1ed91eddf44261f3, 0x0c6d3854f9e0a3ff, 0xd3fd153188a7e4e3, 0x24691fbdca16910c, 0xbe97465cd7625c9d, 0x2aa61cd373f759f4, 0x824d5763a326d62b, 0x1a0ae39e50da20ba
, 0x32d0c8481ee4c3b9, 0x6c3687109cdd18c6, 0xe52717142fbf95da, 0x67bfa41fb52ce9c6, 0x4e24d6a088a01474, 0x49a6ca0ae3fb6626, 0xd67f8faa9103191e, 0x674888f5aa6d3062, 0x4ba73824c2e85a99, 0x406b2fd18d35b314, 0xa7087b1bea728ac1, 0x11d2f222317b160e
, 0xf8946e007e23a469, 0x22a196fabbce31a2, 0x5309ee1bdc1216ba, 0x240fe9953827a324, 0xf9fcb89b63aeb5c7, 0x603b8149ed16b1b0, 0xb1f1876c02cf61fb, 0x4a5e32af612f948b, 0xfc491aede69a8813, 0x1ad9379136e53aa5, 0x5da50db1d5e6c123, 0x2f4014f7fe2c12ca
, 0xe4f6791d7685c3f5, 0x4c218521c3745a9b, 0x0c0521af98555f97, 0x1462a12953cada7b, 0x0bb2ab63d6452c1b, 0x5783c531ec98bb87, 0x737def53605dbc9c, 0x49f982b930e86719, 0x75b16790cb5211e3, 0x45ad6574cdbae99e, 0x1062b72dfeec9851, 0x45029a09cc468c88
, 0x532240de77f3a1f2, 0x17bd291eaa9ad0ea, 0xe0a2d7efc2f8a0a0, 0x3a7412052021778e, 0xb0dfb0976acc90df, 0x7fd603b689a7b1f3, 0x1152579ccb00d6c6, 0x6340743b631849a3, 0xebaa47290e0cda01, 0x143265a6d53fef0b, 0x45325d6fd981e75a, 0x0e9780cc39586f2a
, 0xa4f68d207a8628dd, 0x50d230b51893e841, 0xf3bd769a4bb504b6, 0x55975c063969292e, 0x07727ba25fb8756f, 0x07ff86cf8ed731fd, 0xef57fa40cc35a1f0, 0x70753a70874218fc, 0x615954e2342b973c, 0x5aa9d68f1a59df86, 0x3b8e9e9ff5e44468, 0x2e749114d60a3d23
, 0x14a1b91ec176db4b, 0x55f91a63d69aae6d, 0xf42382327b1b6d27, 0x2acf1f475facaafd, 0xfd9069b479b58968, 0x3baaf4e5c4a45f77, 0xa2ac9ab98a7aaab6, 0x5466cb5018f50981, 0x3e6ba27771ba3205, 0x31ea90cdea1bbbe4, 0x0000416b5c557393, 0x464cb0415a510d7d
, 0xd02087d206ff2bbf, 0x2b9c8ecd7fabe736, 0xb2b56d3842caab0d, 0x046ea0b7767700a7, 0x113a7a889e317310, 0x5992a354bef7d0ca, 0x3edda94ed50388bd, 0x052661f767839154, 0x4c28edf6e19e28e0, 0x1d19c2f2d2f644e5, 0x5d732148db35ab3d, 0x680c4714b83580f5
, 0xa374f282bb80ccec, 0x789e609bc77ae11c, 0x10d2577d599b45f2, 0x1c548b5b857721b1, 0x7baea726b4543fdf, 0x3c1562912d1b4ed2, 0xd6362203b7e82082, 0x1414e523d3c7a900, 0x7ca349951c1d23a9, 0x4da4265e3ce80fb4, 0x7981ebbcaca9ef36, 0x4ebac9e5b5bf980b
, 0xabd2c1dcf49cb5a4, 0x3f54acfc25c6340f, 0x202eeffabbd11cbd, 0x67216b7cb3695e8c, 0xff7cbcf9b23fc9f1, 0x2eebebdff7fa7afb, 0x71156befa111f85e, 0x1b8fd98df522902c, 0x6b28ebad62519791, 0x6cf0ea960e01d8ed, 0xb4617bc2006967d5, 0x323da065cb3df0ad
, 0x31687d0741e24d9c, 0x02db8f2b509a7cc2, 0x9243f85924320527, 0x68c360f01d6e6d2b, 0x2351c5e877d5306a, 0x6f56ccfc85c5f3a9, 0x1b09652837c4928f, 0x0b3337554c83f971, 0xe2931be2ccc783ec, 0x46829694ba08c64f, 0x9f35e36358e2c6ac, 0x1474b333b000d170
, 0x24d792756fc96640, 0x618fda9fef868c5e, 0xb7ff5b125afd9375, 0x778dd97e0440c258, 0xfbff314886219627, 0x3417e1e1e2a7e811, 0x21e959a88f7b7bdc, 0x3508c2eb8c3c8672, 0x827ecdde111c430f, 0x21bcb19fb07aa134, 0xe0c1fa50ab2f5746, 0x401e680b4e6658fa
, 0x2cc24bab313693cc, 0x20541c12b964447a, 0x374975b6fb81c3cc, 0x52905efb344e17f7, 0x79c5c9b56d8b5f9e, 0x3390bf75d2b9a3ec, 0x7ef3807d895bf4e4, 0x2814165a42046b51, 0x7f8cfd09326fe158, 0x3232fb4f4c9762ec, 0x5678d6dacc194d25, 0x6f7caffb0a7545e8
, 0xbd981637b23e7963, 0x691d7b7cb88a0ef5, 0x10ba319ae2062914, 0x06fb144f8295a85b, 0x80e620976bf62f8f, 0x2a425971ec73d6b4, 0x800aa9e741d10b1c, 0x230d7d8bd1a0469b, 0x65aace37428dfe8c, 0x0fcab5297f58b667, 0xcf0e9526943af7b8, 0x7d90915b75d4dae7
, 0x7455a46156259d6b, 0x29bcc06374cce1b5, 0xf2fb0ed3aa87aefd, 0x211a06af0e54dd58, 0x6c0c95c5723de9bc, 0x6299b6ed25008ca7, 0x7fd63e784d4dfb18, 0x2cc93b4d9bc1db30, 0xebc7e2d44c5d13ea, 0x3278e18d4d3d11a0, 0x349e3dd25a215f79, 0x7eb2a7150b30416d
, 0x05f3d7d5f6a094cb, 0x2a3771d48e331405, 0x08ef39e9dc96f009, 0x012248373a364992, 0xf758f92fc9fd4d33, 0x2339d8c6dfd3ca6c, 0x8b000965962673b4, 0x746ff43eb99d9054, 0x47ecdc054a422eff, 0x33d8f7c8267b7f0c, 0x22fe00ac921a42ae, 0x31e57f3d31fcd8e6
, 0xbb912315a1c50869, 0x4ac8cdb0fa7ebbaf, 0x0541d74a60973edf, 0x7234900334b2c5d7, 0xf2e545f730adfa33, 0x224e44e63db5ac96, 0xfcba3d005c6fdeb9, 0x2c93a4e6559936b5, 0x7727a0d7ad88d758, 0x2e33100216719cdd, 0x7b2ef89aeb2c0254, 0x1f6de5b74758afb4
, 0x6ae89047114fb321, 0x3d605e9a6ec6d80d, 0x18e915c727a874d8, 0x699088b5e9d0912f, 0xaf9344618e056f10, 0x1b9169df8245e0b3, 0x5eb8c33d70f4c891, 0x1609ddfb222b13c3, 0x8131c885d1b366ed, 0x7bc3cf9d9cb1a7b0, 0xd297478d2fc93968, 0x13cbb4573a4ea7f5
, 0xdd37b5cc64d5986b, 0x7ed3d1d7d81ab5dc, 0xac53485f23973c9e, 0x0705675d333b91d7, 0xade5d213c43186c1, 0x6a8bdf57b4bfdf14, 0xa87f88a1de717963, 0x17f29220b519bce2, 0x7af2d7fb0f95c610, 0x28d1d3923b144a7c, 0x8e73c3d8972813e1, 0x00100b40c62e72c1
, 0x84de7a81fa1f50da, 0x4fa391d6589d8244, 0xbcc3596f0834b285, 0x4d4acbd60a24e9ce, 0x97fa98b8c1835a0d, 0x33abcf8e29901d0b, 0x60a73d1975b3d082, 0x60666aa4325b948d, 0xad54adb769284a39, 0x227a98d113609b28, 0x4a1e1ffcae6a3872, 0x1e4ee44bd67f818c
, 0x5a74c6bb4387d315, 0x019428c0b1b18795, 0x5cc153e270bbb055, 0x2b3cabdf00dc4a61, 0x834110c026924b57, 0x2d30e985f2d9f217, 0x47116979333389f5, 0x53e3fd6a18202417, 0xb1393cd79c2e5864, 0x58d92935e4112e82, 0x86989a7ec8305b6d, 0x42a8fe4eee28f37a
, 0x74e212ef01591901, 0x3277917a0397b1b9, 0x7bbcbe6e3d687544, 0x0b8957701d09afb6, 0x6cfbc8ee74503668, 0x48a9925ada9f8348, 0x57045753ba2d0f4e, 0x7d69ca3866223d66, 0xc7054ce22917271f, 0x41bce1e1133b51de, 0x3a3ae42df81ec35e, 0x7eaada0f42d47cc3
, 0x13b138f1048a57cc, 0x64f98abd7e915a8f, 0x7af195eb16a0c732, 0x11be81a791d634d2, 0x97d8df47430f61b8, 0x0767c7b381271004, 0x3e949136fb940aa6, 0x3bdee340cd956dba, 0xb250ec4ff91d2602, 0x4cde2454d47f59db, 0xaf5e749530d978cb, 0x5a8e2f2119d4d835
, 0xdf1cb5425a0744df, 0x3d3b08a7bf35d055, 0xc6335e832de4719c, 0x6eb8d97e09154d42, 0x2f6a3f8de3d20dd9, 0x13f23cfd276233da, 0xb4a6b80dfc0fa41c, 0x58d876403acfd7d7, 0x2ad422078b8e139b, 0x73dbee2abbaf494d, 0x09a2758891eca3c8, 0x6ef9a9f1178b0938
, 0xfc7e9ecb90c637da, 0x3a04345fc10b1a7c, 0xc024e9cb62f9ff1f, 0x6c4f9c3aa4aa33d8, 0x049d6995b95ac1f0, 0x2243845195763a1b, 0xa1466a31700ac276, 0x600fb7123a325905, 0x9d391a64a0d35a24, 0x3b093b550641f108, 0x2275de5bfd2e221f, 0x25f5e7465963db1e
, 0x3e220107f7e7fb84, 0x6f06a23bc1b85a8e, 0xb4198d19f6eb0e48, 0x5dc11761dad45fda, 0xba303e492ab52a0d, 0x127c69c73da9f528, 0xd3a5b70cf6c790be, 0x0d72b0c50819da5c, 0x193f90d62ec2cdf7, 0x67f7d0cfc4f46daf, 0x7aec083d52f380ea, 0x7c0a1dda4a28bf4d
, 0x46fd20fe6008cba7, 0x7a588c914115d595, 0x8fb1d3daecf45f78, 0x0851dac094e7b036, 0xcae0a76e2a32a892, 0x104f861322dddb2f, 0xb79d81e46e1f9006, 0x1e4d28d7a2498912, 0xaf3175d3974b89bf, 0x613d00f9a69c55c2, 0x23f6883e8e65226f, 0x072f7ed65c6def05
, 0x6690e643bb38e243, 0x1a81c4a7c9189b15, 0x1056d1669e4749ae, 0x0137f2a7418f190c, 0xed3192796e699d16, 0x3ed76db45c38a37c, 0x78e86d1475a88243, 0x45985aacc495b16e, 0x47d5c8208e8f1030, 0x6dbe5f68b4d0e782, 0x08d3d0182cf7f26b, 0x64c375ce172fadbd
, 0xba0f6db3a20c2875, 0x57e1d90a53241250, 0x0315433fddf8e63e, 0x33344750e37dad9b, 0x62cc0d28ae69b016, 0x435fe80f6100d547, 0x5874aea8669d3df5, 0x3b96913f8264d4a9, 0x738067d6bb1314b0, 0x48cccf24cc6f4ccf, 0x6f5e2bbd68b777af, 0x34c2c37ba9635d66
, 0xd731534900fdbe5b, 0x4e4f9d97afe11d43, 0x81b41214351b73d7, 0x1d48d100ad11a5ae, 0x2a4ee76628e2b151, 0x34902e901877efb8, 0xb5a8561a0fd45394, 0x44317af6d5cd5ac0, 0x354c2469e9068bad, 0x0771fe2761cad022, 0xfda76ee8212d0f2b, 0x76cdeec6d4435495
, 0x55c98575b3e825fd, 0x2983325ed5d73a1b, 0x563c4c4fb3f466e7, 0x731b0fa413338bb0, 0xdeb519ca57a05240, 0x7a7e909b5c4f7351, 0xefb7c153dd2ab28e, 0x11ca1c865dee30b3, 0x013ca8348d9d7de1, 0x575e0bdaeee8cf9a, 0x464c98a21083af7f, 0x683ddcd85c212ee3
, 0x1171f0ab4cd02019, 0x22c7e01c7f4d64c8, 0x972ec0ef3f2e2ed3, 0x623f83c2611a476c, 0x99b3f16be9aa25a1, 0x2d3ebc5468990e0b, 0x5d5fba8546a4d5f2, 0x4716e6919d2986e3, 0x3ab2f2bc183f5d6c, 0x5f6257d3910cd4be, 0x341c6f2a78f94f2b, 0x6ee8390b8a5064f5
, 0x9d8640b9b83ca8e7, 0x033c5ad24466be3d, 0x6f6cd68db30dfd59, 0x52aa6b1c0f90f3f6, 0xfe7bcd4c97403646, 0x11ab3fc960b05fb0, 0x24584b77575896da, 0x427f8deb932da137, 0x928a28cb505306f0, 0x04ae916fe863820e, 0xaabaa98911b9cd3f, 0x59e588ba994d9145
, 0x9b8f1afabeee9e9f, 0x04ffc7ef3476ff8e, 0xe9cf53ce9937b146, 0x73fe42a801524448, 0x224bda3cf3bbaaad, 0x5fa85056d59884a4, 0x8e6eead48345726b, 0x09230936d41736d2, 0xe679eb58d1ad6be7, 0x08bb759b530b1eaf, 0x9688eb527860e24b, 0x13704d2daf9af278
, 0xd9273ac71b906f14, 0x57ee05fbbd40deb5, 0xb7788e19ba9e61eb, 0x7967b6dc1c5d9699, 0x36e043fc230127c0, 0x2a716598bb2d519c, 0xc017b2840d4d1b07, 0x1d3bfa489f756a3f, 0x4ad73abf24318d36, 0x1915e6f53e12625d, 0xb219a7c941f89084, 0x2280087a8f4762fc
, 0x8eb280345fd1b4e7, 0x55b8d4ee5772fd79, 0xc9e63a787e2ce2e1, 0x685741adbda93885, 0xffb830ab11a3b491, 0x7e891121f9356428, 0xc03aea271a629078, 0x71c45932930a2639, 0xe7df192a6bf81795, 0x704aee8f183aadf1, 0x06ddb55a8a7a63d7, 0x52556d8763f3033c
, 0xb76b458c6f0c33a7, 0x28666b87c362b95a, 0x365ae575a4c27b9b, 0x36ef35110562adfd, 0x89955dd8d927f9c7, 0x526e787d6a586c9e, 0x762e0bc4eff988c1, 0x6c9523b4b5ae4946, 0xe90a909688cfe95f, 0x658a7dc8b3ffada3, 0xbee148ba7a58520f, 0x6819007d8573d1cf
, 0x75d3b5ec141be9c5, 0x4bc236ae634f3c27, 0x1192fa9b8b30e894, 0x4129d43e1d092cbf, 0xfcac068558bbea45, 0x513e8d87b8116534, 0x5377a179a155ecd4, 0x6c93531e5545572f, 0x727df81ba09aad91, 0x07527139dbc96250, 0x150320b1d8ba172a, 0x2281e85f60a1809b
, 0x7164b7d524eba6af, 0x50d387163fea4ca8, 0xe90de17d62aebe78, 0x6ab369ba28c0410d, 0x17d07e315a95d138, 0x58b496352453fefd, 0xb87a04dbbc101b92, 0x40a8f0fb757e9b0e, 0x2148b48a696e64d1, 0x4e004a3a350c17d7, 0x17927e9f386b563e, 0x29da9cd441e3e3c5
, 0x883d2dc357417213, 0x2e94653ff7862644, 0x53a37af548453df1, 0x04475db3c300b93b, 0x2d65fa4d815e7204, 0x231a2db74c2c3ccd, 0x1fd734c0cf4d97cd, 0x32d255c105f6d122, 0xbb74fd9201eb07b0, 0x12e33f1c81ac6f60, 0xfb9a6439bea97072, 0x52e14b7db9cdcbc1
, 0x637ac1a91ae374cb, 0x1c8622c35adc8224, 0xeb786c50a64b7d33, 0x362823a7232a5893, 0xf22dafca688d472a, 0x18598f0e0237f7c4, 0x97b8497bfff4bcf1, 0x7abf4cb27a9c5b7f, 0xea47c44e3b3d95d3, 0x58728fe3e1827a43, 0x7fd3681a6df902c8, 0x6db1dbbdc413de79
, 0xbc4effed1ac3007f, 0x7f31a54744887cab, 0xe6559b4f8bd2519a, 0x18a78ec5b0c241db, 0xf6e10285b15d2030, 0x5c1323ea219a8ff4, 0x134b6f20dd116b47, 0x5d0abddbc8998733, 0xa3c993938702e151, 0x0ab6aeb494f6ad5d, 0x8cf3b4beda1815e6, 0x546ce323008c2fdc
, 0xa10eb5a6a78dbe39, 0x26d2e8a8b8457da4, 0x026ccbe31517d806, 0x2a35174b812f562c, 0x57d70499dd7a374d, 0x3368f951acd3c5e5, 0x490b2515f901062c, 0x316109e7c315c377, 0x32e20eba569535cf, 0x496a8c39d667d709, 0x5578096dc44d5e0f, 0x608a162ce73903b0
, 0x6b2e65852cb37cab, 0x75b09a2e6ed609a9, 0x7ac84b3082602455, 0x7690cbb594e84b94, 0xfc85dad9511973fb, 0x738a74b08c9006d0, 0x83233fc939d5883e, 0x7fbfc08b5db3c9f4, 0x81a0e493fb5f7749, 0x2c255ef7e69a77c1, 0x234f02e609cc656f, 0x5960cf0b961f3cec
, 0xac72940237b1f17a, 0x434e038a29d446ac, 0xca6a090e00d8b0c6, 0x1f1aad24001e473e, 0x6d64b6dc133399fe, 0x0899ba41e9dd4607, 0xca590b3f25bbf5df, 0x57217978b0d8ce11, 0xd6b4cb13da6de9ac, 0x3c88520cf564f75d, 0x649fbd5075a7757f, 0x3f2593b90fe72161
, 0xe1bee53e91dcc9a8, 0x010069dce4c74a92, 0xef83968978aa855c, 0x6cd8848183b53d73, 0x0b3df59610e403eb, 0x713225d446180a7f, 0xcc23112cc59850e2, 0x105796b670a3730c, 0xa147f4ec7a2fa4cf, 0x32da1f072d75b253, 0x4e7007455e85f560, 0x76a5376a771fdd60
, 0x47eb4fabdcc699f7, 0x4e45db6334c6ed96, 0x36066f2bab72546f, 0x04f48065593ecdec, 0x3fec02793fbb5601, 0x122f74626b64a526, 0x21d0f66ff83b4dbd, 0x1370610ede647f1c, 0x57b82242b88172c9, 0x527dcbadfdc65ade, 0x5e9c9a04385c93f5, 0x64d1cf9e52548a6c
, 0xba0073337865c994, 0x633ee14e50bcd615, 0xf840228ec4251095, 0x49bb96812a98f08d, 0x82f57d0422f96678, 0x06d7e43bffe7e0e1, 0x33910cca752ae863, 0x04d46e7c66087e38, 0xf14935c4167017c3, 0x3f22e2f44d03c9ac, 0xa6196244f2cd6164, 0x15a2b4ce514fa4db
, 0x5191a04c4abbd0c4, 0x0e763360ecc8a19d, 0xfef583c184a673c0, 0x75c2f30a7c7433e7, 0xe947a55547c7c099, 0x245c7ae44f6e7a83, 0x67a666f9e6bec2d4, 0x5de0b922fa645ac8, 0xdd9b3e4a5cb72e22, 0x0139c2c857adba8e, 0xa7feb68e863ac231, 0x501381ef88ec2da0
, 0xb2b8c6a470f40b01, 0x051d65bdb8363062, 0x4ce90414a6d65714, 0x1e510b525d19df0c, 0x569e723f5d374cf6, 0x4bfe02fd38fde1f0, 0xae7459ebc50f9aa2, 0x0f7e2cb170dfde32, 0x3c3da2326a7407cb, 0x0cfc50a85ffd1842, 0x62ab34c85e85c3c8, 0x22b4d9644bb37333
, 0x57d313b3d87c2d98, 0x4f432c1cba49133f, 0x6163d11fa4befc0c, 0x1ab94e122fddf12e, 0xfb7c9358aefc85a8, 0x5b20068f81d949b1, 0xcf8ed6ff2145c810, 0x5794afc021932d00, 0x5c8987ad9b6e35d5, 0x6bb1f4b836fda03e, 0x794f1fed4a3ea1d7, 0x0cf6d128deb0e7bf
, 0x54ec3e1c65878cf5, 0x002811763ba2200e, 0x382d917051e77b71, 0x49e00cbd013a9e7f, 0xccf576e9a4cf019c, 0x4b4a66287970333a, 0xf772168915edfc1f, 0x278eb5eca6479685, 0x8a95c8b9cf41cf06, 0x6e58c9c7826d39db, 0x478e119889f2fe75, 0x73ecd21991bd98d4
, 0x26e751fe9fbb9502, 0x29825b71b0632e95, 0x21668f96ef8bb5c5, 0x2f2a899e53c9a004, 0x2803292ed4345ce8, 0x72731055c7c65dec, 0x3aaaca9c4b6fe9a5, 0x6228d3ceda8bd671, 0x773e2c5effc48eaf, 0x017ab19e0fea9ac9, 0x9609e10496c8d766, 0x121e89f9b302c30f
, 0x4e87d00a0be96480, 0x09bd8d170ba9dbab, 0xc6756f947ecd4e52, 0x2c9e40bbbccd0f5b, 0x42a5b77669fd812e, 0x66aba9583b080d9e, 0xee55df99d16e77c1, 0x4cc00c5c5eff2509, 0x8c84d5e20ab7c16b, 0x00ae5c96184ffefb, 0xb295e90346dcef54, 0x5d1bda0a39dc3b72
, 0x75f92d72a89b5ef2, 0x259d998c9ff9ac0e, 0x8a1cfb72a6c433c1, 0x23f5b71d49d67604, 0x478d8f30914f62ef, 0x08fe61135218eca9, 0x4da2ce9bc6488c4a, 0x15f1eafd35283e2e, 0xc2d2be3ebc42ea0f, 0x2a5216539d6ee902, 0xa1e99052e7bdeeb2, 0x3a8f2631ec78290c
, 0xb71518a82ebfbfe4, 0x24700671c46ebddc, 0x6ef52d591a221f75, 0x4794614db6a67d92, 0x761f5c8ee4bab607, 0x31d9dd8f2361b5d5, 0x1a45593be8db3b29, 0x7f06c365eb116260, 0x9d305a66e52eb65b, 0x5edcfcb5613eac18, 0xef34fd28154adb75, 0x790f805753b9d742
, 0x6ecd5ac255dfb797, 0x0cbe14db5d9a88db, 0xc1c86c5efa815528, 0x2c636133ba59d887, 0xc75d42c2d9f52297, 0x4bd3540c21e2ebd3, 0x32e7cdf790de6903, 0x1aae3c9837d3e30a, 0xeed028e49d436f09, 0x779ae12351efed1c, 0x6e0145587d9797a5, 0x25156e4cee9a407b
, 0xac2fd82f2ac57119, 0x7f8c026f1d182ed2, 0xeacc0d8fb3241611, 0x5968db65d2d7545a, 0x7d525846b1121dbe, 0x57949fd7b80339cf, 0x471fe9bec9b66c01, 0x5c270057f1268efa, 0xce092463083f656e, 0x16e8241cdc862cf9, 0xb7cb2bbcaa06b312, 0x3c25936bd8863416
, 0x19b8ca966c4a3827, 0x1ae43badfd21e63e, 0x1dfd002b95a6ac6a, 0x4708e27f6d98e997, 0xb5fd6322dc31ac7d, 0x53baf4d9a16dd550, 0x025aa2ea5463960c, 0x5b5b33c7a3cfa54f, 0xdba287866ee96b90, 0x4748c1f3f3a6dc4f, 0x2333ec05a80c154b, 0x4a47745d5b99fb96
, 0x44955b062a6ecded, 0x7791feea9015f170, 0x736bf603d12fc35a, 0x2632adbca5388026, 0x956e4c48e1697c4f, 0x4ee9adfe8600e32d, 0xa584042a0da56406, 0x34a3d7f4bf457353, 0x8d4fd4fe00176fab, 0x15321ee855941f4e, 0x670701ef81f340a4, 0x0c7d7c618aed0ba8
, 0x73283131d9bfd9d6, 0x34935a39e31bac65, 0x466cfbbcaae8b991, 0x250dd54e18478ac6, 0x659e46c51e40de4f, 0x618ea014fec50e04, 0xfe64d883080b877c, 0x572cabbb6688c4f7, 0xa2c817493a834146, 0x06cd734876378120, 0xe3de0b717336a849, 0x36942f5191db53c4
, 0xa3f9adf66abf4d88, 0x2a9a144b8087fa96, 0xfe49fefcb78a5b4f, 0x1be40a8616928bab, 0x07a901975521f7aa, 0x1fc66ea683693510, 0x4dbf0084ba42380e, 0x1f374495b918c737, 0xb8346956a380a00a, 0x1346f4766fcdaa07, 0xb4db5689d46312c1, 0x775e7f3274dc1316
, 0x07898828f32341c0, 0x144390a33b3e86df, 0x70bc604ce1e9c5e4, 0x127652de00220873, 0x2874bc669df50d45, 0x236f4585150161f4, 0x3bfa4ffd318214e2, 0x7cc92a6165059745, 0x2fae0e92090ef72a, 0x26676bd59c4fcc3b, 0x220c030974d1d447, 0x66455887e98686e7
, 0x4164b8e4d8760ddc, 0x5517a86f840feb63, 0xd9b42c6c9371cade, 0x3a7f03ceecc160b9, 0xdd4086d64cae366c, 0x1b6290c327842533, 0x144efcd2a7a0e82b, 0x16621925ca10d31e, 0xa9dcd13118e208f1, 0x5a90f97edcb1c54e, 0x80c47331c8749d99, 0x6f061a3569a80b55
, 0x0f6abf619e2a15c5, 0x29106c98122245f4, 0x5860b10985c9b47f, 0x4f379a379e15f410, 0x2dd6f45df68e1678, 0x2c475167ad9b283c, 0x23b7aa00952a6a3a, 0x5532bc26a40c5365, 0xa5c0a8be3596ce22, 0x4fa3127a9aefa56f, 0x944e843aa973e67f, 0x3c7727d45ae87854
, 0x48fa2ce675117ea4, 0x7bca8e04ad3bbb9c, 0xd57439e4726f88e5, 0x3337d3a6a03b2286, 0xb0b6172902005953, 0x514bd76734e6c0a1, 0xf97f8934eed7c6b4, 0x0abe13cee7f1b75e, 0x6c88107a120e54a7, 0x634f966d7a6e11df, 0x5044c53109b94097, 0x68d49fc65522b73a
, 0x69e295cd8c444666, 0x542c4c5fd999a224, 0x13ff89418b5da76f, 0x7133fa786a87ecb4, 0x2f180926456402b4, 0x52ddada7931c4dcc, 0x6eaf0d2130c71590, 0x014ec2a2ec231826, 0xac05b61443b34dd6, 0x157acbfab118b219, 0xe4e2f4b84ad01099, 0x0abf4a4da29a0eb8
, 0x5f852b85b59eab1f, 0x1bd259c4726869ed, 0xce565d9287790a15, 0x17a48442bcf58a00, 0x01e519522381363b, 0x2336d07a710da07a, 0xcfebf2fbdc714cb2, 0x2f7a51474c23b8a9, 0x77db2a07d4e3716c, 0x40e8d8d2d0a09806, 0x644363ce6d401ae4, 0x53f9cae0470172fd
, 0x58d96ecd8ddadc53, 0x15028204f3d6d696, 0x6f40a09214439ce2, 0x738c5371236c3e56, 0x64f87ee7a28bf9fc, 0x4f1899449a810fee, 0xd0aa95f4bf21e376, 0x6170cc24283856bc, 0x9dfc4927d764ff75, 0x227ea1563fa2e012, 0xaddd3665622ce087, 0x473d3bea07a5285e
, 0xc0b986ee0d2b0eb2, 0x78e584c740dd18ed, 0xd5adbf30a04fd508, 0x1c6aed5ab59bedbb, 0x25d05fccbddb5ba1, 0x4a58fb6b3f896319, 0xdb2f6343fd8144fa, 0x46a445de6d5b07e5, 0xf67a06684fe9e1da, 0x57b2515923b15c9f, 0x50439940820a2a0c, 0x62f4b9b26f04dab5
, 0xe79ea601d01b033d, 0x009bc6176f10fffb, 0x333bff2f907ed39a, 0x253d0a9e626dd400, 0x7a9bbedcfcbef06a, 0x2d1b6a7a5b39342d, 0xbadfb462a124cc9a, 0x2e8cde9d82c15cb0, 0x7c3f81bcd6f1b2a1, 0x04cb0b8fa4075294, 0xfa36d3db38cbd304, 0x59fef93442883553
, 0x91982a741cb9342e, 0x7b9d63ac17b01982, 0x530b4ec25a293ece, 0x611069ad9fa0f0a4, 0x7a262a59b656a79d, 0x6fe6f8f4d6d015b0, 0x2c2fd7641a5d4e50, 0x24b0c507058c911c, 0x834882e492fe45ae, 0x68d0b01b13432761, 0x0eacaaaf94178b8c, 0x123e3a93006d7d01
, 0xecf2fe69377ff33c, 0x4fc960ab4408584b, 0x2adc445b1ee45654, 0x4989681cd1d09a93, 0x79509599afe9e3b6, 0x7f6ffbbeee861c15, 0x2ed2859fd6391b25, 0x5e8bd52289b6ad27, 0xc949280adbce7c79, 0x510999e865f0cd54, 0x7f957314ce7d373b, 0x4b2c0ea4bab08ef2
, 0x2d7cc08b5c05a8db, 0x4609a0ea23507697, 0xe204ba35182c55b8, 0x5e4d5903fdef61e6, 0xfe63842f2826598b, 0x782a3fd3ab62a179, 0xd2f01a1979e5a0f3, 0x0fb4c6bdd637fba2, 0xfbff4c192020c350, 0x14859008c3d223c0, 0x65ed7a889c1a2e55, 0x1d78daf483fa12cb
, 0x5b54d11b01bc09ca, 0x54fde75737306515, 0x89725231105b63a7, 0x712d1f394adcda99, 0xb554006ee9abefab, 0x04dd8f7bbd4c5381, 0x98d22b3a31995549, 0x637a53de6b57122f, 0x8367d69b4c92da63, 0x236f2a9514250df6, 0xb265509af63d7b7c, 0x08522e36bc4b65f8
, 0xabae725012ce8301, 0x493b257197a98ce9, 0x33185838570e5f0a, 0x65f5477ac414eb6c, 0xd002a36854699753, 0x2be693b4d96efdb3, 0x3b32484119bdc53d, 0x55691ac09a8fae1e, 0x0249e394514c047f, 0x765674c90b78171f, 0x1166f64638d6ab37, 0x746adba4cb52d18f
, 0x93e293653dda6cda, 0x5d004ed52ebf0b68, 0x65c7c42d0ad96cc2, 0x3350dbe11cafca74, 0xc638cfa8942fef67, 0x0ff2dfffc5ac1164, 0x9e1b625e649aa471, 0x13a219d03d2eb86d, 0xdb92859ebaf9f7f9, 0x645c50918f7d5abc, 0x25c10cfe99f7e5c6, 0x13d858b53f90170d
, 0xddb258b13ab1e7a6, 0x4849ff49f4e13fc4, 0x9ef87fa85511cda8, 0x48c50d4d3b4d2f7a, 0x6c98422c8007c9ac, 0x3fdd72e65a3d3491, 0x56b18cb165b4ec3b, 0x6e2c6df9e3fc3daa, 0xf6db5aa98ddc97a4, 0x423fd4082f3fb795, 0x42f8f5edf424d0a0, 0x1a091c2696139936
, 0x3161c2bbb3b2d58a, 0x2e8d339eb0fb9099, 0x45ef7d11f6fab685, 0x7f222a068db3da4b, 0x9af96f9742549a7c, 0x55370df31dcec81c, 0xde98e81b131af02e, 0x58bd0622a474acee, 0x8ab40fa7ca882e0d, 0x5b4db195655f2410, 0x4754eb479ada77fd, 0x67a8a437d6fc8a7d
, 0x9888254a4f0c9d58, 0x3232ba83bed0c618, 0x587b0de0207b57d9, 0x020df6becb096aa7, 0xef9e41052a29a8ab, 0x4ae671ee70a15a69, 0x167ce954923ee086, 0x6878c3996c1de887, 0xb29c711490ac097e, 0x1cf41a9c2577d144, 0x0590796ba46d8d29, 0x1c2e6dc8d4aebb65
, 0xbfb904f8ac9b4cb9, 0x4ea1742c786469e7, 0x5a422f48401be57d, 0x0be0afdc77d6d32f, 0x5e8765cba2c738d3, 0x7dad0475059a089d, 0x9288ae0c40df7df6, 0x51c65f97715a16d5, 0xa9615d4c786ff9d4, 0x507ffe03ec0189ef, 0x1c1f46684604e41f, 0x282fe9d567db0efc
, 0xebee7f8381fb8178, 0x5bd4b6045c208d57, 0xf35694743439ed71, 0x7cddd5a373ebc5ec, 0xa58df33cc68e3b5f, 0x40e6714f5c5c8df3, 0xea881d4bfd489131, 0x6b36400b491c28c1, 0xd4475cf594b6303b, 0x5b630cddc72e654a, 0xa0b587ad34394ce3, 0x3ea3ba6014f86275
, 0xc3deac125d20eeee, 0x2ef3568410a2b3bb, 0xee6ba3fac5d7ec00, 0x5fabcb3337aaa23c, 0x6b1212e7b817889a, 0x0b37d285a9be51d1, 0x617ca543d762bf51, 0x0896b4ca694b01d0, 0xe3add9718277a1fb, 0x553dee7dd4784865, 0x904b8f7e936cf430, 0x5b6a78f20b244b90
, 0xa2b876c2914b9bfa, 0x704de952e9d969f4, 0xb04ea1b54b7e7654, 0x5d307bb3949cf660, 0xcee4c23ebd049d17, 0x7a88293bb1031063, 0x00b8432b8286f656, 0x260a9c86a16216e5, 0xd140e6e6629d8686, 0x296011ff5601a000, 0x536f0f76cd9b2928, 0x267409c23a823dd4
, 0x0f041043797f8423, 0x3da6102605962ca9, 0x2e69dfeea02098ea, 0x427e7eeeecd3a0c5, 0x75efa5e8a590793d, 0x1f5841df6dfdfc91, 0x1aa1e1b8b9f3c326, 0x07bd5b0983fcee91, 0xd169420be9c48939, 0x7940334f0bb9023d, 0x9bb330fff113764f, 0x674ff1b0cfe246c7
, 0xe2083f8d7129cbab, 0x7e6223e3d9c04904, 0x9be411a7d5e883a3, 0x72642664e7c25590, 0xbb1f783b5c412322, 0x46716e8fd737280b, 0xfa363eeaeffde271, 0x6c256c131fc2c3b9, 0x13259abfcb2ce1d8, 0x53b96556e96aa708, 0xfaa7c8d25119da19, 0x05019f438e9f8995
, 0x05e1d55a9424f1ee, 0x63e8e14e6c2f3f09, 0xe9d844e997a10158, 0x51904ed1e94a0ca5, 0xb09462d4df6bc6cc, 0x2ee5308e62172691, 0x3f8438484547187a, 0x62b92b8d9739ddd4, 0x3ca54ab5d39f083c, 0x25b3336048a288d4, 0x7cab0fd67e296979, 0x58ba2e783962cbb7
, 0x77808f1a1b8f3515, 0x290c219ee7153bdd, 0x7584441f79128f01, 0x0442db406f5135e3, 0xe741de52ec030a9d, 0x37469756586776b2, 0xbd64c2a7173adde0, 0x2280b66d20888d0c, 0xdd1b53cb4adb0fb2, 0x3974964394c445be, 0x53b6a95e7c7fdd97, 0x6eacdc6f50496d95
, 0x178d04c0578a5bb3, 0x0d171a5f5215c9c8, 0xfe0d0171c504962e, 0x04eece54b220495e, 0xac4d145001db67aa, 0x6577c466962160af, 0xcddae62d99686ad7, 0x7a053a048d230d89, 0x1ff09aa0e605a880, 0x5d260426f355232f, 0xfbdaf7b0b53aab89, 0x5eef31b9eb0df78c
, 0xfb787e56b7276288, 0x4dcccba87d630d06, 0x415e4a4bc0a44b01, 0x0f0a981f71d8ae33, 0xe0ebb786f98a1502, 0x0ea4aa3ce70dc628, 0x8d36240617ebe037, 0x2d20c0e1d2002b5b, 0x336f8aa411a30282, 0x1d87c67d8178ec4c, 0xe468dff8ac26b63b, 0x266086bd7f11c9bc
, 0x05cfeedc80d829f8, 0x146902a029dd3355, 0x413db9327c068394, 0x55fa413791f64c38, 0xe06395c10021bf9d, 0x18d66268cf79ce45, 0x9e7ae6858dcc21bf, 0x3ad51dbe97b558f7, 0x06792c747aeef43c, 0x27ec9b782170abb7, 0x6aafca394a23e935, 0x18f7cbd98db64112
, 0x34146ce6b36edbfa, 0x1dcfb4eab7ccea23, 0x68498e1f45b35467, 0x1b20d71a3b71d412, 0x7a875fc94e602e3e, 0x78c15fa449576c2b, 0xb52326d01ccafe8a, 0x3f53f57324d70666, 0x3830836e39bcebaa, 0x27a30c73dd02c884, 0x5dfed73dedf2306f, 0x75ee4a8b6cf54f74
, 0x97ecc9c5851a8e3e, 0x496b581690c3df2d, 0xf7bba1fe2d169e7d, 0x4b06184810a77bd3, 0x40e6d643b903c7bd, 0x3c90f63b5176906d, 0x92f47e1ac51f1ec6, 0x70c2454c53cc0dcf, 0xb5a75d246c653b4e, 0x7e5173a420a8b0df, 0xcafb44c471d0f4a3, 0x69a3a4e92bbe5977
, 0x26e93183cdfeb424, 0x1e0489b56fa7e130, 0x669befa672fe9979, 0x0f8aea6a7ef65bf9, 0xff0b883ea96b51ff, 0x31a668763c3c8867, 0x6887a0029701c9be, 0x545644cd70c87d63, 0x537b6fb7db9410e0, 0x6ca227f10229b3b9, 0xc7d1b4d71ff22468, 0x522058d3b20569f9
, 0x5f4bfd813a51fb62, 0x105b94a3a42424a1, 0x96dfdb685825857b, 0x14d98588154500bf, 0xb4db83514c7a9404, 0x67aaf998856faf37, 0x1229d7e95dbc821c, 0x7e617a17a2f72bd3, 0xe964cdba7222695a, 0x677619cc40a07eaf, 0x7f82c099a8df7538, 0x2a219175ec95a1ad
, 0x755ac147b51ff3dc, 0x4a87f652f86823ec, 0x6d8d4a923f50278d, 0x4bb952ac98c0120a, 0x968c57a6a31e482c, 0x0855a11481fd5653, 0x3f05db6ac608d16d, 0x33f9e5746e1079c6, 0x1f3458e3ec51f53a, 0x4ae3fc836ceccf81, 0x3c0b2e2db5875ddf, 0x42336a1262cbb5e0
, 0xe3651453cadc3868, 0x25081cfd6e80a2de, 0xd4cb31092872e53a, 0x16ca9349a11a9c37, 0xb1d3ae440d1cb675, 0x41b2d6ecbccbd6a4, 0x475e6a844c3d0ca1, 0x2cd0e0dedbf07023, 0x85ad446ddb002a6e, 0x72a06e5419a64609, 0x9e779387e9a3276c, 0x414a8163a9408b10
, 0x25c7b53c1791333e, 0x3ea57190b42cd838, 0xbf20b346b094f121, 0x47570cba99b06c9d, 0xe6bd01c8746cb5f2, 0x3c0b0b8c4c0968ef, 0xb22009690e243975, 0x251737e4a5643da2, 0x3cdd49123ab89dea, 0x68748cd1e3cc45a6, 0x563746685effea7b, 0x4e4c5b1c86eb3a29
, 0xe1ba017516d32070, 0x5cdd35a0c4ba93a3, 0xdbc66a0c7de30288, 0x22107156a0f700f1, 0x0fb69045aac0f647, 0x111dcb9763d08bc0, 0x266db39f6d78cced, 0x02a32587c7033892, 0x76fc94ce6a2a4b19, 0x474db0f12fcfa96f, 0x0c44584c08377ac7, 0x5f435bf43140f4c0
, 0xb9741c3014eef7a3, 0x54596c23b536ff04, 0xeadf56bb6ea39450, 0x32f24f6e1a656b10, 0x21422e4dd5f54e3f, 0x0d6ad57853660607, 0xf6f62ffdd0bf9928, 0x72569c930015caa7, 0xf4293579931b9216, 0x049d6a4057e6827e, 0x6223e20060be0e05, 0x20d91ae969dfa9a4
, 0x02611b345456d47a, 0x601dd413d1bdea0f, 0xe6b017b26bbc9bf8, 0x63399ff3d6542359, 0xdbdfe225045a9764, 0x10acd93346649beb, 0xc652d5a50e0535ce, 0x49efbd5639c4caf1, 0x65a5dbd8a304de65, 0x08ddebed0e865be8, 0x5db8337d5e715261, 0x34cf4c75496807e2
, 0xd840c7416e44b56a, 0x10fd30d282d8b151, 0x36ffe6df2c1c9568, 0x66d8a38b6d31a2b1, 0x01fad3aa61984774, 0x412a9fd87b303d90, 0x2720945ee0f0ec9e, 0x0c91b4c7ea84cf37, 0x98462f25fd5832f0, 0x6f4cd578c490d842, 0xecc7d24c31ed3342, 0x580ab96994515fd8
, 0x6d8a97ed98465b3e, 0x16995dc010908ae3, 0x50626a4e555b774a, 0x082636e5a8a9b568, 0xa99435cc4823b413, 0x41fc423d10eff4e7, 0x114236dce6f9f9dd, 0x6c3995c4bbe0aadc, 0xf3f22c975935753d, 0x6b1b3f27edec2a78, 0xdbadaac32ccc292e, 0x3856036f8a3795aa
, 0x947154caaec01d73, 0x0a22e573e3f0f49b, 0xc50c949f39c184a3, 0x2aadd0868535d0c8, 0x22bc5bbe5f992446, 0x15d36adfca3ace90, 0x038010e37a6308f9, 0x161b06d8d7180307, 0xcfbf4e3abef8d056, 0x2a1765fe9c7696ba, 0x6a15d44ce18ef392, 0x5405239c0369de64
, 0x5fabda1210f58e29, 0x40cbb03974b37035, 0xa29fdf2875322520, 0x3b32ace85edac547, 0x0f0c92b41d679df8, 0x7f07ecd47a7d2f0c, 0xb5fc65c05accc95a, 0x0e8b1da70636f221, 0xb2ebd131f4e8a846, 0x7df51e4aba57f391, 0xaa2f3d40fef689ed, 0x0ee1e115fde5d582
, 0xf7d025b42e240ae6, 0x29fc1befeb526af2, 0x7c5ffcaff205e565, 0x4cf4d0d8840e2e1e, 0xb8b00d1810ad0ff6, 0x44d3af686ba915ff, 0x86a8fd1eeea8d08c, 0x3eb300adcf6edc4f, 0x8db03c266b588186, 0x289d0fd301e96881, 0xba83ba260cccc170, 0x26ee69546ceb0c77
, 0x1109d8bf92c4ea05, 0x033aa036671937d1, 0x4bd9902e5a664a0b, 0x42bd48ed44fdbb71, 0x7359e19357a9622d, 0x0d6ee92855dae22f, 0xc24debb323643859, 0x4c60fee1e191766e, 0x3beaec0e99faa328, 0x056c2ae1709c5b0a, 0x7fe89e0c62710909, 0x7e3b5cd3ac4e6ce1
, 0xe9d06486ac7370a4, 0x4b1a8c62e99f9429, 0xb11a50e20bc3197f, 0x75ec513c25dac300, 0xfb9fd064b1466dca, 0x290379cfce59308c, 0xca3ee3fb7db99943, 0x2af7a3e930faea44, 0x0d294e6d1505e35b, 0x7d534585181e001f, 0x90285700831d4cfe, 0x419f25105d06c90e
, 0x5f71e79f5f828172, 0x02921e2a43326798, 0xa0981553e84d4a6a, 0x220c82041938573d, 0xfd2b5b78ef20c927, 0x3c99a2dc611caddb, 0xfb1247fd99ed2828, 0x4b3a3739f724890c, 0x7775ea2d7d2d1017, 0x3ab07cb5ba8ac987, 0x82e5123a20a6b5c3, 0x44965098aa82161f
, 0x20948c77e9ac4c0c, 0x521e934ab214157d, 0xc8f4f4052dffedab, 0x1da963c2ef46f27f, 0x3be7631e212fa2e0, 0x0d188e88d1a4184e, 0xb4483ed385de4bae, 0x4ffadfde83d2b0d9, 0xacebd9a51a938608, 0x40968c0c9302b0e8, 0x85704404d06f3a5d, 0x3e9f477a61a26d37
, 0x1da1efc7cbd18d12, 0x4fb87a47b9f2cb04, 0x7556a45e8b5c8caf, 0x7f6991b7723b35cc, 0x3fa10a169532635f, 0x15e61b1cd72bd52f, 0xe6b45dc3b4667c21, 0x45cf3bd4bbf39baf, 0x7343b0636a9d63f9, 0x457551c49ac49567, 0x331e611a3fcec018, 0x7d19e2584756b92d
, 0x78951df174059655, 0x0573cd896a793337, 0xb3e37121fd458870, 0x3cc032b1a1bebc3c, 0x2571dd06d24d5a41, 0x017382ec4aa29ffa, 0x6cda850c15a224ed, 0x6af59bee2d7586d4, 0x287d3c4027f80ee9, 0x6aa570b9e51d4f25, 0xf29f327c5e0490d5, 0x00fb62f93f43edfb
, 0x7b06e602dc313277, 0x5d8dc98e723b039e, 0x5bb61813041a589a, 0x2a4c9f13eef7f1ec, 0x9439edcb4bbaba6f, 0x027f4d494e7784ad, 0x087ae2a2fd6bbc8d, 0x230f37ba41aec2ff, 0x63876e43daaac09c, 0x28abd7ae6e17dbe3, 0xd354d50cf000982a, 0x1dd774a1273aea75
, 0x243658930d4b0902, 0x0df50723a2da63d7, 0x22bc07b9ac9628c5, 0x134123d68aa939cc, 0x4e84ee2cf0d450e2, 0x53a8c6dbd4aa9ed1, 0xd06e741c45610565, 0x608da7f96f2f7e19, 0x59b7fc9fe6a0243c, 0x0da36bb46fd1eb3d, 0x09a11de836914182, 0x3becc1cc0b96f1e4
, 0x820b8a4cad71c17f, 0x2a425dd0204a843c, 0xf6f7fdaae1523c28, 0x5fb74c0c961e6fb1, 0x0c76e0f72b7845a2, 0x273db117946ce778, 0x7a22d35cdea5934f, 0x73aeeb1b24265d5d, 0x938a618552e4392d, 0x6050215beb6c1923, 0xf32f6ab781efbf2f, 0x2e4ece5c476e1354
, 0xf2a4a59613812356, 0x555185da018933fd, 0x2fffbf95863bce54, 0x72644f9c3181e7a6, 0x98c6b1d509e3d624, 0x5bddd5730939d7d0, 0xdd197613d550fbad, 0x7671fafa1facb923, 0x13dbb61148c5b802, 0x616bc5c73ccdc3bd, 0x0b175b4c46fd8871, 0x498a1eeb000ab870
, 0xa49f1ca2d7802521, 0x6906346cce00be5a, 0xf1bc33c727dd52b0, 0x5d005ff3122fd749, 0x51318ad5d7c622e7, 0x50f93d6d15e46e82, 0x88dfa2123ffff3b9, 0x3848e6fce3cac6e5, 0x6cefc31a33ea4f5e, 0x0cc5e7dc4e5e144f, 0xee2009402e59a7e2, 0x257679fdb86f4712
, 0x4cf68953d8b17e83, 0x710f970c16ce2070, 0x4000b8e9e51e6aad, 0x5af48dacd01f24f6, 0x209679d5d3fcc916, 0x0a3538dd7cbe8232, 0x2d6d7aba44d990d2, 0x46c718f2d4b2c1a6, 0x9953d799a378233c, 0x4f4e80f4a682e7a0, 0x9912f04acbb77eee, 0x317432079a195b2d
, 0xaccccda6a1c11e3b, 0x3fd895817d0f3be2, 0x016db17673f750ea, 0x635fc619a24009b6, 0xb8447ab3370da1e7, 0x6c893aa19abf4221, 0x5f35ac703d8508d0, 0x13533d324d4adcb5, 0x84610370dece8512, 0x2223f126f9a70f4b, 0x18f00d60f3bf6a04, 0x174bd78b20ef8543
, 0xeb179bc6a1698189, 0x732bf44a62015302, 0x98352342bc0e4bc6, 0x053f6640c1549e85, 0x65eee8b0397c7ce8, 0x790451f39f2fa27b, 0x36ffa0cb286cdb97, 0x46d07cec4c967bf2, 0x7c849ace30868412, 0x6dee239d339ef499, 0x8ab78548f273e57f, 0x01c5bebd8b7f5ef0
, 0xe440e5f042eae93b, 0x65583f57fe057db6, 0xe6d5d26c24a565c9, 0x6b3b87a0a6ad702f, 0xd3f5d533117b8e64, 0x4addb9d0da92df89, 0xf1bd51990e0f9bfa, 0x30c624ec1dbcd0a4, 0xafaf2f00da7023a0, 0x3086e132b54574e4, 0x93bdbd4bfd3dd8c7, 0x690976ee132c892e
, 0x86fc11c79524d198, 0x0f6b95662e02c734, 0x5b78bb385564f568, 0x55c9b3f55d7cd16b, 0xdf1316434ad1c07f, 0x093d67d3fdf312de, 0xa1fd2257ea57b3d6, 0x4b5b18abe4b54439, 0x66c28f5b59d796b2, 0x7baffe6e642fdea4, 0xb9d3753265e68ae4, 0x40903bd6dfb02d6f
, 0x357958d4d72d6bc8, 0x179330dea4659dd3, 0x5a9ca85bc8721aef, 0x0209f09e03c9b225, 0xc0bf2e9738933495, 0x5e0dde4d715e50c5, 0x2743c96b66a6b951, 0x6af96188a0d6d358, 0xb2f3c72820f2a709, 0x5e9b8fd43327d9a0, 0xf0b13f5324012177, 0x7abdeaf4f741bace
, 0x6f006249351471f7, 0x3204eb91cfe9ed6c, 0xe09af1c83c13afa2, 0x6d70ed88d5de535b, 0x2078873d1a2faa1f, 0x5c73bedb8d96f3da, 0x41bbb407a3a1ce1d, 0x7a40ec2fb54eea85, 0xd6d569cb9dd722e3, 0x10acf67805927b6a, 0x27c61d818cc0ea05, 0x57b175c9f59904e2
, 0x4f7b40bc92b5a60d, 0x51431f647b46b89a, 0xcd84dd55cc2a720e, 0x6b36059700809a1c, 0x78e3e5dd060e9a0f, 0x630c0c1a146c77d4, 0xc9925b0dea8fee2b, 0x4728f0604b16a06d, 0xb4601050635b2318, 0x2484f7281864709b, 0xbe2ed2a2523211db, 0x6425d4ff23dd3a5b
, 0xf0868c09017aef5e, 0x2733d1e1adc6d5ee, 0xa631db49f17f87e9, 0x36d753ced54d5727, 0x451d17fb6c4af537, 0x1dcc4d611dd55b04, 0x0bb8de0c8d3e549b, 0x2fb2ca1271592c3d, 0xd877914ffbc31ced, 0x190809a196504d10, 0x44bdd65a970277e3, 0x13195c678b4b01fa
, 0xe69a41a54f84d41f, 0x61c7c870565e4508, 0xeca2d2fc6f0e1c9b, 0x7f065480e257152a, 0xfaaa9f7c3a8873b0, 0x43fcdb8db58a324a, 0x969a79026e9da7a2, 0x4eab135af328b9d9, 0xb38aaafe87f85f7c, 0x69eba4fe1a6b6f32, 0x5607f6c6b4d27cbc, 0x273072bea774f9e7
, 0x3c1149e3c8d51db0, 0x161f8cd433c28bfa, 0x765a61f218fe70da, 0x442b5d405f2036bb, 0x96f790271c564cc1, 0x3d5dbb33505cc956, 0x621a38b446af395c, 0x2da978b45bb70ce6, 0x755aca711da49388, 0x46f2e33e55e86df8, 0xfc5b454d5cb7be24, 0x67df47d68d8f6d12
, 0x7a1e224893898aad, 0x0400219c89c2d13e, 0x6c969e4d63d460d9, 0x4df64d5df8b60ad2, 0x1feed05a45ff89ed, 0x290c4b59e684b4ef, 0x97ffbc3df096adb6, 0x4ac6037e76561c96, 0x1bc40299115e51b1, 0x7169e0a1d96aa1be, 0x43f55f8b6bac596c, 0x1cc6a0603081a178
, 0x8e1d2db69bc925d0, 0x6ffb86eed51d2931, 0x3ad1eb242e0af1b5, 0x338198152fcd6d7c, 0xc1f381496df13943, 0x05d9242fe1c60b02, 0x39617510de7eec81, 0x24d8ba5ac76b12b8, 0x280eb2db9e548483, 0x6c51317b3a8a93f0, 0xb2a9f90939bd1235, 0x2da9de86c39f9aa6
, 0x7f54917103127b97, 0x7be2be5ad3276169, 0xc969d703d31e9da7, 0x0500df3bbb1f8a4e, 0xea05c77685795917, 0x049575a992d09345, 0xd567f8de2daabe35, 0x383fad35a8e035cb, 0xb9353eb2bbd43d56, 0x52b3953221860c5a, 0xf9e4bcd46dbec03e, 0x4b0db0b4a7b3279c
, 0x8cc5f6b6e1ff80c0, 0x1bd2ce464b552215, 0xd008eb25b39c4236, 0x3b4ce5bb2f42a9fc, 0xe1f249681d153d9d, 0x3e022cb14bc4c5b9, 0x8a11d021c8ed5a53, 0x560d3fb258bec495, 0xf4405852705a6012, 0x5c8bccd2b1b3efd3, 0xd93c0f63ba7ce0c3, 0x337798cb3e93dbba
, 0x7a9f68cf800c8e88, 0x579afe689f3ebcce, 0x7dd41d6cdfbdb4a9, 0x3802410c4e1b274e, 0x64241d770cf0db02, 0x2f7c8133c74bde23, 0xf3c3fd835ed1952e, 0x741b1d88a3cee37b, 0x74e1ae644683c68f, 0x0c80dd9e0f7a91e1, 0x3984d741f3e47c24, 0x4b3eb97b6a39d252
, 0x32e9b9410da9a195, 0x11d09fdc04ec3b41, 0xf92fd5e53cddea30, 0x296e095589e0ce05, 0x4e3200c3a283b696, 0x7e33fbba44ecb32c, 0xed3c039790ad0033, 0x5c8ebb260b5ec084, 0xa667455bb79d2e9d, 0x12fbec9d4f5bb155, 0x3aa5f6bb4d0d8d49, 0x0ca652ed7065d80b
, 0xb7938753d51c6f83, 0x41644ac1a602f9f2, 0x84223d4d63c38f7d, 0x71057b4b8b931282, 0xd39fa015165f47b5, 0x7536c8a19c33c201, 0xbe713ca4166c2dad, 0x456c98c2b4198511, 0x4793f25e1cb44658, 0x1d002f1cfe1a1ba7, 0x9f9ed6e1e1a27957, 0x095dece028426bdb
, 0xe57d3412fc1001d6, 0x481c63a0d9b25e99, 0xc756b6ba0dc02aa5, 0x24af047d79ed4683, 0xe37ac10133b68275, 0x418b45e570802012, 0x87578def0c3900ce, 0x7c5661923b8c9740, 0x5f4ab0a6fdda7366, 0x0ac6100825e4eb3c, 0x308528e42c9e4d32, 0x436e5979933ddde8
, 0x0cd6ebe123352222, 0x63d1768a46f33dc7, 0x96cc55dff38c9273, 0x474438da7140411d, 0xa184b89b81cf6402, 0x6bf820a3aa675050, 0x3bd4720417391f0e, 0x3f2b8f859a8e0cba, 0xed952561b125da29, 0x07eb1ac74165097d, 0xc3f70d0c7db0a9fd, 0x5ab896a489294a6c
, 0xd4b608975c20018d, 0x6243b039f25d0456, 0xf766e98fc24c7464, 0x20035c09d2291e42, 0xcc0e5b5eeb462524, 0x24bcba5505f90657, 0x43a98d98e4fa9bf6, 0x3b621ec4188264d4, 0x633472fe235c812c, 0x31a20844a3316d23, 0x47b80db7d7f5d0bd, 0x22d482f5663780f9
, 0x4df227dc52142020, 0x25076d0624bf137e, 0xcb4a6ee30a657645, 0x0ce469dbb5ada433, 0xfdb06251f65b9c5b, 0x44f82274a8e8f538, 0x98fa4c81cdec4b97, 0x0ccd61d1abb61d0d, 0xb9dc371344c5ab54, 0x35dcd9ccf8e5f919, 0x67fc81f369ba5722, 0x121b5aa1af6024da
, 0xe0b1b16b0fb1f1fa, 0x4dc688d6d3b1805b, 0x05c187cf10e40104, 0x71af39c743daacd9, 0xe691e97f82acf4b3, 0x0c46305b9243bf5b, 0xb063af137fde616b, 0x4e26e72a1de067f6, 0x61fe66d01a221004, 0x172fe9240cea50b1, 0x4ff50d37b2effefc, 0x06be02ab0b89aa5d
, 0xdd4aab96717af213, 0x32322555b58a7ffc, 0x7812aa965889326d, 0x1bd608f60d6457a4, 0x2c7b6b44e999e141, 0x113a86a87856a8a8, 0xd95469fc33814855, 0x4a18dc36f6bfd586, 0x0706b60bdb854fd3, 0x4dc356685650fa90, 0x24ef7cfce41f8dcc, 0x19049c3e632deae8
, 0x5c9a4e28b7138a89, 0x0f0b7dbc1e5087e2, 0xebf49cdc66a362d2, 0x19e4b815e6576c85, 0x1896051ee3b6063d, 0x09ecc741852a68e4, 0x4009034def986795, 0x36b440ff39b4b5e8, 0x9bc2647ee28af1cb, 0x62613c9dd152b3a8, 0xc2018ae5dfae5f2d, 0x29ce5ef30009c855
, 0x0b653558b21d2b1c, 0x45e2c505d1f74936, 0x48304373240553d3, 0x0528569885a82310, 0xa90d402e33924181, 0x5e610edc23cb9555, 0x28890ae7e007d28a, 0x7e5132b6b1ebae37, 0x0d5252eb7c94cb1b, 0x308ddaea1fdbb672, 0x99fac0b431730534, 0x77d54ed63b9325b9
, 0x4d647bcb76c6ec3f, 0x0e968b22ec2cad86, 0x4b22b5ec30b08a35, 0x3b31df3b52326b5c, 0xbe84f638dac3105d, 0x7db085f133ecbed3, 0x7a8b694596f2cf2a, 0x67b2e6c15d16e0aa, 0x4808b20bf173011d, 0x25d5fbbfbe66f864, 0xf67f3f3cd9743987, 0x654250e89617ddf3
, 0xf5a1a7e0ba0a88c0, 0x3616c781799ab50a, 0x2669c27a2d256902, 0x3a8ec380e12fd7dd, 0xa25361f44a418e30, 0x2942f3001d233645, 0x60f1d3b7535a4133, 0x14deaaa12e5c7bdf, 0x0089fbece10c8d6f, 0x4bf7c313757c803d, 0x65aa30bfbb70567d, 0x4fed47af409a3fb3
, 0x07557dd875d3daf5, 0x36c49c2380e3c9bb, 0xa21f643d329ae02f, 0x6cf6f7474338bcb0, 0xb5df78136a0f3012, 0x031fb2df2e00e9d4, 0x4d86fccbe75e79cd, 0x23f890e082d03b7d, 0x5716a1ffb50a8262, 0x0199b50aa6cf3302, 0x6a1be351f86090d5, 0x36095efc13349364
, 0xffe752be8ce46920, 0x65047a340b652f65, 0x320ee55fd03156a6, 0x5af6aa45278409f6, 0xa6caf283b1cf3850, 0x4e3a988f61072f96, 0x750f67926b18f680, 0x09fc3f2927d21a4a, 0x914893c2f2ce1169, 0x4d15b367121b3e75, 0x6cb12559723774f2, 0x3ee5b8c2a70e054a
, 0x7dd9b3518d84d2d7, 0x147d5a5a53f57a58, 0xe1bd0904ad842a05, 0x3a0f3b029c9a5845, 0x7153c03261410074, 0x4e203d6737058c17, 0xebecf5cb79f28af9, 0x574b889870c279f4, 0x326317b005f444a4, 0x7480da44b34f4b1e, 0x7c5f21cdc46275b2, 0x210494b9ee24e4e0
, 0x3cbf6ca1f4aa4ead, 0x6bf3872ccbfed940, 0x19e8a84673a566ca, 0x61a80e16990401a2, 0xea2e029e7f9b3824, 0x5762298465f0ebd3, 0xf60e36d4969f9af0, 0x00b826180531c799, 0x17120ec95cf3c61d, 0x47196cd6de85c7d0, 0xb0d47cff46a5cba3, 0x29271400d7ede26b
, 0x835908353516b894, 0x4bc57f8c1eedec8e, 0x2ec5deede5c0db5f, 0x7b9fc48ac4a689fb, 0xf82ce6de88fc10e5, 0x6c5d84a70e03a3d6, 0x88a211fc4ea531f9, 0x7d5583e5918aa03e, 0xbdf2d70766fb8f39, 0x5926497e734ab18a, 0xd6a9872b800cacb4, 0x757c1cd521fd22d6
, 0x22d50b0c13ec4bc0, 0x288a77d34a15e99a, 0x95c8e78fced3d4eb, 0x45ece109c15be169, 0x878ef262d0132128, 0x48110e9fd98939d6, 0xe3fc5425d2e7741e, 0x050ca6e71f599c65, 0xe02f97605d9fe375, 0x2af48b9bfee410e4, 0xfd34a1c107229a54, 0x43dc6f0cdcbd41fe
, 0x15b4eb7d65cc562b, 0x369a7b0dd3e91248, 0x2b087611edd32810, 0x116b234ddce09d7f, 0xcdb03cae8e90d2b0, 0x4017d51587566038, 0x081793739242b600, 0x5086e8e633cd52a1, 0xf5ddaee155cb8087, 0x773311b60d59a7e9, 0x36e5aa0acadf2068, 0x7126a4281b192882
, 0x54a10df54f7ecef8, 0x3cd7d2fbb6e33f67, 0xac31eb6c3e740c25, 0x517db54840feb2de, 0xf17cb269b3ce27a2, 0x04a8fecd1dcc99e7, 0xfc887c1f2f85a2da, 0x280da7425bb55b01, 0xa1af72f5256a5a53, 0x71da839fc459f465, 0xc203fe7ba6587f71, 0x08a4201f77a4f335
, 0x6cb9ea5683014d96, 0x5da17076b6b51ae2, 0xb55ac168c3e3997f, 0x41b9a32373d78f7a, 0x96f58033b8600a50, 0x6ebfba3ec9d956cc, 0x0ff8883707d66d0c, 0x2f562b035445226f, 0x2388fc015bd368c7, 0x2b7d802ce27f627e, 0x301f0369c24083a6, 0x77e139f6da8d5aaa
, 0x9f78574697fce43c, 0x02726c94565421b6, 0x1ad6007338e26585, 0x6134cc5eb35c02ff, 0x77ae739c9cdcd1e1, 0x04e96543233c7a13, 0x97d3926dcded2e10, 0x6bcdff7e14cebb73, 0x9c46ae2b32489774, 0x04a97b9a0473af8d, 0xb0350bd910d9784e, 0x448212d3e2164ad7
, 0xf3464e0351f5e995, 0x68ab4d24b3ade8d6, 0x86854d534002af20, 0x613f7ffe5de92aeb, 0xb385b4f4608a370a, 0x220dccecbc6f2688, 0xc31ec5384abd3680, 0x25a82841a2000fd8, 0xd19e422504694236, 0x0bc1124d541781f5, 0x0808651edcd99176, 0x41b81f223d429c76
, 0x1a6dcb2662cc80c6, 0x0b101fb0ef0d1f74, 0x6f02aed8f8327119, 0x5b4c5176ccc4a340, 0x8fcefd200d6ee8ed, 0x0548127287f44749, 0xe1efeca1fadd1341, 0x0e74bc189dc9016c, 0xe90470353f46cb12, 0x69513d3455bc890c, 0x9503686f1f2497d1, 0x280a0bb7733f1086
, 0x14e5f99930a91dea, 0x7840ad84b03c3878, 0x46e32c654fdbceb1, 0x7e88d2822bb2cecf, 0x4d78a8aed7f8661d, 0x70eb17416ef40180, 0x97b6f1733c474a10, 0x3d0d27fc4c7084ef, 0x730f60f6a1ee0d71, 0x7bf6e3885d3d9302, 0xa1e8af33742f1611, 0x73b798ec129822ed
, 0x0f669bb094642a70, 0x142927de789fc4a4, 0x0db18e01fa98cbd7, 0x6ae4d37674be1451, 0x7175e98f178b4b74, 0x40534e319bc52c6c, 0xb7211d252c4db879, 0x1a7651f8f3ed1aae, 0x9c9a43932d50cc97, 0x630b232b7201c359, 0x327d77575f5b3839, 0x5f0e19e78431864a
, 0xbfbb00b6530a3bb6, 0x19ba9d60d97f7857, 0x759779de744bd764, 0x5facbe63177791e1, 0xc74ea511c56a3b61, 0x1d8909e84083c31d, 0xcd20094b507af492, 0x2ef1b9c07c92ab37, 0x8430ed9ef8494fc9, 0x3f9170e6df5b1fa1, 0x1fb8dbc837175d73, 0x65b961b58008d022
, 0x7e1afb6816864b6f, 0x54c4b92c534871e9, 0xc0a1dcd60d61ef84, 0x4390f0e992c41298, 0x1e54e2c8b7c27348, 0x7a987e01a2ec308c, 0xee42fbd90c4a89fc, 0x1ed8c77f8d7c609d, 0x569dedaca99a3346, 0x0eb471e609fef4ed, 0xc915522a3b9fd03c, 0x726453b246746bfb
, 0x4ed3cae53dc5fa4b, 0x1bf1e4b34b9feef6, 0x0850df9f0401fac3, 0x0a58d33cb2422e2f, 0x3d197f9603ecfc29, 0x45e46edba1cc432e, 0x96c0c93310d9bcaf, 0x18de3a458be2c33f, 0xc9e65e5bcc12a49a, 0x71a5345f0239b187, 0x53b3b2f01c5710b3, 0x438350f57ce2ec4a
, 0xdbbd368a760391db, 0x4033638dfec29fe2, 0x297ad75ed73117fd, 0x269c08d54b106e8c, 0xa4e3e4fd238b4218, 0x1f48a1cb09208aaa, 0x9575153115cf5fa7, 0x59feeff0876fb74a, 0xfdedb4af6f368710, 0x79be1fe79fa674d4, 0x689d6bbb4c707c39, 0x394a451499057bb1
, 0x5887d4fb21fc43b3, 0x37628dfc4b5c23bf, 0xc66b76944b34bd13, 0x6e97f0a8a45bcb36, 0x3ac6b10139edbbdd, 0x313f4846b6745833, 0xf8758d9777cd9037, 0x02fdc98f02692537, 0x9e79f381fff833a5, 0x25ac5d68c49b105c, 0x1e9f48a076d8c9ee, 0x788c85c9fe9543b3
, 0x776ea51db3b3b778, 0x0007c44055b64db2, 0x3c392c2a82fddd25, 0x65000203be8ee976, 0xea119666ab7c50ab, 0x528b2700e8f82d39, 0xc4aaf797118b8282, 0x55e5a7d5382e0d3a, 0x15a80b22e89f1039, 0x199f68594b1247a0, 0x8d5630750d622435, 0x2687f48cc6def5b2
, 0xa16b0c0259eafaee, 0x7aeb10834e93595a, 0xe31bcf34ce679d9f, 0x4e2c19829eee3c87, 0xa46869cb8ca35c9d, 0x3cd35313c08504eb, 0xa088eca66e98389c, 0x44c562f0f7262740, 0xd3eb8a28f447523a, 0x43a0e059bfe37576, 0x0312c5d6d0f2e0ad, 0x5f30aaf0d1614c61
, 0x6f09a7a6e182b0aa, 0x575db3d21a82296b, 0x6599bb5eee7925e6, 0x093f89458dcc2fe3, 0x70c4af785151fc84, 0x1230c0c519de5480, 0x0e66f8f93075a4f6, 0x5de4a122633a5c6d, 0xdb99cf83f9ece1b6, 0x1c3acd4a13ded617, 0x4dfe69e68f59c447, 0x482ba1f7715a3c16
, 0xefeed2a7c81ea8fd, 0x4e089eeb713a572f, 0x78bc74acfbdf322b, 0x4b4951ce8eb86fbf, 0x0eafb6b46ac6714d, 0x72913ed109f7d404, 0xb498bf6fcde9e3a2, 0x3c08a283ef5ded62, 0x9af09f593a48b346, 0x7ed52441d00d4980, 0xa78e843ee5df44ac, 0x25db12d420a86151
, 0xec840e7e89d049e0, 0x5a34cbe928bf96cc, 0xd875dc5525da882c, 0x2af4442fc256827d, 0x089fb428c2ef5a5d, 0x0b573ace080a3d9c, 0x6f57282554c240da, 0x425ceda6707b6bc9, 0x94b5a8c3dde824fb, 0x264f6f6a445b5da9, 0xadf292191c5c1eb7, 0x5e302e82fa4e5533
, 0xf51712fc44237f35, 0x2b0af62c42e56e66, 0x10392cb4d9c71b75, 0x4d7e08fe8457a95b, 0x210b9eceb04534bf, 0x73329d1c7d88e1e5, 0x667a43fdb4ba79e9, 0x3435ec04276ede87, 0x38b8540a1a78b098, 0x4f6c266e6793bb78, 0x447ea35172754041, 0x109d7b742d8c3dac
, 0xe3ccab45d2a4f6f7, 0x59040bb73f3bbd2a, 0x730b39d65645bab5, 0x5c61aed2f83382aa, 0xa992143de3cf83e1, 0x13455cb889b700f9, 0x54648228b310e2f7, 0x5b837752ee0f733a, 0x3923a6c0e5ea0dd9, 0x5ebebd01fc9ca9a2, 0xa34c205b8fd94258, 0x7d1a10029a0b6cd5
, 0x6c83c02241a46527, 0x4127c85d6be1fc62, 0x26f86ff5ca7240b6, 0x2167391e7dd95cd9, 0x79227506ac78caef, 0x1a2cf919b8832a0f, 0x07745266405cf574, 0x38095a07f5713ae1, 0xe5eeab985ca3e7e7, 0x6a5dd9eeb734d639, 0x991027ebe44a4822, 0x311085fb4de9c1f0
, 0x33f361e21066c3b5, 0x550091d2dfc8688f, 0x376345c5532bac13, 0x0aa0898f990931b5, 0xea2f3346e5d3226e, 0x208790ab78776afc, 0xac7c2ae63433850c, 0x3c5c373ada10ef52, 0x96c1b4003f4cde6a, 0x4546a9c475c09781, 0x6c961fd3e8536294, 0x43f36e63fc0d5066
, 0x296601d8c42167f4, 0x241c1fc38565471b, 0xdb00a27e11ce9617, 0x60381181b7e7e4ee, 0xc1076b7635ac4d52, 0x0166010ffb8dda38, 0x5238f69becc43e0b, 0x63303a2015708b17, 0xe8badb2e5bb22591, 0x3a10a4e218b6131d, 0x236ab01aabf1a7b3, 0x1ce8a51a68a4126f
, 0x59e775e2a2a87928, 0x770b48eb4b738301, 0x0b43c2be176bf79b, 0x1957850fb6424660, 0x44455ee1ecb0ab2a, 0x620ceaa116eef4f0, 0x0198f62cb6183f6b, 0x3274f78eaf2d55db, 0xd2ba4e460cf7ed5f, 0x19cfc17bc0b66f43, 0xcbae6f45b1942722, 0x5d93e44739147b58
, 0xd07180b9d28fc597, 0x35372b21b2ea5a46, 0xed2673477f083464, 0x7a9ebeeecc57e6c2, 0xb51d991a81a6b314, 0x35e7d90f4ed6de58, 0x45f21e209510dd05, 0x446ffd2715c8d380, 0xe69b5c7a9b6d3e76, 0x1379e79fb96912e6, 0xc161c848bd508738, 0x22264a049d8cfff6
, 0x32321a68ff7ef7b3, 0x57b0e50cc585b333, 0x1c08c65ba9d764e7, 0x5534c793f92f00f5, 0x7a1ced97eafe6fe4, 0x6b8933739202599c, 0x618c5f8fcadd3ff2, 0x2a8719b3e6548653, 0x346a9ec5c4200f0c, 0x7a36b8d00d0eda58, 0x844b22b75021accd, 0x769737059fc5e465
, 0xdb1ba69b5019f266, 0x1777242305db9ac1, 0x491d11ad264b6ff3, 0x136198dfc57a3053, 0x4a6cc64741eb7176, 0x14e811c97fc97650, 0x6b64667f71be386d, 0x3286fcadf019eb5e, 0x3f2591f4498e10a0, 0x674fa7c32df7867b, 0xbae8ec7ee100dcf2, 0x03b2c0a20a6372a4
, 0x4c8d76b471e24474, 0x421fb6a7b8a3216b, 0xc672bdb2fe8f514d, 0x202af653d9aff3f5, 0x05e5f80f9626953e, 0x7b721fa3ccd42ffc, 0x99d8e481c0f70479, 0x054c31746d23362b, 0xfbef2e20430e8025, 0x60e1e3f02e7720c2, 0x161701874eb347e3, 0x363924e90cbb77a6
, 0x180f5ee1863a1a6a, 0x2f79c0046ff79fe2, 0x44679866e35447f0, 0x1c64c6dd73e0d636, 0x1d8175566341469d, 0x5ba634965b8b9e87, 0x8f48744f976952a5, 0x744f28d23db94c8a, 0xd15e84b1f232da34, 0x556f3d7aa38bee8c, 0x14693c56e866ef89, 0x1564fb9a0f81eb03
, 0xe97eed56fa2b483f, 0x6d3f7e01aebd1957, 0xae8f128aca3b3e45, 0x3d41e85ba2afd3a9, 0xe4fe485e4b6d8328, 0x65c49b4c3e98098e, 0xe96a00e054d6e91a, 0x394a2122738cd006, 0x715cca3dffd90785, 0x7bc3dcde15890965, 0x6dcdc47a33a148ac, 0x435db9d6dbe1bd55
, 0xd74d4d6e0fd89c27, 0x25e727f6a5380553, 0xbe54127ba6c5189a, 0x65c87d3c3e61939c, 0xc34a6d122a809e2e, 0x7de6b787f097eafa, 0xb8f8b6e701758661, 0x10705fbf97042046, 0x1591614e6da2d44f, 0x7c74f26ec6eb070f, 0x9ad98c1a50249c60, 0x6e1bbd44d64b2302
, 0x937cee76047790f9, 0x5b4ccbc70beaf690, 0x332e79ae75ae0dae, 0x2e6394161d093556, 0x4b378bf68f6849f0, 0x6c419fa0cebba72d, 0x8bb431e1e273f2a4, 0x357cec80bbe024fd, 0x83a6e913962f11a9, 0x7808df02e2523718, 0xb6690b5dabc49e13, 0x6cef23259375972a
, 0xd18ac767b5e551fc, 0x5a0ba1dddb15bd36, 0x6f7923de219e3e1f, 0x3ec23588db9b5cfe, 0xa4fc23d42c83bbe0, 0x21581a00768658cd, 0xa295b6e57110218e, 0x3e7bbab1d15f477f, 0x2266c03d3f0d0635, 0x4174f08a95be03b5, 0xaa1a674abb8cbeb8, 0x6bdf6ba553ae3390
, 0x8a31f824638545e2, 0x2a9e37a0f0eede53, 0x148a53d8cba69f65, 0x64c587e816d96316, 0x777a028a47e97e93, 0x13728e46befb2e0e, 0x13138b44862fa665, 0x0fca8c38a87775f6, 0xcc44bd580dd067fa, 0x40f2f7642e22d02e, 0xab3ba6db80c2f728, 0x5068aa2e2d25b7f9
, 0x5a8a842c0a2923ff, 0x67c39e8a1006c196, 0x8f5cb9ff55460a84, 0x2e735c20a419a518, 0x0c6ee3fcbfdc2da4, 0x5bf6ed60a87b92bd, 0x5e4ce130e8e1608f, 0x0932ceb3e50028e8, 0x793cf8a0538cbfb8, 0x4e89e2c018beb7bd, 0xcaaa79642f5060de, 0x542a38a4d13f0016
, 0xa1b0fd9aac663e55, 0x5158bf1f7b33c0e4, 0x060e82f65a4119fe, 0x32347069a1529fc4, 0x5c96ef69127480d5, 0x409a902134df6ffe, 0xdbe8c392eb6c7013, 0x73f2c48b0e3b4a79, 0xddf5060b937e2dff, 0x1534f901278611d9, 0xf47fe29ae4fd49a7, 0x7a2c0bfe75539f29
, 0x19e04d1b2b0fe7fb, 0x56381ebd8181b50e, 0x5c8970c249df4ac3, 0x08acaece8ede7685, 0xc44f1a71aca0d20b, 0x623edc8d92e4ac3a, 0x5496a7e5885a0c95, 0x20a9ba37315b116e, 0x3765873809f5b55d, 0x23c44c42ebef2ff5, 0x56a96d921f724573, 0x3217815b72b8a9eb
, 0x2cc1b42f5350a489, 0x31f0b36e85b8c70b, 0x504a5c8c4d2ce34d, 0x1af8ea26b3786eac, 0x69bc5e26d7afd62f, 0x21e399d04247bf9a, 0x6e6d6676a88efb27, 0x476212b9fe9a6fd4, 0x0740fb65284168de, 0x5f7570be65e69408, 0x0166c3279dd81c29, 0x6565489007c4ed6d
, 0xbafb5bd37b5219c9, 0x00251709f2e210f7, 0x0d22639b51c1198b, 0x0f3c0df3be3de811, 0x3552612be3374eef, 0x0834744318ffa0aa, 0xcb9f1c1e3557a00c, 0x20c359f5de8b6614, 0xd319482a34d05268, 0x42165771b46b75d7, 0xca336c22e8d911a6, 0x4d072f70067a47e1
, 0x9022c6f101555e9e, 0x4c8c7eaf7cc2d697, 0x629810b2d8044817, 0x25110bc01b06c9c1, 0x1bf9c06bf39eaff7, 0x6cc36f151f52b4e8, 0x76b73a6a14b62068, 0x47dcb0dc89db3821, 0xfe9dfeac2f670f41, 0x625b5c93b973c417, 0x5f8c917930133c1a, 0x6bd35f3e0992bb2b
, 0x03b5391a85409e5e, 0x7981d8fd16362767, 0xdb45c80a32a23cb6, 0x67356a7ef48b2dc3, 0x6189236e9f01adaf, 0x07a1e954e5032bd6, 0x53d627199c69727e, 0x25d67e4163cec014, 0x18e7bb6a63a80738, 0x3112be4cb5dcbc74, 0xad9ad6d381643f04, 0x116112cbeabb734d
, 0x32623abe2d66ff07, 0x4d780300822436de, 0x9bed066c04497808, 0x40db29b39ce86700, 0x6e5e5eb3805602a5, 0x52f227f2b1b9b40d, 0x51c2c4c197a18394, 0x6d8bca423ee270bc, 0xd6e60cfe8fb07f72, 0x7dd66c3970f940c6, 0x66aea7b59a0b17cc, 0x75fcf8b00160d729
, 0xbedc5ea39b2402b5, 0x0dc3600425feedd5, 0xadc1ddf2cb1b6631, 0x205ee93e3aae976a, 0x7a2cb4e333c98498, 0x7d12eb776d56872c, 0x8e339bc1b41599fe, 0x4600f0a53fac9427, 0x1049d3a372f14304, 0x7b54e020b22db742, 0xd567962272a35739, 0x27a1178b1115f0c4
, 0x6cfb39d619c35e1b, 0x5cb96fd1a9d9d486, 0xaf45cef7fb4fffea, 0x4a73d7b2ba9321d1, 0x44b46b4a80be86ac, 0x2769b50579e8f734, 0xab5d109e7472f372, 0x2bccfba1cbe995b6, 0xc00026115332f6a3, 0x7acb287da1561c53, 0x21555c608cd90dd9, 0x7731d1b2878dae13
, 0x32122bf5ec1a0649, 0x592b5fa180ec8467, 0x876be1b5ad9ce66f, 0x484c1cc5bb34819d, 0x08e4cc425b30b06c, 0x2766065f0e4d22ce, 0xd90825644987aeff, 0x3a835fcc7fc456a6, 0xf4d801d2cc806d69, 0x41d767ecca55f839, 0xf2dea9fd01f1e74f, 0x74d01b97462211cb
, 0xe43e280ad29f80cc, 0x5cdf66a69029b231, 0xe8d655a03c862cd9, 0x388e38b58d0e8c79, 0x5d9aaa4848ff83a2, 0x14d6fbee4d6cbe74, 0x0426dcda912109ea, 0x1bb7b9cd75d4b541, 0x3a3c0504b39b8505, 0x35a3c5882b31367a, 0x678793d635a6473a, 0x66abca7e20202034
, 0x4a90ff1dad300021, 0x18f29036544d2684, 0x2036d39b8f69095d, 0x36490f5645d18cc8, 0x9414d7368ad3562e, 0x7f8108a04558487e, 0x93db0e56d653e40b, 0x03f413ea960537bb, 0x984717b77f7267ef, 0x6c5d9da4a5ee7305, 0x725318dc36060a49, 0x274397f8e79a239e
, 0xbda7965b4095bab0, 0x6292b2505c7866e3, 0x451fb6a0672d6733, 0x37c560f40242a859, 0x151e56eb818f1423, 0x63451986f0c22ee1, 0x9275ff873a5c75e1, 0x178cdc734a32b96a, 0xff7adbb24244aacc, 0x76518aa0dfd96ddc, 0x161c1c8c81071219, 0x0584d44c10a3e6dc
, 0x2727282a09e9acab, 0x1298e49c34514ebd, 0x0323d059ca1c0e6d, 0x6072c8b87dd26bc6, 0x36eca2ab28d36f26, 0x2a977cb5aae4ea2a, 0xf157d43a0b9546a7, 0x04d60af0ed661d29, 0x34bc1080126e4402, 0x7677ef9a21589171, 0xbd13797278f07a40, 0x32c0daf0b57f20ac
, 0xbc83fd1b8366dc2e, 0x6cd07286c4e670ec, 0xf35485a3f339dc8a, 0x6e7e9285f2247e8b, 0xa9d19d3a09943bae, 0x43fa5197eed852a6, 0xf911398a043242fe, 0x4a100dcb1312cbe9, 0xbe2fd86be910a692, 0x614fd829368d7937, 0xdb5a98b1a92d578f, 0x46f1d23e1b0dca7e
, 0x8bf4c6725e813f36, 0x68bc89078129ce91, 0xff56503ae28f5c7f, 0x2b6e0f4e42178ce5, 0xa97cd947ec65895b, 0x7aa90b66280ff6c9, 0xebbaf32df158a0a0, 0x6a748d0ac02bb713, 0xdf79b5d619e83397, 0x16934947f6485b69, 0xe75185521ab32881, 0x20791e276a7460c9
, 0xd25c403e22c70bc9, 0x0bf079518e66e1d3, 0x45dd5c971d3711de, 0x66bd2c6a30be232c, 0x607829e5b29e53ca, 0x30ed414e71dc08a2, 0x3fd38589ea0f1d39, 0x5a881a121f37fc5c, 0x27b9394368987a4f, 0x321fe45e13afae2d, 0xc6feb75080f33ea0, 0x02166d52f45eebbd
, 0x15026a1b0ccd2fc9, 0x1141be93d5bc3d6d, 0xfd20df606fc676c9, 0x4059e26b00ad78c4, 0x0709b409cec6b505, 0x68f020e8acf478e5, 0x875d77d1f5df0cfc, 0x66eb377735162ff1, 0x860482ab417a32ae, 0x21175f47da213935, 0xa07ff0cda099ecdb, 0x26ae5f177ae2b8e7
, 0xa9a070ea5120eaf7, 0x2581feeba7383f81, 0x49e0f137f1fa2a7a, 0x7fe93c51cfd1ec62, 0x2d74dbdca7777f7e, 0x562da2ba74e823ff, 0x543b4f8609d77a2e, 0x3a0f65212f234ec8, 0xf842e3fea270ebc6, 0x4524322c6a289e11, 0x80815887aa6a8576, 0x46f49d53c3fe29a3
, 0xbcc93cedfdb0d388, 0x4db312076ef0ad2b, 0x1f2cd56373654ad9, 0x4c6446970034d15f, 0x34d2cdbfd5d7130c, 0x6198950d03db2ae5, 0x736094b72faf1b1a, 0x1f6ca46a9f2588f7, 0xcba0b03d6259772a, 0x24e5a23d8d6be3a8, 0x7090e340c94f6d6f, 0x287ba27ee54e8466
, 0x87320c8822d607f0, 0x44fd5802509df171, 0xf35c09860bf6ba4a, 0x6cf53130ef77cc0a, 0xaa81167a00b48ce4, 0x649f4c775b0d8b48, 0x59a25683ee98d33d, 0x651479007d1061a6, 0x155487411f6e16da, 0x411d036475404bf2, 0xc231f1344162458a, 0x4f36b7633f7dd368
, 0xa98ddc0a4e7a89a4, 0x55d8a5da6eacd542, 0x5c3fb48b1001ed45, 0x5c7785ccafa702b9, 0xa64369fd216afb79, 0x1f405ef10e940669, 0x755f4831bc327b6f, 0x2bc1b67d71f1882d, 0x8eab15cfed7777d0, 0x517370d580d99326, 0x0811b75701c9db39, 0x234d84cb52f7b621
, 0x970c4fbddddae49c, 0x3ba8d842475e41e1, 0xb0720f6ad75e7008, 0x275cd5c5184bf345, 0x5eb9833888d3796a, 0x1b3a42dfde11c2f3, 0x946548fe092b5f4d, 0x119917b50f263cc9, 0x622de955a20a3f82, 0x6a552ea3a60c7ff4, 0xc79230138150372a, 0x18083b9518de76a7
, 0x55fb74dd7d3b5455, 0x523eea9a70ff8334, 0x5994a7335e356271, 0x3bb011f60430f1d2, 0x1ec434cba1d6ea7c, 0x69b632960feb5780, 0x46c50417541ebf07, 0x01470bfbf9d23830, 0xe9551f4c049bc5cc, 0x1c124638f35ee8ed, 0x09ca3a9141e83a38, 0x44daaf3e7411127b
, 0x0e54717b6c2fcd10, 0x518ab46b26d5914b, 0x528ac6c82341e833, 0x2247fa99d41f4672, 0xabe30c65c0f327a2, 0x3ac74e012b77e1b4, 0x35defd694c0e86b3, 0x7c382e10bfe60e4e, 0xf37e382996b8461c, 0x4d47481c53631e1a, 0xac8f167884f7b7b1, 0x5ae1bb6ab1a4c643
, 0x63eb02590829df80, 0x623126862a793fa1, 0x6e1e242f1ce09807, 0x7bf96130aaecfd2b, 0xedc5e9ea10bff70a, 0x66b548233b94d26e, 0x70c70ee4594d30ab, 0x79b0006c8811353e, 0x4352792c91710c1f, 0x0c7bf15181a9f539, 0xfc995ee769e3779c, 0x44871c6cb9dcedcd
, 0x0d180bbf2c9a046b, 0x5445c598c45d0cd9, 0xdefb32386875fb94, 0x5b0d235355660f35, 0xbe1dea825b3a7973, 0x10658ec4e1bbe147, 0x48af5e87fad77504, 0x55f5d3c94a7dd694, 0xa9a3e7062cad6ba2, 0x36c0a7e3f9e0ea31, 0xc4bd65217010aebc, 0x1d031dfc8b9fb598
, 0xe3621c104113889e, 0x774b77ee1e6a6477, 0x124c5b8a07785fd7, 0x5a6c0df18188cada, 0xf4adcd545e72d7be, 0x38100fffb66ba966, 0x2100cbe35fe4a4d0, 0x4489be2df052c175, 0xa03a22403b26899f, 0x5ae4a0a0fec13928, 0x89dfbfb802795eaa, 0x34917e9c4ecf2532
, 0x64b93674c60cbbb3, 0x25c098506334c71d, 0x8a723f66f1ee34e1, 0x3a960adf48f141e4, 0x659f386695e440bb, 0x577a0fbf6e8095e6, 0x8ef419b0f4b25496, 0x044176a30b9e465b, 0x7a98705df2013e6f, 0x77d0b2483aa95ce7, 0x309e917b978effd7, 0x08f1e55bfe942c7f
, 0xfc241629b8d613c8, 0x140f2e35cd68949f, 0x38899f6a3ee4f9fa, 0x7abc8ecdd300f3b5, 0xd3dad23505d23eaf, 0x75e73f09376b2c7c, 0x5644a663b60ec5c4, 0x511ade8afe1eaec9, 0xbb005fe4e1abca89, 0x2838de73b0ca1f6c, 0x800a6658b80d28c8, 0x48aaba61c91641ec
, 0x222759cab704d4e2, 0x106dd3c0ce85beca, 0xa1ce1ce341f69d03, 0x1651b210e8e4ee10, 0x47329a5e7133e136, 0x58c02f47dc9367b9, 0x09dcba56947b02af, 0x435c251178125b48, 0xd56979a3f0cd9315, 0x2f02b0a6422afddb, 0x23920f500731f32d, 0x0ab833238232cb5d
, 0xa7b3d1bfb0bb60db, 0x2342c2a03c6eaec2, 0xac5e6e5a14d5282e, 0x5b9a421ddc42a24b, 0x018506414543e056, 0x6d7c377c084954e6, 0x4f8bf71ed3db1ced, 0x5150dbc15ab10979, 0x00b50a1b373a7fbf, 0x140be5c3d3244705, 0x5005bfe96e5b7911, 0x77cea555bb133f3e
, 0x2ab1e1a9d7a973c6, 0x3897ac98314968d3, 0x9e0f74764b23c9c3, 0x2e5ecbbae41997cd, 0x43e2ea5648f12433, 0x3a515a0e4808e69c, 0x17d36c03c36bb343, 0x44cebd053481ce43, 0x89008656c21b0d76, 0x2f8513fcb9009be6, 0x2e223f90208a0e83, 0x3828c2d4efd36a73
, 0xbf17d64f89a8527d, 0x59ebb42b9656151d, 0x7d7bc7245c7dc5ef, 0x191b682a0cb695ec, 0x8931172fad9f9add, 0x239b6cbbab2ebdcf, 0x76932f9ca7002dd1, 0x0c140548f858d8b5, 0x6c7adfddcf741ea5, 0x3b39c4b9e2e1a567, 0xc5135a25f87436fe, 0x690d8fecb7dd0ae0
, 0xd782a618ecda10c2, 0x4f2a84b3134cf832, 0x35a81f71bbc955a4, 0x457f88ed64ae6398, 0xc27eb71c31479985, 0x4ae91808569aab32, 0xa5f2e9785a75eb11, 0x619cb199b837ed36, 0x0e7e5912b9484e40, 0x3b5831e87fdbcaf0, 0x49a2779c2d2b039d, 0x3d4b81e07f49061a
, 0xaa119b0fa222b55c, 0x265c1b11b42fd4e2, 0x6b4d28e519dd7637, 0x3d2da7900de5a4b2, 0x99b06586b5f21d63, 0x4ce62bd9e6a1ee18, 0xb671e753932f8c92, 0x390b7821d0987834, 0x1adf7c73c3f1fc2f, 0x78c636a8514a7af9, 0xaee3b35fe11e7533, 0x7fbd199278f6ffd7
, 0x41aabbf4363d77de, 0x1b27fdf18b96bf6a, 0xda264a1dff9a981c, 0x36efc08530c0bf9a, 0x5bd8862a5d830854, 0x23d7c905e656e6cb, 0x4523324c5b64fdcf, 0x36627f376238665f, 0x564f53925c6d5ea4, 0x17c7cc86a1913022, 0xf90db52a543b009b, 0x15192dc91f8b994b
, 0x80bfa3c1a79ec6e2, 0x48fca8ea99772ecc, 0xfee6a3b98c0f1824, 0x46a8c75601b81e22, 0x2cb3c402a8895fcc, 0x1d1dff9c04305ce2, 0xc1aefe78e85971d7, 0x79c6a083ab5a80b2, 0x379c7bca5dbf2518, 0x2419358989b3ca02, 0xc9c42c9cfa5f470e, 0x4481c2ce91b14459
, 0x6b04dea1ea26deca, 0x26ee3ceee0d0a101, 0xe36cc6bcd8fa4f26, 0x4d14709719764fbd, 0xe0572a706f1fef52, 0x0f75fb69a23f2ec1, 0x32ae4b04a864cf3b, 0x0b6373a91b944773, 0x1a8f2bc20bd088af, 0x586b0d5ace401747, 0xa0e6b094a3c51433, 0x1752a123c268c1c7
, 0x643c2a93b5770ea1, 0x536cb9d1b71eeb43, 0x6bfb0525d0cc6b3f, 0x1f4dcfeec3adefc3, 0x28a0169dd0bf57f0, 0x1336c9aa20a35449, 0xbbcda068703ad7a1, 0x5e33478283c1e03d, 0xf1997733d18fdaf2, 0x789af507a17bb867, 0x79970c14d5695613, 0x79452342e845256f
, 0x6c12f9367a26a018, 0x11beda1c8f9cdfbe, 0x720e6ddf24b30929, 0x7706e91e3e544755, 0x4460381d3a6c9059, 0x7e01916c3678c424, 0x6024355a61d2bb07, 0x68bae01d79c869e2, 0xf21cbcff285df659, 0x02f7ee6aeb57c933, 0xce0f078c17266467, 0x039b4fdb5170a103
, 0xd5de0fec61a4ae1b, 0x33d37a152a778695, 0xea64e40e6a10ded9, 0x1f1d394373bdb213, 0xf63598b6ef59fd14, 0x57922adc3ae52283, 0xe39a90e18b76f4a1, 0x27f3dbebd98a9dae, 0x18179dd9c03804b3, 0x511d72c1912e2d73, 0x88e1f6d24b2f3225, 0x56009999cdc2997f
, 0xda6df977b7d82fe4, 0x76f746bba63da226, 0x0b5facfc3bf13bd7, 0x4a31eb04f66f0e18, 0x8ace73d5e7cfe28f, 0x19aa731bc30c20b1, 0xa91979fe73400317, 0x6795ce71a09c7c9f, 0x93d55501933700ba, 0x3850eaf08b1fd14d, 0x450c5abc89edca71, 0x1be5db848bdfa5ef
, 0x77667d3f4fcf082b, 0x673b6e6c4824bc45, 0x6f22c12a5fe0ed6d, 0x006ee6722b5dfed1, 0xb47a13c1468d0c62, 0x40564879a378e6e4, 0x0bc6b553a9d3ab58, 0x21761c79e44dfcfd, 0x66f36ed3eb1050fb, 0x2e67df1312dd01d3, 0x48744c4a68dbf2ad, 0x7844962b6d6e039c
, 0xe07b5675d378b65f, 0x336262aa3d2c1df0, 0x320a5667d78c2e2b, 0x4f668dd96dda5e2a, 0xe21556795c7b8470, 0x3061905b2ef82bb1, 0xaee53211472206b6, 0x1f87377fee0d7a39, 0xdac58c52a3b1a0c7, 0x6e3c4ce04f0d7ffd, 0xfdffec45d4a3990f, 0x4b5340f79e2ae2c2
, 0x0537c8b7b3d1f332, 0x55292744ae35ee1a, 0x42336d0e6d057f1e, 0x5ac40e9e645cb3d7, 0x848f7b7f845e46c7, 0x74bda86736eff150, 0x891acf622baf4f35, 0x14bcef9cf39667bb, 0x9aa1354d9731b9b3, 0x27e855a19295e59f, 0x1a829a8e10662ed0, 0x3bbc43f9ec4437a7
, 0x8bfa8b1cb1de5341, 0x3432778068d35549, 0xe3d807da41f25a48, 0x1bb6ee1ce2efe552, 0x08d9bded0bd3affc, 0x290f1c5299a917a8, 0xda8dfd79562f8939, 0x1bf7aae68686211f, 0x2ab6daf9bc860765, 0x7bef6e2f0eb58a0b, 0x8746faab7c439b94, 0x017ea87750bb8bda
, 0xf8dfeb22239c9a7c, 0x35cec0d2887b3a13, 0x68aa94ac601f1606, 0x7470553f8ba61767, 0x37894f91c9eac410, 0x55b22aeb8337f732, 0x53f8d90f29a2fe94, 0x0aec068aec69023a, 0x40506162ad6182ee, 0x6a327ff1ac1e5475, 0x968d7095492df3c8, 0x3f93f46195f67521
, 0x4983bca28970d546, 0x2716b931296b53c2, 0xf42b013266b6f8b3, 0x76f29b084b6a369f, 0x8e28749222216249, 0x4f2fa1d3a6c1acfd, 0x0ee66697eab8f954, 0x37c33e28fec0cce5, 0x7d0419e2bafd1dd1, 0x01f04d4299b94daa, 0x5ec06abbc1e5c7e6, 0x3a24c66060ed72a9
, 0x0db764e15f960f26, 0x1d5973d5d59f9c3a, 0xf3dc2608dc6d9149, 0x1d80e0461b72f518, 0x2264dccd49c8b09c, 0x1f03e7a246334d5e, 0x2d6e38871b1fc2ad, 0x418588ae4f284bd3, 0x3efb071bafe1afa2, 0x0799ba0c80bdd8dc, 0xa6b273222dcc4a76, 0x13859f08ac8a4b23
, 0x0194acc2663c5acb, 0x459fa55bd0bbedf6, 0x1b055550f06f8cc1, 0x09e5fad46599ea75, 0x6b3916ef772958a3, 0x4aaaa5c18093a431, 0x8e1503e36610f594, 0x620ef55048a263b9, 0x5a28963c8cb8ecbc, 0x6aee46b1b740c15a, 0x67e39606f59cfea9, 0x13a579e3777ca8b1
, 0x45ad92f61cbb8de3, 0x53068a1a42460eab, 0x9b163546de379578, 0x07bf38a7cecd4860, 0xf84c77031d282de1, 0x402aed6399f78ffc, 0xfb83dd20295f6d45, 0x3702e257340d2ecd, 0xb8db2d8b979b97c8, 0x617526d2a50b0c51, 0xd86f6278313017db, 0x2f35eedec55f9d92
, 0xeecb69493517973b, 0x7a111a74e0baf09a, 0xb82c6da8ec39f63d, 0x4217076312833746, 0x5d36d11f3dda88d9, 0x7baebcb360f2a887, 0x9829b62d093d6cbb, 0x10f17a2f6edf28fd, 0xfe3efa4353f40626, 0x731ca3065c118e34, 0x6185678827960895, 0x07f906a4f4c6355c
, 0x361d9cd10e657142, 0x2b5f5d452dd861ce, 0xa3e01df05d04b69a, 0x533723bc4cfcc0db, 0x820384afa1bbccb5, 0x4e67e941595d8dfd, 0x0f8da50839e13646, 0x6887a0573a596968, 0xe93dd1df5ace7343, 0x0d4076f28ecf96c8, 0x0ba2f854988074c1, 0x5eb2a314a41a40b6
, 0x49ff6d27a676b27e, 0x15f7ca40acd5114e, 0xc171f9a750d7da95, 0x3bedbe891f79eb5c, 0x5b643bceb83f74ff, 0x088b1af3aa331a4c, 0xde294c7e0a60c4a9, 0x0a0770fc8120b151, 0xf09b757a0c7c1937, 0x34b797c03efd9c88, 0x051e3edb2c28cc49, 0x66db34ec5ac5122c
, 0x95fde0d3d3dc8cbf, 0x797897c8121818cf, 0x1fd46d197710f89d, 0x533a505803f809c5, 0xb60f1c090c9fd211, 0x4a7c3479af5c9d82, 0x4bfc3ffa4c8cf5a5, 0x6949f4a61306821f, 0xd814c949c67abcdc, 0x419a5e33166863c4, 0x9de646f6bd0895e0, 0x497cc1449a54545a
, 0x69eb31247fe126f2, 0x323c83233967f477, 0x52e0db4d3d78127d, 0x42a0e188e7b9380c, 0x3a6b011c46e34e7e, 0x79f4168aa9a0b4aa, 0x94270a25d708fa4d, 0x2bb28618cbc9cdc8, 0x741e46bb04606819, 0x02790c52fb2ce982, 0x6dbb92d0c6d0af10, 0x32aa96ae061e9412
, 0x1376700c90d98eaa, 0x4d1dfe650c0a7136, 0xb397f8eef89aff20, 0x4836ac4a041bae37, 0xf37c1076a80a02b8, 0x0d063fa2467b3a37, 0x498f2617b56b7e7b, 0x65ef1194db859a5d, 0xd1fe25d5d28ffcb6, 0x228ee6f49459c083, 0x6b7e82b3b009b15b, 0x713b185ef1fccbfc
, 0x552468f1ff60c298, 0x2b7ba65d02519614, 0x8a86ad90ff0816c2, 0x7bf9249284bd02e5, 0x3008c56e474c2d10, 0x171473b77f804540, 0x15fb79d07bdea766, 0x66ac67c7b9b0951f, 0x34bca15bb6d2f652, 0x13c63dd2687d617b, 0xc515ae237715c19c, 0x0e543c6765fbfef2
, 0x668c80faf156fb5e, 0x1e2e9e3b3d9962b8, 0x89ebaa264394e113, 0x322add21cf1659cf, 0xf9e6e26733619f8e, 0x723bfc8b792147f0, 0x79aef2837d7e092f, 0x1aa61c59290b5011, 0x9955ae576a499cd3, 0x2c3d6e6a5a1ce0da, 0xb864cfa199a8676b, 0x4961a21f1080285f
, 0x828e184adf9d997b, 0x0c84bda97e7ce725, 0xe6974677094cfcc5, 0x4ec8cd773946105b, 0xa48681bcc95fb5c6, 0x6ade87f8f7a5f269, 0x9b97628fdd39c03d, 0x3bde0ee1f19f1842, 0x4ef8c8fb117c0ca1, 0x769bf8f8d07de9bf, 0xc8f5f435b78a57e5, 0x79987aa861bbcf9c
, 0x7f6c557204b02022, 0x119bd819111c69d1, 0xf0c61ef00b3eb70b, 0x4317f0511bfb7b39, 0x36a2b944e84d608e, 0x1c1a3862da3369cb, 0x37dbf471085f1775, 0x3835751e107419ad, 0x04ab0c84bb07a3fe, 0x63758bfbc7df13a0, 0x15ffd20cb554f23e, 0x1ff11c442b1515b7
, 0x171377f1bf937186, 0x615efe82b83538f8, 0x321e7cfae352a761, 0x7af02427d7241502, 0x86546e47f2cc559f, 0x65a1d8a017659d75, 0xc95d8aa5b8bfdac9, 0x01e887cb68990623, 0xf1f8ee8c466bcc3d, 0x40ce5e4f2ba3908f, 0xd2b81a3480c16b35, 0x51625d3eabf708cd
, 0x44d770a210105739, 0x7f1de74a022958a0, 0xfbe4c91bd1e8f732, 0x204fbacb13586460, 0x97d79097d62e3cf8, 0x541ad5591934b114, 0xfdfb47919c141909, 0x354926e5244fdecf, 0x6291b0a0e2e994b0, 0x2b9a9a69d3a6c3d1, 0x8189be54302371e7, 0x3645c65df1a881cd
, 0xdf0460f445e3877b, 0x7ea384dc52d0d26e, 0x0c2e5f768d46b6b0, 0x1f6e62daa7c5d4e6, 0xf8b026b33b2343ee, 0x2b7183c8767d372c, 0xbd45d1b6b6731517, 0x4ddb3d287c470d60, 0x1031dba40263ece2, 0x4e737fa0d659045f, 0x8cbc98d07d09b455, 0x34a35128a2bcb7f5 };
#endif

Просмотреть файл

@ -0,0 +1,125 @@
FourQlib v3.0 (C Edition)
=========================
Optimized implementation for 32-bit ARM and ARM Cortex-M4 with side-channel countermeasures
===========================================================================================
1. CONTENTS:
--------
The "FourQ_ARM_side_channel" folder contains:
makefile - Makefile for compilation on ARM processors (ARMv6 and ARMv7) using GNU GCC
on Linux.
makefile_Cortex-M4 - Makefile for compilation on ARM Cortex-M4 (STM32F4xx series) using GNU GCC
on Linux.
*.c, *.h - Library and header files. Public API for ECC scalar multiplication, key
exchange and signatures is located in FourQ_api.h
ARM/ - Folder with library files implementing low-level arithmetic for ARM.
libopencm3/ - Folder with firmware library files for ARM Cortex-M microcontrollers
random/ - Folder with pseudo-random generation function for ARM Cortex-M4.
tests/ - Test files for 32-bit ARM.
tests_Cortex-M4/ - Test files for ARM Cortex-M4.
README.txt - This readme file.
stm32f4_wrapper.c and stm32f4_wrapper.h are by Joost Rijneveld and can be found at:
https://github.com/joostrijneveld/STM32-getting-started
Files in the folder libopencm3 are from the libopencm3 project (http://libopencm3.org/):
https://github.com/libopencm3/libopencm3
2. SUPPORTED PLATFORMS:
-------------------
This implementation is supported on ARM platforms and includes two variants:
(i) Implementation for ARM processors based on ARMv6 and ARMv7 architectures. This implementation was optimized
for a first generation Raspberry Pi using a 700 MHz ARM1176JZF-S processor (ARMv6 architecture).
(ii) Implementation for ARM Cortex-M4 processors based on the ARMv7-M architecture. This implementation was
developed and optimized on a STM32F4Discovery development board containing a Cortex-M4 STM32F407VG micro-
controller (ARMv7-M architecture). It should be possible to extend the support to Cortex-M3 and Cortex-M7
based devices with small modifications.
See instructions below to choose an implementation option and compile on one of the supported platforms.
3. COMPLEMENTARY CRYPTO FUNCTIONS:
------------------------------
Random values are generated with /dev/urandom in the case of the 32-bit ARM implementation, and with the function
random_int() in the case of the ARM Cortex-M4 implementation.
The library includes an implementation of SHA-512 which is used by default by SchnorrQ signatures.
Users can experiment with different options by replacing functions in the folders "random" and "sha512" and
applying the corresponding changes to the settings in FourQ.h.
4. INSTRUCTIONS:
------------
4.1. BUILDING THE LIBRARY FOR ARMv6 or ARMv7:
---------------------------------------
To compile on Linux using the GNU GCC compiler or the clang compiler, execute the following command from the
command prompt:
make CC=[gcc/clang] EXTENDED_SET=[TRUE/FALSE]
After compilation, run fp_tests, ecc_tests or crypto_tests.
By default GNU GCC is used, as well as the extended settings.
For example, to compile using GNU GCC, execute:
make
As another example, to compile using clang, execute:
make CC=clang
By default EXTENDED_SET is enabled, which sets the following compilation flags: -fwrapv -fomit-frame-pointer
-funroll-loops. To disable this, use EXTENDED_SET=FALSE.
Users are encouraged to experiment with the different flag options.
4.2. BUILDING THE LIBRARY FOR CORTEX-M4 ON THE STM32F4DISCOVERY BOARD:
----------------------------------------------------------------
The following instructions have been tested on a Ubuntu 16.04 Linux machine.
First, install the ARM GNU GCC cross-compiler on the server machine:
sudo apt-get install gcc-arm-none-eabi libc6-dev-i386
Then, download, build and install stlink: https://github.com/texane/stlink
sudo apt-get install libusb-1.0-0-dev
git clone https://github.com/texane/stlink.git
cd stlink
make
cd build/Release/ && sudo make install
To compile the code, execute the following command from the FourQ_ARM_side_channel folder on the server machine:
make -f makefile_Cortex-M4
Power the STM32F4DISCOVERY board (with a USB to mini-USB cable) and connect it to the server machine via a
USB-TTL converter as follows:
VDD -> VDD
GND -> GND
TX -> PA3
RX -> PA2
Then, run from the server machine:
sudo ./tests_Cortex-M4/monitor.sh
From a different terminal window on the server machine, program the device with one of the following commands
from the FourQ_ARM_side_channel folder:
st-flash write tests_Cortex-M4/fp_tests.bin 0x8000000
st-flash write tests_Cortex-M4/ecc_tests.bin 0x8000000
st-flash write tests_Cortex-M4/crypto_tests.bin 0x8000000
The tests should begin to run on the first terminal window.

Просмотреть файл

@ -0,0 +1,168 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: crypto utility functions
************************************************************************************/
#include "FourQ_internal.h"
#include "FourQ_params.h"
#include <string.h>
static digit_t mask4000 = (digit_t)1 << (sizeof(digit_t)*8 - 2);
static digit_t mask7fff = (digit_t)(-1) >> 1;
bool is_zero_ct(digit_t* a, unsigned int nwords)
{ // Check if multiprecision element is zero
digit_t x;
unsigned int i;
x = a[0];
for (i = 1; i < nwords; i++) {
x |= a[i];
}
return (bool)(1 ^ ((x | (0-x)) >> (RADIX-1)));
}
void encode(point_t P, unsigned char* Pencoded)
{ // Encode point P
// SECURITY NOTE: this function does not run in constant time.
digit_t temp1 = (P->x[1][NWORDS_FIELD-1] & mask4000) << 1;
digit_t temp2 = (P->x[0][NWORDS_FIELD-1] & mask4000) << 1;
memmove(Pencoded, P->y, 32);
if (is_zero_ct((digit_t*)P->x, NWORDS_FIELD) == true) {
((digit_t*)Pencoded)[2*NWORDS_FIELD-1] |= temp1;
} else {
((digit_t*)Pencoded)[2*NWORDS_FIELD-1] |= temp2;
}
}
ECCRYPTO_STATUS decode(const unsigned char* Pencoded, point_t P)
{ // Decode point P
// SECURITY NOTE: this function does not run in constant time.
felm_t r, t, t0, t1, t2, t3, t4;
f2elm_t u, v, one = {0};
digit_t sign_dec;
point_extedwards_t R;
unsigned int i, sign;
one[0][0] = 1;
memmove((unsigned char*)P->y, Pencoded, 32); // Decoding y-coordinate and sign
sign = (unsigned int)(Pencoded[31] >> 7);
P->y[1][NWORDS_FIELD-1] &= mask7fff;
fp2sqr1271(P->y, u);
fp2mul1271(u, (felm_t*)&PARAMETER_d, v);
fp2sub1271(u, one, u);
fp2add1271(v, one, v);
fpsqr1271(v[0], t0); // t0 = v0^2
fpsqr1271(v[1], t1); // t1 = v1^2
fpadd1271(t0, t1, t0); // t0 = t0+t1
fpmul1271(u[0], v[0], t1); // t1 = u0*v0
fpmul1271(u[1], v[1], t2); // t2 = u1*v1
fpadd1271(t1, t2, t1); // t1 = t1+t2
fpmul1271(u[1], v[0], t2); // t2 = u1*v0
fpmul1271(u[0], v[1], t3); // t3 = u0*v1
fpsub1271(t2, t3, t2); // t2 = t2-t3
fpsqr1271(t1, t3); // t3 = t1^2
fpsqr1271(t2, t4); // t4 = t2^2
fpadd1271(t3, t4, t3); // t3 = t3+t4
for (i = 0; i < 125; i++) { // t3 = t3^(2^125)
fpsqr1271(t3, t3);
}
fpadd1271(t1, t3, t); // t = t1+t3
mod1271(t);
if (is_zero_ct(t, NWORDS_FIELD) == true) {
fpsub1271(t1, t3, t); // t = t1-t3
}
fpadd1271(t, t, t); // t = 2*t
fpsqr1271(t0, t3); // t3 = t0^2
fpmul1271(t0, t3, t3); // t3 = t3*t0
fpmul1271(t, t3, t3); // t3 = t3*t
fpexp1251(t3, r); // r = t3^(2^125-1)
fpmul1271(t0, r, t3); // t3 = t0*r
fpmul1271(t, t3, P->x[0]); // x0 = t*t3
fpsqr1271(P->x[0], t1);
fpmul1271(t0, t1, t1); // t1 = t0*x0^2
fpdiv1271(P->x[0]); // x0 = x0/2
fpmul1271(t2, t3, P->x[1]); // x1 = t3*t2
fpsub1271(t, t1, t);
mod1271(t);
if (is_zero_ct(t, NWORDS_FIELD) == false) { // If t != t1 then swap x0 and x1
fpcopy1271(P->x[0], t0);
fpcopy1271(P->x[1], P->x[0]);
fpcopy1271(t0, P->x[1]);
}
mod1271(P->x[0]);
if (is_zero_ct((digit_t*)P->x, NWORDS_FIELD) == true) {
sign_dec = ((digit_t*)&P->x[1])[NWORDS_FIELD-1] >> (sizeof(digit_t)*8 - 2);
} else {
sign_dec = ((digit_t*)&P->x[0])[NWORDS_FIELD-1] >> (sizeof(digit_t)*8 - 2);
}
if (sign != (unsigned int)sign_dec) { // If sign of x-coordinate decoded != input sign bit, then negate x-coordinate
fp2neg1271(P->x);
}
point_setup(P, R);
if (ecc_point_validate(R) == false) {
fpneg1271(R->x[1]);
fpcopy1271(R->x[1], P->x[1]);
if (ecc_point_validate(R) == false) { // Final point validation
return ECCRYPTO_ERROR;
}
}
return ECCRYPTO_SUCCESS;
}
void to_Montgomery(const digit_t* ma, digit_t* c)
{ // Converting to Montgomery representation
Montgomery_multiply_mod_order(ma, (digit_t*)&Montgomery_Rprime, c);
}
void from_Montgomery(const digit_t* a, digit_t* mc)
{ // Converting from Montgomery to standard representation
digit_t one[NWORDS_ORDER] = {0};
one[0] = 1;
Montgomery_multiply_mod_order(a, one, mc);
}
const char* FourQ_get_error_message(ECCRYPTO_STATUS Status)
{ // Output error/success message for a given ECCRYPTO_STATUS
struct error_mapping {
unsigned int index;
char* string;
} mapping[ECCRYPTO_STATUS_TYPE_SIZE] = {
{ECCRYPTO_ERROR, ECCRYPTO_MSG_ERROR},
{ECCRYPTO_SUCCESS, ECCRYPTO_MSG_SUCCESS},
{ECCRYPTO_ERROR_DURING_TEST, ECCRYPTO_MSG_ERROR_DURING_TEST},
{ECCRYPTO_ERROR_UNKNOWN, ECCRYPTO_MSG_ERROR_UNKNOWN},
{ECCRYPTO_ERROR_NOT_IMPLEMENTED, ECCRYPTO_MSG_ERROR_NOT_IMPLEMENTED},
{ECCRYPTO_ERROR_NO_MEMORY, ECCRYPTO_MSG_ERROR_NO_MEMORY},
{ECCRYPTO_ERROR_INVALID_PARAMETER, ECCRYPTO_MSG_ERROR_INVALID_PARAMETER},
{ECCRYPTO_ERROR_SHARED_KEY, ECCRYPTO_MSG_ERROR_SHARED_KEY},
{ECCRYPTO_ERROR_SIGNATURE_VERIFICATION, ECCRYPTO_MSG_ERROR_SIGNATURE_VERIFICATION},
};
if (Status >= ECCRYPTO_STATUS_TYPE_SIZE || mapping[Status].string == NULL) {
return "Unrecognized ECCRYPTO_STATUS";
} else {
return mapping[Status].string;
}
};

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,251 @@
/********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: Diffie-Hellman key exchange based on FourQ, including countermeasures
* against side-channel attacks
* option 1: co-factor ecdh using compressed 32-byte public keys,
* (see https://datatracker.ietf.org/doc/draft-ladd-cfrg-4q/).
* option 2: co-factor ecdh using uncompressed, 64-byte public keys.
*********************************************************************************/
#include "FourQ_internal.h"
#include "FourQ_params.h"
#include "../random/random.h"
#include <string.h>
static __inline bool is_neutral_point(point_t P)
{ // Is P the neutral point (0,1)?
// SECURITY NOTE: this function does not run in constant time (input point P is assumed to be public).
if (is_zero_ct((digit_t*)P->x, 2*NWORDS_FIELD) && is_zero_ct(&((digit_t*)P->y)[1], 2*NWORDS_FIELD-1) && is_digit_zero_ct(P->y[0][0] - 1)) {
return true;
}
return false;
}
/*************** ECDH USING COMPRESSED, 32-BYTE PUBLIC KEYS ***************/
ECCRYPTO_STATUS CompressedPublicKeyGeneration_SCA_secure(const unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint)
{ // Compressed public key generation for key exchange
// It produces a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator), and a blinding point BlindingPoint.
// Input: 32-byte SecretKey
// Output: 32-byte PublicKey and 64-byte BlindingPoint
point_t G, R;
point_extedwards_t S;
unsigned char SecretBlinding[32];
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretBlinding, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
// Set up an initial "weak" blinding point R
fp2copy1271((felm_t*)&GENERATOR_x[0], G->x);
fp2copy1271((felm_t*)&GENERATOR_y[0], G->y);
point_setup(G, S);
eccdouble(S);
eccnorm(S, R);
// Computing an initial blinding point. This computation itself is not protected with a secure point blinding
Status = ecc_mul_SCA_secure(G, R, (digit_t*)SecretBlinding, (point_affine*)BlindingPoint, false);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = ecc_mul_SCA_secure(G, (point_affine*)BlindingPoint, (digit_t*)SecretKey, R, false); // Compute public key
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
encode(R, PublicKey); // Encode public key
// Cleanup
clear_words((unsigned int*)SecretBlinding, 256/(sizeof(unsigned int)*8));
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretBlinding, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)BlindingPoint, 512/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 256/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS CompressedKeyGeneration_SCA_secure(unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint)
{ // Keypair generation for key exchange. Public key is compressed to 32 bytes
// It produces a private key SecretKey, a public key PublicKey, which is the encoding of P = SecretKey*G (G is the generator), and a blinding point BlindingPoint.
// Outputs: 32-byte SecretKey, 32-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretKey, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = CompressedPublicKeyGeneration_SCA_secure(SecretKey, PublicKey, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretKey, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)BlindingPoint, 512/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS CompressedSecretAgreement_SCA_secure(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret, unsigned char* BlindingPoint)
{ // Secret agreement computation for key exchange using a compressed, 32-byte public key
// The output is the y-coordinate of SecretKey*A, where A is the decoding of the public key PublicKey.
// Inputs: 32-byte SecretKey, 32-byte PublicKey and 64-byte BlindingPoint
// Output: 32-byte SharedSecret and updated BlindingPoint
point_t A;
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
if ((PublicKey[15] & 0x80) != 0) { // Is bit128(PublicKey) = 0?
Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
goto cleanup;
}
Status = decode(PublicKey, A); // Also verifies that A is on the curve. If it is not, it fails
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = ecc_mul_SCA_secure(A, (point_affine*)BlindingPoint, (digit_t*)SecretKey, A, true);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
if (is_neutral_point(A)) { // Is output = neutral point (0,1)?
Status = ECCRYPTO_ERROR_SHARED_KEY;
goto cleanup;
}
memmove(SharedSecret, (unsigned char*)A->y, 32);
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SharedSecret, 256/(sizeof(unsigned int)*8));
return Status;
}
/*************** ECDH USING UNCOMPRESSED PUBLIC KEYS ***************/
ECCRYPTO_STATUS PublicKeyGeneration_SCA_secure(const unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint)
{ // Public key generation for key exchange
// It produces the public key PublicKey = SecretKey*G, where G is the generator, and a blinding point BlindingPoint.
// Input: 32-byte SecretKey
// Output: 64-byte PublicKey and 64-byte BlindingPoint
point_t G, R;
point_extedwards_t S;
unsigned char SecretBlinding[32];
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretBlinding, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
// Set up an initial "weak" blinding point R
fp2copy1271((felm_t*)&GENERATOR_x[0], G->x);
fp2copy1271((felm_t*)&GENERATOR_y[0], G->y);
point_setup(G, S);
eccdouble(S);
eccnorm(S, R);
// Computing an initial blinding point. This computation itself is not protected with a secure point blinding
Status = ecc_mul_SCA_secure(G, R, (digit_t*)SecretBlinding, (point_affine*)BlindingPoint, false);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = ecc_mul_SCA_secure(G, (point_affine*)BlindingPoint, (digit_t*)SecretKey, (point_affine*)PublicKey, false); // Compute public key
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
// Cleanup
clear_words((unsigned int*)SecretBlinding, 256/(sizeof(unsigned int)*8));
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretBlinding, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)BlindingPoint, 512/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 512/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS KeyGeneration_SCA_secure(unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint)
{ // Keypair generation for key exchange
// It produces a private key SecretKey, the public key PublicKey = SecretKey*G, where G is the generator, and a blinding point BlindingPoint.
// Outputs: 32-byte SecretKey, 64-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretKey, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = PublicKeyGeneration_SCA_secure(SecretKey, PublicKey, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretKey, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 512/(sizeof(unsigned int)*8));
clear_words((unsigned int*)BlindingPoint, 512/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS SecretAgreement_SCA_secure(const unsigned char* SecretKey, const unsigned char* PublicKey, unsigned char* SharedSecret, unsigned char* BlindingPoint)
{ // Secret agreement computation for key exchange
// The output is the y-coordinate of SecretKey*PublicKey.
// Inputs: 32-byte SecretKey, 64-byte PublicKey and 64-byte BlindingPoint
// Output: 32-byte SharedSecret and updated BlindingPoint
point_t A;
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
if (((PublicKey[15] & 0x80) != 0) || ((PublicKey[31] & 0x80) != 0) || ((PublicKey[47] & 0x80) != 0) || ((PublicKey[63] & 0x80) != 0)) { // Are PublicKey_x[i] and PublicKey_y[i] < 2^127?
Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
goto cleanup;
}
Status = ecc_mul_SCA_secure((point_affine*)PublicKey, (point_affine*)BlindingPoint, (digit_t*)SecretKey, A, true); // Also verifies that PublicKey and BlindingPoint are points on the curve. If not, it fails
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
if (is_neutral_point(A)) { // Is output = neutral point (0,1)?
Status = ECCRYPTO_ERROR_SHARED_KEY;
goto cleanup;
}
memmove(SharedSecret, (unsigned char*)A->y, 32);
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SharedSecret, 256/(sizeof(unsigned int)*8));
return Status;
}

Просмотреть файл

@ -0,0 +1,96 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBOPENCM3_CM3_COMMON_H
#define LIBOPENCM3_CM3_COMMON_H
#include <stdint.h>
#include <stdbool.h>
/* This must be placed around external function declaration for C++
* support. */
#ifdef __cplusplus
# define BEGIN_DECLS extern "C" {
# define END_DECLS }
#else
# define BEGIN_DECLS
# define END_DECLS
#endif
/* Full-featured deprecation attribute with fallback for older compilers. */
#ifdef __GNUC__
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4)
# define LIBOPENCM3_DEPRECATED(x) __attribute__((deprecated(x)))
# else
# define LIBOPENCM3_DEPRECATED(x) __attribute__((deprecated))
# endif
#else
# define LIBOPENCM3_DEPRECATED(x)
#endif
/* Generic memory-mapped I/O accessor functions */
#define MMIO8(addr) (*(volatile uint8_t *)(addr))
#define MMIO16(addr) (*(volatile uint16_t *)(addr))
#define MMIO32(addr) (*(volatile uint32_t *)(addr))
#define MMIO64(addr) (*(volatile uint64_t *)(addr))
/* Generic bit-band I/O accessor functions */
#define BBIO_SRAM(addr, bit) \
MMIO32((((uint32_t)addr) & 0x0FFFFF) * 32 + 0x22000000 + (bit) * 4)
#define BBIO_PERIPH(addr, bit) \
MMIO32((((uint32_t)addr) & 0x0FFFFF) * 32 + 0x42000000 + (bit) * 4)
/* Generic bit definition */
#define BIT0 (1<<0)
#define BIT1 (1<<1)
#define BIT2 (1<<2)
#define BIT3 (1<<3)
#define BIT4 (1<<4)
#define BIT5 (1<<5)
#define BIT6 (1<<6)
#define BIT7 (1<<7)
#define BIT8 (1<<8)
#define BIT9 (1<<9)
#define BIT10 (1<<10)
#define BIT11 (1<<11)
#define BIT12 (1<<12)
#define BIT13 (1<<13)
#define BIT14 (1<<14)
#define BIT15 (1<<15)
#define BIT16 (1<<16)
#define BIT17 (1<<17)
#define BIT18 (1<<18)
#define BIT19 (1<<19)
#define BIT20 (1<<20)
#define BIT21 (1<<21)
#define BIT22 (1<<22)
#define BIT23 (1<<23)
#define BIT24 (1<<24)
#define BIT25 (1<<25)
#define BIT26 (1<<26)
#define BIT27 (1<<27)
#define BIT28 (1<<28)
#define BIT29 (1<<29)
#define BIT30 (1<<30)
#define BIT31 (1<<31)
#endif

Просмотреть файл

@ -0,0 +1,110 @@
/** @addtogroup gpio_defines
*
* @author @htmlonly &copy; @endhtmlonly 2011
* Fergus Noble <fergusnoble@gmail.com>
* @author @htmlonly &copy; @endhtmlonly 2012
* Ken Sarkies <ksarkies@internode.on.net>
*
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA GPIO.H
The order of header inclusion is important. gpio.h includes the device
specific memorymap.h header before including this header file.*/
/** @cond */
#ifndef LIBOPENCM3_GPIO_H
#define LIBOPENCM3_GPIO_H
/** @endcond */
#ifndef LIBOPENCM3_GPIO_COMMON_F24_H
#define LIBOPENCM3_GPIO_COMMON_F24_H
/**@{*/
#include "memorymap_f4.h"
#include "gpio_common_f234.h"
/* GPIO port base addresses (for convenience) */
/** @defgroup gpio_port_id GPIO Port IDs
@ingroup gpio_defines
@{*/
#define GPIOG GPIO_PORT_G_BASE
#define GPIOH GPIO_PORT_H_BASE
#define GPIOI GPIO_PORT_I_BASE
/**@}*/
/* --- GPIO registers for STM32F2, STM32F3 and STM32F4 --------------------- */
/* Port mode register (GPIOx_MODER) */
#define GPIOG_MODER GPIO_MODER(GPIOG)
#define GPIOH_MODER GPIO_MODER(GPIOH)
#define GPIOI_MODER GPIO_MODER(GPIOI)
/* Port output type register (GPIOx_OTYPER) */
#define GPIOG_OTYPER GPIO_OTYPER(GPIOG)
#define GPIOH_OTYPER GPIO_OTYPER(GPIOH)
#define GPIOI_OTYPER GPIO_OTYPER(GPIOI)
/* Port output speed register (GPIOx_OSPEEDR) */
#define GPIOG_OSPEEDR GPIO_OSPEEDR(GPIOG)
#define GPIOH_OSPEEDR GPIO_OSPEEDR(GPIOH)
#define GPIOI_OSPEEDR GPIO_OSPEEDR(GPIOI)
/* Port pull-up/pull-down register (GPIOx_PUPDR) */
#define GPIOG_PUPDR GPIO_PUPDR(GPIOG)
#define GPIOH_PUPDR GPIO_PUPDR(GPIOH)
#define GPIOI_PUPDR GPIO_PUPDR(GPIOI)
/* Port input data register (GPIOx_IDR) */
#define GPIOG_IDR GPIO_IDR(GPIOG)
#define GPIOH_IDR GPIO_IDR(GPIOH)
#define GPIOI_IDR GPIO_IDR(GPIOI)
/* Port output data register (GPIOx_ODR) */
#define GPIOG_ODR GPIO_ODR(GPIOG)
#define GPIOH_ODR GPIO_ODR(GPIOH)
#define GPIOI_ODR GPIO_ODR(GPIOI)
/* Port bit set/reset register (GPIOx_BSRR) */
#define GPIOG_BSRR GPIO_BSRR(GPIOG)
#define GPIOH_BSRR GPIO_BSRR(GPIOH)
#define GPIOI_BSRR GPIO_BSRR(GPIOI)
/* Port configuration lock register (GPIOx_LCKR) */
#define GPIOG_LCKR GPIO_LCKR(GPIOG)
#define GPIOH_LCKR GPIO_LCKR(GPIOH)
#define GPIOI_LCKR GPIO_LCKR(GPIOI)
/* Alternate function low register (GPIOx_AFRL) */
#define GPIOG_AFRL GPIO_AFRL(GPIOG)
#define GPIOH_AFRL GPIO_AFRL(GPIOH)
#define GPIOI_AFRL GPIO_AFRL(GPIOI)
/* Alternate function high register (GPIOx_AFRH) */
#define GPIOG_AFRH GPIO_AFRH(GPIOG)
#define GPIOH_AFRH GPIO_AFRH(GPIOH)
#define GPIOI_AFRH GPIO_AFRH(GPIOI)
/**@}*/
#endif
/** @cond */
#endif
/** @endcond */

Просмотреть файл

@ -0,0 +1,89 @@
/** @addtogroup gpio_defines
*
* @author @htmlonly &copy; @endhtmlonly 2011
* Fergus Noble <fergusnoble@gmail.com>
* @author @htmlonly &copy; @endhtmlonly 2012
* Ken Sarkies <ksarkies@internode.on.net>
*
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA GPIO.H
The order of header inclusion is important. gpio.h includes the device
specific memorymap.h header before including this header file.*/
/** @cond */
#if defined(LIBOPENCM3_GPIO_H)
/** @endcond */
#ifndef LIBOPENCM3_GPIO_COMMON_ALL_H
#define LIBOPENCM3_GPIO_COMMON_ALL_H
/**@{*/
/* --- Convenience macros -------------------------------------------------- */
/* --- GPIO_LCKR values ---------------------------------------------------- */
#define GPIO_LCKK (1 << 16)
/* GPIO_LCKR[15:0]: LCKy: Port x lock bit y (y = 0..15) */
/* GPIO number definitions (for convenience) */
/** @defgroup gpio_pin_id GPIO Pin Identifiers
@ingroup gpio_defines
@{*/
#define GPIO0 (1 << 0)
#define GPIO1 (1 << 1)
#define GPIO2 (1 << 2)
#define GPIO3 (1 << 3)
#define GPIO4 (1 << 4)
#define GPIO5 (1 << 5)
#define GPIO6 (1 << 6)
#define GPIO7 (1 << 7)
#define GPIO8 (1 << 8)
#define GPIO9 (1 << 9)
#define GPIO10 (1 << 10)
#define GPIO11 (1 << 11)
#define GPIO12 (1 << 12)
#define GPIO13 (1 << 13)
#define GPIO14 (1 << 14)
#define GPIO15 (1 << 15)
#define GPIO_ALL 0xffff
/**@}*/
void gpio_set(uint32_t gpioport, uint16_t gpios);
void gpio_clear(uint32_t gpioport, uint16_t gpios);
uint16_t gpio_get(uint32_t gpioport, uint16_t gpios);
void gpio_toggle(uint32_t gpioport, uint16_t gpios);
uint16_t gpio_port_read(uint32_t gpioport);
void gpio_port_write(uint32_t gpioport, uint16_t data);
void gpio_port_config_lock(uint32_t gpioport, uint16_t gpios);
/**@}*/
#endif
/** @cond */
#else
#warning "gpio_common_all.h should not be included explicitly, only via gpio.h"
#endif
/** @endcond */

Просмотреть файл

@ -0,0 +1,270 @@
/** @addtogroup gpio_defines
*
* @author @htmlonly &copy; @endhtmlonly 2011
* Fergus Noble <fergusnoble@gmail.com>
* @author @htmlonly &copy; @endhtmlonly 2012
* Ken Sarkies <ksarkies@internode.on.net>
*
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
* Copyright (C) 2012 Ken Sarkies <ksarkies@internode.on.net>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA GPIO.H
The order of header inclusion is important. gpio.h includes the device
specific memorymap.h header before including this header file.*/
/** @cond */
#ifdef LIBOPENCM3_GPIO_H
/** @endcond */
#ifndef LIBOPENCM3_GPIO_COMMON_F234_H
#define LIBOPENCM3_GPIO_COMMON_F234_H
/**@{*/
#include "gpio_common_all.h"
/* GPIO port base addresses (for convenience) */
/** @defgroup gpio_port_id GPIO Port IDs
@ingroup gpio_defines
@{*/
#define GPIOA GPIO_PORT_A_BASE
#define GPIOB GPIO_PORT_B_BASE
#define GPIOC GPIO_PORT_C_BASE
#define GPIOD GPIO_PORT_D_BASE
#define GPIOE GPIO_PORT_E_BASE
#define GPIOF GPIO_PORT_F_BASE
/**@}*/
/* --- GPIO registers for STM32F2, STM32F3 and STM32F4 --------------------- */
/* Port mode register (GPIOx_MODER) */
#define GPIO_MODER(port) MMIO32((port) + 0x00)
#define GPIOA_MODER GPIO_MODER(GPIOA)
#define GPIOB_MODER GPIO_MODER(GPIOB)
#define GPIOC_MODER GPIO_MODER(GPIOC)
#define GPIOD_MODER GPIO_MODER(GPIOD)
#define GPIOE_MODER GPIO_MODER(GPIOE)
#define GPIOF_MODER GPIO_MODER(GPIOF)
/* Port output type register (GPIOx_OTYPER) */
#define GPIO_OTYPER(port) MMIO32((port) + 0x04)
#define GPIOA_OTYPER GPIO_OTYPER(GPIOA)
#define GPIOB_OTYPER GPIO_OTYPER(GPIOB)
#define GPIOC_OTYPER GPIO_OTYPER(GPIOC)
#define GPIOD_OTYPER GPIO_OTYPER(GPIOD)
#define GPIOE_OTYPER GPIO_OTYPER(GPIOE)
#define GPIOF_OTYPER GPIO_OTYPER(GPIOF)
/* Port output speed register (GPIOx_OSPEEDR) */
#define GPIO_OSPEEDR(port) MMIO32((port) + 0x08)
#define GPIOA_OSPEEDR GPIO_OSPEEDR(GPIOA)
#define GPIOB_OSPEEDR GPIO_OSPEEDR(GPIOB)
#define GPIOC_OSPEEDR GPIO_OSPEEDR(GPIOC)
#define GPIOD_OSPEEDR GPIO_OSPEEDR(GPIOD)
#define GPIOE_OSPEEDR GPIO_OSPEEDR(GPIOE)
#define GPIOF_OSPEEDR GPIO_OSPEEDR(GPIOF)
/* Port pull-up/pull-down register (GPIOx_PUPDR) */
#define GPIO_PUPDR(port) MMIO32((port) + 0x0c)
#define GPIOA_PUPDR GPIO_PUPDR(GPIOA)
#define GPIOB_PUPDR GPIO_PUPDR(GPIOB)
#define GPIOC_PUPDR GPIO_PUPDR(GPIOC)
#define GPIOD_PUPDR GPIO_PUPDR(GPIOD)
#define GPIOE_PUPDR GPIO_PUPDR(GPIOE)
#define GPIOF_PUPDR GPIO_PUPDR(GPIOF)
/* Port input data register (GPIOx_IDR) */
#define GPIO_IDR(port) MMIO32((port) + 0x10)
#define GPIOA_IDR GPIO_IDR(GPIOA)
#define GPIOB_IDR GPIO_IDR(GPIOB)
#define GPIOC_IDR GPIO_IDR(GPIOC)
#define GPIOD_IDR GPIO_IDR(GPIOD)
#define GPIOE_IDR GPIO_IDR(GPIOE)
#define GPIOF_IDR GPIO_IDR(GPIOF)
/* Port output data register (GPIOx_ODR) */
#define GPIO_ODR(port) MMIO32((port) + 0x14)
#define GPIOA_ODR GPIO_ODR(GPIOA)
#define GPIOB_ODR GPIO_ODR(GPIOB)
#define GPIOC_ODR GPIO_ODR(GPIOC)
#define GPIOD_ODR GPIO_ODR(GPIOD)
#define GPIOE_ODR GPIO_ODR(GPIOE)
#define GPIOF_ODR GPIO_ODR(GPIOF)
/* Port bit set/reset register (GPIOx_BSRR) */
#define GPIO_BSRR(port) MMIO32((port) + 0x18)
#define GPIOA_BSRR GPIO_BSRR(GPIOA)
#define GPIOB_BSRR GPIO_BSRR(GPIOB)
#define GPIOC_BSRR GPIO_BSRR(GPIOC)
#define GPIOD_BSRR GPIO_BSRR(GPIOD)
#define GPIOE_BSRR GPIO_BSRR(GPIOE)
#define GPIOF_BSRR GPIO_BSRR(GPIOF)
/* Port configuration lock register (GPIOx_LCKR) */
#define GPIO_LCKR(port) MMIO32((port) + 0x1c)
#define GPIOA_LCKR GPIO_LCKR(GPIOA)
#define GPIOB_LCKR GPIO_LCKR(GPIOB)
#define GPIOC_LCKR GPIO_LCKR(GPIOC)
#define GPIOD_LCKR GPIO_LCKR(GPIOD)
#define GPIOE_LCKR GPIO_LCKR(GPIOE)
#define GPIOF_LCKR GPIO_LCKR(GPIOF)
/* Alternate function low register (GPIOx_AFRL) */
#define GPIO_AFRL(port) MMIO32((port) + 0x20)
#define GPIOA_AFRL GPIO_AFRL(GPIOA)
#define GPIOB_AFRL GPIO_AFRL(GPIOB)
#define GPIOC_AFRL GPIO_AFRL(GPIOC)
#define GPIOD_AFRL GPIO_AFRL(GPIOD)
#define GPIOE_AFRL GPIO_AFRL(GPIOE)
#define GPIOF_AFRL GPIO_AFRL(GPIOF)
/* Alternate function high register (GPIOx_AFRH) */
#define GPIO_AFRH(port) MMIO32((port) + 0x24)
#define GPIOA_AFRH GPIO_AFRH(GPIOA)
#define GPIOB_AFRH GPIO_AFRH(GPIOB)
#define GPIOC_AFRH GPIO_AFRH(GPIOC)
#define GPIOD_AFRH GPIO_AFRH(GPIOD)
#define GPIOE_AFRH GPIO_AFRH(GPIOE)
#define GPIOF_AFRH GPIO_AFRH(GPIOF)
/* --- GPIOx_MODER values -------------------------------------------------- */
#define GPIO_MODE(n, mode) ((mode) << (2 * (n)))
#define GPIO_MODE_MASK(n) (0x3 << (2 * (n)))
/** @defgroup gpio_mode GPIO Pin Direction and Analog/Digital Mode
@ingroup gpio_defines
@{*/
#define GPIO_MODE_INPUT 0x0
#define GPIO_MODE_OUTPUT 0x1
#define GPIO_MODE_AF 0x2
#define GPIO_MODE_ANALOG 0x3
/**@}*/
/* --- GPIOx_OTYPER values ------------------------------------------------- */
/** @defgroup gpio_output_type GPIO Output Pin Driver Type
@ingroup gpio_defines
@list Push Pull
@list Open Drain
@{*/
#define GPIO_OTYPE_PP 0x0
#define GPIO_OTYPE_OD 0x1
/**@}*/
/* --- GPIOx_OSPEEDR values ------------------------------------------------ */
#define GPIO_OSPEED(n, speed) ((speed) << (2 * (n)))
#define GPIO_OSPEED_MASK(n) (0x3 << (2 * (n)))
/** @defgroup gpio_speed GPIO Output Pin Speed
@ingroup gpio_defines
@{*/
#define GPIO_OSPEED_2MHZ 0x0
#define GPIO_OSPEED_25MHZ 0x1
#define GPIO_OSPEED_50MHZ 0x2
#define GPIO_OSPEED_100MHZ 0x3
/**@}*/
/* --- GPIOx_PUPDR values -------------------------------------------------- */
#define GPIO_PUPD(n, pupd) ((pupd) << (2 * (n)))
#define GPIO_PUPD_MASK(n) (0x3 << (2 * (n)))
/** @defgroup gpio_pup GPIO Output Pin Pullup
@ingroup gpio_defines
@{*/
#define GPIO_PUPD_NONE 0x0
#define GPIO_PUPD_PULLUP 0x1
#define GPIO_PUPD_PULLDOWN 0x2
/**@}*/
/* --- GPIOx_IDR values ---------------------------------------------------- */
/* GPIOx_IDR[15:0]: IDRy[15:0]: Port input data (y = 0..15) */
/* --- GPIOx_ODR values ---------------------------------------------------- */
/* GPIOx_ODR[15:0]: ODRy[15:0]: Port output data (y = 0..15) */
/* --- GPIOx_BSRR values --------------------------------------------------- */
/* GPIOx_BSRR[31:16]: BRy: Port x reset bit y (y = 0..15) */
/* GPIOx_BSRR[15:0]: BSy: Port x set bit y (y = 0..15) */
/* --- GPIOx_LCKR values --------------------------------------------------- */
#define GPIO_LCKK (1 << 16)
/* GPIOx_LCKR[15:0]: LCKy: Port x lock bit y (y = 0..15) */
/* --- GPIOx_AFRL/H values ------------------------------------------------- */
/* Note: AFRL is used for bits 0..7, AFRH is used for 8..15 */
/* See datasheet table 6 (pg. 48) for alternate function mappings. */
#define GPIO_AFR(n, af) ((af) << ((n) * 4))
#define GPIO_AFR_MASK(n) (0xf << ((n) * 4))
/** @defgroup gpio_af_num Alternate Function Pin Selection
@ingroup gpio_defines
@{*/
#define GPIO_AF0 0x0
#define GPIO_AF1 0x1
#define GPIO_AF2 0x2
#define GPIO_AF3 0x3
#define GPIO_AF4 0x4
#define GPIO_AF5 0x5
#define GPIO_AF6 0x6
#define GPIO_AF7 0x7
#define GPIO_AF8 0x8
#define GPIO_AF9 0x9
#define GPIO_AF10 0xa
#define GPIO_AF11 0xb
#define GPIO_AF12 0xc
#define GPIO_AF13 0xd
#define GPIO_AF14 0xe
#define GPIO_AF15 0xf
/**@}*/
/* Note: EXTI source selection is now in the SYSCFG peripheral. */
/* --- Function prototypes ------------------------------------------------- */
/*
* Note: The F2 and F4 series have a completely new GPIO peripheral with
* different configuration options. Here we implement a different API partly to
* more closely match the peripheral capabilities and also to deliberately
* break compatibility with old F1 code so there is no confusion with similar
* sounding functions that have very different functionality.
*/
void gpio_mode_setup(uint32_t gpioport, uint8_t mode, uint8_t pull_up_down,
uint16_t gpios);
void gpio_set_output_options(uint32_t gpioport, uint8_t otype, uint8_t speed,
uint16_t gpios);
void gpio_set_af(uint32_t gpioport, uint8_t alt_func_num, uint16_t gpios);
/**@}*/
#endif
/** @cond */
#else
#warning "gpio_common_f234.h should not be included explicitly, only via gpio.h"
#endif
/** @endcond */

Просмотреть файл

@ -0,0 +1,85 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBOPENCM3_CM3_MEMORYMAP_H
#define LIBOPENCM3_CM3_MEMORYMAP_H
/* --- ARM Cortex-M0, M3 and M4 specific definitions ----------------------- */
/* Private peripheral bus - Internal */
#define PPBI_BASE (0xE0000000U)
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
/* ITM: Instrumentation Trace Macrocell */
#define ITM_BASE (PPBI_BASE + 0x0000)
/* DWT: Data Watchpoint and Trace unit */
#define DWT_BASE (PPBI_BASE + 0x1000)
/* FPB: Flash Patch and Breakpoint unit */
#define FPB_BASE (PPBI_BASE + 0x2000)
#endif
/* PPBI_BASE + 0x3000 (0xE000 3000 - 0xE000 DFFF): Reserved */
#define SCS_BASE (PPBI_BASE + 0xE000)
/* PPBI_BASE + 0xF000 (0xE000 F000 - 0xE003 FFFF): Reserved */
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
#define TPIU_BASE (PPBI_BASE + 0x40000)
#endif
/* --- SCS: System Control Space --- */
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
/* ITR: Interrupt Type Register */
#define ITR_BASE (SCS_BASE + 0x0000)
#endif
/* SYS_TICK: System Timer */
#define SYS_TICK_BASE (SCS_BASE + 0x0010)
/* NVIC: Nested Vector Interrupt Controller */
#define NVIC_BASE (SCS_BASE + 0x0100)
/* SCB: System Control Block */
#define SCB_BASE (SCS_BASE + 0x0D00)
/* MPU: Memory protection unit */
#define MPU_BASE (SCS_BASE + 0x0D90)
/* Those defined only on CM0*/
#if defined(__ARM_ARCH_6M__)
/* DEBUG: Debug control and configuration */
#define DEBUG_BASE (SCS_BASE + 0x0DF0)
#endif
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
/* STE: Software Trigger Interrupt Register */
#define STIR_BASE (SCS_BASE + 0x0F00)
/* ID: ID space */
#define ID_BASE (SCS_BASE + 0x0FD0)
#endif
#endif

Просмотреть файл

@ -0,0 +1,155 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBOPENCM3_MEMORYMAP_H
#define LIBOPENCM3_MEMORYMAP_H
#include "memorymap.h"
/* --- STM32F4 specific peripheral definitions ----------------------------- */
/* Memory map for all busses */
#define PERIPH_BASE (0x40000000U)
#define PERIPH_BASE_APB1 (PERIPH_BASE + 0x00000)
#define PERIPH_BASE_APB2 (PERIPH_BASE + 0x10000)
#define PERIPH_BASE_AHB1 (PERIPH_BASE + 0x20000)
#define PERIPH_BASE_AHB2 0x50000000U
#define PERIPH_BASE_AHB3 0x60000000U
/* Register boundary addresses */
/* APB1 */
#define TIM2_BASE (PERIPH_BASE_APB1 + 0x0000)
#define TIM3_BASE (PERIPH_BASE_APB1 + 0x0400)
#define TIM4_BASE (PERIPH_BASE_APB1 + 0x0800)
#define TIM5_BASE (PERIPH_BASE_APB1 + 0x0c00)
#define TIM6_BASE (PERIPH_BASE_APB1 + 0x1000)
#define TIM7_BASE (PERIPH_BASE_APB1 + 0x1400)
#define TIM12_BASE (PERIPH_BASE_APB1 + 0x1800)
#define TIM13_BASE (PERIPH_BASE_APB1 + 0x1c00)
#define TIM14_BASE (PERIPH_BASE_APB1 + 0x2000)
/* PERIPH_BASE_APB1 + 0x2400 (0x4000 2400 - 0x4000 27FF): Reserved */
#define RTC_BASE (PERIPH_BASE_APB1 + 0x2800)
#define WWDG_BASE (PERIPH_BASE_APB1 + 0x2c00)
#define IWDG_BASE (PERIPH_BASE_APB1 + 0x3000)
#define I2S2_EXT_BASE (PERIPH_BASE_APB1 + 0x3400)
#define SPI2_BASE (PERIPH_BASE_APB1 + 0x3800)
#define SPI3_BASE (PERIPH_BASE_APB1 + 0x3c00)
#define I2S3_EXT_BASE (PERIPH_BASE_APB1 + 0x4000)
#define USART2_BASE (PERIPH_BASE_APB1 + 0x4400)
#define USART3_BASE (PERIPH_BASE_APB1 + 0x4800)
#define UART4_BASE (PERIPH_BASE_APB1 + 0x4c00)
#define UART5_BASE (PERIPH_BASE_APB1 + 0x5000)
#define I2C1_BASE (PERIPH_BASE_APB1 + 0x5400)
#define I2C2_BASE (PERIPH_BASE_APB1 + 0x5800)
#define I2C3_BASE (PERIPH_BASE_APB1 + 0x5C00)
/* PERIPH_BASE_APB1 + 0x6000 (0x4000 6000 - 0x4000 63FF): Reserved */
#define BX_CAN1_BASE (PERIPH_BASE_APB1 + 0x6400)
#define BX_CAN2_BASE (PERIPH_BASE_APB1 + 0x6800)
/* PERIPH_BASE_APB1 + 0x6C00 (0x4000 6C00 - 0x4000 6FFF): Reserved */
#define POWER_CONTROL_BASE (PERIPH_BASE_APB1 + 0x7000)
#define DAC_BASE (PERIPH_BASE_APB1 + 0x7400)
#define UART7_BASE (PERIPH_BASE_APB1 + 0x7800)
#define UART8_BASE (PERIPH_BASE_APB1 + 0x7c00)
/* PERIPH_BASE_APB1 + 0x7800 (0x4000 8000 - 0x4000 FFFF): Reserved */
/* APB2 */
#define TIM1_BASE (PERIPH_BASE_APB2 + 0x0000)
#define TIM8_BASE (PERIPH_BASE_APB2 + 0x0400)
/* PERIPH_BASE_APB2 + 0x0800 (0x4001 0800 - 0x4001 0FFF): Reserved */
#define USART1_BASE (PERIPH_BASE_APB2 + 0x1000)
#define USART6_BASE (PERIPH_BASE_APB2 + 0x1400)
/* PERIPH_BASE_APB2 + 0x1800 (0x4001 1800 - 0x4001 1FFF): Reserved */
#define ADC1_BASE (PERIPH_BASE_APB2 + 0x2000)
#define ADC2_BASE (PERIPH_BASE_APB2 + 0x2100)
#define ADC3_BASE (PERIPH_BASE_APB2 + 0x2200)
#define ADC_COMMON_BASE (PERIPH_BASE_APB2 + 0x2300)
/* PERIPH_BASE_APB2 + 0x2400 (0x4001 2400 - 0x4001 27FF): Reserved */
#define SDIO_BASE (PERIPH_BASE_APB2 + 0x2C00)
/* PERIPH_BASE_APB2 + 0x2C00 (0x4001 2C00 - 0x4001 2FFF): Reserved */
#define SPI1_BASE (PERIPH_BASE_APB2 + 0x3000)
#define SPI4_BASE (PERIPH_BASE_APB2 + 0x3400)
/* PERIPH_BASE_APB2 + 0x3500 (0x4001 3500 - 0x4001 37FF): Reserved */
#define SYSCFG_BASE (PERIPH_BASE_APB2 + 0x3800)
#define EXTI_BASE (PERIPH_BASE_APB2 + 0x3C00)
#define TIM9_BASE (PERIPH_BASE_APB2 + 0x4000)
#define TIM10_BASE (PERIPH_BASE_APB2 + 0x4400)
#define TIM11_BASE (PERIPH_BASE_APB2 + 0x4800)
/* PERIPH_BASE_APB2 + 0x4C00 (0x4001 4C00 - 0x4001 4FFF): Reserved */
#define SPI5_BASE (PERIPH_BASE_APB2 + 0x5000)
#define SPI6_BASE (PERIPH_BASE_APB2 + 0x5400)
#define SAI1_BASE (PERIPH_BASE_APB2 + 0x5800)
#define LTDC_BASE (PERIPH_BASE_APB2 + 0x6800)
/* PERIPH_BASE_APB2 + 0x6C00 (0x4001 6C00 - 0x4001 FFFF): Reserved */
/* AHB1 */
#define GPIO_PORT_A_BASE (PERIPH_BASE_AHB1 + 0x0000)
#define GPIO_PORT_B_BASE (PERIPH_BASE_AHB1 + 0x0400)
#define GPIO_PORT_C_BASE (PERIPH_BASE_AHB1 + 0x0800)
#define GPIO_PORT_D_BASE (PERIPH_BASE_AHB1 + 0x0C00)
#define GPIO_PORT_E_BASE (PERIPH_BASE_AHB1 + 0x1000)
#define GPIO_PORT_F_BASE (PERIPH_BASE_AHB1 + 0x1400)
#define GPIO_PORT_G_BASE (PERIPH_BASE_AHB1 + 0x1800)
#define GPIO_PORT_H_BASE (PERIPH_BASE_AHB1 + 0x1C00)
#define GPIO_PORT_I_BASE (PERIPH_BASE_AHB1 + 0x2000)
/* PERIPH_BASE_AHB1 + 0x2400 (0x4002 2400 - 0x4002 2FFF): Reserved */
#define CRC_BASE (PERIPH_BASE_AHB1 + 0x3000)
/* PERIPH_BASE_AHB1 + 0x3400 (0x4002 3400 - 0x4002 37FF): Reserved */
#define RCC_BASE (PERIPH_BASE_AHB1 + 0x3800)
#define FLASH_MEM_INTERFACE_BASE (PERIPH_BASE_AHB1 + 0x3C00)
#define BKPSRAM_BASE (PERIPH_BASE_AHB1 + 0x4000)
/* PERIPH_BASE_AHB1 + 0x5000 (0x4002 5000 - 0x4002 5FFF): Reserved */
#define DMA1_BASE (PERIPH_BASE_AHB1 + 0x6000)
#define DMA2_BASE (PERIPH_BASE_AHB1 + 0x6400)
/* PERIPH_BASE_AHB1 + 0x6800 (0x4002 6800 - 0x4002 7FFF): Reserved */
#define ETHERNET_BASE (PERIPH_BASE_AHB1 + 0x8000)
/* PERIPH_BASE_AHB1 + 0x9400 (0x4002 9400 - 0x4003 FFFF): Reserved */
#define USB_OTG_HS_BASE (PERIPH_BASE_AHB1 + 0x20000)
/* PERIPH_BASE_AHB1 + 0x60000 (0x4008 0000 - 0x4FFF FFFF): Reserved */
/* AHB2 */
#define USB_OTG_FS_BASE (PERIPH_BASE_AHB2 + 0x00000)
/* PERIPH_BASE_AHB2 + 0x40000 (0x5004 0000 - 0x5004 FFFF): Reserved */
#define DCMI_BASE (PERIPH_BASE_AHB2 + 0x50000)
/* PERIPH_BASE_AHB2 + 0x50400 (0x5005 0400 - 0x5005 FFFF): Reserved */
#define CRYP_BASE (PERIPH_BASE_AHB2 + 0x60000)
#define HASH_BASE (PERIPH_BASE_AHB2 + 0x60400)
/* PERIPH_BASE_AHB2 + 0x60C00 (0x5006 0C00 - 0x5006 07FF): Reserved */
#define RNG_BASE (PERIPH_BASE_AHB2 + 0x60800)
/* PERIPH_BASE_AHB2 + 0x61000 (0x5006 1000 - 0x5FFF FFFF): Reserved */
/* AHB3 */
#define FSMC_BASE (PERIPH_BASE_AHB3 + 0x40000000U)
/* PPIB */
#define DBGMCU_BASE (PPBI_BASE + 0x00042000)
/* Device Electronic Signature */
#define DESIG_FLASH_SIZE_BASE (0x1FFF7A22U)
#define DESIG_UNIQUE_ID_BASE (0x1FFF7A10U)
#define DESIG_UNIQUE_ID0 MMIO32(DESIG_UNIQUE_ID_BASE)
#define DESIG_UNIQUE_ID1 MMIO32(DESIG_UNIQUE_ID_BASE + 4)
#define DESIG_UNIQUE_ID2 MMIO32(DESIG_UNIQUE_ID_BASE + 8)
/* ST provided factory calibration values @ 3.3V */
#define ST_VREFINT_CAL MMIO16(0x1FFF7A2A)
#define ST_TSENSE_CAL1_30C MMIO16(0x1FFF7A2C)
#define ST_TSENSE_CAL2_110 MMIO16(0x1FFF7A2E)
#endif

Просмотреть файл

@ -0,0 +1,213 @@
/* This file is part of the libopencm3 project.
*
* It was generated by the irq2nvic_h script.
*/
#ifndef LIBOPENCM3_STM32_F4_NVIC_H
#define LIBOPENCM3_STM32_F4_NVIC_H
#include "nvic_cm3.h"
/** @defgroup CM3_nvic_defines_STM32F4 User interrupts for STM32 F4 series
@ingroup CM3_nvic_defines
@{*/
#define NVIC_NVIC_WWDG_IRQ 0
#define NVIC_PVD_IRQ 1
#define NVIC_TAMP_STAMP_IRQ 2
#define NVIC_RTC_WKUP_IRQ 3
#define NVIC_FLASH_IRQ 4
#define NVIC_RCC_IRQ 5
#define NVIC_EXTI0_IRQ 6
#define NVIC_EXTI1_IRQ 7
#define NVIC_EXTI2_IRQ 8
#define NVIC_EXTI3_IRQ 9
#define NVIC_EXTI4_IRQ 10
#define NVIC_DMA1_STREAM0_IRQ 11
#define NVIC_DMA1_STREAM1_IRQ 12
#define NVIC_DMA1_STREAM2_IRQ 13
#define NVIC_DMA1_STREAM3_IRQ 14
#define NVIC_DMA1_STREAM4_IRQ 15
#define NVIC_DMA1_STREAM5_IRQ 16
#define NVIC_DMA1_STREAM6_IRQ 17
#define NVIC_ADC_IRQ 18
#define NVIC_CAN1_TX_IRQ 19
#define NVIC_CAN1_RX0_IRQ 20
#define NVIC_CAN1_RX1_IRQ 21
#define NVIC_CAN1_SCE_IRQ 22
#define NVIC_EXTI9_5_IRQ 23
#define NVIC_TIM1_BRK_TIM9_IRQ 24
#define NVIC_TIM1_UP_TIM10_IRQ 25
#define NVIC_TIM1_TRG_COM_TIM11_IRQ 26
#define NVIC_TIM1_CC_IRQ 27
#define NVIC_TIM2_IRQ 28
#define NVIC_TIM3_IRQ 29
#define NVIC_TIM4_IRQ 30
#define NVIC_I2C1_EV_IRQ 31
#define NVIC_I2C1_ER_IRQ 32
#define NVIC_I2C2_EV_IRQ 33
#define NVIC_I2C2_ER_IRQ 34
#define NVIC_SPI1_IRQ 35
#define NVIC_SPI2_IRQ 36
#define NVIC_USART1_IRQ 37
#define NVIC_USART2_IRQ 38
#define NVIC_USART3_IRQ 39
#define NVIC_EXTI15_10_IRQ 40
#define NVIC_RTC_ALARM_IRQ 41
#define NVIC_USB_FS_WKUP_IRQ 42
#define NVIC_TIM8_BRK_TIM12_IRQ 43
#define NVIC_TIM8_UP_TIM13_IRQ 44
#define NVIC_TIM8_TRG_COM_TIM14_IRQ 45
#define NVIC_TIM8_CC_IRQ 46
#define NVIC_DMA1_STREAM7_IRQ 47
#define NVIC_FSMC_IRQ 48
#define NVIC_SDIO_IRQ 49
#define NVIC_TIM5_IRQ 50
#define NVIC_SPI3_IRQ 51
#define NVIC_UART4_IRQ 52
#define NVIC_UART5_IRQ 53
#define NVIC_TIM6_DAC_IRQ 54
#define NVIC_TIM7_IRQ 55
#define NVIC_DMA2_STREAM0_IRQ 56
#define NVIC_DMA2_STREAM1_IRQ 57
#define NVIC_DMA2_STREAM2_IRQ 58
#define NVIC_DMA2_STREAM3_IRQ 59
#define NVIC_DMA2_STREAM4_IRQ 60
#define NVIC_ETH_IRQ 61
#define NVIC_ETH_WKUP_IRQ 62
#define NVIC_CAN2_TX_IRQ 63
#define NVIC_CAN2_RX0_IRQ 64
#define NVIC_CAN2_RX1_IRQ 65
#define NVIC_CAN2_SCE_IRQ 66
#define NVIC_OTG_FS_IRQ 67
#define NVIC_DMA2_STREAM5_IRQ 68
#define NVIC_DMA2_STREAM6_IRQ 69
#define NVIC_DMA2_STREAM7_IRQ 70
#define NVIC_USART6_IRQ 71
#define NVIC_I2C3_EV_IRQ 72
#define NVIC_I2C3_ER_IRQ 73
#define NVIC_OTG_HS_EP1_OUT_IRQ 74
#define NVIC_OTG_HS_EP1_IN_IRQ 75
#define NVIC_OTG_HS_WKUP_IRQ 76
#define NVIC_OTG_HS_IRQ 77
#define NVIC_DCMI_IRQ 78
#define NVIC_CRYP_IRQ 79
#define NVIC_HASH_RNG_IRQ 80
#define NVIC_FPU_IRQ 81
#define NVIC_UART7_IRQ 82
#define NVIC_UART8_IRQ 83
#define NVIC_SPI4_IRQ 84
#define NVIC_SPI5_IRQ 85
#define NVIC_SPI6_IRQ 86
#define NVIC_SAI1_IRQ 87
#define NVIC_LCD_TFT_IRQ 88
#define NVIC_LCD_TFT_ERR_IRQ 89
#define NVIC_DMA2D_IRQ 90
#define NVIC_IRQ_COUNT 91
/**@}*/
/** @defgroup CM3_nvic_isrprototypes_STM32F4 User interrupt service routines (ISR) prototypes for STM32 F4 series
@ingroup CM3_nvic_isrprototypes
@{*/
void WEAK nvic_wwdg_isr(void);
void WEAK pvd_isr(void);
void WEAK tamp_stamp_isr(void);
void WEAK rtc_wkup_isr(void);
void WEAK flash_isr(void);
void WEAK rcc_isr(void);
void WEAK exti0_isr(void);
void WEAK exti1_isr(void);
void WEAK exti2_isr(void);
void WEAK exti3_isr(void);
void WEAK exti4_isr(void);
void WEAK dma1_stream0_isr(void);
void WEAK dma1_stream1_isr(void);
void WEAK dma1_stream2_isr(void);
void WEAK dma1_stream3_isr(void);
void WEAK dma1_stream4_isr(void);
void WEAK dma1_stream5_isr(void);
void WEAK dma1_stream6_isr(void);
void WEAK adc_isr(void);
void WEAK can1_tx_isr(void);
void WEAK can1_rx0_isr(void);
void WEAK can1_rx1_isr(void);
void WEAK can1_sce_isr(void);
void WEAK exti9_5_isr(void);
void WEAK tim1_brk_tim9_isr(void);
void WEAK tim1_up_tim10_isr(void);
void WEAK tim1_trg_com_tim11_isr(void);
void WEAK tim1_cc_isr(void);
void WEAK tim2_isr(void);
void WEAK tim3_isr(void);
void WEAK tim4_isr(void);
void WEAK i2c1_ev_isr(void);
void WEAK i2c1_er_isr(void);
void WEAK i2c2_ev_isr(void);
void WEAK i2c2_er_isr(void);
void WEAK spi1_isr(void);
void WEAK spi2_isr(void);
void WEAK usart1_isr(void);
void WEAK usart2_isr(void);
void WEAK usart3_isr(void);
void WEAK exti15_10_isr(void);
void WEAK rtc_alarm_isr(void);
void WEAK usb_fs_wkup_isr(void);
void WEAK tim8_brk_tim12_isr(void);
void WEAK tim8_up_tim13_isr(void);
void WEAK tim8_trg_com_tim14_isr(void);
void WEAK tim8_cc_isr(void);
void WEAK dma1_stream7_isr(void);
void WEAK fsmc_isr(void);
void WEAK sdio_isr(void);
void WEAK tim5_isr(void);
void WEAK spi3_isr(void);
void WEAK uart4_isr(void);
void WEAK uart5_isr(void);
void WEAK tim6_dac_isr(void);
void WEAK tim7_isr(void);
void WEAK dma2_stream0_isr(void);
void WEAK dma2_stream1_isr(void);
void WEAK dma2_stream2_isr(void);
void WEAK dma2_stream3_isr(void);
void WEAK dma2_stream4_isr(void);
void WEAK eth_isr(void);
void WEAK eth_wkup_isr(void);
void WEAK can2_tx_isr(void);
void WEAK can2_rx0_isr(void);
void WEAK can2_rx1_isr(void);
void WEAK can2_sce_isr(void);
void WEAK otg_fs_isr(void);
void WEAK dma2_stream5_isr(void);
void WEAK dma2_stream6_isr(void);
void WEAK dma2_stream7_isr(void);
void WEAK usart6_isr(void);
void WEAK i2c3_ev_isr(void);
void WEAK i2c3_er_isr(void);
void WEAK otg_hs_ep1_out_isr(void);
void WEAK otg_hs_ep1_in_isr(void);
void WEAK otg_hs_wkup_isr(void);
void WEAK otg_hs_isr(void);
void WEAK dcmi_isr(void);
void WEAK cryp_isr(void);
void WEAK hash_rng_isr(void);
void WEAK fpu_isr(void);
void WEAK uart7_isr(void);
void WEAK uart8_isr(void);
void WEAK spi4_isr(void);
void WEAK spi5_isr(void);
void WEAK spi6_isr(void);
void WEAK sai1_isr(void);
void WEAK lcd_tft_isr(void);
void WEAK lcd_tft_err_isr(void);
void WEAK dma2d_isr(void);
/**@}*/
#endif /* LIBOPENCM3_STM32_F4_NVIC_H */

Просмотреть файл

@ -0,0 +1,172 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
* Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/** @defgroup CM3_nvic_defines NVIC Defines
*
* @brief <b>libopencm3 Cortex Nested Vectored Interrupt Controller</b>
*
* @ingroup CM3_defines
*
* @version 1.0.0
*
* @author @htmlonly &copy; @endhtmlonly 2010 Piotr Esden-Tempski <piotr@esden.net>
*
* @date 18 August 2012
*
* LGPL License Terms @ref lgpl_license
*/
/**@{*/
#ifndef LIBOPENCM3_NVIC_H
#define LIBOPENCM3_NVIC_H
#include <common.h>
#include <memorymap_f4.h>
/* --- NVIC Registers ------------------------------------------------------ */
/* ISER: Interrupt Set Enable Registers */
/* Note: 8 32bit Registers */
/* Note: Single register on CM0 */
#define NVIC_ISER(iser_id) MMIO32(NVIC_BASE + 0x00 + \
((iser_id) * 4))
/* NVIC_BASE + 0x020 (0xE000 E120 - 0xE000 E17F): Reserved */
/* ICER: Interrupt Clear Enable Registers */
/* Note: 8 32bit Registers */
/* Note: Single register on CM0 */
#define NVIC_ICER(icer_id) MMIO32(NVIC_BASE + 0x80 + \
((icer_id) * 4))
/* NVIC_BASE + 0x0A0 (0xE000 E1A0 - 0xE000 E1FF): Reserved */
/* ISPR: Interrupt Set Pending Registers */
/* Note: 8 32bit Registers */
/* Note: Single register on CM0 */
#define NVIC_ISPR(ispr_id) MMIO32(NVIC_BASE + 0x100 + \
((ispr_id) * 4))
/* NVIC_BASE + 0x120 (0xE000 E220 - 0xE000 E27F): Reserved */
/* ICPR: Interrupt Clear Pending Registers */
/* Note: 8 32bit Registers */
/* Note: Single register on CM0 */
#define NVIC_ICPR(icpr_id) MMIO32(NVIC_BASE + 0x180 + \
((icpr_id) * 4))
/* NVIC_BASE + 0x1A0 (0xE000 E2A0 - 0xE00 E2FF): Reserved */
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
/* IABR: Interrupt Active Bit Register */
/* Note: 8 32bit Registers */
#define NVIC_IABR(iabr_id) MMIO32(NVIC_BASE + 0x200 + \
((iabr_id) * 4))
#endif
/* NVIC_BASE + 0x220 (0xE000 E320 - 0xE000 E3FF): Reserved */
/* IPR: Interrupt Priority Registers */
/* Note: 240 8bit Registers */
/* Note: 32 8bit Registers on CM0 */
#define NVIC_IPR(ipr_id) MMIO8(NVIC_BASE + 0x300 + \
(ipr_id))
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
/* STIR: Software Trigger Interrupt Register */
#define NVIC_STIR MMIO32(STIR_BASE)
#endif
/* --- IRQ channel numbers-------------------------------------------------- */
/* Cortex M0, M3 and M4 System Interrupts */
/** @defgroup nvic_sysint Cortex M0/M3/M4 System Interrupts
@ingroup CM3_nvic_defines
IRQ numbers -3 and -6 to -9 are reserved
@{*/
#define NVIC_NMI_IRQ -14
#define NVIC_HARD_FAULT_IRQ -13
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
#define NVIC_MEM_MANAGE_IRQ -12
#define NVIC_BUS_FAULT_IRQ -11
#define NVIC_USAGE_FAULT_IRQ -10
#endif
/* irq numbers -6 to -9 are reserved */
#define NVIC_SV_CALL_IRQ -5
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
#define DEBUG_MONITOR_IRQ -4
#endif
/* irq number -3 reserved */
#define NVIC_PENDSV_IRQ -2
#define NVIC_SYSTICK_IRQ -1
/**@}*/
/* Note: User interrupts are family specific and are defined in a family
* specific header file in the corresponding subfolder.
*/
#define WEAK __attribute__((weak))
#include "nvic.h"
/* --- NVIC functions ------------------------------------------------------ */
void nvic_enable_irq(uint8_t irqn);
void nvic_disable_irq(uint8_t irqn);
uint8_t nvic_get_pending_irq(uint8_t irqn);
void nvic_set_pending_irq(uint8_t irqn);
void nvic_clear_pending_irq(uint8_t irqn);
uint8_t nvic_get_irq_enabled(uint8_t irqn);
void nvic_set_priority(uint8_t irqn, uint8_t priority);
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
uint8_t nvic_get_active_irq(uint8_t irqn);
void nvic_generate_software_interrupt(uint16_t irqn);
#endif
void WEAK reset_handler(void);
void WEAK nmi_handler(void);
void WEAK hard_fault_handler(void);
void WEAK sv_call_handler(void);
void WEAK pend_sv_handler(void);
void WEAK sys_tick_handler(void);
/* Those defined only on ARMv7 and above */
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
void WEAK mem_manage_handler(void);
void WEAK bus_fault_handler(void);
void WEAK usage_fault_handler(void);
void WEAK debug_monitor_handler(void);
#endif
/**@}*/
#endif

Просмотреть файл

@ -0,0 +1,872 @@
/** @defgroup rcc_defines RCC Defines
*
* @brief <b>Defined Constants and Types for the STM32F4xx Reset and Clock
* Control</b>
*
* @ingroup STM32F4xx_defines
*
* @version 1.0.0
*
* @author @htmlonly &copy; @endhtmlonly 2009
* Federico Ruiz-Ugalde \<memeruiz at gmail dot com\>
* @author @htmlonly &copy; @endhtmlonly 2009
* Uwe Hermann <uwe@hermann-uwe.de>
* @author @htmlonly &copy; @endhtmlonly 2011
* Fergus Noble <fergusnoble@gmail.com>
* @author @htmlonly &copy; @endhtmlonly 2011
* Stephen Caudle <scaudle@doceme.com>
*
* @date 18 August 2012
*
* LGPL License Terms @ref lgpl_license
* */
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2009 Federico Ruiz-Ugalde <memeruiz at gmail dot com>
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LIBOPENCM3_RCC_H
#define LIBOPENCM3_RCC_H
#include "memorymap_f4.h"
#include "common.h"
#include <stdbool.h>
/* --- RCC registers ------------------------------------------------------- */
#define RCC_CR MMIO32(RCC_BASE + 0x00)
#define RCC_PLLCFGR MMIO32(RCC_BASE + 0x04)
#define RCC_CFGR MMIO32(RCC_BASE + 0x08)
#define RCC_CIR MMIO32(RCC_BASE + 0x0c)
#define RCC_AHB1RSTR MMIO32(RCC_BASE + 0x10)
#define RCC_AHB2RSTR MMIO32(RCC_BASE + 0x14)
#define RCC_AHB3RSTR MMIO32(RCC_BASE + 0x18)
/* RCC_BASE + 0x1c Reserved */
#define RCC_APB1RSTR MMIO32(RCC_BASE + 0x20)
#define RCC_APB2RSTR MMIO32(RCC_BASE + 0x24)
/* RCC_BASE + 0x28 Reserved */
/* RCC_BASE + 0x2c Reserved */
#define RCC_AHB1ENR MMIO32(RCC_BASE + 0x30)
#define RCC_AHB2ENR MMIO32(RCC_BASE + 0x34)
#define RCC_AHB3ENR MMIO32(RCC_BASE + 0x38)
/* RCC_BASE + 0x3c Reserved */
#define RCC_APB1ENR MMIO32(RCC_BASE + 0x40)
#define RCC_APB2ENR MMIO32(RCC_BASE + 0x44)
/* RCC_BASE + 0x48 Reserved */
/* RCC_BASE + 0x4c Reserved */
#define RCC_AHB1LPENR MMIO32(RCC_BASE + 0x50)
#define RCC_AHB2LPENR MMIO32(RCC_BASE + 0x54)
#define RCC_AHB3LPENR MMIO32(RCC_BASE + 0x58)
/* RCC_BASE + 0x5c Reserved */
#define RCC_APB1LPENR MMIO32(RCC_BASE + 0x60)
#define RCC_APB2LPENR MMIO32(RCC_BASE + 0x64)
/* RCC_BASE + 0x68 Reserved */
/* RCC_BASE + 0x6c Reserved */
#define RCC_BDCR MMIO32(RCC_BASE + 0x70)
#define RCC_CSR MMIO32(RCC_BASE + 0x74)
/* RCC_BASE + 0x78 Reserved */
/* RCC_BASE + 0x7c Reserved */
#define RCC_SSCGR MMIO32(RCC_BASE + 0x80)
#define RCC_PLLI2SCFGR MMIO32(RCC_BASE + 0x84)
#define RCC_PLLSAICFGR MMIO32(RCC_BASE + 0x88)
#define RCC_DCKCFGR MMIO32(RCC_BASE + 0x8C)
/* --- RCC_CR values ------------------------------------------------------- */
#define RCC_CR_PLLSAIRDY (1 << 29)
#define RCC_CR_PLLSAION (1 << 28)
#define RCC_CR_PLLI2SRDY (1 << 27)
#define RCC_CR_PLLI2SON (1 << 26)
#define RCC_CR_PLLRDY (1 << 25)
#define RCC_CR_PLLON (1 << 24)
#define RCC_CR_CSSON (1 << 19)
#define RCC_CR_HSEBYP (1 << 18)
#define RCC_CR_HSERDY (1 << 17)
#define RCC_CR_HSEON (1 << 16)
/* HSICAL: [15:8] */
/* HSITRIM: [7:3] */
#define RCC_CR_HSIRDY (1 << 1)
#define RCC_CR_HSION (1 << 0)
/* --- RCC_PLLCFGR values -------------------------------------------------- */
/* PLLQ: [27:24] */
#define RCC_PLLCFGR_PLLQ_SHIFT 24
#define RCC_PLLCFGR_PLLSRC (1 << 22)
/* PLLP: [17:16] */
#define RCC_PLLCFGR_PLLP_SHIFT 16
/* PLLN: [14:6] */
#define RCC_PLLCFGR_PLLN_SHIFT 6
/* PLLM: [5:0] */
#define RCC_PLLCFGR_PLLM_SHIFT 0
/* --- RCC_CFGR values ----------------------------------------------------- */
/* MCO2: Microcontroller clock output 2 */
#define RCC_CFGR_MCO2_SHIFT 30
#define RCC_CFGR_MCO2_SYSCLK 0x0
#define RCC_CFGR_MCO2_PLLI2S 0x1
#define RCC_CFGR_MCO2_HSE 0x2
#define RCC_CFGR_MCO2_PLL 0x3
/* MCO1/2PRE: MCO Prescalers */
#define RCC_CFGR_MCO2PRE_SHIFT 27
#define RCC_CFGR_MCO1PRE_SHIFT 24
#define RCC_CFGR_MCOPRE_DIV_NONE 0x0
#define RCC_CFGR_MCOPRE_DIV_2 0x4
#define RCC_CFGR_MCOPRE_DIV_3 0x5
#define RCC_CFGR_MCOPRE_DIV_4 0x6
#define RCC_CFGR_MCOPRE_DIV_5 0x7
/* I2SSRC: I2S clock selection */
#define RCC_CFGR_I2SSRC (1 << 23)
/* MCO1: Microcontroller clock output 1 */
#define RCC_CFGR_MCO1_SHIFT 21
#define RCC_CFGR_MCO1_MASK 0x3
#define RCC_CFGR_MCO1_HSI 0x0
#define RCC_CFGR_MCO1_LSE 0x1
#define RCC_CFGR_MCO1_HSE 0x2
#define RCC_CFGR_MCO1_PLL 0x3
#define RCC_CFGR_MCO_SHIFT RCC_CFGR_MCO1_SHIFT
#define RCC_CFGR_MCO_MASK RCC_CFGR_MCO1_MASK
/* RTCPRE: HSE division factor for RTC clock */
#define RCC_CFGR_RTCPRE_SHIFT 16
#define RCC_CFGR_RTCPRE_MASK 0x1f
/* PPRE1/2: APB high-speed prescalers */
#define RCC_CFGR_PPRE2_SHIFT 13
#define RCC_CFGR_PPRE2_MASK 0x7
#define RCC_CFGR_PPRE1_SHIFT 10
#define RCC_CFGR_PPRE1_MASK 0x7
#define RCC_CFGR_PPRE_DIV_NONE 0x0
#define RCC_CFGR_PPRE_DIV_2 0x4
#define RCC_CFGR_PPRE_DIV_4 0x5
#define RCC_CFGR_PPRE_DIV_8 0x6
#define RCC_CFGR_PPRE_DIV_16 0x7
/* HPRE: AHB high-speed prescaler */
#define RCC_CFGR_HPRE_SHIFT 4
#define RCC_CFGR_HPRE_MASK 0xf
#define RCC_CFGR_HPRE_DIV_NONE 0x0
#define RCC_CFGR_HPRE_DIV_2 (0x8 + 0)
#define RCC_CFGR_HPRE_DIV_4 (0x8 + 1)
#define RCC_CFGR_HPRE_DIV_8 (0x8 + 2)
#define RCC_CFGR_HPRE_DIV_16 (0x8 + 3)
#define RCC_CFGR_HPRE_DIV_64 (0x8 + 4)
#define RCC_CFGR_HPRE_DIV_128 (0x8 + 5)
#define RCC_CFGR_HPRE_DIV_256 (0x8 + 6)
#define RCC_CFGR_HPRE_DIV_512 (0x8 + 7)
/* SWS: System clock switch status */
#define RCC_CFGR_SWS_SHIFT 2
#define RCC_CFGR_SWS_HSI 0x0
#define RCC_CFGR_SWS_HSE 0x1
#define RCC_CFGR_SWS_PLL 0x2
/* SW: System clock switch */
#define RCC_CFGR_SW_SHIFT 0
#define RCC_CFGR_SW_HSI 0x0
#define RCC_CFGR_SW_HSE 0x1
#define RCC_CFGR_SW_PLL 0x2
/* --- RCC_CIR values ------------------------------------------------------ */
/* Clock security system interrupt clear bit */
#define RCC_CIR_CSSC (1 << 23)
/* OSC ready interrupt clear bits */
#define RCC_CIR_PLLI2SRDYC (1 << 21)
#define RCC_CIR_PLLRDYC (1 << 20)
#define RCC_CIR_HSERDYC (1 << 19)
#define RCC_CIR_HSIRDYC (1 << 18)
#define RCC_CIR_LSERDYC (1 << 17)
#define RCC_CIR_LSIRDYC (1 << 16)
/* OSC ready interrupt enable bits */
#define RCC_CIR_PLLI2SRDYIE (1 << 13)
#define RCC_CIR_PLLRDYIE (1 << 12)
#define RCC_CIR_HSERDYIE (1 << 11)
#define RCC_CIR_HSIRDYIE (1 << 10)
#define RCC_CIR_LSERDYIE (1 << 9)
#define RCC_CIR_LSIRDYIE (1 << 8)
/* Clock security system interrupt flag bit */
#define RCC_CIR_CSSF (1 << 7)
/* OSC ready interrupt flag bits */
#define RCC_CIR_PLLI2SRDYF (1 << 5)
#define RCC_CIR_PLLRDYF (1 << 4)
#define RCC_CIR_HSERDYF (1 << 3)
#define RCC_CIR_HSIRDYF (1 << 2)
#define RCC_CIR_LSERDYF (1 << 1)
#define RCC_CIR_LSIRDYF (1 << 0)
/* --- RCC_AHB1RSTR values ------------------------------------------------- */
#define RCC_AHB1RSTR_OTGHSRST (1 << 29)
#define RCC_AHB1RSTR_ETHMACRST (1 << 25)
#define RCC_AHB1RSTR_DMA2RST (1 << 22)
#define RCC_AHB1RSTR_DMA1RST (1 << 21)
#define RCC_AHB1RSTR_CRCRST (1 << 12)
#define RCC_AHB1RSTR_IOPIRST (1 << 8)
#define RCC_AHB1RSTR_IOPHRST (1 << 7)
#define RCC_AHB1RSTR_IOPGRST (1 << 6)
#define RCC_AHB1RSTR_IOPFRST (1 << 5)
#define RCC_AHB1RSTR_IOPERST (1 << 4)
#define RCC_AHB1RSTR_IOPDRST (1 << 3)
#define RCC_AHB1RSTR_IOPCRST (1 << 2)
#define RCC_AHB1RSTR_IOPBRST (1 << 1)
#define RCC_AHB1RSTR_IOPARST (1 << 0)
/* --- RCC_AHB2RSTR values ------------------------------------------------- */
#define RCC_AHB2RSTR_OTGFSRST (1 << 7)
#define RCC_AHB2RSTR_RNGRST (1 << 6)
#define RCC_AHB2RSTR_HASHRST (1 << 5)
#define RCC_AHB2RSTR_CRYPRST (1 << 4)
#define RCC_AHB2RSTR_DCMIRST (1 << 0)
/* --- RCC_AHB3RSTR values ------------------------------------------------- */
#define RCC_AHB3RSTR_FSMCRST (1 << 0)
/* --- RCC_APB1RSTR values ------------------------------------------------- */
#define RCC_APB1RSTR_DACRST (1 << 29)
#define RCC_APB1RSTR_PWRRST (1 << 28)
#define RCC_APB1RSTR_CAN2RST (1 << 26)
#define RCC_APB1RSTR_CAN1RST (1 << 25)
#define RCC_APB1RSTR_I2C3RST (1 << 23)
#define RCC_APB1RSTR_I2C2RST (1 << 22)
#define RCC_APB1RSTR_I2C1RST (1 << 21)
#define RCC_APB1RSTR_UART5RST (1 << 20)
#define RCC_APB1RSTR_UART4RST (1 << 19)
#define RCC_APB1RSTR_USART3RST (1 << 18)
#define RCC_APB1RSTR_USART2RST (1 << 17)
#define RCC_APB1RSTR_SPI3RST (1 << 15)
#define RCC_APB1RSTR_SPI2RST (1 << 14)
#define RCC_APB1RSTR_WWDGRST (1 << 11)
#define RCC_APB1RSTR_TIM14RST (1 << 8)
#define RCC_APB1RSTR_TIM13RST (1 << 7)
#define RCC_APB1RSTR_TIM12RST (1 << 6)
#define RCC_APB1RSTR_TIM7RST (1 << 5)
#define RCC_APB1RSTR_TIM6RST (1 << 4)
#define RCC_APB1RSTR_TIM5RST (1 << 3)
#define RCC_APB1RSTR_TIM4RST (1 << 2)
#define RCC_APB1RSTR_TIM3RST (1 << 1)
#define RCC_APB1RSTR_TIM2RST (1 << 0)
/* --- RCC_APB2RSTR values ------------------------------------------------- */
#define RCC_APB2RSTR_TIM11RST (1 << 18)
#define RCC_APB2RSTR_TIM10RST (1 << 17)
#define RCC_APB2RSTR_TIM9RST (1 << 16)
#define RCC_APB2RSTR_SYSCFGRST (1 << 14)
#define RCC_APB2RSTR_SPI1RST (1 << 12)
#define RCC_APB2RSTR_SDIORST (1 << 11)
#define RCC_APB2RSTR_ADCRST (1 << 8)
#define RCC_APB2RSTR_USART6RST (1 << 5)
#define RCC_APB2RSTR_USART1RST (1 << 4)
#define RCC_APB2RSTR_TIM8RST (1 << 1)
#define RCC_APB2RSTR_TIM1RST (1 << 0)
/* --- RCC_AHB1ENR values ------------------------------------------------- */
#define RCC_AHB1ENR_OTGHSULPIEN (1 << 30)
#define RCC_AHB1ENR_OTGHSEN (1 << 29)
#define RCC_AHB1ENR_ETHMACPTPEN (1 << 28)
#define RCC_AHB1ENR_ETHMACRXEN (1 << 27)
#define RCC_AHB1ENR_ETHMACTXEN (1 << 26)
#define RCC_AHB1ENR_ETHMACEN (1 << 25)
#define RCC_AHB1ENR_DMA2EN (1 << 22)
#define RCC_AHB1ENR_DMA1EN (1 << 21)
#define RCC_AHB1ENR_BKPSRAMEN (1 << 18)
#define RCC_AHB1ENR_CRCEN (1 << 12)
#define RCC_AHB1ENR_IOPIEN (1 << 8)
#define RCC_AHB1ENR_IOPHEN (1 << 7)
#define RCC_AHB1ENR_IOPGEN (1 << 6)
#define RCC_AHB1ENR_IOPFEN (1 << 5)
#define RCC_AHB1ENR_IOPEEN (1 << 4)
#define RCC_AHB1ENR_IOPDEN (1 << 3)
#define RCC_AHB1ENR_IOPCEN (1 << 2)
#define RCC_AHB1ENR_IOPBEN (1 << 1)
#define RCC_AHB1ENR_IOPAEN (1 << 0)
/* --- RCC_AHB2ENR values ------------------------------------------------- */
#define RCC_AHB2ENR_OTGFSEN (1 << 7)
#define RCC_AHB2ENR_RNGEN (1 << 6)
#define RCC_AHB2ENR_HASHEN (1 << 5)
#define RCC_AHB2ENR_CRYPEN (1 << 4)
#define RCC_AHB2ENR_DCMIEN (1 << 0)
/* --- RCC_AHB3ENR values ------------------------------------------------- */
#define RCC_AHB3ENR_FSMCEN (1 << 0)
/* Alternate now that F429 has DRAM controller as well */
#define RCC_AHB3ENR_FMCEN (1 << 0)
/* --- RCC_APB1ENR values ------------------------------------------------- */
#define RCC_APB1ENR_UART8EN (1 << 31)
#define RCC_APB1ENR_UART7EN (1 << 30)
#define RCC_APB1ENR_DACEN (1 << 29)
#define RCC_APB1ENR_PWREN (1 << 28)
#define RCC_APB1ENR_CAN2EN (1 << 26)
#define RCC_APB1ENR_CAN1EN (1 << 25)
#define RCC_APB1ENR_I2C3EN (1 << 23)
#define RCC_APB1ENR_I2C2EN (1 << 22)
#define RCC_APB1ENR_I2C1EN (1 << 21)
#define RCC_APB1ENR_UART5EN (1 << 20)
#define RCC_APB1ENR_UART4EN (1 << 19)
#define RCC_APB1ENR_USART3EN (1 << 18)
#define RCC_APB1ENR_USART2EN (1 << 17)
#define RCC_APB1ENR_SPI3EN (1 << 15)
#define RCC_APB1ENR_SPI2EN (1 << 14)
#define RCC_APB1ENR_WWDGEN (1 << 11)
#define RCC_APB1ENR_TIM14EN (1 << 8)
#define RCC_APB1ENR_TIM13EN (1 << 7)
#define RCC_APB1ENR_TIM12EN (1 << 6)
#define RCC_APB1ENR_TIM7EN (1 << 5)
#define RCC_APB1ENR_TIM6EN (1 << 4)
#define RCC_APB1ENR_TIM5EN (1 << 3)
#define RCC_APB1ENR_TIM4EN (1 << 2)
#define RCC_APB1ENR_TIM3EN (1 << 1)
#define RCC_APB1ENR_TIM2EN (1 << 0)
/* --- RCC_APB2ENR values ------------------------------------------------- */
#define RCC_APB2ENR_LTDCEN (1 << 26)
#define RCC_APB2ENR_SAI1EN (1 << 22)
#define RCC_APB2ENR_SPI6EN (1 << 21)
#define RCC_APB2ENR_SPI5EN (1 << 20)
#define RCC_APB2ENR_TIM11EN (1 << 18)
#define RCC_APB2ENR_TIM10EN (1 << 17)
#define RCC_APB2ENR_TIM9EN (1 << 16)
#define RCC_APB2ENR_SYSCFGEN (1 << 14)
#define RCC_APB2ENR_SPI4EN (1 << 13)
#define RCC_APB2ENR_SPI1EN (1 << 12)
#define RCC_APB2ENR_SDIOEN (1 << 11)
#define RCC_APB2ENR_ADC3EN (1 << 10)
#define RCC_APB2ENR_ADC2EN (1 << 9)
#define RCC_APB2ENR_ADC1EN (1 << 8)
#define RCC_APB2ENR_USART6EN (1 << 5)
#define RCC_APB2ENR_USART1EN (1 << 4)
#define RCC_APB2ENR_TIM8EN (1 << 1)
#define RCC_APB2ENR_TIM1EN (1 << 0)
/* --- RCC_AHB1LPENR values ------------------------------------------------- */
#define RCC_AHB1LPENR_OTGHSULPILPEN (1 << 30)
#define RCC_AHB1LPENR_OTGHSLPEN (1 << 29)
#define RCC_AHB1LPENR_ETHMACPTPLPEN (1 << 28)
#define RCC_AHB1LPENR_ETHMACRXLPEN (1 << 27)
#define RCC_AHB1LPENR_ETHMACTXLPEN (1 << 26)
#define RCC_AHB1LPENR_ETHMACLPEN (1 << 25)
#define RCC_AHB1LPENR_DMA2LPEN (1 << 22)
#define RCC_AHB1LPENR_DMA1LPEN (1 << 21)
#define RCC_AHB1LPENR_BKPSRAMLPEN (1 << 18)
#define RCC_AHB1LPENR_SRAM2LPEN (1 << 17)
#define RCC_AHB1LPENR_SRAM1LPEN (1 << 16)
#define RCC_AHB1LPENR_FLITFLPEN (1 << 15)
#define RCC_AHB1LPENR_CRCLPEN (1 << 12)
#define RCC_AHB1LPENR_IOPILPEN (1 << 8)
#define RCC_AHB1LPENR_IOPHLPEN (1 << 7)
#define RCC_AHB1LPENR_IOPGLPEN (1 << 6)
#define RCC_AHB1LPENR_IOPFLPEN (1 << 5)
#define RCC_AHB1LPENR_IOPELPEN (1 << 4)
#define RCC_AHB1LPENR_IOPDLPEN (1 << 3)
#define RCC_AHB1LPENR_IOPCLPEN (1 << 2)
#define RCC_AHB1LPENR_IOPBLPEN (1 << 1)
#define RCC_AHB1LPENR_IOPALPEN (1 << 0)
/* --- RCC_AHB2LPENR values ------------------------------------------------- */
#define RCC_AHB2LPENR_OTGFSLPEN (1 << 7)
#define RCC_AHB2LPENR_RNGLPEN (1 << 6)
#define RCC_AHB2LPENR_HASHLPEN (1 << 5)
#define RCC_AHB2LPENR_CRYPLPEN (1 << 4)
#define RCC_AHB2LPENR_DCMILPEN (1 << 0)
/* --- RCC_AHB3LPENR values ------------------------------------------------- */
#define RCC_AHB3LPENR_FSMCLPEN (1 << 0)
/* --- RCC_APB1LPENR values ------------------------------------------------- */
#define RCC_APB1LPENR_DACLPEN (1 << 29)
#define RCC_APB1LPENR_PWRLPEN (1 << 28)
#define RCC_APB1LPENR_CAN2LPEN (1 << 26)
#define RCC_APB1LPENR_CAN1LPEN (1 << 25)
#define RCC_APB1LPENR_I2C3LPEN (1 << 23)
#define RCC_APB1LPENR_I2C2LPEN (1 << 22)
#define RCC_APB1LPENR_I2C1LPEN (1 << 21)
#define RCC_APB1LPENR_UART5LPEN (1 << 20)
#define RCC_APB1LPENR_UART4LPEN (1 << 19)
#define RCC_APB1LPENR_USART3LPEN (1 << 18)
#define RCC_APB1LPENR_USART2LPEN (1 << 17)
#define RCC_APB1LPENR_SPI3LPEN (1 << 15)
#define RCC_APB1LPENR_SPI2LPEN (1 << 14)
#define RCC_APB1LPENR_WWDGLPEN (1 << 11)
#define RCC_APB1LPENR_TIM14LPEN (1 << 8)
#define RCC_APB1LPENR_TIM13LPEN (1 << 7)
#define RCC_APB1LPENR_TIM12LPEN (1 << 6)
#define RCC_APB1LPENR_TIM7LPEN (1 << 5)
#define RCC_APB1LPENR_TIM6LPEN (1 << 4)
#define RCC_APB1LPENR_TIM5LPEN (1 << 3)
#define RCC_APB1LPENR_TIM4LPEN (1 << 2)
#define RCC_APB1LPENR_TIM3LPEN (1 << 1)
#define RCC_APB1LPENR_TIM2LPEN (1 << 0)
/* --- RCC_APB2LPENR values ------------------------------------------------- */
#define RCC_APB2LPENR_TIM11LPEN (1 << 18)
#define RCC_APB2LPENR_TIM10LPEN (1 << 17)
#define RCC_APB2LPENR_TIM9LPEN (1 << 16)
#define RCC_APB2LPENR_SYSCFGLPEN (1 << 14)
#define RCC_APB2LPENR_SPI1LPEN (1 << 12)
#define RCC_APB2LPENR_SDIOLPEN (1 << 11)
#define RCC_APB2LPENR_ADC3LPEN (1 << 10)
#define RCC_APB2LPENR_ADC2LPEN (1 << 9)
#define RCC_APB2LPENR_ADC1LPEN (1 << 8)
#define RCC_APB2LPENR_USART6LPEN (1 << 5)
#define RCC_APB2LPENR_USART1LPEN (1 << 4)
#define RCC_APB2LPENR_TIM8LPEN (1 << 1)
#define RCC_APB2LPENR_TIM1LPEN (1 << 0)
/* --- RCC_BDCR values ----------------------------------------------------- */
#define RCC_BDCR_BDRST (1 << 16)
#define RCC_BDCR_RTCEN (1 << 15)
/* RCC_BDCR[9:8]: RTCSEL */
#define RCC_BDCR_LSEBYP (1 << 2)
#define RCC_BDCR_LSERDY (1 << 1)
#define RCC_BDCR_LSEON (1 << 0)
/* --- RCC_CSR values ------------------------------------------------------ */
#define RCC_CSR_LPWRRSTF (1 << 31)
#define RCC_CSR_WWDGRSTF (1 << 30)
#define RCC_CSR_IWDGRSTF (1 << 29)
#define RCC_CSR_SFTRSTF (1 << 28)
#define RCC_CSR_PORRSTF (1 << 27)
#define RCC_CSR_PINRSTF (1 << 26)
#define RCC_CSR_BORRSTF (1 << 25)
#define RCC_CSR_RMVF (1 << 24)
#define RCC_CSR_LSIRDY (1 << 1)
#define RCC_CSR_LSION (1 << 0)
/* --- RCC_SSCGR values ---------------------------------------------------- */
/* PLL spread spectrum clock generation documented in Datasheet. */
#define RCC_SSCGR_SSCGEN (1 << 31)
#define RCC_SSCGR_SPREADSEL (1 << 30)
/* RCC_SSCGR[27:16]: INCSTEP */
#define RCC_SSCGR_INCSTEP_SHIFT 16
/* RCC_SSCGR[15:0]: MODPER */
#define RCC_SSCGR_MODPER_SHIFT 15
/* --- RCC_PLLI2SCFGR values ----------------------------------------------- */
/* RCC_PLLI2SCFGR[30:28]: PLLI2SR */
#define RCC_PLLI2SCFGR_PLLI2SR_SHIFT 28
/* RCC_PLLI2SCFGR[14:6]: PLLI2SN */
#define RCC_PLLI2SCFGR_PLLI2SN_SHIFT 6
/* --- RCC_PLLSAICFGR values ----------------------------------------------- */
/* RCC_PLLSAICFGR[30:28]: PLLSAIR */
#define RCC_PLLSAICFGR_PLLSAIR_SHIFT 28
#define RCC_PLLSAICFGR_PLLSAIR_MASK 0x7
/* RCC_PLLSAICFGR[27:24]: PLLSAIQ */
#define RCC_PLLSAICFGR_PLLSAIQ_SHIFT 24
#define RCC_PLLSAICFGR_PLLSAIQ_MASK 0xF
/* RCC_PLLSAICFGR[14:6]: PLLSAIN */
#define RCC_PLLSAICFGR_PLLSAIN_SHIFT 14
#define RCC_PLLSAICFGR_PLLSAIN_MASK 0x1FF
/* --- RCC_DCKCFGR values -------------------------------------------------- */
#define RCC_DCKCFGR_PLLSAIDIVR_MSK (0x3 << 16)
#define RCC_DCKCFGR_PLLSAIDIVR_DIVR_2 (0x0)
#define RCC_DCKCFGR_PLLSAIDIVR_DIVR_4 (0x1)
#define RCC_DCKCFGR_PLLSAIDIVR_DIVR_8 (0x2)
#define RCC_DCKCFGR_PLLSAIDIVR_DIVR_16 (0x3)
/* PLLSAI1 helper macros */
static inline void rcc_pllsai_enable(void)
{
RCC_CR |= RCC_CR_PLLSAION;
}
static inline bool rcc_pllsai_ready(void)
{
return (RCC_CR & RCC_CR_PLLSAIRDY) != 0;
}
/* pllsain=49..432, pllsaiq=2..15, pllsair=2..7 */
static inline void rcc_pllsai_config(uint16_t pllsain,
uint16_t pllsaiq,
uint16_t pllsair)
{
RCC_PLLSAICFGR = (((pllsain & 0x1ff) << 6) |
((pllsaiq & 0xF) << 24) |
((pllsair & 0x7) << 28));
}
static inline void rcc_ltdc_set_clock_divr(uint8_t pllsaidivr)
{
RCC_DCKCFGR = (((RCC_DCKCFGR &
~RCC_DCKCFGR_PLLSAIDIVR_MSK) |
((pllsaidivr & 0x3) << 16)));
}
/* --- Variable definitions ------------------------------------------------ */
extern uint32_t rcc_ahb_frequency;
extern uint32_t rcc_apb1_frequency;
extern uint32_t rcc_apb2_frequency;
/* --- Function prototypes ------------------------------------------------- */
typedef enum {
CLOCK_3V3_48MHZ,
CLOCK_3V3_84MHZ,
CLOCK_3V3_120MHZ,
CLOCK_3V3_168MHZ,
CLOCK_3V3_END
} clock_3v3_t;
typedef struct {
uint8_t pllm;
uint16_t plln;
uint8_t pllp;
uint8_t pllq;
uint32_t flash_config;
uint8_t hpre;
uint8_t ppre1;
uint8_t ppre2;
uint8_t power_save;
uint32_t apb1_frequency;
uint32_t apb2_frequency;
} clock_scale_t;
extern const clock_scale_t hse_8mhz_3v3[CLOCK_3V3_END];
extern const clock_scale_t hse_12mhz_3v3[CLOCK_3V3_END];
extern const clock_scale_t hse_16mhz_3v3[CLOCK_3V3_END];
extern const clock_scale_t hse_25mhz_3v3[CLOCK_3V3_END];
enum rcc_osc {
PLL, HSE, HSI, LSE, LSI
};
#define _REG_BIT(base, bit) (((base) << 5) + (bit))
enum rcc_periph_clken {
/* AHB1 peripherals*/
RCC_GPIOA = _REG_BIT(0x30, 0),
RCC_GPIOB = _REG_BIT(0x30, 1),
RCC_GPIOC = _REG_BIT(0x30, 2),
RCC_GPIOD = _REG_BIT(0x30, 3),
RCC_GPIOE = _REG_BIT(0x30, 4),
RCC_GPIOF = _REG_BIT(0x30, 5),
RCC_GPIOG = _REG_BIT(0x30, 6),
RCC_GPIOH = _REG_BIT(0x30, 7),
RCC_GPIOI = _REG_BIT(0x30, 8),
RCC_CRC = _REG_BIT(0x30, 12),
RCC_BKPSRAM = _REG_BIT(0x30, 18),
RCC_CCMDATARAM = _REG_BIT(0x30, 20),
RCC_DMA1 = _REG_BIT(0x30, 21),
RCC_DMA2 = _REG_BIT(0x30, 22),
RCC_ETHMAC = _REG_BIT(0x30, 25),
RCC_ETHMACTX = _REG_BIT(0x30, 26),
RCC_ETHMACRX = _REG_BIT(0x30, 27),
RCC_ETHMACPTP = _REG_BIT(0x30, 28),
RCC_OTGHS = _REG_BIT(0x30, 29),
RCC_OTGHSULPI = _REG_BIT(0x30, 30),
/* AHB2 peripherals */
RCC_DCMI = _REG_BIT(0x34, 0),
RCC_CRYP = _REG_BIT(0x34, 4),
RCC_HASH = _REG_BIT(0x34, 5),
RCC_RNG = _REG_BIT(0x34, 6),
RCC_OTGFS = _REG_BIT(0x34, 7),
/* AHB3 peripherals */
RCC_FSMC = _REG_BIT(0x38, 0),
/* APB1 peripherals*/
RCC_TIM2 = _REG_BIT(0x40, 0),
RCC_TIM3 = _REG_BIT(0x40, 1),
RCC_TIM4 = _REG_BIT(0x40, 2),
RCC_TIM5 = _REG_BIT(0x40, 3),
RCC_TIM6 = _REG_BIT(0x40, 4),
RCC_TIM7 = _REG_BIT(0x40, 5),
RCC_TIM12 = _REG_BIT(0x40, 6),
RCC_TIM13 = _REG_BIT(0x40, 7),
RCC_TIM14 = _REG_BIT(0x40, 8),
RCC_WWDG = _REG_BIT(0x40, 11),
RCC_SPI2 = _REG_BIT(0x40, 14),
RCC_SPI3 = _REG_BIT(0x40, 15),
RCC_USART2 = _REG_BIT(0x40, 17),
RCC_USART3 = _REG_BIT(0x40, 18),
RCC_UART4 = _REG_BIT(0x40, 19),
RCC_UART5 = _REG_BIT(0x40, 20),
RCC_I2C1 = _REG_BIT(0x40, 21),
RCC_I2C2 = _REG_BIT(0x40, 22),
RCC_I2C3 = _REG_BIT(0x40, 23),
RCC_CAN1 = _REG_BIT(0x40, 25),
RCC_CAN2 = _REG_BIT(0x40, 26),
RCC_PWR = _REG_BIT(0x40, 28),
RCC_DAC = _REG_BIT(0x40, 29),
RCC_UART7 = _REG_BIT(0x40, 30),/* F2xx, F3xx */
RCC_UART8 = _REG_BIT(0x40, 31),/* F2xx, F3xx */
/* APB2 peripherals */
RCC_TIM1 = _REG_BIT(0x44, 0),
RCC_TIM8 = _REG_BIT(0x44, 1),
RCC_USART1 = _REG_BIT(0x44, 4),
RCC_USART6 = _REG_BIT(0x44, 5),
RCC_ADC1 = _REG_BIT(0x44, 8),
RCC_ADC2 = _REG_BIT(0x44, 9),
RCC_ADC3 = _REG_BIT(0x44, 10),
RCC_SDIO = _REG_BIT(0x44, 11),
RCC_SPI1 = _REG_BIT(0x44, 12),
RCC_SPI4 = _REG_BIT(0x44, 13),/* F2xx, F3xx */
RCC_SYSCFG = _REG_BIT(0x44, 14),
RCC_TIM9 = _REG_BIT(0x44, 16),
RCC_TIM10 = _REG_BIT(0x44, 17),
RCC_TIM11 = _REG_BIT(0x44, 18),
RCC_SPI5 = _REG_BIT(0x44, 20),/* F2xx, F3xx */
RCC_SPI6 = _REG_BIT(0x44, 21),/* F2xx, F3xx */
RCC_SAI1EN = _REG_BIT(0x44, 22),/* F42x, F43x */
RCC_LTDC = _REG_BIT(0x44, 26),/* F42x, F43x */
/* BDCR */
RCC_RTC = _REG_BIT(0x70, 15),
/* AHB1 peripherals*/
SCC_GPIOA = _REG_BIT(0x50, 0),
SCC_GPIOB = _REG_BIT(0x50, 1),
SCC_GPIOC = _REG_BIT(0x50, 2),
SCC_GPIOD = _REG_BIT(0x50, 3),
SCC_GPIOE = _REG_BIT(0x50, 4),
SCC_GPIOF = _REG_BIT(0x50, 5),
SCC_GPIOG = _REG_BIT(0x50, 6),
SCC_GPIOH = _REG_BIT(0x50, 7),
SCC_GPIOI = _REG_BIT(0x50, 8),
SCC_CRC = _REG_BIT(0x50, 12),
SCC_FLTIF = _REG_BIT(0x50, 15),
SCC_SRAM1 = _REG_BIT(0x50, 16),
SCC_SRAM2 = _REG_BIT(0x50, 17),
SCC_BKPSRAM = _REG_BIT(0x50, 18),
SCC_SRAM3 = _REG_BIT(0x50, 19),/* F2xx, F3xx */
SCC_DMA1 = _REG_BIT(0x50, 21),
SCC_DMA2 = _REG_BIT(0x50, 22),
SCC_ETHMAC = _REG_BIT(0x50, 25),
SCC_ETHMACTX = _REG_BIT(0x50, 26),
SCC_ETHMACRX = _REG_BIT(0x50, 27),
SCC_ETHMACPTP = _REG_BIT(0x50, 28),
SCC_OTGHS = _REG_BIT(0x50, 29),
SCC_OTGHSULPI = _REG_BIT(0x50, 30),
/* AHB2 peripherals */
SCC_DCMI = _REG_BIT(0x54, 0),
SCC_CRYP = _REG_BIT(0x54, 4),
SCC_HASH = _REG_BIT(0x54, 5),
SCC_RNG = _REG_BIT(0x54, 6),
SCC_OTGFS = _REG_BIT(0x54, 7),
/* AHB3 peripherals */
SCC_FSMC = _REG_BIT(0x58, 0),
/* APB1 peripherals*/
SCC_TIM2 = _REG_BIT(0x60, 0),
SCC_TIM3 = _REG_BIT(0x60, 1),
SCC_TIM4 = _REG_BIT(0x60, 2),
SCC_TIM5 = _REG_BIT(0x60, 3),
SCC_TIM6 = _REG_BIT(0x60, 4),
SCC_TIM7 = _REG_BIT(0x60, 5),
SCC_TIM12 = _REG_BIT(0x60, 6),
SCC_TIM13 = _REG_BIT(0x60, 7),
SCC_TIM14 = _REG_BIT(0x60, 8),
SCC_WWDG = _REG_BIT(0x60, 11),
SCC_SPI2 = _REG_BIT(0x60, 14),
SCC_SPI3 = _REG_BIT(0x60, 15),
SCC_USART2 = _REG_BIT(0x60, 17),
SCC_USART3 = _REG_BIT(0x60, 18),
SCC_UART4 = _REG_BIT(0x60, 19),
SCC_UART5 = _REG_BIT(0x60, 20),
SCC_I2C1 = _REG_BIT(0x60, 21),
SCC_I2C2 = _REG_BIT(0x60, 22),
SCC_I2C3 = _REG_BIT(0x60, 23),
SCC_CAN1 = _REG_BIT(0x60, 25),
SCC_CAN2 = _REG_BIT(0x60, 26),
SCC_PWR = _REG_BIT(0x60, 28),
SCC_DAC = _REG_BIT(0x60, 29),
SCC_UART7 = _REG_BIT(0x60, 30),/* F2xx, F3xx */
SCC_UART8 = _REG_BIT(0x60, 31),/* F2xx, F3xx */
/* APB2 peripherals */
SCC_TIM1 = _REG_BIT(0x64, 0),
SCC_TIM8 = _REG_BIT(0x64, 1),
SCC_USART1 = _REG_BIT(0x64, 4),
SCC_USART6 = _REG_BIT(0x64, 5),
SCC_ADC1 = _REG_BIT(0x64, 8),
SCC_ADC2 = _REG_BIT(0x64, 9),
SCC_ADC3 = _REG_BIT(0x64, 10),
SCC_SDIO = _REG_BIT(0x64, 11),
SCC_SPI1 = _REG_BIT(0x64, 12),
SCC_SPI4 = _REG_BIT(0x64, 13),/* F2xx, F3xx */
SCC_SYSCFG = _REG_BIT(0x64, 14),
SCC_TIM9 = _REG_BIT(0x64, 16),
SCC_TIM10 = _REG_BIT(0x64, 17),
SCC_TIM11 = _REG_BIT(0x64, 18),
SCC_SPI5 = _REG_BIT(0x64, 20),/* F2xx, F3xx */
SCC_SPI6 = _REG_BIT(0x64, 21),/* F2xx, F3xx */
};
enum rcc_periph_rst {
/* AHB1 peripherals*/
RST_GPIOA = _REG_BIT(0x10, 0),
RST_GPIOB = _REG_BIT(0x10, 1),
RST_GPIOC = _REG_BIT(0x10, 2),
RST_GPIOD = _REG_BIT(0x10, 3),
RST_GPIOE = _REG_BIT(0x10, 4),
RST_GPIOF = _REG_BIT(0x10, 5),
RST_GPIOG = _REG_BIT(0x10, 6),
RST_GPIOH = _REG_BIT(0x10, 7),
RST_GPIOI = _REG_BIT(0x10, 8),
RST_CRC = _REG_BIT(0x10, 12),
RST_DMA1 = _REG_BIT(0x10, 21),
RST_DMA2 = _REG_BIT(0x10, 22),
RST_ETHMAC = _REG_BIT(0x10, 25),
RST_OTGHS = _REG_BIT(0x10, 29),
/* AHB2 peripherals */
RST_DCMI = _REG_BIT(0x14, 0),
RST_CRYP = _REG_BIT(0x14, 4),
RST_HASH = _REG_BIT(0x14, 5),
RST_RNG = _REG_BIT(0x14, 6),
RST_OTGFS = _REG_BIT(0x14, 7),
/* AHB3 peripherals */
RST_FSMC = _REG_BIT(0x18, 0),
/* APB1 peripherals*/
RST_TIM2 = _REG_BIT(0x20, 0),
RST_TIM3 = _REG_BIT(0x20, 1),
RST_TIM4 = _REG_BIT(0x20, 2),
RST_TIM5 = _REG_BIT(0x20, 3),
RST_TIM6 = _REG_BIT(0x20, 4),
RST_TIM7 = _REG_BIT(0x20, 5),
RST_TIM12 = _REG_BIT(0x20, 6),
RST_TIM13 = _REG_BIT(0x20, 7),
RST_TIM14 = _REG_BIT(0x20, 8),
RST_WWDG = _REG_BIT(0x20, 11),
RST_SPI2 = _REG_BIT(0x20, 14),
RST_SPI3 = _REG_BIT(0x20, 15),
RST_USART2 = _REG_BIT(0x20, 17),
RST_USART3 = _REG_BIT(0x20, 18),
RST_UART4 = _REG_BIT(0x20, 19),
RST_UART5 = _REG_BIT(0x20, 20),
RST_I2C1 = _REG_BIT(0x20, 21),
RST_I2C2 = _REG_BIT(0x20, 22),
RST_I2C3 = _REG_BIT(0x20, 23),
RST_CAN1 = _REG_BIT(0x20, 25),
RST_CAN2 = _REG_BIT(0x20, 26),
RST_PWR = _REG_BIT(0x20, 28),
RST_DAC = _REG_BIT(0x20, 29),
RST_UART7 = _REG_BIT(0x20, 30),/* F2xx, F3xx */
RST_UART8 = _REG_BIT(0x20, 31),/* F2xx, F3xx */
/* APB2 peripherals */
RST_TIM1 = _REG_BIT(0x24, 0),
RST_TIM8 = _REG_BIT(0x24, 1),
RST_USART1 = _REG_BIT(0x24, 4),
RST_USART6 = _REG_BIT(0x24, 5),
RST_ADC = _REG_BIT(0x24, 8),
RST_SDIO = _REG_BIT(0x24, 11),
RST_SPI1 = _REG_BIT(0x24, 12),
RST_SPI4 = _REG_BIT(0x24, 13),/* F2xx, F3xx */
RST_SYSCFG = _REG_BIT(0x24, 14),
RST_TIM9 = _REG_BIT(0x24, 16),
RST_TIM10 = _REG_BIT(0x24, 17),
RST_TIM11 = _REG_BIT(0x24, 18),
RST_SPI5 = _REG_BIT(0x24, 20),/* F2xx, F3xx */
RST_SPI6 = _REG_BIT(0x24, 21),/* F2xx, F3xx */
RST_SAI1RST = _REG_BIT(0x24, 22),/* F42x, F43x */
RST_LTDC = _REG_BIT(0x24, 26),/* F42x, F43x */
};
#undef _REG_BIT
void rcc_peripheral_enable_clock(volatile uint32_t *reg, uint32_t en);
void rcc_peripheral_disable_clock(volatile uint32_t *reg, uint32_t en);
void rcc_peripheral_reset(volatile uint32_t *reg, uint32_t reset);
void rcc_peripheral_clear_reset(volatile uint32_t *reg, uint32_t clear_reset);
void rcc_periph_clock_enable(enum rcc_periph_clken clken);
void rcc_periph_clock_disable(enum rcc_periph_clken clken);
void rcc_periph_reset_pulse(enum rcc_periph_rst rst);
void rcc_periph_reset_hold(enum rcc_periph_rst rst);
void rcc_periph_reset_release(enum rcc_periph_rst rst);
void rcc_set_mco(uint32_t mcosrc);
void rcc_osc_ready_int_clear(enum rcc_osc osc);
void rcc_osc_ready_int_enable(enum rcc_osc osc);
void rcc_osc_ready_int_disable(enum rcc_osc osc);
int rcc_osc_ready_int_flag(enum rcc_osc osc);
void rcc_css_int_clear(void);
int rcc_css_int_flag(void);
void rcc_wait_for_osc_ready(enum rcc_osc osc);
void rcc_wait_for_sysclk_status(enum rcc_osc osc);
void rcc_osc_on(enum rcc_osc osc);
void rcc_osc_off(enum rcc_osc osc);
void rcc_css_enable(void);
void rcc_css_disable(void);
void rcc_osc_bypass_enable(enum rcc_osc osc);
void rcc_osc_bypass_disable(enum rcc_osc osc);
void rcc_set_sysclk_source(uint32_t clk);
void rcc_set_pll_source(uint32_t pllsrc);
void rcc_set_ppre2(uint32_t ppre2);
void rcc_set_ppre1(uint32_t ppre1);
void rcc_set_hpre(uint32_t hpre);
void rcc_set_rtcpre(uint32_t rtcpre);
void rcc_set_main_pll_hsi(uint32_t pllm, uint32_t plln, uint32_t pllp,
uint32_t pllq);
void rcc_set_main_pll_hse(uint32_t pllm, uint32_t plln, uint32_t pllp,
uint32_t pllq);
uint32_t rcc_system_clock_source(void);
void rcc_clock_setup_hse_3v3(const clock_scale_t *clock);
#endif

Просмотреть файл

@ -0,0 +1,68 @@
/*
* This file is part of the libopencm3 project.
*
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA RNG.H
The order of header inclusion is important. rng.h includes the device
specific memorymap.h header before including this header file.*/
/** @cond */
#ifndef LIBOPENCM3_RNG_H
#define LIBOPENCM3_RNG_H
#include "memorymap_f4.h"
/** @endcond */
/* --- Random number generator registers ----------------------------------- */
/* Control register */
#define RNG_CR MMIO32(RNG_BASE + 0x00)
/* Status register */
#define RNG_SR MMIO32(RNG_BASE + 0x04)
/* Data register */
#define RNG_DR MMIO32(RNG_BASE + 0x08)
/* --- RNG_CR values ------------------------------------------------------- */
/* RNG ENABLE */
#define RNG_CR_RNGEN (1 << 2)
/* RNG interrupt enable */
#define RNG_CR_IE (1 << 3)
/* --- RNG_SR values ------------------------------------------------------- */
/* Data ready */
#define RNG_SR_DRDY (1 << 0)
/* Clock error current status */
#define RNG_SR_CECS (1 << 1)
/* Seed error current status */
#define RNG_SR_SECS (1 << 2)
/* Clock error interrupt status */
#define RNG_SR_CEIS (1 << 5)
/* Seed error interrupt status */
#define RNG_SR_SEIS (1 << 6)
#endif
/** @cond */
/** @endcond */

Просмотреть файл

@ -0,0 +1,97 @@
/** @addtogroup usart_defines
@author @htmlonly &copy; @endhtmlonly 2011 Uwe Hermann <uwe@hermann-uwe.de>
@author @htmlonly &copy; @endhtmlonly 2011 Stephen Caudle <scaudle@doceme.com>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA USART.H
The order of header inclusion is important. usart.h includes the device
specific memorymap.h header before including this header file.*/
/** @cond */
#ifndef LIBOPENCM3_USART_H
#define LIBOPENCM3_USART_H
/** @endcond */
#ifndef LIBOPENCM3_USART_COMMON_F24_H
#define LIBOPENCM3_USART_COMMON_F24_H
#include "usart_common_f124.h"
/* --- Convenience macros -------------------------------------------------- */
#define USART6 USART6_BASE
#define UART7 UART7_BASE
#define UART8 UART8_BASE
/* --- USART registers ----------------------------------------------------- */
/* Status register (USARTx_SR) */
#define USART6_SR USART_SR(USART6_BASE)
#define UART7_SR USART_SR(UART7)
#define UART8_SR USART_SR(UART8)
/* Data register (USARTx_DR) */
#define USART6_DR USART_DR(USART6_BASE)
#define UART7_DR USART_DR(UART7)
#define UART8_DR USART_DR(UART8)
/* Baud rate register (USARTx_BRR) */
#define USART6_BRR USART_BRR(USART6_BASE)
#define UART7_BRR USART_BRR(UART7)
#define UART8_BRR USART_BRR(UART8)
/* Control register 1 (USARTx_CR1) */
#define USART6_CR1 USART_CR1(USART6_BASE)
#define UART7_CR1 USART_CR1(UART7)
#define UART8_CR1 USART_CR1(UART8)
/* Control register 2 (USARTx_CR2) */
#define USART6_CR2 USART_CR2(USART6_BASE)
#define UART7_CR2 USART_CR2(UART7)
#define UART8_CR2 USART_CR2(UART8)
/* Control register 3 (USARTx_CR3) */
#define USART6_CR3 USART_CR3(USART6_BASE)
#define UART7_CR3 USART_CR3(UART7)
#define UART8_CR3 USART_CR3(UART8)
/* Guard time and prescaler register (USARTx_GTPR) */
#define USART6_GTPR USART_GTPR(USART6_BASE)
#define UART7_GTPR USART_GTPR(UART7)
#define UART8_GTPR USART_GTPR(UART8)
/* --- USART_CR1 values ---------------------------------------------------- */
/* OVER8: Oversampling mode */
#define USART_CR1_OVER8 (1 << 15)
/* --- USART_CR3 values ---------------------------------------------------- */
/* ONEBIT: One sample bit method enable */
#define USART_CR3_ONEBIT (1 << 11)
#endif
/** @cond */
#endif
/** @endcond */

Просмотреть файл

@ -0,0 +1,139 @@
/** @addtogroup usart_defines
*
* @author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA USART.H
The order of header inclusion is important. usart.h includes the device
specific memorymap.h header before including this header file.*/
/** @cond */
#if defined(LIBOPENCM3_USART_H)
/** @endcond */
#ifndef LIBOPENCM3_USART_COMMON_ALL_H
#define LIBOPENCM3_USART_COMMON_ALL_H
/* --- Convenience macros -------------------------------------------------- */
/****************************************************************************/
/** @defgroup usart_reg_base USART register base addresses
@ingroup STM32F_usart_defines
@{*/
#define USART1 USART1_BASE
#define USART2 USART2_BASE
#define USART3 USART3_BASE
/**@}*/
#define UART4 UART4_BASE
#define UART5 UART5_BASE
/* --- Convenience defines ------------------------------------------------- */
/* CR1_PCE / CR1_PS combined values */
/****************************************************************************/
/** @defgroup usart_cr1_parity USART Parity Selection
@ingroup STM32F_usart_defines
@{*/
#define USART_PARITY_NONE 0x00
#define USART_PARITY_EVEN USART_CR1_PCE
#define USART_PARITY_ODD (USART_CR1_PS | USART_CR1_PCE)
/**@}*/
#define USART_PARITY_MASK (USART_CR1_PS | USART_CR1_PCE)
/* CR1_TE/CR1_RE combined values */
/****************************************************************************/
/** @defgroup usart_cr1_mode USART Tx/Rx Mode Selection
@ingroup STM32F_usart_defines
@{*/
#define USART_MODE_RX USART_CR1_RE
#define USART_MODE_TX USART_CR1_TE
#define USART_MODE_TX_RX (USART_CR1_RE | USART_CR1_TE)
/**@}*/
#define USART_MODE_MASK (USART_CR1_RE | USART_CR1_TE)
/****************************************************************************/
/** @defgroup usart_cr2_stopbits USART Stop Bit Selection
@ingroup STM32F_usart_defines
@{*/
#define USART_STOPBITS_1 USART_CR2_STOPBITS_1 /* 1 stop bit */
#define USART_STOPBITS_0_5 USART_CR2_STOPBITS_0_5 /* .5 stop bit */
#define USART_STOPBITS_2 USART_CR2_STOPBITS_2 /* 2 stop bits */
#define USART_STOPBITS_1_5 USART_CR2_STOPBITS_1_5 /* 1.5 stop bit*/
/**@}*/
/* CR3_CTSE/CR3_RTSE combined values */
/****************************************************************************/
/** @defgroup usart_cr3_flowcontrol USART Hardware Flow Control Selection
@ingroup STM32F_usart_defines
@{*/
#define USART_FLOWCONTROL_NONE 0x00
#define USART_FLOWCONTROL_RTS USART_CR3_RTSE
#define USART_FLOWCONTROL_CTS USART_CR3_CTSE
#define USART_FLOWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE)
/**@}*/
#define USART_FLOWCONTROL_MASK (USART_CR3_RTSE | USART_CR3_CTSE)
/* --- Function prototypes ------------------------------------------------- */
void usart_set_baudrate(uint32_t usart, uint32_t baud);
void usart_set_databits(uint32_t usart, uint32_t bits);
void usart_set_stopbits(uint32_t usart, uint32_t stopbits);
void usart_set_parity(uint32_t usart, uint32_t parity);
void usart_set_mode(uint32_t usart, uint32_t mode);
void usart_set_flow_control(uint32_t usart, uint32_t flowcontrol);
void usart_enable(uint32_t usart);
void usart_disable(uint32_t usart);
void usart_send(uint32_t usart, uint16_t data);
uint16_t usart_recv(uint32_t usart);
void usart_wait_send_ready(uint32_t usart);
void usart_wait_recv_ready(uint32_t usart);
void usart_send_blocking(uint32_t usart, uint16_t data);
uint16_t usart_recv_blocking(uint32_t usart);
void usart_enable_rx_dma(uint32_t usart);
void usart_disable_rx_dma(uint32_t usart);
void usart_enable_tx_dma(uint32_t usart);
void usart_disable_tx_dma(uint32_t usart);
void usart_enable_rx_interrupt(uint32_t usart);
void usart_disable_rx_interrupt(uint32_t usart);
void usart_enable_tx_interrupt(uint32_t usart);
void usart_disable_tx_interrupt(uint32_t usart);
void usart_enable_error_interrupt(uint32_t usart);
void usart_disable_error_interrupt(uint32_t usart);
bool usart_get_flag(uint32_t usart, uint32_t flag);
bool usart_get_interrupt_source(uint32_t usart, uint32_t flag);
#endif
/** @cond */
#else
#warning "usart_common_all.h should not be included directly, only via usart.h"
#endif
/** @endcond */
/**@}*/

Просмотреть файл

@ -0,0 +1,288 @@
/** @addtogroup usart_defines
@author @htmlonly &copy; @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
/* THIS FILE SHOULD NOT BE INCLUDED DIRECTLY, BUT ONLY VIA USART.H
The order of header inclusion is important. usart.h includes the device
specific memorymap.h header before including this header file.*/
/** @cond */
#if defined(LIBOPENCM3_USART_H)
/** @endcond */
#ifndef LIBOPENCM3_USART_COMMON_F124_H
#define LIBOPENCM3_USART_COMMON_F124_H
#include "usart_common_all.h"
/* --- USART registers ----------------------------------------------------- */
/* Status register (USARTx_SR) */
#define USART_SR(usart_base) MMIO32((usart_base) + 0x00)
#define USART1_SR USART_SR(USART1_BASE)
#define USART2_SR USART_SR(USART2_BASE)
#define USART3_SR USART_SR(USART3_BASE)
#define UART4_SR USART_SR(UART4_BASE)
#define UART5_SR USART_SR(UART5_BASE)
/* Data register (USARTx_DR) */
#define USART_DR(usart_base) MMIO32((usart_base) + 0x04)
#define USART1_DR USART_DR(USART1_BASE)
#define USART2_DR USART_DR(USART2_BASE)
#define USART3_DR USART_DR(USART3_BASE)
#define UART4_DR USART_DR(UART4_BASE)
#define UART5_DR USART_DR(UART5_BASE)
/* Baud rate register (USARTx_BRR) */
#define USART_BRR(usart_base) MMIO32((usart_base) + 0x08)
#define USART1_BRR USART_BRR(USART1_BASE)
#define USART2_BRR USART_BRR(USART2_BASE)
#define USART3_BRR USART_BRR(USART3_BASE)
#define UART4_BRR USART_BRR(UART4_BASE)
#define UART5_BRR USART_BRR(UART5_BASE)
/* Control register 1 (USARTx_CR1) */
#define USART_CR1(usart_base) MMIO32((usart_base) + 0x0c)
#define USART1_CR1 USART_CR1(USART1_BASE)
#define USART2_CR1 USART_CR1(USART2_BASE)
#define USART3_CR1 USART_CR1(USART3_BASE)
#define UART4_CR1 USART_CR1(UART4_BASE)
#define UART5_CR1 USART_CR1(UART5_BASE)
/* Control register 2 (USARTx_CR2) */
#define USART_CR2(usart_base) MMIO32((usart_base) + 0x10)
#define USART1_CR2 USART_CR2(USART1_BASE)
#define USART2_CR2 USART_CR2(USART2_BASE)
#define USART3_CR2 USART_CR2(USART3_BASE)
#define UART4_CR2 USART_CR2(UART4_BASE)
#define UART5_CR2 USART_CR2(UART5_BASE)
/* Control register 3 (USARTx_CR3) */
#define USART_CR3(usart_base) MMIO32((usart_base) + 0x14)
#define USART1_CR3 USART_CR3(USART1_BASE)
#define USART2_CR3 USART_CR3(USART2_BASE)
#define USART3_CR3 USART_CR3(USART3_BASE)
#define UART4_CR3 USART_CR3(UART4_BASE)
#define UART5_CR3 USART_CR3(UART5_BASE)
/* Guard time and prescaler register (USARTx_GTPR) */
#define USART_GTPR(usart_base) MMIO32((usart_base) + 0x18)
#define USART1_GTPR USART_GTPR(USART1_BASE)
#define USART2_GTPR USART_GTPR(USART2_BASE)
#define USART3_GTPR USART_GTPR(USART3_BASE)
#define UART4_GTPR USART_GTPR(UART4_BASE)
#define UART5_GTPR USART_GTPR(UART5_BASE)
/* --- USART_SR values ----------------------------------------------------- */
/****************************************************************************/
/** @defgroup usart_sr_flags USART Status register Flags
@ingroup STM32F_usart_defines
@{*/
/** CTS: CTS flag */
/** @note: undefined on UART4 and UART5 */
#define USART_SR_CTS (1 << 9)
/** LBD: LIN break detection flag */
#define USART_SR_LBD (1 << 8)
/** TXE: Transmit data buffer empty */
#define USART_SR_TXE (1 << 7)
/** TC: Transmission complete */
#define USART_SR_TC (1 << 6)
/** RXNE: Read data register not empty */
#define USART_SR_RXNE (1 << 5)
/** IDLE: Idle line detected */
#define USART_SR_IDLE (1 << 4)
/** ORE: Overrun error */
#define USART_SR_ORE (1 << 3)
/** NE: Noise error flag */
#define USART_SR_NE (1 << 2)
/** FE: Framing error */
#define USART_SR_FE (1 << 1)
/** PE: Parity error */
#define USART_SR_PE (1 << 0)
/**@}*/
/* --- USART_DR values ----------------------------------------------------- */
/* USART_DR[8:0]: DR[8:0]: Data value */
#define USART_DR_MASK 0x1FF
/* --- USART_BRR values ---------------------------------------------------- */
/* DIV_Mantissa[11:0]: mantissa of USARTDIV */
#define USART_BRR_DIV_MANTISSA_MASK (0xFFF << 4)
/* DIV_Fraction[3:0]: fraction of USARTDIV */
#define USART_BRR_DIV_FRACTION_MASK 0xF
/* --- USART_CR1 values ---------------------------------------------------- */
/* UE: USART enable */
#define USART_CR1_UE (1 << 13)
/* M: Word length */
#define USART_CR1_M (1 << 12)
/* WAKE: Wakeup method */
#define USART_CR1_WAKE (1 << 11)
/* PCE: Parity control enable */
#define USART_CR1_PCE (1 << 10)
/* PS: Parity selection */
#define USART_CR1_PS (1 << 9)
/* PEIE: PE interrupt enable */
#define USART_CR1_PEIE (1 << 8)
/* TXEIE: TXE interrupt enable */
#define USART_CR1_TXEIE (1 << 7)
/* TCIE: Transmission complete interrupt enable */
#define USART_CR1_TCIE (1 << 6)
/* RXNEIE: RXNE interrupt enable */
#define USART_CR1_RXNEIE (1 << 5)
/* IDLEIE: IDLE interrupt enable */
#define USART_CR1_IDLEIE (1 << 4)
/* TE: Transmitter enable */
#define USART_CR1_TE (1 << 3)
/* RE: Receiver enable */
#define USART_CR1_RE (1 << 2)
/* RWU: Receiver wakeup */
#define USART_CR1_RWU (1 << 1)
/* SBK: Send break */
#define USART_CR1_SBK (1 << 0)
/* --- USART_CR2 values ---------------------------------------------------- */
/* LINEN: LIN mode enable */
#define USART_CR2_LINEN (1 << 14)
/* STOP[13:12]: STOP bits */
#define USART_CR2_STOPBITS_1 (0x00 << 12) /* 1 stop bit */
#define USART_CR2_STOPBITS_0_5 (0x01 << 12) /* 0.5 stop bits */
#define USART_CR2_STOPBITS_2 (0x02 << 12) /* 2 stop bits */
#define USART_CR2_STOPBITS_1_5 (0x03 << 12) /* 1.5 stop bits */
#define USART_CR2_STOPBITS_MASK (0x03 << 12)
#define USART_CR2_STOPBITS_SHIFT 12
/* CLKEN: Clock enable */
#define USART_CR2_CLKEN (1 << 11)
/* CPOL: Clock polarity */
#define USART_CR2_CPOL (1 << 10)
/* CPHA: Clock phase */
#define USART_CR2_CPHA (1 << 9)
/* LBCL: Last bit clock pulse */
#define USART_CR2_LBCL (1 << 8)
/* LBDIE: LIN break detection interrupt enable */
#define USART_CR2_LBDIE (1 << 6)
/* LBDL: LIN break detection length */
#define USART_CR2_LBDL (1 << 5)
/* ADD[3:0]: Address of the usart node */
#define USART_CR2_ADD_MASK 0xF
/* --- USART_CR3 values ---------------------------------------------------- */
/* CTSIE: CTS interrupt enable */
/* Note: N/A on UART4 & UART5 */
#define USART_CR3_CTSIE (1 << 10)
/* CTSE: CTS enable */
/* Note: N/A on UART4 & UART5 */
#define USART_CR3_CTSE (1 << 9)
/* RTSE: RTS enable */
/* Note: N/A on UART4 & UART5 */
#define USART_CR3_RTSE (1 << 8)
/* DMAT: DMA enable transmitter */
/* Note: N/A on UART5 */
#define USART_CR3_DMAT (1 << 7)
/* DMAR: DMA enable receiver */
/* Note: N/A on UART5 */
#define USART_CR3_DMAR (1 << 6)
/* SCEN: Smartcard mode enable */
/* Note: N/A on UART4 & UART5 */
#define USART_CR3_SCEN (1 << 5)
/* NACK: Smartcard NACK enable */
/* Note: N/A on UART4 & UART5 */
#define USART_CR3_NACK (1 << 4)
/* HDSEL: Half-duplex selection */
#define USART_CR3_HDSEL (1 << 3)
/* IRLP: IrDA low-power */
#define USART_CR3_IRLP (1 << 2)
/* IREN: IrDA mode enable */
#define USART_CR3_IREN (1 << 1)
/* EIE: Error interrupt enable */
#define USART_CR3_EIE (1 << 0)
/* --- USART_GTPR values --------------------------------------------------- */
/* GT[7:0]: Guard time value */
/* Note: N/A on UART4 & UART5 */
#define USART_GTPR_GT_MASK (0xFF << 8)
/* PSC[7:0]: Prescaler value */
/* Note: N/A on UART4/5 */
#define USART_GTPR_PSC_MASK 0xFF
/* TODO */ /* Note to Uwe: what needs to be done here? */
#endif
/** @cond */
#else
#warning "usart_common_all.h should not be included directly, only via usart.h"
#endif
/** @endcond */
/**@}*/

Двоичные данные
FourQ_ARM_side_channel/libopencm3/lib/libopencm3_stm32f4.a Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -0,0 +1,78 @@
#### Makefile for compilation using GNU GCC or clang on ARM-based processors without using NEON ####
OPT=-O3 # Optimization option by default
CC=gcc
ifeq "$(CC)" "gcc"
COMPILER=gcc
else ifeq "$(CC)" "clang"
COMPILER=clang
endif
ADDITIONAL_SETTINGS=-fwrapv -fomit-frame-pointer -funroll-loops
ifeq "$(EXTENDED_SET)" "FALSE"
ADDITIONAL_SETTINGS=
endif
INLINING_SETTINGS=
ifeq "$(CC)" "gcc"
INLINING_SETTINGS=-finline-functions -finline-limit=100
endif
CFLAGS=-c $(OPT) $(ADDITIONAL_SETTINGS) -D _ARM_ -D __LINUX__ $(INLINING_SETTINGS)
LDFLAGS=
OBJECTS=eccp2.o fp2_1271_arm.o crypto_util.o schnorrq.o kex.o sha512.o random.o
OBJECTS_FP_TEST=$(OBJECTS) fp_tests.o test_extras.o
OBJECTS_ECC_TEST=ecc_tests.o test_extras.o $(OBJECTS)
OBJECTS_CRYPTO_TEST=crypto_tests.o $(OBJECTS) test_extras.o
OBJECTS_ALL=$(OBJECTS) $(OBJECTS_FP_TEST) $(OBJECTS_ECC_TEST) $(OBJECTS_CRYPTO_TEST)
all: crypto_test ecc_test fp_test
crypto_test: $(OBJECTS_CRYPTO_TEST)
$(CC) -o crypto_test $(OBJECTS_CRYPTO_TEST) -lrt
ecc_test: $(OBJECTS_ECC_TEST)
$(CC) -o ecc_test $(OBJECTS_ECC_TEST) -lrt
fp_test: $(OBJECTS_FP_TEST)
$(CC) -o fp_test $(OBJECTS_FP_TEST) -lrt
eccp2.o: eccp2.c FourQ_internal.h ARM/fp_arm.h
$(CC) $(CFLAGS) eccp2.c
fp2_1271_arm.o: ARM/fp2_1271_arm.S
$(CC) $(CFLAGS) ARM/fp2_1271_arm.S
schnorrq.o: schnorrq.c
$(CC) $(CFLAGS) schnorrq.c
kex.o: kex.c
$(CC) $(CFLAGS) kex.c
crypto_util.o: crypto_util.c
$(CC) $(CFLAGS) crypto_util.c
sha512.o: ../sha512/sha512.c
$(CC) $(CFLAGS) ../sha512/sha512.c
random.o: ../random/random.c
$(CC) $(CFLAGS) ../random/random.c
test_extras.o: tests/test_extras.c
$(CC) $(CFLAGS) tests/test_extras.c
crypto_tests.o: tests/crypto_tests.c
$(CC) $(CFLAGS) tests/crypto_tests.c
ecc_tests.o: tests/ecc_tests.c
$(CC) $(CFLAGS) tests/ecc_tests.c
fp_tests.o: tests/fp_tests.c FourQ_internal.h
$(CC) $(CFLAGS) tests/fp_tests.c
.PHONY: clean
clean:
rm -f crypto_test ecc_test fp_test fp2_1271_arm.o $(OBJECTS_ALL)

Просмотреть файл

@ -0,0 +1,62 @@
#### Makefile for compilation using GNU GCC on ARM-based Cortex-M4 microcontroller ####
OPT=-Ofast # Optimization option by default
INLINING_SETTINGS=-finline-functions -finline-limit=100
LDSCRIPT = stm32f407x6.ld
CC=gcc
PREFIX = arm-none-eabi
ARMCC = $(PREFIX)-$(CC)
ARCH_FLAGS = -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -MD -DSTM32F4
CFLAGS = -c $(OPT) $(ADDITIONAL_SETTINGS) -D _ARM_ -D __LINUX__ $(INLINING_SETTINGS) -I./libopencm3/include -fno-common
LDFLAGS += --static -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group -T$(LDSCRIPT) -nostartfiles -Wl,--gc-sections $(ARCH_FLAGS)
OBJECTS=eccp2.o fp2_1271_arm_Cortex-M4.o crypto_util.o schnorrq.o kex.o sha512.o test_extras.o random_Cortex-M4.o stm32f4_wrapper.o
all: lib tests_Cortex-M4/crypto_tests.bin tests_Cortex-M4/ecc_tests.bin tests_Cortex-M4/fp_tests.bin
lib: $(OBJECTS)
$(PREFIX)-ar cr tests_Cortex-M4/libfourq.a $(OBJECTS)
tests_Cortex-M4/crypto_tests.bin: tests_Cortex-M4/crypto_tests.elf
$(PREFIX)-objcopy -Obinary tests_Cortex-M4/crypto_tests.elf tests_Cortex-M4/crypto_tests.bin
tests_Cortex-M4/ecc_tests.bin: tests_Cortex-M4/ecc_tests.elf
$(PREFIX)-objcopy -Obinary tests_Cortex-M4/ecc_tests.elf tests_Cortex-M4/ecc_tests.bin
tests_Cortex-M4/fp_tests.bin: tests_Cortex-M4/fp_tests.elf
$(PREFIX)-objcopy -Obinary tests_Cortex-M4/fp_tests.elf tests_Cortex-M4/fp_tests.bin
tests_Cortex-M4/crypto_tests.elf: crypto_tests.o $(LDSCRIPT) tests_Cortex-M4/libfourq.a
$(ARMCC) -o tests_Cortex-M4/crypto_tests.elf crypto_tests.o tests_Cortex-M4/libfourq.a $(LDFLAGS) libopencm3/lib/libopencm3_stm32f4.a
tests_Cortex-M4/ecc_tests.elf: ecc_tests.o $(LDSCRIPT) tests_Cortex-M4/libfourq.a
$(ARMCC) -o tests_Cortex-M4/ecc_tests.elf ecc_tests.o tests_Cortex-M4/libfourq.a $(LDFLAGS) libopencm3/lib/libopencm3_stm32f4.a
tests_Cortex-M4/fp_tests.elf: fp_tests.o $(LDSCRIPT) tests_Cortex-M4/libfourq.a
$(ARMCC) -o tests_Cortex-M4/fp_tests.elf fp_tests.o tests_Cortex-M4/libfourq.a $(LDFLAGS) libopencm3/lib/libopencm3_stm32f4.a
%.o: %.c
$(ARMCC) $(CFLAGS) $(ARCH_FLAGS) -o $@ -c $<
%.o: tests_Cortex-M4/%.c
$(ARMCC) $(CFLAGS) $(ARCH_FLAGS) -o $@ -c $<
%.o: random/%.c
$(ARMCC) $(CFLAGS) $(ARCH_FLAGS) -o $@ -c $<
%.o: ../sha512/%.c
$(ARMCC) $(CFLAGS) $(ARCH_FLAGS) -o $@ -c $<
%.o: ARM/%.S
$(ARMCC) $(CFLAGS) $(ARCH_FLAGS) -o $@ -c $<
stm32f4_wrapper.o: stm32f4_wrapper.c
$(ARMCC) $(CFLAGS) $(ARCH_FLAGS) -Wno-overflow -o $@ -c $<
.PHONY: clean
clean:
rm -f *.d *.o tests_Cortex-M4/*.o tests_Cortex-M4/*.d tests_Cortex-M4/*.a tests_Cortex-M4/*.bin tests_Cortex-M4/*.elf

Просмотреть файл

@ -0,0 +1,21 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: pseudorandom generation functions
************************************************************************************/
#include "../FourQ_internal.h"
#include "../stm32f4_wrapper.h"
ECCRYPTO_STATUS random_bytes(unsigned char* random_array, unsigned int nbytes)
{ // Generation of "nbytes" of random bytes
if ((nbytes & 0x03) != 0) return ECCRYPTO_ERROR_INVALID_PARAMETER;
rng_setup();
random_int((uint32_t*)random_array, nbytes/4);
return ECCRYPTO_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,223 @@
/**********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: digital signature SchnorrQ
*
* See "SchnorrQ: Schnorr signatures on FourQ" by Craig Costello and Patrick Longa,
* MSR Technical Report, 2016. Available at:
* https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/SchnorrQ.pdf.
***********************************************************************************/
#include "FourQ_internal.h"
#include "FourQ_params.h"
#include "../random/random.h"
#include "../sha512/sha512.h"
#include <malloc.h>
#include <string.h>
ECCRYPTO_STATUS SchnorrQ_KeyGeneration_SCA_secure(const unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint)
{ // SchnorrQ public key generation
// It produces a blinding point BlindingPoint and a public key PublicKey, which is the encoding of P = s*G, where G is the generator and
// s is the output of hashing SecretKey and taking the least significant 32 bytes of the result.
// Input: 32-byte SecretKey
// Output: 32-byte PublicKey and 64-byte BlindingPoint
point_t G, R;
point_extedwards_t S;
unsigned char k[64], SecretBlinding[32];
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretBlinding, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
// Set up an initial "weak" blinding point R
fp2copy1271((felm_t*)&GENERATOR_x[0], G->x);
fp2copy1271((felm_t*)&GENERATOR_y[0], G->y);
point_setup(G, S);
eccdouble(S);
eccnorm(S, R);
// Computing an initial blinding point. This computation itself is not protected with a secure point blinding
Status = ecc_mul_SCA_secure(G, R, (digit_t*)SecretBlinding, (point_affine*)BlindingPoint, false);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
if (CryptoHashFunction(SecretKey, 32, k) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
Status = ecc_mul_SCA_secure(G, (point_affine*)BlindingPoint, (digit_t*)k, R, false); // Compute public key
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
encode(R, PublicKey); // Encode public key
// Cleanup
clear_words((unsigned int*)SecretBlinding, 256/(sizeof(unsigned int)*8));
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretBlinding, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)BlindingPoint, 512/(sizeof(unsigned int)*8));
clear_words((unsigned int*)k, 512/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 256/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS SchnorrQ_FullKeyGeneration_SCA_secure(unsigned char* SecretKey, unsigned char* PublicKey, unsigned char* BlindingPoint)
{ // SchnorrQ keypair generation
// It produces a blinding point BlindingPoint, a private key SecretKey and computes the public key PublicKey, which is the encoding of P = s*G,
// where G is the generator and s is the output of hashing SecretKey and taking the least significant 32 bytes of the result.
// Outputs: 32-byte SecretKey, 32-byte PublicKey and 64-byte BlindingPoint
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
Status = RandomBytesFunction(SecretKey, 32);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
Status = SchnorrQ_KeyGeneration_SCA_secure(SecretKey, PublicKey, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
return ECCRYPTO_SUCCESS;
cleanup:
clear_words((unsigned int*)SecretKey, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)PublicKey, 256/(sizeof(unsigned int)*8));
clear_words((unsigned int*)BlindingPoint, 512/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS SchnorrQ_Sign_SCA_secure(const unsigned char* SecretKey, const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, unsigned char* Signature, unsigned char* BlindingPoint)
{ // SchnorrQ signature generation
// It produces the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte SecretKey, 32-byte PublicKey, Message of size SizeMessage in bytes, and 64-byte BlindingPoint
// Output: 64-byte Signature and updated BlindingPoint
point_t G, R;
unsigned char k[64], r[64], h[64], *temp = NULL;
digit_t* H = (digit_t*)h;
digit_t* S = (digit_t*)(Signature+32);
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
if (CryptoHashFunction(SecretKey, 32, k) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
temp = (unsigned char*)calloc(1, SizeMessage+64);
if (temp == NULL) {
Status = ECCRYPTO_ERROR_NO_MEMORY;
goto cleanup;
}
memmove(temp+32, k+32, 32);
memmove(temp+64, Message, SizeMessage);
if (CryptoHashFunction(temp+32, SizeMessage+32, r) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
fp2copy1271((felm_t*)&GENERATOR_x[0], G->x);
fp2copy1271((felm_t*)&GENERATOR_y[0], G->y);
Status = ecc_mul_SCA_secure(G, (point_affine*)BlindingPoint, (digit_t*)r, R, false); // Also verifies that BlindingPoint is a point on the curve. If not, it fails
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
encode(R, Signature); // Encode lowest 32 bytes of signature
memmove(temp, Signature, 32);
memmove(temp+32, PublicKey, 32);
if (CryptoHashFunction(temp, SizeMessage+64, h) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
modulo_order((digit_t*)r, (digit_t*)r);
modulo_order(H, H);
to_Montgomery((digit_t*)k, S); // Converting to Montgomery representation
to_Montgomery(H, H); // Converting to Montgomery representation
Montgomery_multiply_mod_order(S, H, S);
from_Montgomery(S, S); // Converting back to standard representation
subtract_mod_order((digit_t*)r, S, S);
Status = ECCRYPTO_SUCCESS;
cleanup:
if (temp != NULL)
free(temp);
clear_words((unsigned int*)k, 512/(sizeof(unsigned int)*8));
clear_words((unsigned int*)r, 512/(sizeof(unsigned int)*8));
return Status;
}
ECCRYPTO_STATUS SchnorrQ_Verify(const unsigned char* PublicKey, const unsigned char* Message, const unsigned int SizeMessage, const unsigned char* Signature, unsigned int* valid)
{ // SchnorrQ signature verification
// It verifies the signature Signature of a message Message of size SizeMessage in bytes
// Inputs: 32-byte PublicKey, 64-byte Signature, and Message of size SizeMessage in bytes
// Output: true (valid signature) or false (invalid signature)
point_t A;
unsigned char *temp, h[64];
unsigned int i;
ECCRYPTO_STATUS Status = ECCRYPTO_ERROR_UNKNOWN;
*valid = false;
temp = (unsigned char*)calloc(1, SizeMessage+64);
if (temp == NULL) {
Status = ECCRYPTO_ERROR_NO_MEMORY;
goto cleanup;
}
if (((PublicKey[15] & 0x80) != 0) || ((Signature[15] & 0x80) != 0) || (Signature[63] != 0) || ((Signature[62] & 0xC0) != 0)) { // Are bit128(PublicKey) = bit128(Signature) = 0 and Signature+32 < 2^246?
Status = ECCRYPTO_ERROR_INVALID_PARAMETER;
goto cleanup;
}
Status = decode(PublicKey, A); // Also verifies that A is on the curve. If it is not, it fails
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
memmove(temp, Signature, 32);
memmove(temp+32, PublicKey, 32);
memmove(temp+64, Message, SizeMessage);
if (CryptoHashFunction(temp, SizeMessage+64, h) != 0) {
Status = ECCRYPTO_ERROR;
goto cleanup;
}
Status = ecc_mul_double((digit_t*)(Signature+32), A, (digit_t*)h, A);
if (Status != ECCRYPTO_SUCCESS) {
goto cleanup;
}
encode(A, (unsigned char*)A);
for (i = 0; i < NWORDS_ORDER; i++) {
if (((digit_t*)A)[i] != ((digit_t*)Signature)[i]) {
goto cleanup;
}
}
*valid = true;
cleanup:
if (temp != NULL)
free(temp);
return Status;
}

Просмотреть файл

@ -0,0 +1,114 @@
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
* Copyright (C) 2011 Stephen Caudle <scaudle@doceme.com>
* Copyright (C) 2013 Sergey Krukowski <softsr@yahoo.de>
* Copyright (C) 2015 Joost Rijneveld <joost@joostrijneveld.nl>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/* Linker script for the STM32F407VGT6 chip (1024K flash, 192K RAM). */
/* Define memory regions. */
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 1024K
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
ccm (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
}
/* Enforce emmition of the vector table. */
EXTERN (vector_table)
/* Define the entry point of the output file. */
ENTRY(reset_handler)
/* Define sections. */
SECTIONS
{
.text : {
*(.vectors) /* Vector table */
*(.text*) /* Program code */
. = ALIGN(4);
*(.rodata*) /* Read-only data */
. = ALIGN(4);
} >rom
/* C++ Static constructors/destructors, also used for __attribute__
* ((constructor)) and the likes */
.preinit_array : {
. = ALIGN(4);
__preinit_array_start = .;
KEEP (*(.preinit_array))
__preinit_array_end = .;
} >rom
.init_array : {
. = ALIGN(4);
__init_array_start = .;
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array))
__init_array_end = .;
} >rom
.fini_array : {
. = ALIGN(4);
__fini_array_start = .;
KEEP (*(.fini_array))
KEEP (*(SORT(.fini_array.*)))
__fini_array_end = .;
} >rom
/*
* Another section used by C++ stuff, appears when using newlib with
* 64bit (long long) printf support
*/
.ARM.extab : {
*(.ARM.extab*)
} >rom
.ARM.exidx : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >rom
. = ALIGN(4);
_etext = .;
.data : {
_data = .;
*(.data*) /* Read-write initialized data */
. = ALIGN(4);
_edata = .;
} >ram AT >rom
_data_loadaddr = LOADADDR(.data);
.bss : {
*(.bss*) /* Read-write zero initialized data */
*(COMMON)
. = ALIGN(4);
_ebss = .;
} >ram
/*
* The .eh_frame section appears to be used for C++ exception handling.
* You may need to fix this if you're using C++.
*/
/DISCARD/ : { *(.eh_frame) }
. = ALIGN(4);
end = .;
}
PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram));

Просмотреть файл

@ -0,0 +1,80 @@
#include <stdint.h>
#include <rcc.h>
#include <gpio.h>
#include <usart.h>
#include <nvic.h>
#include <rng.h>
#include "stm32f4_wrapper.h"
void clock_setup(void)
{
rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_48MHZ]);
rcc_periph_clock_enable(RCC_GPIOD);
rcc_periph_clock_enable(RCC_GPIOA);
rcc_periph_clock_enable(RCC_USART2);
rcc_periph_clock_enable(RCC_DMA1);
rcc_periph_clock_enable(RCC_RNG);
}
void gpio_setup(void)
{
gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO2 | GPIO3);
gpio_set_af(GPIOA, GPIO_AF7, GPIO2 | GPIO3);
gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT,GPIO_PUPD_NONE, GPIO12);
}
void usart_setup(int baud)
{
usart_set_baudrate(USART2, baud);
usart_set_databits(USART2, 8);
usart_set_stopbits(USART2, USART_STOPBITS_1);
usart_set_mode(USART2, USART_MODE_TX_RX);
usart_set_parity(USART2, USART_PARITY_NONE);
usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE);
usart_enable(USART2);
gpio_set(GPIOD, GPIO12);
}
void rng_setup(void)
{
RNG_CR |= RNG_CR_IE;
RNG_CR |= RNG_CR_RNGEN;
}
void send_USART_str(const unsigned char* in)
{
gpio_toggle(GPIOD, GPIO12);
int i;
for(i = 0; in[i] != 0; i++) {
usart_send_blocking(USART2, in[i]);
}
usart_send_blocking(USART2, '\r');
usart_send_blocking(USART2, '\n');
}
void signal_host(void)
{
usart_send_blocking(USART2, (char)4);
}
void random_int(uint32_t* urnd, int n)
{
unsigned int last_value=0;
unsigned int new_value=0;
int i;
unsigned int error_bits = 0;
for(i = 0; i < n; i++)
{
error_bits = RNG_SR_SEIS | RNG_SR_CEIS;
while (new_value == last_value) {
if (((RNG_SR & error_bits) == 0) && ((RNG_SR & RNG_SR_DRDY) == 1)) {
new_value = RNG_DR;
}
}
last_value = new_value;
urnd[i] = new_value;
}
}

Просмотреть файл

@ -0,0 +1,14 @@
#ifndef STM32F4_WRAPPER_H
#define STM32F4_WRAPPER_H
void clock_setup(void);
void gpio_setup(void);
void usart_setup(int baud);
void rng_setup(void);
void signal_host(void);
void send_USART_str(const unsigned char* in);
void random_int(uint32_t*,int);
#endif

Просмотреть файл

@ -0,0 +1,78 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: table lookup functions
************************************************************************************/
#ifndef __TABLE_LOOKUP_H__
#define __TABLE_LOOKUP_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
#include "FourQ_internal.h"
void table_lookup_1x16(point_extedwards_t* table, point_extedwards_t P, unsigned int digit)
{ // Constant-time table lookup using "interleaved" masking to extract a point represented as (X,Y,Z,T) in extended twisted Edwards coordinates
// Inputs: digit and table containing 16 points
// Output: P = table[digit]
point_extedwards_t point;
unsigned int i, j;
digit_t mask, temp, value = 0xAAAAAAAA;
f2elm_t tt;
ecccopy(table[0], point); // point = table[0]
for (i = 1; i < 16; i++)
{
digit--;
// While digit>=0 mask = 0x55...5 else mask = 0xAA...A
mask = ((digit_t)digit >> (RADIX-1)) - 1;
mask = (mask & ~value) | (~mask & value);
fp2copy1271(table[i]->x, tt); // tt = table[i]
for (j = 0; j < NWORDS_FIELD; j++) {
temp = point->x[0][j] ^ tt[0][j];
point->x[0][j] = ((mask & temp) ^ point->x[0][j]) ^ (value & temp);
temp = point->x[1][j] ^ tt[1][j];
point->x[1][j] = ((mask & temp) ^ point->x[1][j]) ^ (value & temp);
}
fp2copy1271(table[i]->y, tt);
for (j = 0; j < NWORDS_FIELD; j++) {
temp = point->y[0][j] ^ tt[0][j];
point->y[0][j] = ((mask & temp) ^ point->y[0][j]) ^ (value & temp);
temp = point->y[1][j] ^ tt[1][j];
point->y[1][j] = ((mask & temp) ^ point->y[1][j]) ^ (value & temp);
}
fp2copy1271(table[i]->z, tt);
for (j = 0; j < NWORDS_FIELD; j++) {
temp = point->z[0][j] ^ tt[0][j];
point->z[0][j] = ((mask & temp) ^ point->z[0][j]) ^ (value & temp);
temp = point->z[1][j] ^ tt[1][j];
point->z[1][j] = ((mask & temp) ^ point->z[1][j]) ^ (value & temp);
}
fp2copy1271(table[i]->t, tt);
for (j = 0; j < NWORDS_FIELD; j++) {
temp = point->t[0][j] ^ tt[0][j];
point->t[0][j] = ((mask & temp) ^ point->t[0][j]) ^ (value & temp);
temp = point->t[1][j] ^ tt[1][j];
point->t[1][j] = ((mask & temp) ^ point->t[1][j]) ^ (value & temp);
}
}
ecccopy(point, P);
}
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,368 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: testing code for cryptographic functions based on FourQ
************************************************************************************/
#include "../FourQ_api.h"
#include "../FourQ_params.h"
#include "test_extras.h"
#include <stdio.h>
// Benchmark and test parameters
#if defined(GENERIC_IMPLEMENTATION)
#define BENCH_LOOPS 100 // Number of iterations per bench
#define TEST_LOOPS 100 // Number of iterations per test
#else
#define BENCH_LOOPS 10000
#define TEST_LOOPS 1000
#endif
ECCRYPTO_STATUS SchnorrQ_test()
{ // Test the SchnorrQ digital signature scheme
int n, passed;
void *msg = NULL;
unsigned int len, valid = false;
unsigned char SecretKey[32], PublicKey[32], Signature[64], BlindingPoint[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing the SchnorrQ signature scheme. Includes side-channel countermeasures: \n\n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Signature key generation
Status = SchnorrQ_FullKeyGeneration_SCA_secure(SecretKey, PublicKey, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Signature computation
msg = "a";
len = 1;
Status = SchnorrQ_Sign_SCA_secure(SecretKey, PublicKey, msg, len, Signature, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Valid signature test
Status = SchnorrQ_Verify(PublicKey, msg, len, Signature, &valid);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
if (valid == false) {
passed = 0;
break;
}
// Invalid signature test (flipping one bit of the message)
msg = "b";
Status = SchnorrQ_Verify(PublicKey, msg, len, Signature, &valid);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
if (valid == true) {
passed = 0;
break;
}
}
if (passed==1) printf(" Signature tests.................................................................. PASSED");
else { printf(" Signature tests... FAILED"); printf("\n"); Status = ECCRYPTO_ERROR_SIGNATURE_VERIFICATION; }
printf("\n");
return Status;
}
ECCRYPTO_STATUS SchnorrQ_run()
{ // Benchmark the SchnorrQ digital signature scheme
int n;
unsigned long long nsec, nsec1, nsec2;
void *msg = NULL;
unsigned int len = 0, valid = false;
unsigned char SecretKey[32], PublicKey[32], Signature[64], BlindingPoint[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking the SchnorrQ signature scheme. Includes side-channel countermeasures: \n\n");
nsec = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
Status = SchnorrQ_FullKeyGeneration_SCA_secure(SecretKey, PublicKey, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" SchnorrQ's key generation runs in ............................................... %8lld nsec", nsec/BENCH_LOOPS);
printf("\n");
nsec = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
Status = SchnorrQ_Sign_SCA_secure(SecretKey, PublicKey, msg, len, Signature, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" SchnorrQ's signing runs in ...................................................... %8lld nsec", nsec/BENCH_LOOPS);
printf("\n");
nsec = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
Status = SchnorrQ_Verify(PublicKey, msg, len, Signature, &valid);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" SchnorrQ's verification runs in ................................................. %8lld nsec", nsec/BENCH_LOOPS);
printf("\n");
return Status;
}
ECCRYPTO_STATUS compressedkex_test()
{ // Test ECDH key exchange based on FourQ
int n, passed;
unsigned int i;
unsigned char SecretKeyA[32], PublicKeyA[32], BlindingPointA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[32], BlindingPointB[64], SecretAgreementB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing DH key exchange using compressed, 32-byte public keys. Includes side-channel countermeasures: \n\n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Alice's keypair generation
Status = CompressedKeyGeneration_SCA_secure(SecretKeyA, PublicKeyA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's keypair generation
Status = CompressedKeyGeneration_SCA_secure(SecretKeyB, PublicKeyB, BlindingPointB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Alice's shared secret computation
Status = CompressedSecretAgreement_SCA_secure(SecretKeyA, PublicKeyB, SecretAgreementA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's shared secret computation
Status = CompressedSecretAgreement_SCA_secure(SecretKeyB, PublicKeyA, SecretAgreementB, BlindingPointB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
for (i = 0; i < 32; i++) {
if (SecretAgreementA[i] != SecretAgreementB[i]) {
passed = 0;
break;
}
}
}
if (passed==1) printf(" DH key exchange tests............................................................ PASSED");
else { printf(" DH key exchange tests... FAILED"); printf("\n"); Status = ECCRYPTO_ERROR_SHARED_KEY; }
printf("\n");
return Status;
}
ECCRYPTO_STATUS compressedkex_run()
{ // Benchmark ECDH key exchange based on FourQ
int n;
unsigned long long nsec, nsec1, nsec2;
unsigned char SecretKeyA[32], PublicKeyA[32], BlindingPointA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[32], BlindingPointB[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking DH key exchange using compressed, 32-byte public keys. Includes side-channel countermeasures: \n\n");
nsec = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
Status = CompressedKeyGeneration_SCA_secure(SecretKeyA, PublicKeyA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
nsec2 = cpu_nseconds();
nsec = nsec + (nsec2 - nsec1);
}
printf(" Keypair generation runs in ...................................................... %8lld nsec", nsec / BENCH_LOOPS);
printf("\n");
Status = CompressedKeyGeneration_SCA_secure(SecretKeyB, PublicKeyB, BlindingPointB);
nsec = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
Status = CompressedSecretAgreement_SCA_secure(SecretKeyA, PublicKeyB, SecretAgreementA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
nsec2 = cpu_nseconds();
nsec = nsec + (nsec2 - nsec1);
}
printf(" Secret agreement runs in ........................................................ %8lld nsec", nsec / BENCH_LOOPS);
printf("\n");
return Status;
}
ECCRYPTO_STATUS kex_test()
{ // Test ECDH key exchange based on FourQ
int n, passed;
unsigned int i;
unsigned char SecretKeyA[32], PublicKeyA[64], BlindingPointA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[64], BlindingPointB[64], SecretAgreementB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing DH key exchange using uncompressed, 64-byte public keys. Includes side-channel countermeasures: \n\n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Alice's keypair generation
Status = KeyGeneration_SCA_secure(SecretKeyA, PublicKeyA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's keypair generation
Status = KeyGeneration_SCA_secure(SecretKeyB, PublicKeyB, BlindingPointB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Alice's shared secret computation
Status = SecretAgreement_SCA_secure(SecretKeyA, PublicKeyB, SecretAgreementA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's shared secret computation
Status = SecretAgreement_SCA_secure(SecretKeyB, PublicKeyA, SecretAgreementB, BlindingPointB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
for (i = 0; i < 32; i++) {
if (SecretAgreementA[i] != SecretAgreementB[i]) {
passed = 0;
break;
}
}
}
if (passed==1) printf(" DH key exchange tests............................................................ PASSED");
else { printf(" DH key exchange tests... FAILED"); printf("\n"); Status = ECCRYPTO_ERROR_SHARED_KEY; }
printf("\n");
return Status;
}
ECCRYPTO_STATUS kex_run()
{ // Benchmark ECDH key exchange based on FourQ
int n;
unsigned long long nsec, nsec1, nsec2;
unsigned char SecretKeyA[32], PublicKeyA[64], BlindingPointA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[64], BlindingPointB[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking DH key exchange using uncompressed, 64-byte public keys. Includes side-channel countermeasures: \n\n");
nsec = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
Status = KeyGeneration_SCA_secure(SecretKeyA, PublicKeyA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
nsec2 = cpu_nseconds();
nsec = nsec + (nsec2 - nsec1);
}
printf(" Keypair generation runs in ...................................................... %8lld nsec", nsec / BENCH_LOOPS);
printf("\n");
Status = KeyGeneration_SCA_secure(SecretKeyB, PublicKeyB, BlindingPointB);
nsec = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
Status = SecretAgreement_SCA_secure(SecretKeyA, PublicKeyB, SecretAgreementA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
nsec2 = cpu_nseconds();
nsec = nsec + (nsec2 - nsec1);
}
printf(" Secret agreement runs in ........................................................ %8lld nsec", nsec / BENCH_LOOPS);
printf("\n");
return Status;
}
int main()
{
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
Status = SchnorrQ_test(); // Test SchnorrQ signature scheme
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = SchnorrQ_run(); // Benchmark SchnorrQ signature scheme
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = compressedkex_test(); // Test Diffie-Hellman key exchange using compressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = compressedkex_run(); // Benchmark Diffie-Hellman key exchange using compressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = kex_test(); // Test Diffie-Hellman key exchange using uncompressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
Status = kex_run(); // Benchmark Diffie-Hellman key exchange using uncompressed public keys
if (Status != ECCRYPTO_SUCCESS) {
printf("\n\n Error detected: %s \n\n", FourQ_get_error_message(Status));
return false;
}
return true;
}

Просмотреть файл

@ -0,0 +1,456 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: testing code for FourQ's curve arithmetic
************************************************************************************/
#include "../FourQ_api.h"
#include "../FourQ_params.h"
#include "../FourQ_tables.h"
#include "test_extras.h"
#include <stdio.h>
// Benchmark and test parameters
#define BENCH_LOOPS 100 // Number of iterations per bench
#define SHORT_BENCH_LOOPS 10 // Number of iterations per bench (for expensive operations)
#define TEST_LOOPS 1000 // Number of iterations per test
bool ecc_test()
{
bool clear_cofactor, OK = true;
unsigned int n;
int passed;
point_t A, R;
point_extedwards_t P, Q;
f2elm_t t1;
uint64_t scalar[4], res_x[4], res_y[4];
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing FourQ's curve arithmetic: \n\n");
// Point doubling
passed = 1;
eccset(A);
point_setup(A, P);
for (n=0; n<TEST_LOOPS; n++)
{
eccdouble(P); // 2*P
}
eccnorm(P, A);
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0xC9099C54855859D6; res_x[1] = 0x2C3FD8822C82270F; res_x[2] = 0xA7B3F6E2043E8E68; res_x[3] = 0x4DA5B9E83AA7A1B2;
res_y[0] = 0x3EE089F0EB49AA14; res_y[1] = 0x2001EB3A57688396; res_y[2] = 0x1FEE5617A7E954CD; res_y[3] = 0x0FFDB0D761421F50;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Point doubling tests .................................................................... PASSED");
else { printf(" Point doubling tests ... FAILED"); printf("\n"); return false; }
printf("\n");
// Point addition
eccset(A);
point_setup(A, P);
for (n=0; n<TEST_LOOPS; n++)
{
ecccopy(P, Q);
eccadd(P, Q, P); // 2*P
}
eccnorm(P, A);
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0xC9099C54855859D6; res_x[1] = 0x2C3FD8822C82270F; res_x[2] = 0xA7B3F6E2043E8E68; res_x[3] = 0x4DA5B9E83AA7A1B2;
res_y[0] = 0x3EE089F0EB49AA14; res_y[1] = 0x2001EB3A57688396; res_y[2] = 0x1FEE5617A7E954CD; res_y[3] = 0x0FFDB0D761421F50;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
eccset(A);
point_setup(A, P);
ecccopy(P, Q);
eccdouble(P); // P = 2P
for (n=0; n<TEST_LOOPS; n++)
{
eccadd(P, Q, P); // P = P+Q
}
eccnorm(P, A);
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0x6480B1EF0A151DB0; res_x[1] = 0x3E243958590C4D90; res_x[2] = 0xAA270F644A65D473; res_x[3] = 0x5327AF7D84238CD0;
res_y[0] = 0x5E06003D73C43EB1; res_y[1] = 0x3EF69A49CB7E0237; res_y[2] = 0x4E752648AC2EF0AB; res_y[3] = 0x293EB1E26DD23B4E;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Point addition tests .................................................................... PASSED");
else { printf(" Point addition tests ... FAILED"); printf("\n"); return false; }
printf("\n");
// Psi endomorphism
eccset(A);
point_setup(A, P);
for (n=0; n<TEST_LOOPS; n++)
{
ecc_psi(P); // P = Psi(P)
}
eccnorm(P, A);
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0xD8F3C8C24A2BC7E2; res_x[1] = 0x75AF54EDB41A2B93; res_x[2] = 0x4DE2466701F009A9; res_x[3] = 0x065249F9EDE0C798;
res_y[0] = 0x1C6E119ADD608104; res_y[1] = 0x06DBB85BFFB7C21E; res_y[2] = 0xFD234D6C4CFA3EC1; res_y[3] = 0x060A30903424BF13;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Psi endomorphism tests .................................................................. PASSED");
else { printf(" Psi endomorphism tests ... FAILED"); printf("\n"); return false; }
printf("\n");
// Phi endomorphism
eccset(A);
point_setup(A, P);
for (n=0; n<TEST_LOOPS; n++)
{
ecc_phi(P); // P = Phi(P)
eccnorm(P, A);
point_setup(A, P);
}
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0xD5B5A3061287DB16; res_x[1] = 0x5550AAB9E7A620EE; res_x[2] = 0xEC321E6CF33610FC; res_x[3] = 0x3E61EBB9A1CB0210;
res_y[0] = 0x7E2851D5A8E83FB9; res_y[1] = 0x5474BF8EC55603AE; res_y[2] = 0xA5077613491788D5; res_y[3] = 0x5476093DBF8BF6BF;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Phi endomorphism tests .................................................................. PASSED");
else { printf(" Phi endomorphism tests ... FAILED"); printf("\n"); return false; }
printf("\n");
// Scalar multiplication
eccset(A);
eccset(R);
clear_cofactor = false;
scalar[0] = 0x3AD457AB55456230; scalar[1] = 0x3A8B3C2C6FD86E0C; scalar[2] = 0x7E38F7C9CFBB9166; scalar[3] = 0x0028FD6CBDA458F0;
for (n=0; n<TEST_LOOPS; n++)
{
scalar[1] = scalar[2];
scalar[2] += scalar[0];
ecc_mul_SCA_secure(A, R, (digit_t*)scalar, A, clear_cofactor);
}
res_x[0] = 0xDFD2B477BD494BEF; res_x[1] = 0x257C122BBFC94A1B; res_x[2] = 0x769593547237C459; res_x[3] = 0x469BF80CB5B11F01;
res_y[0] = 0x281C5067996F3344; res_y[1] = 0x0901B3817C0E936C; res_y[2] = 0x4FE8C429915F1245; res_y[3] = 0x570B948EACACE210;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
eccset(A);
eccset(R);
clear_cofactor = true;
scalar[0] = 0x3AD457AB55456230; scalar[1] = 0x3A8B3C2C6FD86E0C; scalar[2] = 0x7E38F7C9CFBB9166; scalar[3] = 0x0028FD6CBDA458F0;
for (n=0; n<TEST_LOOPS; n++)
{
scalar[1] = scalar[2];
scalar[2] += scalar[0];
ecc_mul_SCA_secure(A, R, (digit_t*)scalar, A, clear_cofactor);
}
res_x[0] = 0x85CF54A3BEE3FD23; res_x[1] = 0x7A7EC43976FAAD92; res_x[2] = 0x7697567B785E2327; res_x[3] = 0x4CBDAB448B1539F2;
res_y[0] = 0xE9193B41CDDF94D0; res_y[1] = 0x5AA6C859ECC810D5; res_y[2] = 0xAA876E760AA8B331; res_y[3] = 0x320C53F02230094A;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) printf(" Scalar multiplication tests ............................................................. PASSED");
else { printf(" Scalar multiplication tests ... FAILED"); printf("\n"); return false; }
printf("\n");
{
point_t PP, QQ, RR, UU, TT;
point_extedwards_t AA, BB;
uint64_t k[4], l[4], kk[4];
// Double scalar multiplication
eccset(QQ);
eccset(PP);
eccset(R);
for (n=0; n<TEST_LOOPS; n++)
{
random_scalar_test(kk);
ecc_mul_SCA_secure(QQ, R, (digit_t*)kk, QQ, false);
random_scalar_test(k);
random_scalar_test(l);
ecc_mul_double((digit_t*)k, QQ, (digit_t*)l, RR);
ecc_mul_SCA_secure(PP, R, (digit_t*)k, UU, false);
ecc_mul_SCA_secure(QQ, R, (digit_t*)l, TT, false);
point_setup(UU, AA);
point_setup(TT, BB);
eccadd(BB, AA, BB);
eccnorm(BB, UU);
if (fp2compare64((uint64_t*)UU->x,(uint64_t*)RR->x)!=0 || fp2compare64((uint64_t*)UU->y,(uint64_t*)RR->y)!=0) { passed=0; break; }
}
if (passed==1) printf(" Double scalar multiplication tests ...................................................... PASSED");
else { printf(" Double scalar multiplication tests ... FAILED"); printf("\n"); return false; }
printf("\n");
}
return OK;
}
bool ecc_run()
{
bool OK = true;
unsigned int n, i, digit=1;
unsigned long long nsec, nsec1, nsec2;
point_t A, B, R;
point_extedwards_t P, Q, RR, Table[16];
f2elm_t t1;
uint64_t scalar[4];
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking FourQ's curve arithmetic \n\n");
// Point doubling (twisted Edwards a=-1)
eccset(A);
point_setup(A, P);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
eccdouble(P);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Point doubling runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Point addition (twisted Edwards a=-1)
eccset(A);
point_setup(A, P);
ecccopy(P, Q);
eccdouble(P); // P = 2P
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
eccadd(P, Q, P);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Point addition runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Psi endomorphism
eccset(A);
point_setup(A, P);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
ecc_psi(P);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Psi mapping runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Phi endomorphism
eccset(A);
point_setup(A, P);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
ecc_phi(P);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Phi mapping runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Scalar decomposition
{
uint64_t scalars[4];
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
decompose(scalar, scalars);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Scalar decomposition runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
}
// Scalar recoding
{
unsigned int digits[72];
uint128_t rand_scalars[4];
unsigned char rand_bytes[4] = {1};
random_scalar_test(scalar);
randomize(scalar, rand_bytes, rand_scalars);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
recode(rand_scalars, digits);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Scalar recoding runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
}
// Precomputation
eccset(A);
point_setup(A, P);
ecccopy(P, RR);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 100; i++) {
ecc_precomp(P, RR, Table);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Precomputation runs in ... %8lld nsec", nsec/(BENCH_LOOPS*100));
printf("\n");
// Table lookup
eccset(A);
point_setup(A, P);
ecccopy(P, RR);
ecc_precomp(P, RR, Table);
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
table_lookup_1x16(Table, Q, digit);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Table lookup runs in ... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// Scalar multiplication
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
eccset(A);
eccset(R);
nsec1 = cpu_nseconds();
for (i = 0; i < 100; i++) {
ecc_mul_SCA_secure(A, R, (digit_t*)scalar, B, false);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Scalar multiplication (without clearing cofactor) runs in ...... %8lld nsec", nsec/(SHORT_BENCH_LOOPS*100));
printf("\n");
random_scalar_test(scalar);
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
eccset(A);
eccset(R);
nsec1 = cpu_nseconds();
for (i = 0; i < 100; i++) {
ecc_mul_SCA_secure(A, R, (digit_t*)scalar, B, true);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Scalar multiplication (including clearing cofactor) runs in .... %8lld nsec", nsec/(SHORT_BENCH_LOOPS*100));
printf("\n");
{
point_t PP, QQ, RR;
uint64_t k[4], l[4], kk[4];
// Double scalar multiplication
eccset(QQ);
eccset(PP);
random_scalar_test(kk);
ecc_mul_SCA_secure(QQ, PP, (digit_t*)kk, QQ, false);
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
random_scalar_test(k);
random_scalar_test(l);
nsec1 = cpu_nseconds();
ecc_mul_double((digit_t*)k, QQ, (digit_t*)l, RR);
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" Double scalar mul runs in ... %8lld nsec with wP=%d and wQ=%d", nsec/SHORT_BENCH_LOOPS, WP_DOUBLEBASE, WQ_DOUBLEBASE);
printf("\n");
}
return OK;
}
int main()
{
bool OK = true;
OK = OK && ecc_test(); // Test FourQ's curve functions
OK = OK && ecc_run(); // Benchmark FourQ's curve functions
return OK;
}

Просмотреть файл

@ -0,0 +1,229 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: testing code for FourQ's field arithmetic
************************************************************************************/
#include "../FourQ_internal.h"
#include "test_extras.h"
#include "../../random/random.h"
#include <stdio.h>
// Benchmark and test parameters
#define BENCH_LOOPS 10000 // Number of iterations per bench
#define SHORT_BENCH_LOOPS 1000 // Number of iterations per bench (for expensive operations)
#define TEST_LOOPS 1000 // Number of iterations per test
bool fp2_test()
{ // Tests for the quadratic extension field arithmetic
bool OK = true;
int n, passed;
f2elm_t a, b, c, d, e, f;
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Testing quadratic extension field arithmetic over GF((2^127-1)^2): \n\n");
// GF(p^2) multiplication using p = 2^127-1
passed = 1;
for (n=0; n<TEST_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b); fp2random1271_test(c);
fp2random1271_test(d); fp2random1271_test(e); fp2random1271_test(f);
fp2mul1271(a, b, d); // d = a*b
mod1271(d[0]); mod1271(d[1]);
fp2mul1271(b, a, e); // e = b*a
mod1271(e[0]); mod1271(e[1]);
if (fp2compare64((uint64_t*)d,(uint64_t*)e)!=0) { passed=0; break; }
fp2mul1271(a, b, d); fp2mul1271(d, c, e); // e = (a*b)*c
mod1271(e[0]); mod1271(e[1]);
fp2mul1271(b, c, d); fp2mul1271(d, a, f); // f = a*(b*c)
mod1271(f[0]); mod1271(f[1]);
if (fp2compare64((uint64_t*)e,(uint64_t*)f)!=0) { passed=0; break; }
fp2add1271(b, c, d); fp2mul1271(a, d, e); // e = a*(b+c)
mod1271(e[0]); mod1271(e[1]);
fp2mul1271(a, b, d); fp2mul1271(a, c, f); fp2add1271(d, f, f); // f = a*b+a*c
mod1271(f[0]); mod1271(f[1]);
if (fp2compare64((uint64_t*)e,(uint64_t*)f)!=0) { passed=0; break; }
fp2zero1271(b); b[0][0] = 1;
fp2mul1271(a, b, d); // d = a*1
mod1271(d[0]); mod1271(d[1]);
if (fp2compare64((uint64_t*)a,(uint64_t*)d)!=0) { passed=0; break; }
fp2zero1271(b);
fp2mul1271(a, b, d); // d = a*0
mod1271(d[0]); mod1271(d[1]);
if (fp2compare64((uint64_t*)b,(uint64_t*)d)!=0) { passed=0; break; }
}
if (passed==1) printf(" GF(p^2) multiplication tests .................................................................... PASSED");
else { printf(" GF(p^2) multiplication tests... FAILED"); printf("\n"); return false; }
printf("\n");
// GF(p^2) squaring using p = 2^127-1
passed = 1;
for (n=0; n<TEST_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b); fp2random1271_test(c);
fp2sqr1271(a, b); // b = a^2
fp2mul1271(a, a, c); // c = a*a
if (fp2compare64((uint64_t*)b,(uint64_t*)c)!=0) { passed=0; break; }
fp2zero1271(a);
fp2sqr1271(a, d); // d = 0^2
if (fp2compare64((uint64_t*)a,(uint64_t*)d)!=0) { passed=0; break; }
}
if (passed==1) printf(" GF(p^2) squaring tests........................................................................... PASSED");
else { printf(" GF(p^2) squaring tests... FAILED"); printf("\n"); return false; }
printf("\n");
// GF(p^2) inversion using p = 2^127-1
passed = 1;
for (n=0; n<TEST_LOOPS; n++)
{
fp2random1271_test(a);
fp2zero1271(d); d[0][0] = 1;
fp2copy1271(a, b);
fp2inv1271(a);
fp2mul1271(a, b, c); // c = a*a^-1 = 1
mod1271(c[0]); mod1271(c[1]);
if (fp2compare64((uint64_t*)c,(uint64_t*)d)!=0) { passed=0; break; }
}
if (passed==1) printf(" GF(p^2) inversion tests.......................................................................... PASSED");
else { printf(" GF(p^2) inversion tests... FAILED"); printf("\n"); return false; }
printf("\n");
return OK;
}
bool fp2_run()
{
bool OK = true;
int n, i, j;
unsigned long long nsec, nsec1, nsec2;
f2elm_t a, b, c, d, e, f, rand_f2elmt[73];
printf("\n--------------------------------------------------------------------------------------------------------\n\n");
printf("Benchmarking quadratic extension field arithmetic over GF((2^127-1)^2): \n\n");
// GF(p^2) addition using p = 2^127-1
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b);
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
fp2add1271(a, b, c);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" GF(p^2) addition runs in ............... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// GF(p^2) subtraction using p = 2^127-1
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b);
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
fp2sub1271(a, b, c);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" GF(p^2) subtraction runs in ............ %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// GF(p^2) squaring using p = 2^127-1
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a);
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
fp2sqr1271(a, b);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" GF(p^2) squaring runs in ............... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// GF(p^2) multiplication using p = 2^127-1
nsec = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b); fp2random1271_test(c);
nsec1 = cpu_nseconds();
for (i = 0; i < 1000; i++) {
fp2mul1271(a, b, c);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" GF(p^2) multiplication runs in ......... %8lld nsec", nsec/(BENCH_LOOPS*1000));
printf("\n");
// GF(p^2) inversion using p = 2^127-1
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b); fp2random1271_test(c);
nsec1 = cpu_nseconds();
for (i = 0; i < 100; i++) {
fp2inv1271(a);
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" GF(p^2) inversion runs in .............. %8lld nsec", nsec/(SHORT_BENCH_LOOPS*100));
printf("\n");
// PRNG for scalar multiplication
nsec = 0;
for (n=0; n<SHORT_BENCH_LOOPS; n++)
{
nsec1 = cpu_nseconds();
for (i = 0; i < 10; i++) {
RandomBytesFunction((unsigned char*)&rand_f2elmt[0], 73*32);
for (j = 0; j < 73; j++) {
rand_f2elmt[j][0][NWORDS_FIELD-1] &= (digit_t)(-1) >> 1;
rand_f2elmt[j][1][NWORDS_FIELD-1] &= (digit_t)(-1) >> 1;
}
}
nsec2 = cpu_nseconds();
nsec = nsec+(nsec2-nsec1);
}
printf(" PRNG generation for scalar mul runs in . %8lld nsec", nsec/(SHORT_BENCH_LOOPS*10));
printf("\n");
return OK;
}
int main()
{
bool OK = true;
OK = OK && fp2_test(); // Test quadratic extension field operations using p = 2^127-1
OK = OK && fp2_run(); // Benchmark quadratic extension field operations using p = 2^127-1
return OK;
}

Просмотреть файл

@ -0,0 +1,137 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: utility functions for tests
************************************************************************************/
#include "../FourQ_internal.h"
#include "test_extras.h"
#if (OS_TARGET == OS_LINUX) && (TARGET == TARGET_ARM)
#include <time.h>
#endif
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int64_t cpu_nseconds(void)
{ // Access system counter for benchmarking
struct timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return (int64_t)(time.tv_sec*1e9 + time.tv_nsec);
}
int fp2compare64(uint64_t* a, uint64_t* b)
{ // Comparing uint64_t digits of two quadratic extension field elements, ai=bi? : (0) equal, (1) unequal
// NOTE: this function does not have constant-time execution. TO BE USED FOR TESTING ONLY.
unsigned int i;
for (i = 0; i < (2*NWORDS64_FIELD); i++) {
if (a[i] != b[i]) return 1;
}
return 0;
}
void random_scalar_test(uint64_t* a)
{ // Generating a pseudo-random scalar value in [0, 2^256-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
unsigned char* string = (unsigned char*)&a[0];
unsigned int i;
for (i = 0; i < (sizeof(uint64_t)*NWORDS64_ORDER); i++) {
string[i] = (unsigned char)rand();
}
}
void fp2random1271_test(f2elm_t a)
{ // Generating a pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
digit_t mask_7fff = (digit_t)-1 >> 1;
random_scalar_test((uint64_t*)&a[0]);
a[0][NWORDS_FIELD-1] &= mask_7fff;
a[1][NWORDS_FIELD-1] &= mask_7fff;
}
bool verify_mLSB_recoding(uint64_t* scalar, int* digits)
{ // Verification of the mLSB-set's recoding algorithm used in fixed-base scalar multiplication
unsigned int j, l = L_FIXEDBASE, d = D_FIXEDBASE;
uint64_t temp, temp2, carry, borrow, generated_scalar[NWORDS64_ORDER] = {0};
int i, digit;
for (i = (l-1); i >= 0; i--)
{
// Shift generated scalar to the left by 1 (multiply by 2)
temp = ((generated_scalar[0] >> (RADIX64-1)) & 1) ;
generated_scalar[0] = generated_scalar[0] << 1;
for (j = 1; j < NWORDS64_ORDER; j++) {
temp2 = ((generated_scalar[j] >> (RADIX64-1)) & 1) ;
generated_scalar[j] = (generated_scalar[j] << 1) | temp;
temp = temp2;
}
// generated scalar + digit_i
if (i < (int)d) {
digit = digits[i] | 1;
if (digit >= 0) {
generated_scalar[0] = generated_scalar[0] + digit;
carry = (generated_scalar[0] < (unsigned int)digit);
for (j = 1; j < NWORDS64_ORDER; j++)
{
generated_scalar[j] = generated_scalar[j] + carry;
carry = (generated_scalar[j] < carry);
}
} else {
borrow = 0;
temp = (uint64_t)(-digit);
for (j = 0; j < NWORDS64_ORDER; j++)
{
temp2 = generated_scalar[j] - temp;
carry = (generated_scalar[j] < temp);
generated_scalar[j] = temp2 - borrow;
borrow = carry || (temp2 < borrow);
temp = 0;
}
}
} else {
digit = digits[i]*(digits[i-(i/d)*d] | 1);
if (digit >= 0) {
generated_scalar[0] = generated_scalar[0] + digit;
carry = (generated_scalar[0] < (unsigned int)digit);
for (j = 1; j < NWORDS64_ORDER; j++)
{
generated_scalar[j] = generated_scalar[j] + carry;
carry = (generated_scalar[j] < carry);
}
} else {
borrow = 0;
temp = (uint64_t)(-digit);
for (j = 0; j < NWORDS64_ORDER; j++)
{
temp2 = generated_scalar[j] - temp;
carry = (generated_scalar[j] < temp);
generated_scalar[j] = temp2 - borrow;
borrow = carry || (temp2 < borrow);
temp = 0;
}
}
}
}
for (j = 0; j < NWORDS64_ORDER; j++)
{
if (scalar[j] != generated_scalar[j])
return false;
}
return true;
}

Просмотреть файл

@ -0,0 +1,40 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: utility header file for tests
************************************************************************************/
#ifndef __TEST_EXTRAS_H__
#define __TEST_EXTRAS_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
// Access system counter for benchmarking
int64_t cpu_nseconds(void);
// Comparing uint64_t digits of two quadratic extension field elements, ai=bi? : (0) equal, (1) unequal
int fp2compare64(uint64_t* a, uint64_t* b);
// Generating a pseudo-random scalar value in [0, 2^256-1]
void random_scalar_test(uint64_t* a);
// Generating a pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
void fp2random1271_test(f2elm_t a);
// Verification of the mLSB-set's recoding algorithm used in fixed-base scalar multiplication
bool verify_mLSB_recoding(uint64_t* scalar, int* digits);
#ifdef __cplusplus
}
#endif
#endif

Просмотреть файл

@ -0,0 +1,386 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: testing code for cryptographic functions based on FourQ
************************************************************************************/
#include "../FourQ_internal.h"
#include "../FourQ_params.h"
#include "test_extras.h"
#include "../stm32f4_wrapper.h"
#include <stdio.h>
static unsigned int *DWT_CYCCNT = (unsigned int*)0xE0001004;
static unsigned int *DWT_CTRL = (unsigned int*)0xE0001000;
static unsigned int *SCB_DEMCR = (unsigned int*)0xE000EDFC;
// Benchmark and test parameters
#define BENCH_LOOPS 10 // Number of iterations per bench
#define TEST_LOOPS 10 // Number of iterations per test
#define cpucycles() (*DWT_CYCCNT);
static void print_test(const char *text)
{
unsigned char output[100];
sprintf((char*)output, "%s", text);
send_USART_str(output);
}
static void print_bench(const char *s, unsigned int cycles)
{
unsigned char output[100];
sprintf((char*)output, "%s %8u cycles", s, cycles);
send_USART_str(output);
}
ECCRYPTO_STATUS SchnorrQ_test()
{ // Test the SchnorrQ digital signature scheme
int n, passed;
void *msg = NULL;
unsigned int len, valid = false;
unsigned char SecretKey[32], PublicKey[32], Signature[64], BlindingPoint[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Testing the SchnorrQ signature scheme. Includes side-channel countermeasures: \n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Signature key generation
Status = SchnorrQ_FullKeyGeneration_SCA_secure(SecretKey, PublicKey, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Signature computation
msg = "a";
len = 1;
Status = SchnorrQ_Sign_SCA_secure(SecretKey, PublicKey, msg, len, Signature, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Valid signature test
Status = SchnorrQ_Verify(PublicKey, msg, len, Signature, &valid);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
if (valid == false) {
passed = 0;
break;
}
// Invalid signature test (flipping one bit of the message)
msg = "b";
Status = SchnorrQ_Verify(PublicKey, msg, len, Signature, &valid);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
if (valid == true) {
passed = 0;
break;
}
}
if (passed==1) print_test(" Signature tests.................................................................. PASSED");
else { print_test(" Signature tests... FAILED"); print_test("\n"); Status = ECCRYPTO_ERROR_SIGNATURE_VERIFICATION; }
return Status;
}
ECCRYPTO_STATUS SchnorrQ_run()
{ // Benchmark the SchnorrQ digital signature scheme
int n;
unsigned int cycles, cycles1, cycles2;
void *msg = NULL;
unsigned int len = 0, valid = false;
unsigned char SecretKey[32], PublicKey[32], Signature[64], BlindingPoint[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Benchmarking the SchnorrQ signature scheme. Includes side-channel countermeasures: \n");
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = SchnorrQ_FullKeyGeneration_SCA_secure(SecretKey, PublicKey, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" SchnorrQ's key generation runs in ............................................... ", cycles/BENCH_LOOPS);
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = SchnorrQ_Sign_SCA_secure(SecretKey, PublicKey, msg, len, Signature, BlindingPoint);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" SchnorrQ's signing runs in ...................................................... ", cycles/BENCH_LOOPS);
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = SchnorrQ_Verify(PublicKey, msg, len, Signature, &valid);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" SchnorrQ's verification runs in ................................................. ", cycles/BENCH_LOOPS);
return Status;
}
ECCRYPTO_STATUS compressedkex_test()
{ // Test ECDH key exchange based on FourQ
int n, passed;
unsigned int i;
unsigned char SecretKeyA[32], PublicKeyA[32], BlindingPointA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[32], BlindingPointB[64], SecretAgreementB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Testing DH key exchange using compressed, 32-byte public keys. Includes side-channel countermeasures: \n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Alice's keypair generation
Status = CompressedKeyGeneration_SCA_secure(SecretKeyA, PublicKeyA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's keypair generation
Status = CompressedKeyGeneration_SCA_secure(SecretKeyB, PublicKeyB, BlindingPointB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Alice's shared secret computation
Status = CompressedSecretAgreement_SCA_secure(SecretKeyA, PublicKeyB, SecretAgreementA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's shared secret computation
Status = CompressedSecretAgreement_SCA_secure(SecretKeyB, PublicKeyA, SecretAgreementB, BlindingPointB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
for (i = 0; i < 32; i++) {
if (SecretAgreementA[i] != SecretAgreementB[i]) {
passed = 0;
break;
}
}
}
if (passed==1) print_test(" DH key exchange tests............................................................ PASSED");
else { print_test(" DH key exchange tests... FAILED"); print_test("\n"); Status = ECCRYPTO_ERROR_SHARED_KEY; }
return Status;
}
ECCRYPTO_STATUS compressedkex_run()
{ // Benchmark ECDH key exchange based on FourQ
int n;
unsigned int cycles, cycles1, cycles2;
unsigned char SecretKeyA[32], PublicKeyA[32], BlindingPointA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[32], BlindingPointB[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Benchmarking DH key exchange using compressed, 32-byte public keys. Includes side-channel countermeasures: \n");
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = CompressedKeyGeneration_SCA_secure(SecretKeyA, PublicKeyA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
print_bench(" Keypair generation runs in ...................................................... ", cycles/BENCH_LOOPS);
Status = CompressedKeyGeneration_SCA_secure(SecretKeyB, PublicKeyB, BlindingPointB);
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = CompressedSecretAgreement_SCA_secure(SecretKeyA, PublicKeyB, SecretAgreementA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
print_bench(" Secret agreement runs in ........................................................ ", cycles/BENCH_LOOPS);
return Status;
}
ECCRYPTO_STATUS kex_test()
{ // Test ECDH key exchange based on FourQ
int n, passed;
unsigned int i;
unsigned char SecretKeyA[32], PublicKeyA[64], BlindingPointA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[64], BlindingPointB[64], SecretAgreementB[32];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Testing DH key exchange using uncompressed, 64-byte public keys. Includes side-channel countermeasures: \n");
passed = 1;
for (n = 0; n < TEST_LOOPS; n++)
{
// Alice's keypair generation
Status = KeyGeneration_SCA_secure(SecretKeyA, PublicKeyA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's keypair generation
Status = KeyGeneration_SCA_secure(SecretKeyB, PublicKeyB, BlindingPointB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Alice's shared secret computation
Status = SecretAgreement_SCA_secure(SecretKeyA, PublicKeyB, SecretAgreementA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
// Bob's shared secret computation
Status = SecretAgreement_SCA_secure(SecretKeyB, PublicKeyA, SecretAgreementB, BlindingPointB);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
for (i = 0; i < 32; i++) {
if (SecretAgreementA[i] != SecretAgreementB[i]) {
passed = 0;
break;
}
}
}
if (passed==1) print_test(" DH key exchange tests............................................................ PASSED");
else { print_test(" DH key exchange tests... FAILED"); print_test("\n"); Status = ECCRYPTO_ERROR_SHARED_KEY; }
return Status;
}
ECCRYPTO_STATUS kex_run()
{ // Benchmark ECDH key exchange based on FourQ
int n;
unsigned int cycles, cycles1, cycles2;
unsigned char SecretKeyA[32], PublicKeyA[64], BlindingPointA[64], SecretAgreementA[32];
unsigned char SecretKeyB[32], PublicKeyB[64], BlindingPointB[64];
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Benchmarking DH key exchange using uncompressed, 64-byte public keys. Includes side-channel countermeasures: \n");
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = KeyGeneration_SCA_secure(SecretKeyA, PublicKeyA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
print_bench(" Keypair generation runs in ...................................................... ", cycles/BENCH_LOOPS);
Status = KeyGeneration_SCA_secure(SecretKeyB, PublicKeyB, BlindingPointB);
cycles = 0;
for (n = 0; n < BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
Status = SecretAgreement_SCA_secure(SecretKeyA, PublicKeyB, SecretAgreementA, BlindingPointA);
if (Status != ECCRYPTO_SUCCESS) {
return Status;
}
cycles2 = cpucycles();
cycles = cycles + (cycles2 - cycles1);
}
print_bench(" Secret agreement runs in ........................................................ ", cycles/BENCH_LOOPS);
return Status;
}
int main()
{
clock_setup();
gpio_setup();
usart_setup(115200);
rng_setup();
*SCB_DEMCR = *SCB_DEMCR | 0x01000000;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CTRL = *DWT_CTRL | 1 ; // enable the counter
ECCRYPTO_STATUS Status = ECCRYPTO_SUCCESS;
Status = SchnorrQ_test(); // Test SchnorrQ signature scheme
if (Status != ECCRYPTO_SUCCESS) {
print_test("\n\n Error detected \n\n");
return false;
}
Status = SchnorrQ_run(); // Benchmark SchnorrQ signature scheme
if (Status != ECCRYPTO_SUCCESS) {
print_test("\n\n Error detected \n\n");
return false;
}
Status = compressedkex_test(); // Test Diffie-Hellman key exchange using compressed public keys
if (Status != ECCRYPTO_SUCCESS) {
print_test("\n\n Error detected \n\n");
return false;
}
Status = compressedkex_run(); // Benchmark Diffie-Hellman key exchange using compressed public keys
if (Status != ECCRYPTO_SUCCESS) {
print_test("\n\n Error detected \n\n");
return false;
}
Status = kex_test(); // Test Diffie-Hellman key exchange using uncompressed public keys
if (Status != ECCRYPTO_SUCCESS) {
print_test("\n\n Error detected \n\n");
return false;
}
Status = kex_run(); // Benchmark Diffie-Hellman key exchange using uncompressed public keys
if (Status != ECCRYPTO_SUCCESS) {
print_test("\n\n Error detected \n\n");
return false;
}
signal_host();
return 0;
}

Просмотреть файл

@ -0,0 +1,468 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: testing code for FourQ's curve arithmetic
************************************************************************************/
#include "../FourQ_internal.h"
#include "../FourQ_params.h"
#include "../FourQ_tables.h"
#include "test_extras.h"
#include "../stm32f4_wrapper.h"
#include <stdio.h>
static unsigned int *DWT_CYCCNT = (unsigned int*)0xE0001004;
static unsigned int *DWT_CTRL = (unsigned int*)0xE0001000;
static unsigned int *SCB_DEMCR = (unsigned int*)0xE000EDFC;
// Benchmark and test parameters
#define BENCH_LOOPS 10 // Number of iterations per bench
#define TEST_LOOPS 10 // Number of iterations per test
#define cpucycles() (*DWT_CYCCNT);
static void print_test(const char *text)
{
unsigned char output[100];
sprintf((char*)output, "%s", text);
send_USART_str(output);
}
static void print_bench(const char *s, unsigned int cycles)
{
unsigned char output[100];
sprintf((char*)output, "%s %8u cycles", s, cycles);
send_USART_str(output);
}
bool ecc_test()
{
bool clear_cofactor, OK = true;
unsigned int n;
int passed;
point_t A, R;
point_extedwards_t P, Q;
f2elm_t t1;
uint64_t scalar[4], res_x[4], res_y[4];
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Testing FourQ's curve arithmetic: \n");
// Point doubling
passed = 1;
eccset(A);
point_setup(A, P);
for (n=0; n<TEST_LOOPS; n++)
{
eccdouble(P); // 2*P
}
eccnorm(P, A);
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0xFA4FAD9EC7732700; res_x[1] = 0x619F5D1FD93BC4F5; res_x[2] = 0x814B78DADF6A9024; res_x[3] = 0x72EC1D429F026578;
res_y[0] = 0x7FF28C92C8CEF9DE; res_y[1] = 0x799208A76EAD2BA3; res_y[2] = 0x9B1AE60FFFCB520A; res_y[3] = 0x051698145D42F3E2;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) print_test(" Point doubling tests .................................................................... PASSED");
else { print_test(" Point doubling tests ... FAILED"); print_test("\n"); return false; }
// Point addition
eccset(A);
point_setup(A, P);
for (n=0; n<TEST_LOOPS; n++)
{
ecccopy(P, Q);
eccadd(P, Q, P); // 2*P
}
eccnorm(P, A);
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0xFA4FAD9EC7732700; res_x[1] = 0x619F5D1FD93BC4F5; res_x[2] = 0x814B78DADF6A9024; res_x[3] = 0x72EC1D429F026578;
res_y[0] = 0x7FF28C92C8CEF9DE; res_y[1] = 0x799208A76EAD2BA3; res_y[2] = 0x9B1AE60FFFCB520A; res_y[3] = 0x051698145D42F3E2;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
eccset(A);
point_setup(A, P);
ecccopy(P, Q);
eccdouble(P); // P = 2P
for (n=0; n<TEST_LOOPS; n++)
{
eccadd(P, Q, P); // P = P+Q
}
eccnorm(P, A);
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0xB92B573D2C4B06FF; res_x[1] = 0x6B62D585800A9F6A; res_x[2] = 0xECB6DFB3FA1ACB7C; res_x[3] = 0xD9D9F54A8335E2B;
res_y[0] = 0xDF3BD744D9BB783D; res_y[1] = 0x2B827EEDA23988A6; res_y[2] = 0x947C187247366CDD; res_y[3] = 0x3B7E00BA2F9525B3;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) print_test(" Point addition tests .................................................................... PASSED");
else { print_test(" Point addition tests ... FAILED"); print_test("\n"); return false; }
// Psi endomorphism
eccset(A);
point_setup(A, P);
for (n=0; n<TEST_LOOPS; n++)
{
ecc_psi(P); // P = Psi(P)
}
eccnorm(P, A);
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0xABC340A7DDC08580; res_x[1] = 0x6B74D34E155D2119; res_x[2] = 0x1B6E0A6DC6A5BC70; res_x[3] = 0x5CAE354597C9106A;
res_y[0] = 0xE276B58944E2D60B; res_y[1] = 0x1812145CDE0E8DCB; res_y[2] = 0xF4D6895A6375AA22; res_y[3] = 0x1A593C1711EEBCDE;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) print_test(" Psi endomorphism tests .................................................................. PASSED");
else { print_test(" Psi endomorphism tests ... FAILED"); print_test("\n"); return false; }
// Phi endomorphism
eccset(A);
point_setup(A, P);
for (n=0; n<TEST_LOOPS; n++)
{
ecc_phi(P); // P = Phi(P)
eccnorm(P, A);
point_setup(A, P);
}
mod1271(A->x[0]); mod1271(A->x[1]); // Fully reduced P
mod1271(A->y[0]); mod1271(A->y[1]);
// Result
res_x[0] = 0x1365D931AFEBC83E; res_x[1] = 0x1873BB71FF4FFF87; res_x[2] = 0x7BF9ACB5C770F61F; res_x[3] = 0x773EA05D9B4B0D62;
res_y[0] = 0xCFFDD1A374E18F42; res_y[1] = 0x369B19C1F39C1A97; res_y[2] = 0x38B8E623E4E0049A; res_y[3] = 0x12435E356960429A;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) print_test(" Phi endomorphism tests .................................................................. PASSED");
else { print_test(" Phi endomorphism tests ... FAILED"); print_test("\n"); return false; }
// Scalar multiplication
eccset(A);
eccset(R);
clear_cofactor = false;
scalar[0] = 0x3AD457AB55456230; scalar[1] = 0x3A8B3C2C6FD86E0C; scalar[2] = 0x7E38F7C9CFBB9166; scalar[3] = 0x0028FD6CBDA458F0;
for (n=0; n<TEST_LOOPS; n++)
{
scalar[1] = scalar[2];
scalar[2] += scalar[0];
ecc_mul_SCA_secure(A, R, (digit_t*)scalar, A, clear_cofactor);
}
res_x[0] = 0x8F7033298B9CD5A4; res_x[1] = 0x6A60DF430E52E299; res_x[2] = 0x51D6EAFEEA829A8B; res_x[3] = 0x56F40C1CE3C3CD34;
res_y[0] = 0x5B611ABE0387F840; res_y[1] = 0x59C6A5C83477F57C; res_y[2] = 0xF33C879AB74E2490; res_y[3] = 0x12C18E67FB2A3A9D;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
eccset(A);
eccset(R);
clear_cofactor = true;
scalar[0] = 0x3AD457AB55456230; scalar[1] = 0x3A8B3C2C6FD86E0C; scalar[2] = 0x7E38F7C9CFBB9166; scalar[3] = 0x0028FD6CBDA458F0;
for (n=0; n<TEST_LOOPS; n++)
{
scalar[1] = scalar[2];
scalar[2] += scalar[0];
ecc_mul_SCA_secure(A, R, (digit_t*)scalar, A, clear_cofactor);
}
res_x[0] = 0x10EA7CF4F502CF5E; res_x[1] = 0x4FC1A5862ACAF69B; res_x[2] = 0x886D85328FB1E1A9; res_x[3] = 0x6F134E7E5129772A;
res_y[0] = 0x35FFAD6E8F0681DC; res_y[1] = 0x681067510F99389E; res_y[2] = 0xA4BE7A70A1820895; res_y[3] = 0x34C0A821F434D672;
if (fp2compare64((uint64_t*)A->x, res_x)!=0 || fp2compare64((uint64_t*)A->y, res_y)!=0) passed=0;
if (passed==1) print_test(" Scalar multiplication tests ............................................................. PASSED");
else { print_test(" Scalar multiplication tests ... FAILED"); print_test("\n"); return false; }
{
point_t PP, QQ, RR, UU, TT;
point_extedwards_t AA, BB;
uint64_t k[4], l[4], kk[4];
// Double scalar multiplication
eccset(QQ);
eccset(PP);
eccset(R);
for (n=0; n<TEST_LOOPS; n++)
{
random_scalar_test(kk);
ecc_mul_SCA_secure(QQ, R, (digit_t*)kk, QQ, false);
random_scalar_test(k);
random_scalar_test(l);
ecc_mul_double((digit_t*)k, QQ, (digit_t*)l, RR);
ecc_mul_SCA_secure(PP, R, (digit_t*)k, UU, false);
ecc_mul_SCA_secure(QQ, R, (digit_t*)l, TT, false);
point_setup(UU, AA);
point_setup(TT, BB);
eccadd(BB, AA, BB);
eccnorm(BB, UU);
if (fp2compare64((uint64_t*)UU->x,(uint64_t*)RR->x)!=0 || fp2compare64((uint64_t*)UU->y,(uint64_t*)RR->y)!=0) { passed=0; break; }
}
if (passed==1) print_test(" Double scalar multiplication tests ...................................................... PASSED");
else { print_test(" Double scalar multiplication tests ... FAILED"); print_test("\n"); return false; }
}
return OK;
}
bool ecc_run()
{
bool OK = true;
unsigned int n, i, digit=1;
unsigned int cycles, cycles1, cycles2;
point_t A, B, R;
point_extedwards_t P, Q, RR, Table[16];
f2elm_t t1;
uint64_t scalar[4];
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Benchmarking FourQ's curve arithmetic \n");
// Point doubling (twisted Edwards a=-1)
eccset(A);
point_setup(A, P);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
for (i = 0; i < 10; i++) {
eccdouble(P);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Point doubling runs in ... ", cycles/(BENCH_LOOPS*10));
// Point addition (twisted Edwards a=-1)
eccset(A);
point_setup(A, P);
ecccopy(P, Q);
eccdouble(P); // P = 2P
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
for (i = 0; i < 10; i++) {
eccadd(P, Q, P);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Point addition runs in ... ", cycles/(BENCH_LOOPS*10));
// Psi endomorphism
eccset(A);
point_setup(A, P);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
for (i = 0; i < 10; i++) {
ecc_psi(P);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Psi mapping runs in ... ", cycles/(BENCH_LOOPS*10));
// Phi endomorphism
eccset(A);
point_setup(A, P);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
for (i = 0; i < 10; i++) {
ecc_phi(P);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Phi mapping runs in ... ", cycles/(BENCH_LOOPS*10));
// Scalar decomposition
{
uint64_t scalars[4];
random_scalar_test(scalar);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
for (i = 0; i < 10; i++) {
decompose(scalar, scalars);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Scalar decomposition runs in ... ", cycles/(BENCH_LOOPS*10));
}
// Scalar recoding
{
unsigned int digits[72];
uint128_t rand_scalars[4];
unsigned char rand_bytes[4] = {1};
random_scalar_test(scalar);
randomize(scalar, rand_bytes, rand_scalars);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
for (i = 0; i < 10; i++) {
recode(rand_scalars, digits);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Scalar recoding runs in ... ", cycles/(BENCH_LOOPS*10));
}
// Precomputation
eccset(A);
point_setup(A, P);
ecccopy(P, RR);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
ecc_precomp(P, RR, Table);
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Precomputation runs in ... ", cycles/BENCH_LOOPS);
// Table lookup
eccset(A);
point_setup(A, P);
ecccopy(P, RR);
ecc_precomp(P, RR, Table);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
cycles1 = cpucycles();
for (i = 0; i < 10; i++) {
table_lookup_1x16(Table, Q, digit);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Table lookup runs in ... ", cycles/(BENCH_LOOPS*10));
// Scalar multiplication
random_scalar_test(scalar);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
eccset(A);
eccset(R);
cycles1 = cpucycles();
ecc_mul_SCA_secure(A, R, (digit_t*)scalar, B, false);
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Scalar multiplication (without clearing cofactor) runs in ... ", cycles/BENCH_LOOPS);
random_scalar_test(scalar);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
eccset(A);
eccset(R);
cycles1 = cpucycles();
ecc_mul_SCA_secure(A, R, (digit_t*)scalar, B, true);
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Scalar multiplication (including clearing cofactor) runs in ... ", cycles/BENCH_LOOPS);
{
point_t PP, QQ, RR;
uint64_t k[4], l[4], kk[4];
// Double scalar multiplication
eccset(QQ);
eccset(PP);
random_scalar_test(kk);
ecc_mul_SCA_secure(QQ, PP, (digit_t*)kk, QQ, false);
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
random_scalar_test(k);
random_scalar_test(l);
cycles1 = cpucycles();
ecc_mul_double((digit_t*)k, QQ, (digit_t*)l, RR);
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" Double scalar mul runs in ... ", cycles/BENCH_LOOPS);
}
return OK;
}
int main()
{
clock_setup();
gpio_setup();
usart_setup(115200);
rng_setup();
*SCB_DEMCR = *SCB_DEMCR | 0x01000000;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CTRL = *DWT_CTRL | 1 ; // enable the counter
bool OK = true;
OK = OK && ecc_test(); // Test FourQ's curve functions
OK = OK && ecc_run(); // Benchmark FourQ's curve functions
signal_host();
return OK;
}

Просмотреть файл

@ -0,0 +1,234 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: testing code for FourQ's field arithmetic
************************************************************************************/
#include "../FourQ_internal.h"
#include "test_extras.h"
#include "../stm32f4_wrapper.h"
#include <stdio.h>
static unsigned int *DWT_CYCCNT = (unsigned int*)0xE0001004;
static unsigned int *DWT_CTRL = (unsigned int*)0xE0001000;
static unsigned int *SCB_DEMCR = (unsigned int*)0xE000EDFC;
// Benchmark and test parameters
#define BENCH_LOOPS 100 // Number of iterations per bench
#define TEST_LOOPS 100 // Number of iterations per test
#define cpucycles() (*DWT_CYCCNT);
static void print_test(const char *text)
{
unsigned char output[100];
sprintf((char*)output, "%s", text);
send_USART_str(output);
}
static void print_bench(const char *s, unsigned int cycles)
{
unsigned char output[100];
sprintf((char*)output, "%s %8u cycles", s, cycles);
send_USART_str(output);
}
bool fp2_test()
{ // Tests for the quadratic extension field arithmetic
bool OK = true;
int n, passed;
f2elm_t a, b, c, d, e, f;
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Testing quadratic extension field arithmetic over GF((2^127-1)^2): \n");
// GF(p^2) multiplication using p = 2^127-1
passed = 1;
for (n=0; n<TEST_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b); fp2random1271_test(c);
fp2random1271_test(d); fp2random1271_test(e); fp2random1271_test(f);
fp2mul1271(a, b, d); // d = a*b
mod1271(d[0]); mod1271(d[1]);
fp2mul1271(b, a, e); // e = b*a
mod1271(e[0]); mod1271(e[1]);
if (fp2compare64((uint64_t*)d,(uint64_t*)e)!=0) { passed=0; break; }
fp2mul1271(a, b, d); fp2mul1271(d, c, e); // e = (a*b)*c
mod1271(e[0]); mod1271(e[1]);
fp2mul1271(b, c, d); fp2mul1271(d, a, f); // f = a*(b*c)
mod1271(f[0]); mod1271(f[1]);
if (fp2compare64((uint64_t*)e,(uint64_t*)f)!=0) { passed=0; break; }
fp2add1271(b, c, d); fp2mul1271(a, d, e); // e = a*(b+c)
mod1271(e[0]); mod1271(e[1]);
fp2mul1271(a, b, d); fp2mul1271(a, c, f); fp2add1271(d, f, f); // f = a*b+a*c
mod1271(f[0]); mod1271(f[1]);
if (fp2compare64((uint64_t*)e,(uint64_t*)f)!=0) { passed=0; break; }
fp2zero1271(b); b[0][0] = 1;
fp2mul1271(a, b, d); // d = a*1
mod1271(d[0]); mod1271(d[1]);
if (fp2compare64((uint64_t*)a,(uint64_t*)d)!=0) { passed=0; break; }
fp2zero1271(b);
fp2mul1271(a, b, d); // d = a*0
mod1271(d[0]); mod1271(d[1]);
if (fp2compare64((uint64_t*)b,(uint64_t*)d)!=0) { passed=0; break; }
}
if (passed==1) print_test(" GF(p^2) multiplication tests .................................................................... PASSED");
else { print_test(" GF(p^2) multiplication tests... FAILED"); print_test("\n"); return false; }
// GF(p^2) squaring using p = 2^127-1
passed = 1;
for (n=0; n<TEST_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b); fp2random1271_test(c);
fp2sqr1271(a, b); // b = a^2
fp2mul1271(a, a, c); // c = a*a
if (fp2compare64((uint64_t*)b,(uint64_t*)c)!=0) { passed=0; break; }
fp2zero1271(a);
fp2sqr1271(a, d); // d = 0^2
if (fp2compare64((uint64_t*)a,(uint64_t*)d)!=0) { passed=0; break; }
}
if (passed==1) print_test(" GF(p^2) squaring tests........................................................................... PASSED");
else { print_test(" GF(p^2) squaring tests... FAILED"); print_test("\n"); return false; }
// GF(p^2) inversion using p = 2^127-1
passed = 1;
for (n=0; n<TEST_LOOPS; n++)
{
fp2random1271_test(a);
fp2zero1271(d); d[0][0] = 1;
fp2copy1271(a, b);
fp2inv1271(a);
fp2mul1271(a, b, c); // c = a*a^-1 = 1
mod1271(c[0]); mod1271(c[1]);
if (fp2compare64((uint64_t*)c,(uint64_t*)d)!=0) { passed=0; break; }
}
if (passed==1) print_test(" GF(p^2) inversion tests.......................................................................... PASSED");
else { print_test(" GF(p^2) inversion tests... FAILED"); print_test("\n"); return false; }
return OK;
}
bool fp2_run()
{
bool OK = true;
int n, i;
unsigned long long cycles, cycles1, cycles2;
f2elm_t a, b, c, d, e, f;
print_test("\n--------------------------------------------------------------------------------------------------------\n");
print_test("Benchmarking quadratic extension field arithmetic over GF((2^127-1)^2): \n");
// GF(p^2) addition using p = 2^127-1
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b);
cycles1 = cpucycles();
for (i = 0; i < 1000; i++) {
fp2add1271(a, b, c);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" GF(p^2) addition runs in ............... ", cycles/(BENCH_LOOPS*1000));
// GF(p^2) subtraction using p = 2^127-1
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b);
cycles1 = cpucycles();
for (i = 0; i < 1000; i++) {
fp2sub1271(a, b, c);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" GF(p^2) subtraction runs in ............ ", cycles/(BENCH_LOOPS*1000));
// GF(p^2) squaring using p = 2^127-1
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a);
cycles1 = cpucycles();
for (i = 0; i < 1000; i++) {
fp2sqr1271(a, b);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" GF(p^2) squaring runs in ............... ", cycles/(BENCH_LOOPS*1000));
// GF(p^2) multiplication using p = 2^127-1
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b); fp2random1271_test(c);
cycles1 = cpucycles();
for (i = 0; i < 1000; i++) {
fp2mul1271(a, b, c);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" GF(p^2) multiplication runs in ......... ", cycles/(BENCH_LOOPS*1000));
// GF(p^2) inversion using p = 2^127-1
cycles = 0;
for (n=0; n<BENCH_LOOPS; n++)
{
fp2random1271_test(a); fp2random1271_test(b); fp2random1271_test(c);
cycles1 = cpucycles();
for (i = 0; i < 100; i++) {
fp2inv1271(a);
}
cycles2 = cpucycles();
cycles = cycles+(cycles2-cycles1);
}
print_bench(" GF(p^2) inversion runs in .............. ", cycles/(BENCH_LOOPS*100));
return OK;
}
int main()
{
clock_setup();
gpio_setup();
usart_setup(115200);
rng_setup();
*SCB_DEMCR = *SCB_DEMCR | 0x01000000;
*DWT_CYCCNT = 0; // reset the counter
*DWT_CTRL = *DWT_CTRL | 1 ; // enable the counter
bool OK = true;
OK = OK && fp2_test(); // Test quadratic extension field operations using p = 2^127-1
OK = OK && fp2_run(); // Benchmark quadratic extension field operations using p = 2^127-1
signal_host();
return OK;
}

Просмотреть файл

@ -0,0 +1,6 @@
#!/bin/sh
DEVICE=/dev/ttyUSB0
stty -F $DEVICE raw icanon eof \^d 115200
$1 write $2 0x8000000 >/dev/null 2>&1
cat < $DEVICE

Просмотреть файл

@ -0,0 +1,124 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: utility functions for tests
************************************************************************************/
#include "../FourQ_internal.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int fp2compare64(uint64_t* a, uint64_t* b)
{ // Comparing uint64_t digits of two quadratic extension field elements, ai=bi? : (0) equal, (1) unequal
// NOTE: this function does not have constant-time execution. TO BE USED FOR TESTING ONLY.
unsigned int i;
for (i = 0; i < (2*NWORDS64_FIELD); i++) {
if (a[i] != b[i]) return 1;
}
return 0;
}
void random_scalar_test(uint64_t* a)
{ // Generating a pseudo-random scalar value in [0, 2^256-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
unsigned char* string = (unsigned char*)&a[0];
unsigned int i;
for (i = 0; i < (sizeof(uint64_t)*NWORDS64_ORDER); i++) {
string[i] = (unsigned char)rand();
}
}
void fp2random1271_test(f2elm_t a)
{ // Generating a pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
// NOTE: distribution is not fully uniform. TO BE USED FOR TESTING ONLY.
digit_t mask_7fff = (digit_t)-1 >> 1;
random_scalar_test((uint64_t*)&a[0]);
a[0][NWORDS_FIELD-1] &= mask_7fff;
a[1][NWORDS_FIELD-1] &= mask_7fff;
}
bool verify_mLSB_recoding(uint64_t* scalar, int* digits)
{ // Verification of the mLSB-set's recoding algorithm used in fixed-base scalar multiplication
unsigned int j, l = L_FIXEDBASE, d = D_FIXEDBASE;
uint64_t temp, temp2, carry, borrow, generated_scalar[NWORDS64_ORDER] = {0};
int i, digit;
for (i = (l-1); i >= 0; i--)
{
// Shift generated scalar to the left by 1 (multiply by 2)
temp = ((generated_scalar[0] >> (RADIX64-1)) & 1) ;
generated_scalar[0] = generated_scalar[0] << 1;
for (j = 1; j < NWORDS64_ORDER; j++) {
temp2 = ((generated_scalar[j] >> (RADIX64-1)) & 1) ;
generated_scalar[j] = (generated_scalar[j] << 1) | temp;
temp = temp2;
}
// generated scalar + digit_i
if (i < (int)d) {
digit = digits[i] | 1;
if (digit >= 0) {
generated_scalar[0] = generated_scalar[0] + digit;
carry = (generated_scalar[0] < (unsigned int)digit);
for (j = 1; j < NWORDS64_ORDER; j++)
{
generated_scalar[j] = generated_scalar[j] + carry;
carry = (generated_scalar[j] < carry);
}
} else {
borrow = 0;
temp = (uint64_t)(-digit);
for (j = 0; j < NWORDS64_ORDER; j++)
{
temp2 = generated_scalar[j] - temp;
carry = (generated_scalar[j] < temp);
generated_scalar[j] = temp2 - borrow;
borrow = carry || (temp2 < borrow);
temp = 0;
}
}
} else {
digit = digits[i]*(digits[i-(i/d)*d] | 1);
if (digit >= 0) {
generated_scalar[0] = generated_scalar[0] + digit;
carry = (generated_scalar[0] < (unsigned int)digit);
for (j = 1; j < NWORDS64_ORDER; j++)
{
generated_scalar[j] = generated_scalar[j] + carry;
carry = (generated_scalar[j] < carry);
}
} else {
borrow = 0;
temp = (uint64_t)(-digit);
for (j = 0; j < NWORDS64_ORDER; j++)
{
temp2 = generated_scalar[j] - temp;
carry = (generated_scalar[j] < temp);
generated_scalar[j] = temp2 - borrow;
borrow = carry || (temp2 < borrow);
temp = 0;
}
}
}
}
for (j = 0; j < NWORDS64_ORDER; j++)
{
if (scalar[j] != generated_scalar[j])
return false;
}
return true;
}

Просмотреть файл

@ -0,0 +1,37 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: utility header file for tests
************************************************************************************/
#ifndef __TEST_EXTRAS_H__
#define __TEST_EXTRAS_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
// Comparing uint64_t digits of two quadratic extension field elements, ai=bi? : (0) equal, (1) unequal
int fp2compare64(uint64_t* a, uint64_t* b);
// Generating a pseudo-random scalar value in [0, 2^256-1]
void random_scalar_test(uint64_t* a);
// Generating a pseudo-random GF(p^2) element a+b*i, where a,b in [0, 2^127-1]
void fp2random1271_test(f2elm_t a);
// Verification of the mLSB-set's recoding algorithm used in fixed-base scalar multiplication
bool verify_mLSB_recoding(uint64_t* scalar, int* digits);
#ifdef __cplusplus
}
#endif
#endif

61
random/random.c Normal file
Просмотреть файл

@ -0,0 +1,61 @@
/***********************************************************************************
* FourQlib: a high-performance crypto library based on the elliptic curve FourQ
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* Abstract: pseudo-random function
************************************************************************************/
#include "random.h"
#include <stdlib.h>
#include <stdbool.h>
#if defined(__WINDOWS__)
#include <windows.h>
#include <bcrypt.h>
#elif defined(__LINUX__)
#include <unistd.h>
#include <fcntl.h>
static int lock = -1;
#endif
static __inline void delay(unsigned int count)
{
while (count--) {}
}
int random_bytes(unsigned char* random_array, unsigned int nbytes)
{ // Generation of "nbytes" of random values
#if defined(__WINDOWS__)
if (!BCRYPT_SUCCESS(BCryptGenRandom(NULL, random_array, nbytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG))) {
return false;
}
#elif defined(__LINUX__)
int r, n = nbytes, count = 0;
if (lock == -1) {
do {
lock = open("/dev/urandom", O_RDONLY);
if (lock == -1) {
delay(0xFFFFF);
}
} while (lock == -1);
}
while (n > 0) {
do {
r = read(lock, random_array+count, n);
if (r == -1) {
delay(0xFFFF);
}
} while (r == -1);
count += r;
n -= r;
}
#endif
return true;
}

20
random/random.h Normal file
Просмотреть файл

@ -0,0 +1,20 @@
#ifndef __RANDOM_H__
#define __RANDOM_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
// Generate random bytes and output the result to random_array
int random_bytes(unsigned char* random_array, unsigned int nbytes);
#ifdef __cplusplus
}
#endif
#endif

306
sha512/sha512.c Normal file
Просмотреть файл

@ -0,0 +1,306 @@
/*
20080913
D. J. Bernstein
Public domain.
*/
#include "sha512.h"
typedef unsigned long long uint64;
static uint64 load_bigendian(const unsigned char *x)
{
return
(uint64) (x[7]) \
| (((uint64) (x[6])) << 8) \
| (((uint64) (x[5])) << 16) \
| (((uint64) (x[4])) << 24) \
| (((uint64) (x[3])) << 32) \
| (((uint64) (x[2])) << 40) \
| (((uint64) (x[1])) << 48) \
| (((uint64) (x[0])) << 56)
;
}
static void store_bigendian(unsigned char *x,uint64 u)
{
x[7] = (unsigned char)u; u >>= 8;
x[6] = (unsigned char)u; u >>= 8;
x[5] = (unsigned char)u; u >>= 8;
x[4] = (unsigned char)u; u >>= 8;
x[3] = (unsigned char)u; u >>= 8;
x[2] = (unsigned char)u; u >>= 8;
x[1] = (unsigned char)u; u >>= 8;
x[0] = (unsigned char)u;
}
#define SHR(x,c) ((x) >> (c))
#define ROTR(x,c) (((x) >> (c)) | ((x) << (64 - (c))))
#define Ch(x,y,z) ((x & y) ^ (~x & z))
#define Maj(x,y,z) ((x & y) ^ (x & z) ^ (y & z))
#define Sigma0(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
#define Sigma1(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
#define sigma0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x,7))
#define sigma1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x,6))
#define M(w0,w14,w9,w1) w0 = sigma1(w14) + w9 + sigma0(w1) + w0;
#define EXPAND \
M(w0 ,w14,w9 ,w1 ) \
M(w1 ,w15,w10,w2 ) \
M(w2 ,w0 ,w11,w3 ) \
M(w3 ,w1 ,w12,w4 ) \
M(w4 ,w2 ,w13,w5 ) \
M(w5 ,w3 ,w14,w6 ) \
M(w6 ,w4 ,w15,w7 ) \
M(w7 ,w5 ,w0 ,w8 ) \
M(w8 ,w6 ,w1 ,w9 ) \
M(w9 ,w7 ,w2 ,w10) \
M(w10,w8 ,w3 ,w11) \
M(w11,w9 ,w4 ,w12) \
M(w12,w10,w5 ,w13) \
M(w13,w11,w6 ,w14) \
M(w14,w12,w7 ,w15) \
M(w15,w13,w8 ,w0 )
#define F(w,k) \
T1 = h + Sigma1(e) + Ch(e,f,g) + k + w; \
T2 = Sigma0(a) + Maj(a,b,c); \
h = g; \
g = f; \
f = e; \
e = d + T1; \
d = c; \
c = b; \
b = a; \
a = T1 + T2;
static int crypto_hashblocks_sha512(unsigned char *statebytes,const unsigned char *in,unsigned long long inlen)
{
uint64 state[8];
uint64 a;
uint64 b;
uint64 c;
uint64 d;
uint64 e;
uint64 f;
uint64 g;
uint64 h;
uint64 T1;
uint64 T2;
a = load_bigendian(statebytes + 0); state[0] = a;
b = load_bigendian(statebytes + 8); state[1] = b;
c = load_bigendian(statebytes + 16); state[2] = c;
d = load_bigendian(statebytes + 24); state[3] = d;
e = load_bigendian(statebytes + 32); state[4] = e;
f = load_bigendian(statebytes + 40); state[5] = f;
g = load_bigendian(statebytes + 48); state[6] = g;
h = load_bigendian(statebytes + 56); state[7] = h;
while (inlen >= 128) {
uint64 w0 = load_bigendian(in + 0);
uint64 w1 = load_bigendian(in + 8);
uint64 w2 = load_bigendian(in + 16);
uint64 w3 = load_bigendian(in + 24);
uint64 w4 = load_bigendian(in + 32);
uint64 w5 = load_bigendian(in + 40);
uint64 w6 = load_bigendian(in + 48);
uint64 w7 = load_bigendian(in + 56);
uint64 w8 = load_bigendian(in + 64);
uint64 w9 = load_bigendian(in + 72);
uint64 w10 = load_bigendian(in + 80);
uint64 w11 = load_bigendian(in + 88);
uint64 w12 = load_bigendian(in + 96);
uint64 w13 = load_bigendian(in + 104);
uint64 w14 = load_bigendian(in + 112);
uint64 w15 = load_bigendian(in + 120);
F(w0 ,0x428a2f98d728ae22ULL)
F(w1 ,0x7137449123ef65cdULL)
F(w2 ,0xb5c0fbcfec4d3b2fULL)
F(w3 ,0xe9b5dba58189dbbcULL)
F(w4 ,0x3956c25bf348b538ULL)
F(w5 ,0x59f111f1b605d019ULL)
F(w6 ,0x923f82a4af194f9bULL)
F(w7 ,0xab1c5ed5da6d8118ULL)
F(w8 ,0xd807aa98a3030242ULL)
F(w9 ,0x12835b0145706fbeULL)
F(w10,0x243185be4ee4b28cULL)
F(w11,0x550c7dc3d5ffb4e2ULL)
F(w12,0x72be5d74f27b896fULL)
F(w13,0x80deb1fe3b1696b1ULL)
F(w14,0x9bdc06a725c71235ULL)
F(w15,0xc19bf174cf692694ULL)
EXPAND
F(w0 ,0xe49b69c19ef14ad2ULL)
F(w1 ,0xefbe4786384f25e3ULL)
F(w2 ,0x0fc19dc68b8cd5b5ULL)
F(w3 ,0x240ca1cc77ac9c65ULL)
F(w4 ,0x2de92c6f592b0275ULL)
F(w5 ,0x4a7484aa6ea6e483ULL)
F(w6 ,0x5cb0a9dcbd41fbd4ULL)
F(w7 ,0x76f988da831153b5ULL)
F(w8 ,0x983e5152ee66dfabULL)
F(w9 ,0xa831c66d2db43210ULL)
F(w10,0xb00327c898fb213fULL)
F(w11,0xbf597fc7beef0ee4ULL)
F(w12,0xc6e00bf33da88fc2ULL)
F(w13,0xd5a79147930aa725ULL)
F(w14,0x06ca6351e003826fULL)
F(w15,0x142929670a0e6e70ULL)
EXPAND
F(w0 ,0x27b70a8546d22ffcULL)
F(w1 ,0x2e1b21385c26c926ULL)
F(w2 ,0x4d2c6dfc5ac42aedULL)
F(w3 ,0x53380d139d95b3dfULL)
F(w4 ,0x650a73548baf63deULL)
F(w5 ,0x766a0abb3c77b2a8ULL)
F(w6 ,0x81c2c92e47edaee6ULL)
F(w7 ,0x92722c851482353bULL)
F(w8 ,0xa2bfe8a14cf10364ULL)
F(w9 ,0xa81a664bbc423001ULL)
F(w10,0xc24b8b70d0f89791ULL)
F(w11,0xc76c51a30654be30ULL)
F(w12,0xd192e819d6ef5218ULL)
F(w13,0xd69906245565a910ULL)
F(w14,0xf40e35855771202aULL)
F(w15,0x106aa07032bbd1b8ULL)
EXPAND
F(w0 ,0x19a4c116b8d2d0c8ULL)
F(w1 ,0x1e376c085141ab53ULL)
F(w2 ,0x2748774cdf8eeb99ULL)
F(w3 ,0x34b0bcb5e19b48a8ULL)
F(w4 ,0x391c0cb3c5c95a63ULL)
F(w5 ,0x4ed8aa4ae3418acbULL)
F(w6 ,0x5b9cca4f7763e373ULL)
F(w7 ,0x682e6ff3d6b2b8a3ULL)
F(w8 ,0x748f82ee5defb2fcULL)
F(w9 ,0x78a5636f43172f60ULL)
F(w10,0x84c87814a1f0ab72ULL)
F(w11,0x8cc702081a6439ecULL)
F(w12,0x90befffa23631e28ULL)
F(w13,0xa4506cebde82bde9ULL)
F(w14,0xbef9a3f7b2c67915ULL)
F(w15,0xc67178f2e372532bULL)
EXPAND
F(w0 ,0xca273eceea26619cULL)
F(w1 ,0xd186b8c721c0c207ULL)
F(w2 ,0xeada7dd6cde0eb1eULL)
F(w3 ,0xf57d4f7fee6ed178ULL)
F(w4 ,0x06f067aa72176fbaULL)
F(w5 ,0x0a637dc5a2c898a6ULL)
F(w6 ,0x113f9804bef90daeULL)
F(w7 ,0x1b710b35131c471bULL)
F(w8 ,0x28db77f523047d84ULL)
F(w9 ,0x32caab7b40c72493ULL)
F(w10,0x3c9ebe0a15c9bebcULL)
F(w11,0x431d67c49c100d4cULL)
F(w12,0x4cc5d4becb3e42b6ULL)
F(w13,0x597f299cfc657e2aULL)
F(w14,0x5fcb6fab3ad6faecULL)
F(w15,0x6c44198c4a475817ULL)
a += state[0];
b += state[1];
c += state[2];
d += state[3];
e += state[4];
f += state[5];
g += state[6];
h += state[7];
state[0] = a;
state[1] = b;
state[2] = c;
state[3] = d;
state[4] = e;
state[5] = f;
state[6] = g;
state[7] = h;
in += 128;
inlen -= 128;
}
store_bigendian(statebytes + 0,state[0]);
store_bigendian(statebytes + 8,state[1]);
store_bigendian(statebytes + 16,state[2]);
store_bigendian(statebytes + 24,state[3]);
store_bigendian(statebytes + 32,state[4]);
store_bigendian(statebytes + 40,state[5]);
store_bigendian(statebytes + 48,state[6]);
store_bigendian(statebytes + 56,state[7]);
return (int)inlen;
}
static const unsigned char iv[64] = {
0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
} ;
typedef unsigned long long uint64;
int crypto_sha512(const unsigned char *in, unsigned long long inlen, unsigned char *out)
{
unsigned char h[64];
unsigned char padded[256];
int i;
unsigned long long bytes = inlen;
for (i = 0;i < 64;++i) h[i] = iv[i];
crypto_hashblocks_sha512(h,in,inlen);
in += inlen;
inlen &= 127;
in -= inlen;
for (i = 0;i < inlen;++i) padded[i] = in[i];
padded[inlen] = 0x80;
if (inlen < 112) {
for (i = (int)inlen + 1;i < 119;++i) padded[i] = 0;
padded[119] = (unsigned char)(bytes >> 61);
padded[120] = (unsigned char)(bytes >> 53);
padded[121] = (unsigned char)(bytes >> 45);
padded[122] = (unsigned char)(bytes >> 37);
padded[123] = (unsigned char)(bytes >> 29);
padded[124] = (unsigned char)(bytes >> 21);
padded[125] = (unsigned char)(bytes >> 13);
padded[126] = (unsigned char)(bytes >> 5);
padded[127] = (unsigned char)(bytes << 3);
crypto_hashblocks_sha512(h,padded,128);
} else {
for (i = (int)inlen + 1;i < 247;++i) padded[i] = 0;
padded[247] = (unsigned char)(bytes >> 61);
padded[248] = (unsigned char)(bytes >> 53);
padded[249] = (unsigned char)(bytes >> 45);
padded[250] = (unsigned char)(bytes >> 37);
padded[251] = (unsigned char)(bytes >> 29);
padded[252] = (unsigned char)(bytes >> 21);
padded[253] = (unsigned char)(bytes >> 13);
padded[254] = (unsigned char)(bytes >> 5);
padded[255] = (unsigned char)(bytes << 3);
crypto_hashblocks_sha512(h,padded,256);
}
for (i = 0;i < 64;++i) out[i] = h[i];
return 0;
}

20
sha512/sha512.h Normal file
Просмотреть файл

@ -0,0 +1,20 @@
#ifndef __SHA512_H__
#define __SHA512_H__
// For C++
#ifdef __cplusplus
extern "C" {
#endif
// Hashing using SHA-512. Output is 64 bytes long
int crypto_sha512(const unsigned char *in, unsigned long long inlen, unsigned char *out);
#ifdef __cplusplus
}
#endif
#endif