Skip to content

Commit fdc81e2

Browse files
committed
Further EC implementation & scaffolding
1 parent 0d54839 commit fdc81e2

File tree

2 files changed

+459
-1
lines changed

2 files changed

+459
-1
lines changed

Classes/FCryptoBigInt.uc

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,34 @@ static final function MemSet_UInt16(
310310
}
311311
}
312312

313+
// See MemSet_UInt16.
314+
// TODO: move to dedicated memory class.
315+
static final function MemSet_UInt16_Static37(
316+
out int S[37],
317+
byte C,
318+
int NumBytes,
319+
optional int Offset = 0
320+
)
321+
{
322+
local int IntIndex;
323+
local int ByteIndex;
324+
local int Shift;
325+
local int Mask;
326+
327+
Shift = 8;
328+
Mask = 0xff << Shift;
329+
IntIndex = Offset;
330+
for (ByteIndex = 0; ByteIndex < NumBytes; ++ByteIndex)
331+
{
332+
S[IntIndex] = (S[IntIndex] & ~Mask) | ((C & 0xff) << Shift);
333+
// Shift = (Shift + 8) % 16;
334+
Shift = (Shift + 8) & 15;
335+
// IntIndex += ByteIndex % 2;
336+
IntIndex += ByteIndex & 1;
337+
Mask = 0xff << Shift;
338+
}
339+
}
340+
313341
/**
314342
* C-style memset operation.
315343
* Offset is the number of byte values
@@ -330,6 +358,22 @@ static final function MemSet_Byte(
330358
}
331359
}
332360

361+
// See MemSet_Byte.
362+
static final function MemSet_Byte_Static66(
363+
out byte S[66],
364+
byte C,
365+
int NumBytes,
366+
optional int Offset = 0
367+
)
368+
{
369+
local int ByteIndex;
370+
371+
for (ByteIndex = Offset; ByteIndex < NumBytes; ++ByteIndex)
372+
{
373+
S[ByteIndex] = C;
374+
}
375+
}
376+
333377
/**
334378
* C-style memcpy operation.
335379
* Offsets are the number of uint16_t values
@@ -442,6 +486,18 @@ static final function Zero(
442486
MemSet_UInt16(X, 0, ((BitLen + 15) >>> 4) * SIZEOF_UINT16_T, 1);
443487
}
444488

489+
// See Zero.
490+
static final function Zero_Static37(
491+
out int X[37],
492+
int BitLen
493+
)
494+
{
495+
// *x ++ = bit_len;
496+
// memset(x, 0, ((bit_len + 15) >> 4) * sizeof *x);
497+
X[0] = BitLen & 0xFFFF; // @ALIGN-32-16.
498+
MemSet_UInt16_Static37(X, 0, ((BitLen + 15) >>> 4) * SIZEOF_UINT16_T, 1);
499+
}
500+
445501
/*
446502
* Add b[] to a[] and return the carry (0 or 1). If ctl is 0, then a[]
447503
* is unmodified, but the carry is still computed and returned. The
@@ -477,6 +533,64 @@ static final function int Add(
477533
return Cc;
478534
}
479535

536+
// See Add.
537+
static final function int Add_Static37(
538+
out int A[37],
539+
const out int B[37],
540+
int Ctl
541+
)
542+
{
543+
local int Cc;
544+
local int U;
545+
local int M;
546+
local int Aw;
547+
local int Bw;
548+
local int Naw;
549+
550+
Cc = 0;
551+
M = (A[0] + 31) >>> 4;
552+
553+
for (U = 1; U < M; ++U)
554+
{
555+
Aw = A[U];
556+
Bw = B[U];
557+
Naw = Aw + Bw + Cc;
558+
Cc = Naw >>> 15;
559+
A[U] = MUX(Ctl, Naw & 0x7FFF, Aw) & 0xFFFF; // @ALIGN-32-16.
560+
}
561+
562+
return Cc;
563+
}
564+
565+
// See Add.
566+
static final function int Add_Static37_DynB(
567+
out int A[37],
568+
const out array<int> B,
569+
int Ctl
570+
)
571+
{
572+
local int Cc;
573+
local int U;
574+
local int M;
575+
local int Aw;
576+
local int Bw;
577+
local int Naw;
578+
579+
Cc = 0;
580+
M = (A[0] + 31) >>> 4;
581+
582+
for (U = 1; U < M; ++U)
583+
{
584+
Aw = A[U];
585+
Bw = B[U];
586+
Naw = Aw + Bw + Cc;
587+
Cc = Naw >>> 15;
588+
A[U] = MUX(Ctl, Naw & 0x7FFF, Aw) & 0xFFFF; // @ALIGN-32-16.
589+
}
590+
591+
return Cc;
592+
}
593+
480594
/*
481595
* Subtract b[] from a[] and return the carry (0 or 1). If ctl is 0,
482596
* then a[] is unmodified, but the carry is still computed and returned.
@@ -517,6 +631,65 @@ static final function int Sub(
517631
return Cc;
518632
}
519633

634+
// See Sub.
635+
static final function int Sub_Static37_DynB(
636+
out int A[37],
637+
const out array<int> B,
638+
int Ctl
639+
)
640+
{
641+
local int Cc;
642+
local int U;
643+
local int M;
644+
local int Aw;
645+
local int Bw;
646+
local int Naw;
647+
648+
Cc = 0;
649+
M = (A[0] + 31) >>> 4;
650+
651+
for (U = 1; U < M; ++U)
652+
{
653+
Aw = A[U];
654+
Bw = B[U];
655+
Naw = Aw - Bw - Cc;
656+
CC = Naw >>> 31;
657+
A[U] = MUX(Ctl, Naw & 0x7FFF, Aw) & 0xFFFF; // @ALIGN-32-16.
658+
}
659+
660+
return Cc;
661+
}
662+
663+
// See Sub.
664+
static final function int Sub_Static37(
665+
out int A[37],
666+
const out int B[37],
667+
int Ctl
668+
)
669+
{
670+
local int Cc;
671+
local int U;
672+
local int M;
673+
local int Aw;
674+
local int Bw;
675+
local int Naw;
676+
677+
Cc = 0;
678+
M = (A[0] + 31) >>> 4;
679+
680+
for (U = 1; U < M; ++U)
681+
{
682+
Aw = A[U];
683+
Bw = B[U];
684+
Naw = Aw - Bw - Cc;
685+
CC = Naw >>> 31;
686+
A[U] = MUX(Ctl, Naw & 0x7FFF, Aw) & 0xFFFF; // @ALIGN-32-16.
687+
}
688+
689+
return Cc;
690+
}
691+
692+
520693
/*
521694
* Compute the actual bit length of an integer. The argument X should
522695
* point to the first (least significant) value word of the integer.
@@ -1161,6 +1334,54 @@ static final function Encode(
11611334
}
11621335
}
11631336

1337+
// See Encode.
1338+
static final function Encode_Static66(
1339+
out byte Dst[66],
1340+
int Len,
1341+
const out array<int> X
1342+
)
1343+
{
1344+
local int U;
1345+
local int XLen;
1346+
local int Acc;
1347+
local int AccLen;
1348+
1349+
XLen = (X[0] + 15) >>> 4;
1350+
if (XLen == 0)
1351+
{
1352+
// NOTE: BearSSL assumes all parameters are user-allocated.
1353+
// In UnrealScript we'll make an exception here to avoid a bug
1354+
// where MemSet is called with Len == 0. TODO: SHOULD WE DO THIS?
1355+
// Probably no way to avoid this since we are not dealing with
1356+
// pointers in UScript like original BearSSL code does.
1357+
if (Len == 0)
1358+
{
1359+
Len = 1;
1360+
}
1361+
1362+
// memset(dst, 0, len);
1363+
MemSet_Byte_Static66(Dst, 0, Len);
1364+
return;
1365+
}
1366+
U = 1;
1367+
Acc = 0;
1368+
AccLen = 0;
1369+
while (Len-- > 0)
1370+
{
1371+
if (AccLen < 8)
1372+
{
1373+
if (U <= XLen)
1374+
{
1375+
Acc += X[U++] << AccLen;
1376+
}
1377+
AccLen += 15;
1378+
}
1379+
Dst[Len] = Acc;
1380+
Acc = Acc >>> 8;
1381+
AccLen -= 8;
1382+
}
1383+
}
1384+
11641385
/*
11651386
* Convert a modular integer back from Montgomery representation. The
11661387
* integer x[] MUST be lower than m[], but with the same announced bit
@@ -1847,6 +2068,38 @@ static final function ModPow(
18472068
}
18482069
}
18492070

2071+
// See ModPow.
2072+
static final function ModPow_S37_S66_Dyn_S37_S37(
2073+
out int X[37],
2074+
const out byte E[66],
2075+
int ELen,
2076+
const out array<int> M,
2077+
int M0I,
2078+
out int T1[37],
2079+
out int T2[37]
2080+
)
2081+
{
2082+
local int MLen;
2083+
local int K;
2084+
local int Ctl;
2085+
2086+
// TODO: body for this func.
2087+
2088+
MLen = ((M[0] + 31) >>> 4) * SIZEOF_UINT16_T;
2089+
// MemCpy(T1, X, MLen);
2090+
// ToMonty(T1, M);
2091+
// Zero(X, M[0]);
2092+
// X[1] = 1;
2093+
// for (K = 0; K < (ELen << 3); ++K)
2094+
// {
2095+
// Ctl = (E[ELen - 1 - (K >>> 3)] >>> (K & 7)) & 1;
2096+
// MontyMul_S37_S37_S37_DynM(T2, X, T1, M, M0I);
2097+
// CCOPY(Ctl, X, T2, MLen);
2098+
// MontyMul_S37_S37_S37_DynM(T2, T1, T1, M, M0I);
2099+
// MemCpy(T1, T2, MLen);
2100+
// }
2101+
}
2102+
18502103
/*
18512104
* Compute a modular Montgomery multiplication. d[] is filled with the
18522105
* value of x*y/R modulo m[] (where R is the Montgomery factor). The
@@ -1925,6 +2178,76 @@ static final function MontyMul(
19252178
Sub(D, M, NEQ(DH, 0) | NOT(Sub(D, M, 0)));
19262179
}
19272180

2181+
// See MontyMul.
2182+
static final function MontyMul_S37_S37_S37_DynM(
2183+
out int D[37],
2184+
const out int X[37],
2185+
const out int Y[37],
2186+
const out array<int> M,
2187+
int M0I
2188+
)
2189+
{
2190+
local int Len;
2191+
local int Len4;
2192+
local int U;
2193+
local int V;
2194+
local int Dh;
2195+
local int F;
2196+
local int Xu;
2197+
local int R;
2198+
local int Zh;
2199+
local int Z;
2200+
2201+
Len = (M[0] + 15) >>> 4;
2202+
Len4 = Len & ~3;
2203+
Zero_Static37(D, M[0]);
2204+
Dh = 0;
2205+
for (U = 0; U < Len; ++U)
2206+
{
2207+
Xu = X[U + 1];
2208+
// f = MUL15((d[1] + MUL15(x[u + 1], y[1])) & 0x7FFF, m0i) & 0x7FFF;
2209+
F = (((D[1] + (X[U + 1] * Y[1])) & 0x7FFF) * M0I) & 0x7FFF;
2210+
R = 0;
2211+
for (V = 0; V < Len4; V += 4)
2212+
{
2213+
Z = D[V + 1] + (Xu * Y[V + 1]) + (F * M[V + 1]) + R;
2214+
R = Z >>> 15;
2215+
D[V/*+0*/] = Z & 0x7FFF;
2216+
Z = D[V + 2] + (Xu * Y[V + 2]) + (F * M[V + 2]) + R;
2217+
R = Z >>> 15;
2218+
D[V + 1] = Z & 0x7FFF;
2219+
Z = D[V + 3] + (Xu * Y[V + 3]) + (F * M[V + 3]) + R;
2220+
R = Z >>> 15;
2221+
D[V + 2] = Z & 0x7FFF;
2222+
Z = D[V + 4] + (Xu * Y[V + 4]) + (F * M[V + 4]) + R;
2223+
R = Z >>> 15;
2224+
D[V + 3] = Z & 0x7FFF;
2225+
}
2226+
2227+
for (Z = 0; V < Len; ++V)
2228+
{
2229+
Z = D[V + 1] + (Xu * Y[V + 1]) + (F * M[V + 1]) + R;
2230+
R = Z >>> 15;
2231+
D[V/*+0*/] = Z & 0x7FFF;
2232+
}
2233+
2234+
Zh = Dh + R;
2235+
D[Len] = Zh & 0x7FFF;
2236+
Dh = Zh >>> 15;
2237+
}
2238+
2239+
/*
2240+
* Restore the bit length (it was overwritten in the loop above).
2241+
*/
2242+
D[0] = M[0];
2243+
2244+
/*
2245+
* d[] may be greater than m[], but it is still lower than twice
2246+
* the modulus.
2247+
*/
2248+
Sub_Static37_DynB(D, M, NEQ(DH, 0) | NOT(Sub_Static37_DynB(D, M, 0)));
2249+
}
2250+
19282251
/*
19292252
* Compute a modular exponentiation. x[] MUST be an integer modulo m[]
19302253
* (same announced bit length, lower value). m[] MUST be odd. The

0 commit comments

Comments
 (0)