Skip to content

Commit 61f0007

Browse files
Corrected padding algorithm TANSI_X9_23_Padding, TISO10126Padding, and TISO7816Padding:
If the data length is a multiply of block size an additional padding is added (identical to PKCS7/PKCS5). Corrected TISO7816Padding.HasValidPadding
1 parent 4fd884b commit 61f0007

File tree

1 file changed

+35
-65
lines changed

1 file changed

+35
-65
lines changed

Source/DECCipherPaddings.pas

Lines changed: 35 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,11 @@ TFixedBytePadding = class abstract(TPaddingBase)
218218
/// The length of the block in bytes.
219219
/// </param>
220220
/// <returns>
221-
/// Length of the padding in bytes.
221+
/// Length of the padding in bytes. Can not be zero. When the DataSize
222+
/// is a multiply of the BlockSize the method returns the sum of DataSize and
223+
/// BlockSize.
222224
/// </returns>
223-
class function GetPadLength(DataSize, BlockSize: Integer): Integer; virtual; abstract;
225+
class function GetPadLength(DataSize, BlockSize: Integer): Integer; virtual;
224226

225227
/// <summary>
226228
/// Retrieves the padding character used to fill up the last block(s).
@@ -396,21 +398,6 @@ TFixedBytePadding = class abstract(TPaddingBase)
396398
/// </remarks>
397399
TPKCS7Padding = class(TFixedBytePadding)
398400
strict protected
399-
/// <summary>
400-
/// Calculated the length of the padding.
401-
/// </summary>
402-
/// <param name="DataSize">
403-
/// The length of the data.
404-
/// </param>
405-
/// <param name="BlockSize">
406-
/// The length of the block.
407-
/// </param>
408-
/// <returns>
409-
/// Length of the padding. Can not be zero. When the DataSize is a multiply
410-
/// of the BlockSize the method returns the BlockSize.
411-
/// </returns>
412-
class function GetPadLength(DataSize, BlockSize: Integer): Integer; override;
413-
414401
/// <summary>
415402
/// Check if block size is supported by the concerete padding algorithm.
416403
/// </summary>
@@ -439,8 +426,8 @@ TPKCS7Padding = class(TFixedBytePadding)
439426
end;
440427

441428
/// <summary>
442-
/// PKCS#5 is a subset of the PKCS#7 padding algorithm. Better use PKCS#7
443-
/// where possible.
429+
/// PKCS#5 is a subset of the PKCS#7 padding algorithm for block size of
430+
/// 8 bytes. Better use PKCS#7 where possible.
444431
/// </summary>
445432
TPKCS5Padding = class(TPKCS7Padding)
446433
strict protected
@@ -451,7 +438,7 @@ TPKCS5Padding = class(TPKCS7Padding)
451438
/// The length of the block size for PKCS#5 must be 8.
452439
/// </param>
453440
/// <returns>
454-
/// True, if block size is in expected range of 1..255, otherwise false.
441+
/// True, if block size is 8, otherwise false.
455442
/// </returns>
456443
class function IsBlockSizeValid(BlockSize: Integer): Boolean; override;
457444
end;
@@ -468,21 +455,6 @@ TPKCS5Padding = class(TPKCS7Padding)
468455
/// </remarks>
469456
TANSI_X9_23_Padding = class(TFixedBytePadding)
470457
strict protected
471-
/// <summary>
472-
/// Calculates the length of the pad.
473-
/// </summary>
474-
/// <param name="DataSize">
475-
/// The length of the data in byte.
476-
/// </param>
477-
/// <param name="BlockSize">
478-
/// The length of the block in byte.
479-
/// </param>
480-
/// <returns>
481-
/// Length of the padding. Can be zero when the DataSize is a multiply of
482-
/// the BlockSize.
483-
/// </returns>
484-
class function GetPadLength(DataSize, BlockSize: Integer): Integer; override;
485-
486458
/// <summary>
487459
/// Check if block size is supported by the concerete padding algorithm.
488460
/// </summary>
@@ -560,19 +532,15 @@ TISO10126Padding = class(TANSI_X9_23_Padding)
560532
TISO7816Padding = class(TFixedBytePadding)
561533
strict protected
562534
/// <summary>
563-
/// Calculates the length of the padding.
535+
/// Check if block size is supported by the concerete padding algorithm.
564536
/// </summary>
565-
/// <param name="DataSize">
566-
/// The length of the data in bytes.
567-
/// </param>
568537
/// <param name="BlockSize">
569-
/// The length of the block in bytes.
538+
/// The length of the block size must be 1 or higher.
570539
/// </param>
571540
/// <returns>
572-
/// Length of the padding in bytes. Can not be zero when the DataSize is a
573-
/// multiply of the BlockSize.
541+
/// True, if block size is > 0, otherwise false.
574542
/// </returns>
575-
class function GetPadLength(DataSize, BlockSize: Integer): Integer; override;
543+
class function IsBlockSizeValid(BlockSize: Integer): Boolean; override;
576544
public
577545
/// <summary>
578546
/// Adds padding to the specified data, depending on the padding byte
@@ -676,6 +644,11 @@ class function TFixedBytePadding.AddPadding(const Data : RawByteString;
676644
ProtectBytes(Buf);
677645
end;
678646

647+
class function TFixedBytePadding.GetPadLength(DataSize, BlockSize: Integer): Integer;
648+
begin
649+
Result := BlockSize - (DataSize mod BlockSize);
650+
end;
651+
679652
class function TFixedBytePadding.HasValidPadding(const Data : TBytes;
680653
BlockSize : Integer): Boolean;
681654
var
@@ -688,6 +661,9 @@ class function TFixedBytePadding.HasValidPadding(const Data : TBytes;
688661
if not IsBlockSizeValid(BlockSize) then
689662
exit(false);
690663

664+
if Length(Data) mod BlockSize <> 0 then
665+
exit(false);
666+
691667
PadLength := Data[High(Data)];
692668
if (PadLength <= 0) or (PadLength > BlockSize) then
693669
exit(false);
@@ -735,12 +711,6 @@ class function TFixedBytePadding.RemovePadding(const Data : string;
735711

736712
{ TPKCS7Padding }
737713

738-
class function TPKCS7Padding.GetPadLength(DataSize,
739-
BlockSize: integer): integer;
740-
begin
741-
Result := BlockSize - (DataSize mod BlockSize);
742-
end;
743-
744714
class function TPKCS7Padding.IsBlockSizeValid(BlockSize: Integer): Boolean;
745715
begin
746716
Result := (BlockSize > 0) and (BlockSize < 256);
@@ -775,28 +745,26 @@ class function TANSI_X9_23_Padding.GetPaddingByte(PaddingLength : Integer;
775745
Result := 0;
776746
end;
777747

778-
class function TANSI_X9_23_Padding.GetPadLength(DataSize,
779-
BlockSize : Integer): Integer;
780-
begin
781-
Result := DataSize mod BlockSize;
782-
end;
783-
784748
class function TANSI_X9_23_Padding.HasValidPadding(const Data : TBytes;
785749
BlockSize : Integer): Boolean;
786750
var
787751
PadLength : Integer;
788752
begin
753+
if Length(Data) = 0 then
754+
exit(false);
755+
789756
if not IsBlockSizeValid(BlockSize) then
790757
exit(false);
791758

792-
PadLength := Data[High(Data)];
793-
if (PadLength <= 0) or (PadLength > BlockSize) then
759+
if Length(Data) mod BlockSize <> 0 then
794760
exit(false);
795761

796-
// check only last padding byte according to standard
797-
if (Data[High(Data)] <> GetPaddingByte(PadLength, true)) then
762+
PadLength := Data[High(Data)];
763+
if (PadLength <= 0) or (PadLength > BlockSize) then
798764
exit(false);
799765

766+
// Padding bytes cannot be tested as the content is not defined and does
767+
// not necessarily have to be zero!
800768
Result := true;
801769
end;
802770

@@ -813,10 +781,9 @@ class function TISO10126Padding.GetPaddingByte(PaddingLength : Integer;
813781

814782
{ TISO7816Padding }
815783

816-
class function TISO7816Padding.GetPadLength(DataSize,
817-
BlockSize: Integer): Integer;
784+
class function TISO7816Padding.IsBlockSizeValid(BlockSize: Integer): Boolean;
818785
begin
819-
Result := DataSize mod BlockSize;
786+
Result := BlockSize > 0;
820787
end;
821788

822789
class function TISO7816Padding.AddPadding(const Data: TBytes;
@@ -846,14 +813,17 @@ class function TISO7816Padding.HasValidPadding(const Data : TBytes;
846813
var
847814
I: Integer;
848815
begin
816+
if Length(Data) = 0 then
817+
exit(false);
818+
849819
if not IsBlockSizeValid(BlockSize) then
850820
exit(false);
851821

852-
if (Length(Data) = 0) or ((BlockSize > 0) and (Length(Data) mod BlockSize <> 0)) then
822+
if Length(Data) mod BlockSize <> 0 then
853823
exit(false);
854824

855825
I := High(Data);
856-
while (I > 0) and (Data[I] <> 0) do
826+
while (I > 0) and (Data[I] = 0) do
857827
dec(I);
858828

859829
if Data[I] <> $80 then
@@ -871,7 +841,7 @@ class function TISO7816Padding.RemovePadding(const Data : TBytes;
871841
raise EDECCipherException.CreateResFmt(@sInvalidPadding, [ClassName]);
872842

873843
I := High(Data);
874-
while (I > 0) and (Data[I] <> 0) do
844+
while (I > 0) and (Data[I] = 0) do
875845
dec(I);
876846
if Data[I] <> $80 then
877847
raise EDECCipherException.CreateResFmt(@sInvalidPadding, [ClassName]);

0 commit comments

Comments
 (0)