fcl-hash: fixed freeing TBigIntContext.BIRadix and migrated to mode objfpc

This commit is contained in:
mattias 2022-04-28 23:10:01 +02:00
parent 67905957cb
commit 864b2ad3f3
3 changed files with 121 additions and 147 deletions

View File

@ -335,7 +335,7 @@ begin
begin begin
Line:=sl[i]; Line:=sl[i];
if not PemLineIsBase64(Line) then if not PemLineIsBase64(Line) then
exit; raise Exception.Create('20220428220523');
TxtBase64:=TxtBase64+Line; TxtBase64:=TxtBase64+Line;
end; end;
Result:=basenenc.Base64.Decode(TxtBase64,True); Result:=basenenc.Base64.Decode(TxtBase64,True);

View File

@ -159,10 +159,9 @@ begin
try try
ASNParse(PublicKeyDER,List); ASNParse(PublicKeyDER,List);
//for i:=0 to List.Count-1 do begin {$IFDEF TLS_DEBUG}
// ASNParse_GetItem(List,i,ASNType,ASNSize); ASNDebugList('X509RsaPublicKeyInitFromDER',List);
// writeln('X509RsaPublicKeyInitFromDER ',i,'/',List.Count,' ASNType=',hexstr(ASNType,2),' ASNSize=',ASNSize,' S="',List[i],'"'); {$ENDIF}
//end;
if List.Count<7 then if List.Count<7 then
raise Exception.Create('20220428180055'); raise Exception.Create('20220428180055');
@ -186,7 +185,6 @@ begin
// check null // check null
ASNParse_GetItem(List,3,ASNType,ASNSize); ASNParse_GetItem(List,3,ASNType,ASNSize);
writeln('X509RsaPublicKeyInitFromDER ',ASNType,' ',ASNSize);
if ASNType<>ASN1_NULL then if ASNType<>ASN1_NULL then
raise Exception.Create('20220428181659'); raise Exception.Create('20220428181659');
@ -206,8 +204,8 @@ begin
{$IFDEF TLS_DEBUG} {$IFDEF TLS_DEBUG}
writeln('X509RsaPublicKeyInitFromDER: '); writeln('X509RsaPublicKeyInitFromDER: ');
writeln(' Modulus=',BytesToHexStr(RSA.Modulus)); writeln(' Modulus=$',BytesToHexStr(RSA.Modulus));
writeln(' Exponent=',BytesToHexStr(RSA.Exponent)); writeln(' Exponent=$',BytesToHexStr(RSA.Exponent));
{$ENDIF} {$ENDIF}
finally finally
List.Free; List.Free;
@ -330,12 +328,12 @@ begin
if Len > Size-11 then if Len > Size-11 then
Exit; Exit;
{$IFDEF CRYPTO_DEBUG} {$IFDEF CRYPTO_DEBUG}
writeln('RSAEncryptSign - Len = ' + IntToStr(Len) + ' Size = ' + IntToStr(Size) + ' Padding = ' + IntToStr(Padding)); //To Do writeln('RSAEncryptSign - Len = ' + IntToStr(Len) + ' Size = ' + IntToStr(Size) + ' Padding = ' + IntToStr(Padding)); //To Do
{$ENDIF} {$ENDIF}
if Size > RSA_MODULUS_BYTES_MAX then if Size > RSA_MODULUS_BYTES_MAX then
Imported := GetMem(Size) Imported := GetMem(Size)
else else
Imported := @Block; Imported := @Block[0];
try try
// Leading zero to ensure encryption block is less than modulus (when converted to an integer) // Leading zero to ensure encryption block is less than modulus (when converted to an integer)
Imported[0]:=0; Imported[0]:=0;
@ -373,14 +371,14 @@ begin
if Sign then if Sign then
begin begin
// Sign with Private Key // Sign with Private Key
Encrypted:=BICRT(RSA.Context,Decrypted,RSA.DP,RSA.DQ,RSA.P,RSA.Q,RSA.QInv); Encrypted:=BICRT(RSA.Context,Decrypted,RSA.DP,RSA.DQ,RSA.P,RSA.Q,RSA.QInv); // this releases Decrypted
end else end else
begin begin
// Encrypt with Public Key // Encrypt with Public Key
RSA.Context.ModOffset:=BIGINT_M_OFFSET; RSA.Context.ModOffset:=BIGINT_M_OFFSET;
Encrypted:=BIModPower(RSA.Context,Decrypted,RSA.E); Encrypted:=BIModPower(RSA.Context,Decrypted,RSA.E); // this releases Decrypted
end; end;
BIExport(RSA.Context,Encrypted,Output,Size); BIExport(RSA.Context,Encrypted,Output,Size); // this releases Encrypted
{$IFDEF CRYPTO_DEBUG} {$IFDEF CRYPTO_DEBUG}
writeln('RSAEncryptSign - Output Size = ' + IntToStr(Size) + ' Output = ',Output,Size); writeln('RSAEncryptSign - Output Size = ' + IntToStr(Size) + ' Output = ',Output,Size);

View File

@ -13,7 +13,7 @@ interface
uses SysUtils; uses SysUtils;
{ $DEFINE BIGINT_DEBUG} // Enable debug output/functions for BitInt unit {$DEFINE BIGINT_DEBUG} // Enable debug output/functions for BitInt unit
const const
// Maintain a number of precomputed variables when doing reduction // Maintain a number of precomputed variables when doing reduction
@ -43,9 +43,6 @@ type
PBISignedLongComponent = ^TBISignedLongComponent; PBISignedLongComponent = ^TBISignedLongComponent;
TBISignedLongComponent = Int64; // A signed double precision component TBISignedLongComponent = Int64; // A signed double precision component
PBIComponents = ^TBIComponents;
TBIComponents = array[0..(MaxInt div SizeOf(TBIComponent))-1] of TBIComponent;
type type
PPBigInt = ^PBigInt; PPBigInt = ^PBigInt;
PBigInt = ^TBigInt; PBigInt = ^TBigInt;
@ -57,8 +54,6 @@ type
Components: PBIComponent; // A ptr to the actual component data Components: PBIComponent; // A ptr to the actual component data
procedure ToString(out S: AnsiString); procedure ToString(out S: AnsiString);
end; end;
PBigInts = ^TBigInts;
TBigInts = array[0..(MaxInt div SizeOf(PBigInt)) - 1] of PBigInt;
{Maintains the state of the cache, and a number of variables used in reduction} {Maintains the state of the cache, and a number of variables used in reduction}
PBigIntContext = ^TBigIntContext; PBigIntContext = ^TBigIntContext;
@ -80,12 +75,12 @@ procedure BIInitialize(out Context: TBigIntContext);
procedure BITerminate(var Context: TBigIntContext); procedure BITerminate(var Context: TBigIntContext);
procedure BIPermanent(BI: PBigInt); procedure BIPermanent(BI: PBigInt);
procedure BIDepermanent(BI: PBigInt); procedure BIDepermanent(BI: PBigInt);
procedure BIRelease(var Context: TBigIntContext; BI:PBigInt); procedure BIRelease(var Context: TBigIntContext; BI: PBigInt);
function BICopy(BI: PBigInt): PBigInt; function BICopy(BI: PBigInt): PBigInt;
function BIClone(var Context: TBigIntContext; const BI: TBigInt): PBigInt; function BIClone(var Context: TBigIntContext; const BI: TBigInt): PBigInt;
procedure BIExport(var Context: TBigIntContext; BI: PBigInt; Data: PByte; Size: Integer); procedure BIExport(var Context: TBigIntContext; BI: PBigInt; Data: PByte; Size: Integer; Release: boolean = true);
function BIImport(var Context: TBigIntContext; Data: PByte; const Size: Integer): PBigInt; overload; function BIImport(var Context: TBigIntContext; Data: PByte; const Size: Integer): PBigInt; overload;
function BIImport(var Context: TBigIntContext; const Data: TBytes): PBigInt; overload; function BIImport(var Context: TBigIntContext; const Data: TBytes): PBigInt; overload;
function BIImport(var Context: TBigIntContext; const Data: AnsiString): PBigInt; overload; function BIImport(var Context: TBigIntContext; const Data: AnsiString): PBigInt; overload;
@ -142,23 +137,19 @@ end;
{Perform a sanity check on bi} {Perform a sanity check on bi}
function BICheck(const BI: TBigInt): Boolean; inline; function BICheck(const BI: TBigInt): Boolean; inline;
begin begin
{$IFDEF BIGINT_DEBUG} {$IFDEF BIGINT_DEBUG}
if BI.References <= 0 then if BI.References <= 0 then
begin begin
XLog(tlDebug, 'TLS', 'BICheck - Zero or negative References in TBigInt'); writeln('BICheck - Zero or negative References in TBigInt');
Result := False; raise Exception.Create('20220428201452');
Exit;
end; end;
if BI.Next <> nil then if BI.Next <> nil then
begin begin
XLog(tlDebug, 'TLS', 'BICheck - Attempt to use a TBigInt from the free list'); writeln('BICheck - Attempt to use a TBigInt from the free list');
Result := False; raise Exception.Create('20220428201508');
Exit;
end; end;
{$ENDIF}
Result:=True; Result:=True;
{$ELSE}
Result:=True;
{$ENDIF}
end; end;
// Delete any leading 0's (and allow for 0) // Delete any leading 0's (and allow for 0)
@ -166,14 +157,11 @@ procedure BITrim(BI: PBigInt);
begin begin
if not BICheck(BI^) then if not BICheck(BI^) then
Exit; Exit;
while (PBIComponents(BI^.Components)^[BI^.Size-1] = 0) and (BI^.Size > 1) do while (BI^.Components[BI^.Size-1] = 0) and (BI^.Size > 1) do
Dec(BI^.Size); Dec(BI^.Size);
end; end;
procedure BIAddComponents(var Context: TBigIntContext; BI: PBigInt; N: Integer); procedure BIResizeComponents(BI: PBigInt; N: Integer);
var
OldComponents: PBIComponent;
OldMaxComponents: Int32;
begin begin
if N > BI^.MaxComponents then if N > BI^.MaxComponents then
begin begin
@ -181,7 +169,7 @@ begin
ReAllocMem(BI^.Components, BI^.MaxComponents*BIGINT_COMP_BYTE_SIZE); ReAllocMem(BI^.Components, BI^.MaxComponents*BIGINT_COMP_BYTE_SIZE);
end; end;
if N > BI^.Size then if N > BI^.Size then
FillChar(PBIComponents(BI^.Components)^[BI^.Size], (N-BI^.Size)*BIGINT_COMP_BYTE_SIZE, 0); FillByte(BI^.Components[BI^.Size], (N-BI^.Size)*BIGINT_COMP_BYTE_SIZE, 0);
BI^.Size := N; BI^.Size := N;
end; end;
@ -190,21 +178,18 @@ begin
if Context.FreeList <> nil then if Context.FreeList <> nil then
begin begin
Result := Context.FreeList; Result := Context.FreeList;
if Result^.References <> 0 then
raise Exception.Create('20220428200026');
Context.FreeList := Result^.Next; Context.FreeList := Result^.Next;
Dec(Context.FreeCount); Dec(Context.FreeCount);
if Result^.References <> 0 then BIResizeComponents(Result, Size);
begin
Result := nil;
Exit;
end;
BIAddComponents(Context, Result, Size);
end else end else
begin begin
Result := AllocMem(SizeOf(TBigint)); Result := AllocMem(SizeOf(TBigint));
Result^.Components := AllocMem((Size*2)*BIGINT_COMP_BYTE_SIZE); Result^.Components := AllocMem((Size*2)*BIGINT_COMP_BYTE_SIZE);
Result^.MaxComponents := Size*2; // Allow space to expand Result^.MaxComponents := Size*2; // Allow space to expand
Result^.Size := Size;
end; end;
Result^.Size := Size;
Result^.References := 1; Result^.References := 1;
Result^.Next := nil; Result^.Next := nil;
Inc(Context.ActiveCount); Inc(Context.ActiveCount);
@ -218,7 +203,7 @@ var
begin begin
I := BIGINT_COMP_BIT_SIZE-1; I := BIGINT_COMP_BIT_SIZE-1;
Shift:=BIGINT_COMP_RADIX div 2; Shift:=BIGINT_COMP_RADIX div 2;
Test:=PBIComponents(BIExp^.Components)^[BIExp^.Size - 1]; {Assume no leading zeroes} Test:=BIExp^.Components[BIExp^.Size - 1]; {Assume no leading zeroes}
if not BICheck(BIExp^) then if not BICheck(BIExp^) then
begin begin
Result:=-1; Result:=-1;
@ -242,12 +227,12 @@ var
NumShifts: Integer; NumShifts: Integer;
Shift, Test: TBIComponent; Shift, Test: TBIComponent;
begin begin
Test := PBIComponents(BIExp^.Components)^[Offset div BIGINT_COMP_BIT_SIZE]; Test := BIExp^.Components[Offset div BIGINT_COMP_BIT_SIZE];
NumShifts := Offset mod BIGINT_COMP_BIT_SIZE; NumShifts := Offset mod BIGINT_COMP_BIT_SIZE;
if not BICheck(BIExp^) then if not BICheck(BIExp^) then
begin begin
Result := False; Result := False;
Exit; Exit;
end; end;
Shift := 1 shl NumShifts; Shift := 1 shl NumShifts;
Result := (Test and Shift) <> 0; Result := (Test and Shift) <> 0;
@ -274,7 +259,7 @@ begin
A := BIA^.Components; A := BIA^.Components;
FillChar(R^, (N+1) * BIGINT_COMP_BYTE_SIZE, 0); FillChar(R^, (N+1) * BIGINT_COMP_BYTE_SIZE, 0);
repeat repeat
Tmp := R^ + TBILongComponent(PBIComponents(A)^[J]) * B + Carry; // Avoid overflow Tmp := R^ + TBILongComponent(A[J]) * B + Carry; // Avoid overflow
R^ := Tmp; // Downsize R^ := Tmp; // Downsize
Inc(R); Inc(R);
Carry := Tmp shr BIGINT_COMP_BIT_SIZE; Carry := Tmp shr BIGINT_COMP_BIT_SIZE;
@ -285,7 +270,7 @@ begin
BITrim(Result); BITrim(Result);
end; end;
function BIIntDivide(var Context: TBigIntContext; BIR: PBigInt; Denom: TBIComponent): PBigInt; function BIIntDivide(BIR: PBigInt; Denom: TBIComponent): PBigInt;
var var
I: Integer; I: Integer;
R: TBILongComponent; R: TBILongComponent;
@ -298,8 +283,8 @@ begin
I := BIR^.Size-1; I := BIR^.Size-1;
R := 0; R := 0;
repeat repeat
R := (R shl BIGINT_COMP_BIT_SIZE) + PBIComponents(BIR^.Components)^[I]; R := (R shl BIGINT_COMP_BIT_SIZE) + BIR^.Components[I];
PBIComponents(BIR^.Components)^[I] := R div Denom; BIR^.Components[I] := R div Denom;
R := R mod Denom; R := R mod Denom;
Dec(I); Dec(I);
until I < 0; until I < 0;
@ -320,10 +305,10 @@ begin
end; end;
I := BIR^.Size-NumShifts; I := BIR^.Size-NumShifts;
X := BIR^.Components; X := BIR^.Components;
Y := @PBIComponents(BIR^.Components)^[NumShifts]; Y := @BIR^.Components[NumShifts];
if I <= 0 then // Have we completely right shifted? if I <= 0 then // Have we completely right shifted?
begin begin
PBIComponents(BIR^.Components)^[0]:=0; {Return 0} BIR^.Components[0]:=0; {Return 0}
BIR^.Size:=1; BIR^.Size:=1;
Result:=BIR; Result:=BIR;
Exit; Exit;
@ -339,7 +324,7 @@ begin
end; end;
// Take each component and shift it up (in terms of components) // Take each component and shift it up (in terms of components)
function BICompLeftShift(var Context: TBigIntContext; BIR: PBigInt; NumShifts: Integer): PBigInt; function BICompLeftShift(BIR: PBigInt; NumShifts: Integer): PBigInt;
var var
I: Integer; I: Integer;
X: PBIComponent; X: PBIComponent;
@ -356,16 +341,16 @@ begin
Result:=BIR; Result:=BIR;
Exit; Exit;
end; end;
BIAddComponents(Context, BIR, BIR^.Size+NumShifts); BIResizeComponents(BIR, BIR^.Size+NumShifts);
X := @(PBIComponents(BIR^.Components)^[I + NumShifts]); X := @(BIR^.Components[I + NumShifts]);
Y := @(PBIComponents(BIR^.Components)^[I]); Y := @(BIR^.Components[I]);
repeat repeat
X^ := Y^; X^ := Y^;
Dec(X); Dec(X);
Dec(Y); Dec(Y);
Dec(I); Dec(I);
until I < 0; until I < 0;
FillChar(BIR^.Components^, NumShifts*BIGINT_COMP_BYTE_SIZE, 0); // Zero least significant components FillByte(BIR^.Components^, NumShifts*BIGINT_COMP_BYTE_SIZE, 0); // Zero least significant components
Result := BIR; Result := BIR;
end; end;
@ -390,7 +375,7 @@ begin
SR := BIR^.Components; SR := BIR^.Components;
SA := BIA^.Components; SA := BIA^.Components;
SB := BIB^.Components; SB := BIB^.Components;
FillChar(BIR^.Components^, (N+T) * BIGINT_COMP_BYTE_SIZE, 0); FillByte(BIR^.Components^, (N+T) * BIGINT_COMP_BYTE_SIZE, 0);
repeat repeat
Carry := 0; Carry := 0;
RIndex := I; RIndex := I;
@ -403,13 +388,13 @@ begin
repeat repeat
if (InnerPartial > 0) and (RIndex >= InnerPartial) then if (InnerPartial > 0) and (RIndex >= InnerPartial) then
Break; Break;
Tmp := PBIComponents(SR)^[RIndex] + TBILongComponent(PBIComponents(SA)^[J]) * PBIComponents(SB)^[I] + Carry; // Avoid overflow Tmp := SR[RIndex] + TBILongComponent(SA[J]) * SB[I] + Carry; // Avoid overflow
PBIComponents(SR)^[RIndex] := Tmp; // Downsize SR[RIndex] := Tmp; // Downsize
Inc(RIndex); Inc(RIndex);
Carry := Tmp shr BIGINT_COMP_BIT_SIZE; Carry := Tmp shr BIGINT_COMP_BIT_SIZE;
Inc(J); Inc(J);
until J >= N; until J >= N;
PBIComponents(SR)^[RIndex] := Carry; SR[RIndex] := Carry;
Inc(I); Inc(I);
until I >= T; until I >= T;
BIRelease(Context,BIA); BIRelease(Context,BIA);
@ -435,32 +420,32 @@ begin
X := BI^.Components; X := BI^.Components;
FillChar(W^,BIR^.Size * BIGINT_COMP_BYTE_SIZE,0); FillChar(W^,BIR^.Size * BIGINT_COMP_BYTE_SIZE,0);
repeat repeat
Tmp := PBIComponents(W)^[2*I] + TBILongComponent(PBIComponents(X)^[I]) * PBIComponents(X)^[I]; // Avoid overflow Tmp := W[2*I] + TBILongComponent(X[I]) * X[I]; // Avoid overflow
PBIComponents(W)^[2 * I] := Tmp; W[2 * I] := Tmp;
Carry := Tmp shr BIGINT_COMP_BIT_SIZE; Carry := Tmp shr BIGINT_COMP_BIT_SIZE;
J := I+1; J := I+1;
while J < T do while J < T do
begin begin
C := 0; C := 0;
XX := TBILongComponent(PBIComponents(X)^[I]) * PBIComponents(X)^[J]; // Avoid overflow XX := TBILongComponent(X[I]) * X[J]; // Avoid overflow
if BIGINT_COMP_MAX-XX < XX then if BIGINT_COMP_MAX-XX < XX then
C := 1; C := 1;
Tmp := XX shl 1; Tmp := XX shl 1;
if BIGINT_COMP_MAX-Tmp < PBIComponents(W)^[I + J] then if BIGINT_COMP_MAX-Tmp < W[I + J] then
C := 1; C := 1;
Tmp := Tmp + PBIComponents(W)^[I + J]; Tmp := Tmp + W[I + J];
if BIGINT_COMP_MAX-Tmp < Carry then if BIGINT_COMP_MAX-Tmp < Carry then
C := 1; C := 1;
Tmp := Tmp + Carry; Tmp := Tmp + Carry;
PBIComponents(W)^[I + J] := Tmp; W[I + J] := Tmp;
Carry := Tmp shr BIGINT_COMP_BIT_SIZE; Carry := Tmp shr BIGINT_COMP_BIT_SIZE;
if C > 0 then if C > 0 then
Carry := Carry + BIGINT_COMP_RADIX; Carry := Carry + BIGINT_COMP_RADIX;
Inc(J); Inc(J);
end; end;
Tmp := PBIComponents(W)^[I+T]+Carry; Tmp := W[I+T]+Carry;
PBIComponents(W)^[I+T] := Tmp; W[I+T] := Tmp;
PBIComponents(W)^[I+T+1] := Tmp shr BIGINT_COMP_BIT_SIZE; W[I+T+1] := Tmp shr BIGINT_COMP_BIT_SIZE;
Inc(I); Inc(I);
until I >= T; until I >= T;
BIRelease(Context, BI); BIRelease(Context, BI);
@ -495,44 +480,49 @@ begin
Inc(I); Inc(I);
end; end;
Context.G := AllocMem(K*SizeOf(PBigInt)); Context.G := AllocMem(K*SizeOf(PBigInt));
PBigInts(Context.G)^[0] := BIClone(Context, G1^); Context.G[0] := BIClone(Context, G1^);
BIPermanent(PBigInts(Context.G)^[0]); BIPermanent(Context.G[0]);
G2 := BIResidue(Context, BISquare(Context, PBigInts(Context.G)^[0])); {g^2} G2 := BIResidue(Context, BISquare(Context, Context.G[0])); {g^2}
for I := 1 to K-1 do for I := 1 to K-1 do
begin begin
PBigInts(Context.G)^[I] := BIResidue(Context, BIMultiply(Context, PBigInts(Context.G)^[I-1], BICopy(G2))); Context.G[I] := BIResidue(Context, BIMultiply(Context, Context.G[I-1], BICopy(G2)));
BIPermanent(PBigInts(Context.G)^[I]); BIPermanent(Context.G[I]);
end; end;
BIRelease(Context, G2); BIRelease(Context, G2);
Context.Window := K; Context.Window := K;
end; end;
procedure BIInitialize(out Context: TBigIntContext); procedure BIInitialize(out Context: TBigIntContext);
var
BIRadix: PBigInt;
begin begin
Context:=Default(TBigIntContext); Context:=Default(TBigIntContext);
Context.BIRadix := BIAllocate(Context, 2); BIRadix:=BIAllocate(Context, 2);
PBIComponents(Context.BIRadix^.Components)^[0] := 0; Context.BIRadix := BIRadix;
PBIComponents(Context.BIRadix^.Components)^[1] := 1; BIRadix^.Components[0] := 0;
BIPermanent(Context.BIRadix); BIRadix^.Components[1] := 1;
BIPermanent(BIRadix);
end; end;
// Close the bigint context and free any resources // Close the bigint context and free any resources
procedure BITerminate(var Context: TBigIntContext); procedure BITerminate(var Context: TBigIntContext);
Var Var
BI,BN : PBigInt; BI,BNext : PBigInt;
begin begin
FreeMem(Context.BIRadix); BIRelease(Context, Context.BIRadix);
Context.BIRadix := nil;
BI:=Context.FreeList; BI:=Context.FreeList;
While BI<>Nil do While BI<>Nil do
begin begin
BN:=BI^.Next; BNext:=BI^.Next;
if BI^.Components<>Nil then if BI^.Components<>Nil then
FreeMem(BI^.Components); FreeMem(BI^.Components);
FreeMem(BI); FreeMem(BI);
BI:=BN; BI:=BNext;
end; end;
Context.FreeList:=nil;
end; end;
// Make a bigint object "unfreeable" if BIFree() is called on it // Make a bigint object "unfreeable" if BIFree() is called on it
@ -541,24 +531,17 @@ begin
if not BICheck(BI^) then if not BICheck(BI^) then
Exit; Exit;
if BI^.References <> 1 then if BI^.References <> 1 then
begin raise Exception.Create('20220428195735');
//XLog(tlDebug, 'TLS', 'BIPermanent - References not equal to one');
//To Do //Log Error /Raise Exception
Exit;
end;
BI^.References := BIGINT_PERMANENT; BI^.References := BIGINT_PERMANENT;
end; end;
// Take a permanent object and make it freeable // Take a permanent object and make it freeable
procedure BIDepermanent(BI: PBigInt); procedure BIDepermanent(BI: PBigInt);
begin begin
if not BICHeck(BI^) then if not BICheck(BI^) then
Exit; Exit;
if BI^.References <> BIGINT_PERMANENT then if BI^.References <> BIGINT_PERMANENT then
begin raise Exception.Create('20220428203636');
// XLog(tlDebug, 'TLS', 'BIDepermanent - References not equal to BIGINT_PERMANENT');
Exit;
end;
BI^.References := 1; BI^.References := 1;
end; end;
@ -576,8 +559,10 @@ begin
Context.FreeList := BI; Context.FreeList := BI;
Inc(Context.FreeCount); Inc(Context.FreeCount);
Dec(Context.ActiveCount); Dec(Context.ActiveCount);
// if Context.ActiveCount < 0 then {$IFDEF BIGINT_DEBUG}
// XLog(tlWarning, 'TLS', 'BIFree - ActiveCount less than zero'); if Context.ActiveCount < 0 then
raise Exception.Create('20220428203546');
{$ENDIF}
end; end;
{==============================================================================} {==============================================================================}
@ -606,7 +591,8 @@ begin
System.Move(BI.Components^, Result^.Components^, BI.Size*BIGINT_COMP_BYTE_SIZE); System.Move(BI.Components^, Result^.Components^, BI.Size*BIGINT_COMP_BYTE_SIZE);
end; end;
procedure BIExport(var Context: TBigIntContext; BI: PBigInt; Data: PByte; Size: Integer); procedure BIExport(var Context: TBigIntContext; BI: PBigInt; Data: PByte;
Size: Integer; Release: boolean);
{Take a bigint and convert it into a byte sequence} {Take a bigint and convert it into a byte sequence}
{Context: The bigint session context} {Context: The bigint session context}
{BI: The bigint to be converted} {BI: The bigint to be converted}
@ -616,28 +602,25 @@ var
I: Integer; I: Integer;
J: Integer; J: Integer;
K: Integer; K: Integer;
Mask: TBIComponent;
Num: Integer;
begin begin
if not BICheck(BI^) then if not BICheck(BI^) then
Exit; Exit;
FillChar(Data^,Size,0); FillByte(Data^,Size,0);
K := Size-1; K := Size-1;
try try
for I := 0 to BI^.Size - 1 do for I := 0 to BI^.Size - 1 do
begin begin
for J := 0 to BIGINT_COMP_BYTE_SIZE - 1 do for J := 0 to BIGINT_COMP_BYTE_SIZE - 1 do
begin begin
Mask := $FF shl (J * 8); Data[K]:=(BI^.Components[I] shr (J * 8)) and $ff;
Num := (PBIComponents(BI^.Components)^[I] and Mask) shr (J * 8);
PByteArray(Data)^[K]:=Num;
Dec(K); Dec(K);
if K < 0 then if K < 0 then
Exit; Exit;
end; end;
end; end;
finally finally
BIRelease(Context,BI); if Release then
BIRelease(Context,BI);
end; end;
end; end;
@ -651,10 +634,10 @@ begin
J := 0; J := 0;
Offset := 0; Offset := 0;
Result := BIAllocate(Context, (Size+BIGINT_COMP_BYTE_SIZE-1) div BIGINT_COMP_BYTE_SIZE); Result := BIAllocate(Context, (Size+BIGINT_COMP_BYTE_SIZE-1) div BIGINT_COMP_BYTE_SIZE);
FillChar(Result^.Components^, Result^.Size*BIGINT_COMP_BYTE_SIZE, 0); FillByte(Result^.Components^, Result^.Size*BIGINT_COMP_BYTE_SIZE, 0);
for I := Size-1 downto 0 do for I := Size-1 downto 0 do
begin begin
PBIComponents(Result^.Components)^[Offset] := PBIComponents(Result^.Components)^[Offset] + (PByteArray(Data)^[I] shl (J * 8)); Result^.Components[Offset] := Result^.Components[Offset] + (TBIComponent(Data[I]) shl (J * 8));
Inc(J); Inc(J);
if J = BIGINT_COMP_BYTE_SIZE then if J = BIGINT_COMP_BYTE_SIZE then
begin begin
@ -666,7 +649,7 @@ end;
function BIImport(var Context: TBigIntContext; const Data: TBytes): PBigInt; function BIImport(var Context: TBigIntContext; const Data: TBytes): PBigInt;
begin begin
Result := BIImport(Context, PByte(Data), Length(Data)); Result := BIImport(Context, @Data[0], Length(Data));
end; end;
function BIImport(var Context: TBigIntContext; const Data: AnsiString): PBigInt; overload; function BIImport(var Context: TBigIntContext; const Data: AnsiString): PBigInt; overload;
@ -681,7 +664,7 @@ end;
function IntToBI(var Context: TBigIntContext; I: TBIComponent): PBigInt; function IntToBI(var Context: TBigIntContext; I: TBIComponent): PBigInt;
begin begin
Result := BIAllocate(Context,1); Result := BIAllocate(Context,1);
PBIComponents(Result^.Components)^[0] := I; Result^.Components[0] := I;
end; end;
function BIAdd(var Context: TBigIntContext; BIA, BIB: PBigInt): PBigInt; function BIAdd(var Context: TBigIntContext; BIA, BIB: PBigInt): PBigInt;
@ -701,8 +684,8 @@ begin
Exit; Exit;
end; end;
N := Max(BIA^.Size, BIB^.Size); N := Max(BIA^.Size, BIB^.Size);
BIAddComponents(Context, BIA, N+1); BIResizeComponents(BIA, N+1);
BIAddComponents(Context, BIB, N); BIResizeComponents(BIB, N);
PA := BIA^.Components; PA := BIA^.Components;
PB := BIB^.Components; PB := BIB^.Components;
repeat repeat
@ -746,7 +729,7 @@ begin
Exit; Exit;
end; end;
N := BIA^.Size; N := BIA^.Size;
BIAddComponents(Context, BIB, N); BIResizeComponents(BIB, N);
PA := BIA^.Components; PA := BIA^.Components;
PB := BIB^.Components; PB := BIB^.Components;
repeat repeat
@ -780,17 +763,17 @@ function BIDivide(var Context: TBigIntContext; U, V: PBigInt; IsMod: Boolean): P
function BIDivide_V1(V:PBigInt):TBIComponent; inline; function BIDivide_V1(V:PBigInt):TBIComponent; inline;
begin // V1 for division begin // V1 for division
Result := PBIComponents(V^.Components)^[V^.Size-1]; Result := V^.Components[V^.Size-1];
end; end;
function BIDivide_V2(V: PBigInt): TBIComponent; inline; function BIDivide_V2(V: PBigInt): TBIComponent; inline;
begin // V2 for division begin // V2 for division
Result := PBIComponents(V^.Components)^[V^.Size-2]; Result := V^.Components[V^.Size-2];
end; end;
function BIDivide_U(TmpU: PBigInt; J: Integer): TBIComponent; inline; function BIDivide_U(TmpU: PBigInt; J: Integer): TBIComponent; inline;
begin // U(J) for division begin // U(J) for division
Result := PBIComponents(TmpU^.Components)^[TmpU^.Size-J-1]; Result := TmpU^.Components[TmpU^.Size-J-1];
end; end;
var var
@ -833,10 +816,10 @@ begin
V:=BIIntMultiply(Context,V,D); V:=BIIntMultiply(Context,V,D);
end; end;
if OrigUSize = U^.Size then if OrigUSize = U^.Size then
BIAddComponents(Context, U, OrigUSize+1); // New digit position u0 BIResizeComponents(U, OrigUSize+1); // New digit position u0
repeat repeat
// Get a temporary short version of u // Get a temporary short version of u
System.Move(PBIComponents(U^.Components)^[U^.Size-N-1-J], TmpU^.Components^, (N+1) * BIGINT_COMP_BYTE_SIZE); System.Move(U^.Components[U^.Size-N-1-J], TmpU^.Components^, (N+1) * BIGINT_COMP_BYTE_SIZE);
// Calculate q' // Calculate q'
if BIDivide_U(TmpU, 0) = BIDivide_V1(V) then if BIDivide_U(TmpU, 0) = BIDivide_V1(V) then
begin begin
@ -855,11 +838,11 @@ begin
if QDash > 0 then if QDash > 0 then
begin // Multiply and subtract begin // Multiply and subtract
TmpU := BISubtract(Context, TmpU, BIIntMultiply(Context, BICopy(V), QDash), IsNegative); TmpU := BISubtract(Context, TmpU, BIIntMultiply(Context, BICopy(V), QDash), IsNegative);
BIAddComponents(Context, TmpU, N+1); BIResizeComponents(TmpU, N+1);
PBIComponents(Quotient^.Components)^[Quotient^.Size-J-1] := QDash; Quotient^.Components[Quotient^.Size-J-1] := QDash;
if IsNegative then if IsNegative then
begin // Add back begin // Add back
Dec(PBIComponents(Quotient^.Components)^[Quotient^.Size-J-1]); Dec(Quotient^.Components[Quotient^.Size-J-1]);
TmpU := BIAdd(Context, TmpU, BICopy(V)); TmpU := BIAdd(Context, TmpU, BICopy(V));
// Lop off the carry // Lop off the carry
Dec(TmpU^.Size); Dec(TmpU^.Size);
@ -867,10 +850,10 @@ begin
end; end;
end else end else
begin begin
PBIComponents(Quotient^.Components)^[Quotient^.Size-J-1] := 0; Quotient^.Components[Quotient^.Size-J-1] := 0;
end; end;
// Copy back to U // Copy back to U
System.Move(TmpU^.Components^, PBIComponents(U^.Components)^[U^.Size-N-1-J], (N+1) * BIGINT_COMP_BYTE_SIZE); System.Move(TmpU^.Components^, U^.Components[U^.Size-N-1-J], (N+1) * BIGINT_COMP_BYTE_SIZE);
Inc(J); Inc(J);
until J > M; until J > M;
BIRelease(Context, TmpU); BIRelease(Context, TmpU);
@ -879,7 +862,7 @@ begin
begin // Get the remainder begin // Get the remainder
BIRelease(Context, Quotient);; BIRelease(Context, Quotient);;
BITrim(U); BITrim(U);
Result := BIIntDivide(Context, U, D); Result := BIIntDivide(U, D);
end else end else
begin // Get the quotient begin // Get the quotient
BIRelease(Context, U); BIRelease(Context, U);
@ -950,7 +933,7 @@ begin
Dec(J); Dec(J);
end; end;
PartExp := (PartExp-1) div 2; // Adjust for array PartExp := (PartExp-1) div 2; // Adjust for array
BIR := BIResidue(Context, BIMultiply(Context, BIR, PBigInts(Context.G)^[PartExp])); BIR := BIResidue(Context, BIMultiply(Context, BIR, Context.G[PartExp]));
I := L-1; I := L-1;
end else end else
begin // Square it begin // Square it
@ -960,8 +943,8 @@ begin
until I < 0; until I < 0;
for I := 0 to Context.Window-1 do for I := 0 to Context.Window-1 do
begin // Cleanup begin // Cleanup
BIDepermanent(PBigInts(Context.G)^[I]); BIDepermanent(Context.G[I]);
BIRelease(Context, PBigInts(Context.G)^[I]); BIRelease(Context, Context.G[I]);
end; end;
BIRelease(Context, BI); BIRelease(Context, BI);
BIRelease(Context, BIExp); BIRelease(Context, BIExp);
@ -1016,24 +999,17 @@ begin
Result := -1; Result := -1;
Exit; Exit;
end; end;
// Same number of components. Compare starting from the high end and working down
A := BIA^.Components; A := BIA^.Components;
B := BIB^.Components; B := BIB^.Components;
// Same number of components. Compare starting from the high end and working down for I := BIA^.Size-1 downto 0 do
begin
if A[I] > B[I] then
Exit(1)
else if A[I] < B[I] then
Exit(-1);
end;
Result := 0; Result := 0;
I := BIA^.Size-1;
repeat
if PBIComponents(A)^[I] > PBIComponents(B)^[I] then
begin
Result := 1;
Exit;
end;
if PBIComponents(A)^[I] < PBIComponents(B)^[I] then
begin
Result := -1;
Exit;
end;
Dec(I);
until I < 0;
end; end;
// Pre-compute some of the expensive steps in reduction // Pre-compute some of the expensive steps in reduction
@ -1047,14 +1023,14 @@ var
K: Integer; K: Integer;
begin begin
K := BIM^.Size; K := BIM^.Size;
D := BIGINT_COMP_RADIX div (TBILongComponent(PBIComponents(BIM^.Components)^[K-1]) + 1); D := BIGINT_COMP_RADIX div (TBILongComponent(BIM^.Components[K-1]) + 1);
Context.BIMod[ModOffset] := BIM; Context.BIMod[ModOffset] := BIM;
BIPermanent(Context.BIMod[ModOffset]); BIPermanent(Context.BIMod[ModOffset]);
Context.BINormalisedMod[ModOffset] := BIIntMultiply(Context, BIM, D); Context.BINormalisedMod[ModOffset] := BIIntMultiply(Context, BIM, D);
BIPermanent(Context.BINormalisedMod[ModOffset]); BIPermanent(Context.BINormalisedMod[ModOffset]);
Context.BImu[ModOffset] := BIDivide(Context, BICompLeftShift(Context, BIClone(Context, Context.BIRadix^), K*2-1), Context.BIMod[ModOffset], False); Context.BImu[ModOffset] := BIDivide(Context, BICompLeftShift(BIClone(Context, Context.BIRadix^), K*2-1), Context.BIMod[ModOffset], False);
BIPermanent(Context.BImu[ModOffset]); BIPermanent(Context.BImu[ModOffset]);
Context.BIbk1[ModOffset] := BICompLeftShift(Context, IntToBI(Context,1), K+1); Context.BIbk1[ModOffset] := BICompLeftShift(IntToBI(Context,1), K+1);
BIPermanent(Context.BIbk1[ModOffset]); BIPermanent(Context.BIbk1[ModOffset]);
end; end;
@ -1144,7 +1120,7 @@ begin
end; end;
Result := BIRegularSquare(Context, BI); Result := BIRegularSquare(Context, BI);
{$ELSE} {$ELSE}
Result := BIMultiply(Context, BICopy(BI), BI) Result := BIMultiply(Context, BICopy(BI), BI);
{$ENDIF} {$ENDIF}
end; end;
@ -1187,7 +1163,7 @@ begin
for J := BIGINT_COMP_NUM_NIBBLES-1 downto 0 do for J := BIGINT_COMP_NUM_NIBBLES-1 downto 0 do
begin begin
Mask := $0F shl (J*4); Mask := $0F shl (J*4);
Num := (PBIComponents(BI^.Components)^[I] and Mask) shr (J*4); Num := (BI^.Components[I] and Mask) shr (J*4);
S[K]:=Digits[Num and $F]; S[K]:=Digits[Num and $F];
inc(K); inc(K);
end; end;
@ -1220,7 +1196,7 @@ begin
Result := nil; Result := nil;
Exit; Exit;
end; end;
PBIComponents(BIR^.Components)^[Offset] := PBIComponents(BIR^.Components)^[Offset] + LongWord(Num shl (J * 4)); BIR^.Components[Offset] := BIR^.Components[Offset] + (LongWord(Num) shl (J * 4));
Inc(J); Inc(J);
if J = BIGINT_COMP_NUM_NIBBLES then if J = BIGINT_COMP_NUM_NIBBLES then
begin begin