Browse Source

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

mattias 3 years ago
parent
commit
864b2ad3f3
3 changed files with 121 additions and 147 deletions
  1. 1 1
      packages/fcl-hash/src/fppem.pp
  2. 10 12
      packages/fcl-hash/src/fprsa.pas
  3. 110 134
      packages/fcl-hash/src/fptlsbigint.pas

+ 1 - 1
packages/fcl-hash/src/fppem.pp

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

+ 10 - 12
packages/fcl-hash/src/fprsa.pas

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

+ 110 - 134
packages/fcl-hash/src/fptlsbigint.pas

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