diff --git a/Demos/Cipher_FMX/MainFormCipherFMX.fmx b/Demos/Cipher_FMX/MainFormCipherFMX.fmx index c25082e5..c026bfce 100644 --- a/Demos/Cipher_FMX/MainFormCipherFMX.fmx +++ b/Demos/Cipher_FMX/MainFormCipherFMX.fmx @@ -2,8 +2,8 @@ object FormMain: TFormMain Left = 0 Top = 0 Caption = 'FMX Cipher Demo' - ClientHeight = 910 - ClientWidth = 402 + ClientHeight = 908 + ClientWidth = 404 FormFactor.Width = 320 FormFactor.Height = 480 FormFactor.Devices = [Desktop] @@ -13,13 +13,13 @@ object FormMain: TFormMain DesignerMasterStyle = 0 object VertScrollBox1: TVertScrollBox Align = Client - Size.Width = 402.00000000000000000 - Size.Height = 910.00000000000000000 + Size.Width = 404.00000000000000000 + Size.Height = 908.00000000000000000 Size.PlatformDefault = False StyleLookup = 'scrollboxstyle' TabOrder = 6 - Viewport.Width = 386.00000000000000000 - Viewport.Height = 910.00000000000000000 + Viewport.Width = 388.00000000000000000 + Viewport.Height = 908.00000000000000000 object LayoutTop: TLayout Size.Width = 400.00000000000000000 Size.Height = 313.00000000000000000 diff --git a/Docs/DEC65.pdf b/Docs/DEC65.pdf index 1a54b73b..ba390039 100644 Binary files a/Docs/DEC65.pdf and b/Docs/DEC65.pdf differ diff --git a/Docs/VersionHistory.pdf b/Docs/VersionHistory.pdf index 100dfbdf..43bea7b5 100644 Binary files a/Docs/VersionHistory.pdf and b/Docs/VersionHistory.pdf differ diff --git a/NOTICE.txt b/NOTICE.txt index c0041c7c..65c9dd4d 100644 --- a/NOTICE.txt +++ b/NOTICE.txt @@ -2,7 +2,7 @@ DEC - Delphi Encryption Compendium Version 6.5 Copyright (c) 2018 - 2020 Norman Gallery (ng931884 [at] gmx [dot] de) -Copyright (c) 2016 - 2024 Markus Humm (markus [dot] humm [at] googlemail [dot] com) (main contact) +Copyright (c) 2016 - 2025 Markus Humm (markus [dot] humm [at] googlemail [dot] com) (main contact) Copyright (c) 2008 - 2019 Frederik A. Winkelsdorf (winkelsdorf [at] gmail [dot] com) Copyright (c) 1999 - 2008 Hagen Reddmann (HaReddmann [at] T-Online [dot] de) @@ -30,6 +30,8 @@ alexrayne Stevie danielmarschall Christoph Schneider (Schneider Infosystems AG) +mikerabat +icTrainer Parts of the work loosely based on the works of Wolfgang Erhardt, who is unfortunately dead already. diff --git a/Source/DEC60.dpr b/Source/DEC60.dpr index 36f91885..bca0efc0 100644 --- a/Source/DEC60.dpr +++ b/Source/DEC60.dpr @@ -47,7 +47,11 @@ uses DECHashBitBase in 'DECHashBitBase.pas', DECCipherModesGCM in 'DECCipherModesGCM.pas', DECZIPHelper in 'DECZIPHelper.pas', - DECCipherPaddings in 'DECCipherPaddings.pas'; + DECCipherPaddings in 'DECCipherPaddings.pas', + DECCipherModesCCM in 'DECCipherModesCCM.pas', + DECAuthenticatedCipherModesBase in 'DECAuthenticatedCipherModesBase.pas', + DECCipherModesPoly1305 in 'DECCipherModesPoly1305.pas', + DECCPUSupport in 'DECCPUSupport.pas'; begin try diff --git a/Source/DEC60.dproj b/Source/DEC60.dproj index 5afc74b3..59d43f73 100644 --- a/Source/DEC60.dproj +++ b/Source/DEC60.dproj @@ -1,7 +1,7 @@  {34FB3EC0-D6C0-4F92-9FEE-3E0E87C91FC4} - 20.2 + 20.3 None DEC60.dpr True @@ -85,13 +85,13 @@ $(BDS)\bin\Artwork\Android\FM_NotificationIcon_48x48.png $(BDS)\bin\Artwork\Android\FM_NotificationIcon_72x72.png $(BDS)\bin\Artwork\Android\FM_NotificationIcon_96x96.png - package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34 + package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=35 Debug true $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png - package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34 + package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=35 Debug true Base @@ -176,6 +176,9 @@ + + + @@ -233,12 +236,48 @@ + + + DEC60.exe + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + + + + .\ + true + + 1 @@ -353,6 +392,16 @@ 1 + + + res\values-v35 + 1 + + + res\values-v35 + 1 + + res\drawable-anydpi-v26 diff --git a/Source/DECAuthenticatedCipherModesBase.pas b/Source/DECAuthenticatedCipherModesBase.pas new file mode 100644 index 00000000..1b392833 --- /dev/null +++ b/Source/DECAuthenticatedCipherModesBase.pas @@ -0,0 +1,322 @@ +{***************************************************************************** + The DEC team (see file NOTICE.txt) licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. A copy of this licence is found in the root directory + of this project in the file LICENCE.txt or alternatively at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*****************************************************************************} +unit DECAuthenticatedCipherModesBase; + +interface + +{$INCLUDE DECOptions.inc} + +uses + {$IFDEF FPC} + SysUtils, + {$ELSE} + System.SysUtils, + {$ENDIF} + DECTypes; + +type + /// + /// Exception raised when nonce has a wrong length + /// + EDECNonceLengthException = class(EDECException); + /// + /// Exception raised when authentication value has wrong length + /// + EDECAuthLengthException = class(EDECException); + + /// + /// A method of this type needs to be supplied for encrypting or decrypting + /// a block via this GCM algorithm. The method is implemented as a parameter, + /// to avoid the need to bring TGCM in the inheritance chain. TGCM thus can + /// be used for composition instead of inheritance. + /// + /// + /// Data to be encrypted + /// + /// + /// In this memory the encrypted result will be written + /// + /// + /// Size of source in byte + /// + TEncodeDecodeMethod = procedure(Source, Dest: Pointer; Size: Integer) of Object; + + /// + /// Base class for authenticated cipher modes + /// + TAuthenticatedCipherModesBase = class(TObject) + private + /// + /// Flag that indicates if the method has been initialized + /// + fAuthMethodInit : boolean; + + /// + /// Length of the processed buffer + /// + fEncDecLen : Int64; + strict protected + /// + /// The data which shall be authenticated in parallel to the encryption + /// + FDataToAuthenticate : TBytes; + /// + /// Length of the authentication tag to generate in byte + /// + FCalcAuthenticationTagLength : UInt32; + /// + /// Generated authentication tag + /// + FCalcAuthenticationTag : TBytes; + + /// + /// Expected authentication tag value, will be compared with actual value + /// when decryption finished. + /// + FExpectedAuthenticationTag : TBytes; + + /// + /// Reference to the encode method of the actual cipher used + /// + FEncryptionMethod : TEncodeDecodeMethod; + + /// + /// Defines the length of the resulting authentication value in bit. + /// + /// + /// Sets the length of Authenticaton_tag in bit, values as per specification + /// of the concrete algorithm implemented in a child class + /// + procedure SetAuthenticationTagLength(const Value: UInt32); virtual; + /// + /// Returns the length of the calculated authehtication value in bit + /// + /// + /// Length of the calculated authentication value in bit + /// + function GetAuthenticationTagBitLength: UInt32; virtual; + + + /// + /// Initialize the authentication procedure. This is a good place to initialize + /// the data structures and initialize with the (unencrypted) authenticated buffer + /// + procedure InitAuth; virtual; abstract; + + /// + /// Updates the mac. Can be called multiple times! + /// + procedure UpdateWithEncDecBuf(buf : PUInt8Array; Size : Integer); virtual; abstract; + + /// + /// finalize the MAC - typically the processed buffer lengths are incorporated here. + /// + procedure FinalizeMAC( authLen, encDecBufSize : Int64 ); virtual; abstract; + + /// + /// Encoding/Decoding routine that is called in the Encode/Decode routine. + /// This version simply calls the EncryptionMethod givin in the init call + /// + procedure LocEncodeDecode(Source, Dest: Pointer; Size: Integer); virtual; + + procedure Burn; virtual; abstract; + + public + /// + /// Should be called when starting encryption/decryption in order to + /// initialize internal tables etc. + /// + /// + /// Encryption method of the cypher used + /// + /// + /// Initialization vector + /// + procedure Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); virtual; + + /// + /// Encodes a block of data using the supplied cipher + /// + /// + /// Plain text to encrypt + /// + /// + /// Ciphertext after encryption + /// + /// + /// Number of bytes to encrypt + /// + procedure Encode(Source, + Dest : PUInt8Array; + Size : Integer); virtual; + /// + /// Decodes a block of data using the supplied cipher + /// + /// + /// Encrypted ciphertext to decrypt + /// + /// + /// Plaintext after decryption + /// + /// + /// Number of bytes to decrypt + /// + procedure Decode(Source, + Dest : PUInt8Array; + Size : Integer); virtual; + + /// + /// Call this function to calculate the final MAC - typically one updates the + /// remaining buffer with buffer lengths. + /// + procedure FinalizeAEAD; + + /// + /// Returns a list of authentication tag lengths explicitely specified by + /// the official specification of the standard. + /// + /// + /// List of bit lengths + /// + function GetStandardAuthenticationTagBitLengths:TStandardBitLengths; virtual; + + /// + /// The data which shall be authenticated in parallel to the encryption + /// + property DataToAuthenticate : TBytes + read FDataToAuthenticate + write FDataToAuthenticate; + /// + /// Sets the length of AuthenticatonTag in bit, values as per official + /// specification are: 128, 120, 112, 104, or 96 bit. For certain + /// applications, they may be 64 or 32 as well, but the use of these two + /// tag lengths constrains the length of the input data and the lifetime + /// of the key. + /// + property AuthenticationTagBitLength : UInt32 + read GetAuthenticationTagBitLength + write SetAuthenticationTagLength; + /// + /// Calculated authentication value + /// + property CalculatedAuthenticationTag : TBytes + read FCalcAuthenticationTag + write FCalcAuthenticationTag; + + /// + /// Expected authentication tag value, will be compared with actual value + /// when decryption finished. + /// + property ExpectedAuthenticationTag : TBytes + read FExpectedAuthenticationTag + write FExpectedAuthenticationTag; + end; + +implementation + +uses + DECUtil; + +{ TAuthenticatedCipherModesBase } + +procedure TAuthenticatedCipherModesBase.Decode(Source, Dest: PUInt8Array; + Size: Integer); +begin + if not fAuthMethodInit then + begin + InitAuth; + fAuthMethodInit := True; + end; + + UpdateWithEncDecBuf(Source, size); + LocEncodeDecode(Source, Dest, Size); + inc(fEncDecLen, Size); +end; + +procedure TAuthenticatedCipherModesBase.Encode(Source, Dest: PUInt8Array; + Size: Integer); +begin + if not fAuthMethodInit then + begin + InitAuth; + fAuthMethodInit := True; + end; + + LocEncodeDecode(Source, Dest, Size); + UpdateWithEncDecBuf(Dest, size); + inc(fEncDecLen, Size); +end; + +procedure TAuthenticatedCipherModesBase.FinalizeAEAD; +begin + if not fAuthMethodInit then + begin + InitAuth; + fAuthMethodInit := True; + end; + + SetLength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); + FinalizeMAC(Length(FDataToAuthenticate), fEncDecLen); + + Burn; +end; + +function TAuthenticatedCipherModesBase.GetAuthenticationTagBitLength: UInt32; +begin + Result := FCalcAuthenticationTagLength shl 3; +end; + +function TAuthenticatedCipherModesBase.GetStandardAuthenticationTagBitLengths: TStandardBitLengths; +begin + SetLength(Result, 0); +end; + +procedure TAuthenticatedCipherModesBase.Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); +var + CalcAuthLength : Integer; +begin + Assert(Assigned(EncryptionMethod), 'No encryption method specified'); + + // Clear calculated authentication value + fAuthMethodInit := False; + CalcAuthLength := Length(FCalcAuthenticationTag); + if (CalcAuthLength > 0) then + begin + ProtectBytes(FCalcAuthenticationTag); + SetLength(FCalcAuthenticationTag, CalcAuthLength); + FillChar(FCalcAuthenticationTag[0], CalcAuthLength, #0); + end; + + fEncDecLen := 0; + FEncryptionMethod := EncryptionMethod; +end; + +procedure TAuthenticatedCipherModesBase.LocEncodeDecode(Source, Dest: Pointer; + Size: Integer); +begin + FEncryptionMethod(Source, Dest, Size); +end; + +procedure TAuthenticatedCipherModesBase.SetAuthenticationTagLength(const Value: UInt32); +begin + FCalcAuthenticationTagLength := Value shr 3; + SetLength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); +end; + +end. diff --git a/Source/DECCPUSupport.pas b/Source/DECCPUSupport.pas new file mode 100644 index 00000000..1a81ce18 --- /dev/null +++ b/Source/DECCPUSupport.pas @@ -0,0 +1,117 @@ +{***************************************************************************** + The DEC team (see file NOTICE.txt) licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. A copy of this licence is found in the root directory + of this project in the file LICENCE.txt or alternatively at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*****************************************************************************} + +/// +/// x86 and x64 CPU instruction support functions. +/// this class only works for intel cpus - arm will result. +/// The functions defined here return true if the feature is availabe +/// for the cpu +/// + +unit DECCPUSupport; + +interface + +type + TDEC_CPUSupport = class(TObject) + public + // flags are set in initialization + class var AES : boolean; + class var AVX : boolean; + class var AVX2 : boolean; + + class var SSE : boolean; + class var SSE2 : boolean; + class var SSE3 : boolean; + class var SSE41 : boolean; + class var SSE42 : boolean; + + class var RDRand : boolean; + class var RDSeed : boolean; + end; + +implementation + +{$IFDEF CPUX64} +{$DEFINE x64} +{$ENDIF} +{$IFDEF cpux86_64} +{$DEFINE x64} +{$ENDIF} + +{$IFDEF CPU86} +{$DEFINE x86} +{$ENDIF} +{$IFDEF CPUX86} +{$DEFINE x86} +{$ENDIF} + +{$IFDEF CPU386} +{$DEFINE x86} +{$ENDIF} + + +{$IF Defined(x64) or Defined(x86)} +{$WARN SYMBOL_PLATFORM OFF} +procedure InitFlags; +var reg : TCPUIDRec; + nids : LongWord; +begin + reg := GetCPUID(0, 0); + nids := reg.EAX; + + + if nids >= 1 then + begin + reg := GetCPUID(1, 0); + TDEC_CPUSupport.SSE := (reg.EDX and (1 shl 25)) <> 0; + TDEC_CPUSupport.SSE2 := (reg.EDX and (1 shl 26)) <> 0; + TDEC_CPUSupport.SSE3 := (reg.ECX and (1 shl 9)) <> 0; + TDEC_CPUSupport.SSE41 := (reg.ECX and (1 shl 19)) <> 0; + TDEC_CPUSupport.SSE42 := (reg.ECX and (1 shl 20)) <> 0; + TDEC_CPUSupport.AES := (reg.ECX and (1 shl 25)) <> 0; + + TDEC_CPUSupport.AVX := (reg.ECX and (1 shl 28)) <> 0; + TDEC_CPUSupport.RDRAND := (reg.ECX and (1 shl 30)) <> 0; + end; + + if nids >= 7 then + begin + reg := GetCPUID($7); + TDEC_CPUSupport.AVX2 := (reg.EBX and (1 shl 5)) <> 0; + TDEC_CPUSupport.RDSEED := (reg.EBX and (1 shl 18)) <> 0; + end; +end; +{$ENDIF} + +initialization + TDEC_CPUSupport.AES := False; + TDEC_CPUSupport.AVX := False; + TDEC_CPUSupport.AVX2 := False; + + TDEC_CPUSupport.SSE := False; + TDEC_CPUSupport.SSE2 := False; + TDEC_CPUSupport.SSE3 := False; + TDEC_CPUSupport.SSE41 := False; + TDEC_CPUSupport.SSE42 := False; + + TDEC_CPUSupport.RDRand := False; + TDEC_CPUSupport.RDSeed := False; +{$IF Defined(x64) or Defined(x86)} + InitFlags; +{$IFEND} +end. diff --git a/Source/DECCipherBase.pas b/Source/DECCipherBase.pas index 456f681d..99e0a4fc 100644 --- a/Source/DECCipherBase.pas +++ b/Source/DECCipherBase.pas @@ -182,7 +182,9 @@ interface cmCFS8, // 8Bit CFS, double CFB cmCFSx, // CFS on Blocksize bytes cmECBx, // Electronic Code Book - cmGCM // Galois Counter Mode + cmGCM, // Galois Counter Mode + cmCCM, // Counter with CBC-MAC Mode + cmPoly1305 // Poly1305 for ChaCha {$IFDEF DEC3_CMCTS} ,cmCTS3 // double CBC, with less secure padding of truncated final block // for DEC 3.0 compatibility only (see DECOptions.inc) @@ -228,7 +230,11 @@ TDECCipher = class(TDECObject) /// This is the size of FData in byte /// FDataSize : Integer; - private + + /// + /// Sets the desired padding mode, means how block ciphers treat + /// incompletely filled last blocks. + /// procedure SetPaddingMode(const Value: TPaddingMode); strict protected /// @@ -1007,7 +1013,7 @@ procedure TDECCipher.Init(const Key; Size: Integer; const IVector; if (Size > Context.KeySize) and (not (ctNull in Context.CipherType)) then raise EDECCipherException.CreateRes(@sKeyMaterialTooLarge); - if (FInitVectorSize > FBufferSize) and (not (FMode = cmGCM)) then + if (FInitVectorSize > FBufferSize) and (not (FMode in [cmGCM, cmPoly1305])) then raise EDECCipherException.CreateRes(@sIVMaterialTooLarge); DoInit(Key, Size); diff --git a/Source/DECCipherFormats.pas b/Source/DECCipherFormats.pas index 5a754d70..42a7da59 100644 --- a/Source/DECCipherFormats.pas +++ b/Source/DECCipherFormats.pas @@ -730,10 +730,10 @@ function TDECFormattedCipher.EncodeBytes(const Source: TBytes): TBytes; begin SetLength(Result, Length(Source)); if Length(Result) > 0 then - Encode(Source[0], Result[0], Length(Source)) - else - if (FMode = cmGCM) then - EncodeGCM(@Source, @Result, 0); + Encode(Source[0], Result[0], Length(Source)); + //else +// if (FMode = cmGCM) then +// EncodeWithAuthObj(nil, nil, 0); end; begin @@ -745,18 +745,15 @@ function TDECFormattedCipher.EncodeBytes(const Source: TBytes): TBytes; function TDECFormattedCipher.DecodeBytes(const Source: TBytes): TBytes; begin - Result := Source; + SetLength(Result, Length(Source)); if Length(Result) > 0 then begin - if (FMode = cmGCM) then - SetLength(Result, Length(Source)); - Decode(Source[0], Result[0], Length(Source)); - end - else - if (FMode = cmGCM) then - DecodeGCM(@Source, @Result, 0); + end; + //else + //if (FMode = cmGCM) then + // DecodeGCM(nil, nil, 0); if not (FPaddingClass = nil) then Result := FPaddingClass.RemovePadding(Result, Context.BlockSize); @@ -784,7 +781,7 @@ procedure TDECFormattedCipher.DoEncodeDecodeStream(const Source, Dest: TStream; StartPos := Pos; doPadding := false; doStartOnlyPadding := (DataSize = 0) and IsEncode and - (FPaddingMode <> pmNone); + (FPaddingMode <> pmNone); if (DataSize > 0) or doStartOnlyPadding then begin diff --git a/Source/DECCipherInterface.pas b/Source/DECCipherInterface.pas index 90389bf6..1e11c6fa 100644 --- a/Source/DECCipherInterface.pas +++ b/Source/DECCipherInterface.pas @@ -26,6 +26,8 @@ interface {$ENDIF} DECTypes, DECCipherBase, DECFormatBase; +{$I DECOptions.inc} + type /// /// Common interface for all ciphers. Some ciphers may have additional diff --git a/Source/DECCipherModes.pas b/Source/DECCipherModes.pas index aa9ef832..e687f63b 100644 --- a/Source/DECCipherModes.pas +++ b/Source/DECCipherModes.pas @@ -26,7 +26,8 @@ interface {$ELSE} System.SysUtils, {$ENDIF} - DECTypes, DECCipherBase, DECCipherModesGCM, DECCipherInterface; + DECTypes, DECCipherBase, + DECCipherInterface, DECAuthenticatedCipherModesBase; type /// @@ -138,17 +139,12 @@ TDECCipherModes = class(TDECCipher, IDECAuthenticatedCipher) procedure SetExpectedAuthenticationResult(const Value: TBytes); strict protected /// - /// Implementation of the Galois counter mode. Only created when gmGCM is - /// set as mode. + /// Implementation of the Galois counter mode, poly1305 or ccm. Only created if + /// such a mode is selected /// - FGCM : TGCM; - /// - /// Raises an EDECCipherException exception and provides the correct value - /// for block size in that message - /// - /// - /// Exception raised unconditionally. - /// + fAuthObj : TAuthenticatedCipherModesBase; + + procedure ReportInvalidMessageLength(Cipher: TDECCipher); /// /// Allows to run code after the initialization vector has been initialized @@ -238,7 +234,8 @@ TDECCipherModes = class(TDECCipher, IDECAuthenticatedCipher) /// Implemented in its own unit, but needed here to be callable even if /// source length is 0. /// - procedure EncodeGCM(Source, Dest: PUInt8Array; Size: Integer); virtual; + procedure EncodeWithAuthObj(Source, Dest: PUInt8Array; Size: Integer); virtual; + {$IFDEF DEC3_CMCTS} /// /// double CBC, with @@ -322,10 +319,11 @@ TDECCipherModes = class(TDECCipher, IDECAuthenticatedCipher) /// inputstream into feedback register. /// procedure DecodeCTSx(Source, Dest: PUInt8Array; Size: Integer); virtual; - /// - /// Galois Counter Mode, details are implemented in DECCipherModesGCM + + /// + /// Decoding for gcm, poly1305 and ccm, details are implemented in special units. /// - procedure DecodeGCM(Source, Dest: PUInt8Array; Size: Integer); virtual; + procedure DecodeWithAuthObj(Source, Dest: PUInt8Array; Size: Integer); virtual; {$IFDEF DEC3_CMCTS} /// /// double CBC @@ -400,7 +398,7 @@ TDECCipherModes = class(TDECCipher, IDECAuthenticatedCipher) /// in addition to encrypting it. This property contains the data which /// shall be authenticated in parallel to the encryption. Some authenticated /// modes still generate an authentication result even if no additional - /// data is supplied via this property, e.g. cmGCM is one of those. + /// data is supplied via this property, e.g. cmGCM or cmCCM are such ones. /// property DataToAuthenticate : TBytes read GetDataToAuthenticate @@ -410,10 +408,8 @@ TDECCipherModes = class(TDECCipher, IDECAuthenticatedCipher) /// Some block chaining modes have the ability to authenticate the message /// in addition to encrypting it. /// Represents the length of CalculatedAuthenticationResult in bit, values - /// as per specification are: 128, 120, 112, 104, or 96 bit. For certain - /// applications, they may be 64 or 32 as well, but the use of these two - /// tag lengths constrains the length of the input data and the lifetime - /// of the key. + /// as per specification can be retrieved via + /// GetStandardAuthenticationTagBitLengths method /// property AuthenticationResultBitLength : Integer read GetAuthenticationResultBitLength @@ -453,7 +449,10 @@ implementation {$ELSE} System.TypInfo, {$ENDIF} - DECUtil; + DECUtil, + DECCipherModesGCM, + DECCipherModesCCM, + DECCipherModesPoly1305; resourcestring sInvalidMessageLength = 'Message length for mode %0:s must be a multiple of %1:d bytes'; @@ -477,27 +476,30 @@ procedure TDECCipherModes.ReportInvalidMessageLength(Cipher: TDECCipher); procedure TDECCipherModes.SetDataToAuthenticate(const Value: TBytes); begin - if (FMode = cmGCM) then - FGCM.DataToAuthenticate := Value - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM']); + if Assigned(fAuthObj) + then + fAuthObj.DataToAuthenticate := Value + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; procedure TDECCipherModes.SetExpectedAuthenticationResult(const Value: TBytes); begin - if (FMode = cmGCM) then - FGCM.ExpectedAuthenticationTag := Value - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM']); + if Assigned(fAuthObj) + then + fAuthObj.ExpectedAuthenticationTag := Value + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; procedure TDECCipherModes.SetAuthenticationResultBitLength( const Value: Integer); begin - if (FMode = cmGCM) then - FGCM.AuthenticationTagBitLength := Value - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM']); + if Assigned(fAuthObj) + then + fAuthObj.AuthenticationTagBitLength := Value + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; procedure TDECCipherModes.Encode(const Source; var Dest; DataSize: Integer); @@ -517,7 +519,9 @@ procedure TDECCipherModes.Encode(const Source; var Dest; DataSize: Integer); cmOFBx: EncodeOFBx(@Source, @Dest, DataSize); cmCFS8: EncodeCFS8(@Source, @Dest, DataSize); cmCFSx: EncodeCFSx(@Source, @Dest, DataSize); - cmGCM : EncodeGCM(@Source, @Dest, DataSize); + cmGCM, + cmPoly1305, + cmCCM: EncodeWithAuthObj(@Source, @Dest, DataSize); end; end; @@ -689,63 +693,78 @@ procedure TDECCipherModes.EncodeOFBx(Source, Dest: PUInt8Array; Size: Integer); function TDECCipherModes.GetDataToAuthenticate: TBytes; begin - if (FMode = cmGCM) then - Result := FGCM.DataToAuthenticate - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM']); + if Assigned(fAuthObj) + then + Result := fAuthObj.DataToAuthenticate + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM, cmPoly1305 or cCCM']); end; function TDECCipherModes.GetExpectedAuthenticationResult: TBytes; begin - if (FMode = cmGCM) then - Result := FGCM.ExpectedAuthenticationTag - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM']); + if Assigned(fAuthObj) + then + Result := fAuthObj.ExpectedAuthenticationTag + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM, cmPoly1305 or cmCCM']); end; function TDECCipherModes.GetStandardAuthenticationTagBitLengths: TStandardBitLengths; begin - case FMode of - cmGCM: Result := FGCM.GetStandardAuthenticationTagBitLengths; - else - begin - SetLength(Result, 1); - Result[0] := 0; - end; - end; + if Assigned(fAuthObj) + then + Result := fAuthObj.GetStandardAuthenticationTagBitLengths + else + begin + SetLength(Result, 1); + Result[0] := 0; + end; end; function TDECCipherModes.GetAuthenticationResultBitLength: Integer; begin - if (FMode = cmGCM) then - Result := FGCM.AuthenticationTagBitLength - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM']); + if Assigned(fAuthObj) + then + Result := fAuthObj.AuthenticationTagBitLength + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM, cmPoly1305 or cmCCM']); end; function TDECCipherModes.GetCalcAuthenticatonResult: TBytes; begin - if (FMode = cmGCM) then - Result := FGCM.CalculatedAuthenticationTag - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM']); + if Assigned(fAuthObj) + then + Result := fAuthObj.CalculatedAuthenticationTag + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM, cmPoly1305 or cmCCM']); end; procedure TDECCipherModes.InitMode; begin - if FMode = TCipherMode.cmGCM then + if FMode in [TCipherMode.cmGCM, TCipherMode.cmCCM, TCipherMode.cmPoly1305] then begin - if Context.BlockSize = 16 then - FGCM := TGCM.Create + if (Context.BlockSize = 16) then + begin + case FMode of + cmGCM: fAuthObj := TGCM.Create; + cmCCM: fAuthObj := TCCM.Create; + cmPoly1305: fAuthObj := TPoly1305.Create; + end; + end + else if (Context.BlockSize < 16) and (TCipherMode.cmPoly1305 = FMode) + then + fAuthObj := TPoly1305.Create else - // GCM requires a cipher with 128 bit block size + // GCM and CCM require a cipher with 128 bit block size raise EDECCipherException.CreateResFmt(@sInvalidBlockSize, [128, GetEnumName(TypeInfo(TCipherMode), Integer(FMode))]); end else - if Assigned(FGCM) then - FreeAndNil(FGCM); + begin + if Assigned(fAuthObj) then + FreeAndNil(fAuthObj); + end; end; procedure TDECCipherModes.EncodeCFSx(Source, Dest: PUInt8Array; Size: Integer); @@ -838,23 +857,12 @@ procedure TDECCipherModes.EncodeCTSx(Source, Dest: PUInt8Array; Size: Integer); FState := csEncode; end; -procedure TDECCipherModes.EncodeGCM(Source, Dest: PUInt8Array; Size: Integer); -var - PlainText, - CipherText : TBytes; +procedure TDECCipherModes.EncodeWithAuthObj(Source, Dest: PUInt8Array; Size: Integer); begin - if (Size > 0) then - begin - PlainText := TBytes(@Source^); - CipherText := TBytes(@Dest^); - end - else - begin - SetLength(PlainText, 0); - SetLength(CipherText, 0); - end; + if (Size < 0) then + Size := 0; - FGCM.EncodeGCM(PlainText, CipherText, Size); + fAuthObj.Encode(Source, Dest, Size); end; {$IFDEF DEC3_CMCTS} @@ -899,7 +907,9 @@ procedure TDECCipherModes.Decode(const Source; var Dest; DataSize: Integer); cmOFBx: DecodeOFBx(@Source, @Dest, DataSize); cmCFS8: DecodeCFS8(@Source, @Dest, DataSize); cmCFSx: DecodeCFSx(@Source, @Dest, DataSize); - cmGCM : DecodeGCM(@Source, @Dest, DataSize); + cmGCM, + cmPoly1305, + cmCCM : DecodeWithAuthObj(@Source, @Dest, DataSize); end; end; @@ -938,23 +948,12 @@ procedure TDECCipherModes.DecodeECBx(Source, Dest: PUInt8Array; Size: Integer); end; end; -procedure TDECCipherModes.DecodeGCM(Source, Dest: PUInt8Array; Size: Integer); -var - PlainText, - CipherText : TBytes; +procedure TDECCipherModes.DecodeWithAuthObj(Source, Dest: PUInt8Array; Size: Integer); begin - if (Size > 0) then - begin - PlainText := TBytes(@Source^); - CipherText := TBytes(@Dest^); - end - else - begin - SetLength(PlainText, 0); - SetLength(CipherText, 0); - end; + if (Size < 0) then + Size := 0; - FGCM.DecodeGCM(PlainText, CipherText, Size); + fAuthObj.Decode(Source, Dest, Size); end; procedure TDECCipherModes.DecodeCFB8(Source, Dest: PUInt8Array; Size: Integer); @@ -1102,29 +1101,32 @@ procedure TDECCipherModes.DecodeOFBx(Source, Dest: PUInt8Array; Size: Integer); destructor TDECCipherModes.Destroy; begin - FGCM.Free; + fAuthObj.Free; - inherited; + inherited; end; procedure TDECCipherModes.Done; begin - inherited; - - if (FMode = cmGCM) then + if Assigned(fAuthObj) then begin - if (length(FGCM.ExpectedAuthenticationTag) > 0) and - (not IsEqual(FGCM.ExpectedAuthenticationTag, FGCM.CalculatedAuthenticationTag)) then - raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); + fAuthObj.FinalizeAEAD; + + if (length(fAuthObj.ExpectedAuthenticationTag) > 0) and + (not IsEqual(fAuthObj.ExpectedAuthenticationTag, fAuthObj.CalculatedAuthenticationTag)) + then + raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); end; + + inherited; end; procedure TDECCipherModes.OnAfterInitVectorInitialization(const OriginalInitVector: TBytes); begin inherited; - if (FMode = cmGCM) then - FGCM.Init(self.DoEncode, OriginalInitVector); + if Assigned(fAuthObj) then + fAuthObj.Init(self.DoEncode, OriginalInitVector); end; procedure TDECCipherModes.DecodeCFSx(Source, Dest: PUInt8Array; Size: Integer); diff --git a/Source/DECCipherModesCCM.pas b/Source/DECCipherModesCCM.pas new file mode 100644 index 00000000..966ce7a4 --- /dev/null +++ b/Source/DECCipherModesCCM.pas @@ -0,0 +1,439 @@ +{***************************************************************************** + The DEC team (see file NOTICE.txt) licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. A copy of this licence is found in the root directory + of this project in the file LICENCE.txt or alternatively at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*****************************************************************************} + +// Based on: aes_ccm.pas from Wolfgang Erhard +unit DECCipherModesCCM; + +interface + +{$INCLUDE DECOptions.inc} + +uses + {$IFDEF FPC} + SysUtils, + {$ELSE} + System.SysUtils, + {$ENDIF} + DECTypes, + DECAuthenticatedCipherModesBase; + +resourcestring + sWrongNonceLength = 'Wrong nonce/IV length. Must be between 7 and 13'; + sWrongNonceLengthDetailed = 'Nonce longer than 15 byte. Act. length: %0:d'; + sWrongCCMAuthLength = 'CCM authentication tag needs to have a length of ' + + '4, 6, 8, 10, 12, 14 or 16 byte'; + +type + /// + /// Counter with CBC-MAC Mode specific methods + /// + TCCM = class(TAuthenticatedCipherModesBase) + strict private + /// + /// Unmodified initialization vector + /// + FOrigInitVector : TBytes; + /// + /// Init vector which is modified during processing + /// + FInitVector : TBlock16Byte; + + /// + /// Encodes or decodes a block of data using the supplied cipher + /// + /// + /// Plain text to encrypt or decrypt, depending on encode parameter + /// + /// + /// Ciphertext or plaintext after encryption or decryption, depending on + /// encode parameter + /// + /// + /// Number of bytes to encrypt or decrypt + /// + /// + /// When true it is encrypting data, else it is descrypting data + /// + procedure EncodeDecode(Source, Dest: PUInt8Array; Size: Integer; Encode: Boolean); + strict protected + /// + /// Defines the length of the resulting authentication value in bit. + /// + /// + /// Sets the length of Authenticaton_tag in bit, values as per specification + /// are: 32, 48, 64, 80, 96, 112, 128 + /// + procedure SetAuthenticationTagLength(const Value: UInt32); override; + + // ########################################### + // #### Empty routines - just to satisfy the interface + procedure InitAuth; override; + procedure UpdateWithEncDecBuf(buf : PUInt8Array; Size : Integer); override; + procedure LocEncodeDecode(Source, Dest: Pointer; Size: Integer); override; + procedure FinalizeMAC( authLen, encDecBufSize : Int64 ); override; + + procedure Burn; override; + public + /// + /// Savely clear any buffers + /// + destructor Destroy; override; + /// + /// Should be called when starting encryption/decryption in order to + /// initialize internal tables etc. + /// + /// + /// Encryption method of the cypher used + /// + /// + /// Initialization vector + /// + procedure Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); override; + + /// + /// Encodes a block of data using the supplied cipher + /// + /// + /// Plain text to encrypt + /// + /// + /// Ciphertext after encryption + /// + /// + /// Number of bytes to encrypt + /// + procedure Encode(Source, + Dest : PUInt8Array; + Size : Integer); override; + /// + /// Decodes a block of data using the supplied cipher + /// + /// + /// Encrypted ciphertext to decrypt + /// + /// + /// Plaintext after decryption + /// + /// + /// Number of bytes to decrypt + /// + procedure Decode(Source, + Dest : PUInt8Array; + Size : Integer); override; + + /// + /// Returns a list of authentication tag lengths explicitely specified by + /// the official specification of the standard. + /// + /// + /// List of bit lengths + /// + function GetStandardAuthenticationTagBitLengths:TStandardBitLengths; override; + end; + +implementation + +uses + DECUtil; + +const + /// + /// Size of one block to be processed in byte + /// + cBlockSize = SizeOf(TBlock16Byte); + +resourcestring + /// + /// Exception raised when a size but no source data pointer was passed + /// + sInvalidSourcePointer = 'No source data pointer passed'; + +procedure TCCM.Decode(Source, Dest: PUInt8Array; Size: Integer); +begin + EncodeDecode(Source, Dest, Size, false); +end; + +destructor TCCM.Destroy; +begin + if (Length(FOrigInitVector) > 0) then + ProtectBytes(FOrigInitVector); + + ProtectBuffer(FInitVector, SizeOf(FInitVector)); + ProtectBytes(FCalcAuthenticationTag); + ProtectBytes(FExpectedAuthenticationTag); + + inherited; +end; + +procedure TCCM.Encode(Source, Dest: PUInt8Array; Size: Integer); +begin + EncodeDecode(Source, Dest, Size, true); +end; + +procedure TCCM.EncodeDecode(Source, Dest: PUInt8Array; + Size: Integer; + Encode: Boolean); +var + ecc : TBlock16Byte; // encrypted counter + FixedTagBuf : TBlock16Byte; // during calculation buffer of authentication tag + // might need to be bigger than then one specified + // by the user + len : Int32; + k, L : UInt16; + b : UInt8; + pb : PByte; + AuthDataLen : Integer; // Length of data to authenticate in bytes + InitVectLen : Integer; // Length of the init vector in bytes + + Buf : TBlock16Byte; + + // Increment CTR[15]..CTR[16-L] + procedure IncCTR(var CTR: TBlock16Byte); + var + j: integer; + begin + for j := 15 downto 16-L do + begin + if (CTR[j] = $FF) then + CTR[j] := 0 + else + begin + inc(CTR[j]); + exit; + end; + end; + end; + +begin + if (Size > 0) and + ((not Assigned(Source)) or (not Assigned(Dest))) then + raise EDECCipherException.Create(sInvalidSourcePointer); + + AuthDataLen := Length(FDataToAuthenticate); + InitVectLen := Length(FOrigInitVector); + + // calculate L value = max(number of bytes needed for sLen, 15-nLen) + len := Size; + L := 0; + while (len > 0) do + begin + inc(L); + len := len shr 8; + end; + + // Length of nonce (= init vector) is InitVectLen + if (InitVectLen + L > 15) then + raise EDECNonceLengthException.CreateFmt(sWrongNonceLengthDetailed, + [InitVectLen + L]); + + // Force Length(FInitVector) + L = 15. Since nLen <= 13, L is at least 2 + L := 15 - InitVectLen; + + // compose B_0 = Flags | Nonce N | l(m) + // octet 0: Flags = 64*HdrPresent | 8*((tLen-2) div 2 | (L-1) + + if (AuthDataLen > 0) then + b := 64 + else + b := 0; + + // Typecast for L-1 possible, since L is at least 2, see comment above + Buf[0] := b or ((FCalcAuthenticationTagLength-2) shl 2) or UInt16(L-1); + // octets 1..15-L is nonce + pb := @FOrigInitvector[0]; + for k := 1 to 15-L do + begin + Buf[k] := pb^; + inc(pb); + end; + + // octets 16-L .. 15: l(m) + len := Size; + for k := 1 to L do + begin + Buf[16-k] := len and $FF; + len := len shr 8; + end; + + FEncryptionMethod(@Buf[0], @Buf[0], Length(Buf)); + + // process header + if (AuthDataLen > 0) then + begin + // octets 0..1: encoding of hLen. Note: since we allow max $FEFF bytes + // only these two octets are used. Generally up to 10 octets are needed. + Buf[0] := Buf[0] xor (AuthDataLen shr 8); + Buf[1] := Buf[1] xor (AuthDataLen and $FF); + // now append the hdr data + len := 2; + pb := @FDataToAuthenticate[0]; + for k:= 1 to AuthDataLen do + begin + if (len = 16) then + begin + FEncryptionMethod(@Buf[0], @Buf[0], Length(Buf)); + len := 0; + end; + Buf[len] := Buf[len] xor pb^; + inc(len); + inc(pb); + end; + + if (len <> 0) then + FEncryptionMethod(@Buf[0], @Buf[0], Length(Buf)); + end; + + // setup the counter for source text processing + pb := @FOrigInitVector[0]; + FInitVector[0] := (L-1) and $FF; + for k := 1 to 15 do + begin + if (k < 16-L) then + begin + FInitVector[k] := pb^; + inc(pb); + end + else + FInitVector[k] := 0; + end; + + // process full source text blocks + while (Size >= 16) do + begin + IncCTR(FInitVector); + FEncryptionMethod(@FInitVector[0], @ecc[0], Length(FInitVector)); + + if Encode then + begin + XORBuffers(Source[0], Buf[0], 16, Buf[0]); + XORBuffers(Source[0], ecc[0], 16, Dest[0]); + end + else + begin + XORBuffers(Source[0], ecc[0], 16, Dest[0]); + XORBuffers(Dest[0], Buf[0], 16, Buf[0]); + end; + + FEncryptionMethod(@Buf[0], @Buf[0], Length(Buf)); + + inc(PByte(Source), cBlockSize); + inc(PByte(Dest), cBlockSize); + dec(Size, cBlockSize); + end; + + if (Size > 0) then + begin + // handle remaining bytes of source text + IncCTR(FInitVector); + + FEncryptionMethod(@FInitVector[0], @ecc[0], Length(ecc)); + + for k := 0 to UInt16(Size - 1) do + begin + if Encode then + begin + b := PByte(Source)^; + PByte(Dest)^ := b xor ecc[k]; + end + else + begin + b := PByte(Source)^ xor ecc[k]; + PByte(Dest)^ := b; + end; + Buf[k] := Buf[k] xor b; + inc(PByte(Source)); + inc(PByte(Dest)); + end; + + FEncryptionMethod(@Buf[0], @Buf[0], Length(Buf)); + end; + + // setup counter for the tag (zero the count) + for k := 15 downto 16-L do + FInitVector[k] := 0; + + FEncryptionMethod(@FInitVector[0], @ecc[0], Length(ecc)); + + // store the TAG/Authentication result value + XORBuffers(Buf[0], ecc[0], 16, FixedTagBuf); + Move(FixedTagBuf[0], FCalcAuthenticationTag[0], length(FCalcAuthenticationTag)); + + ProtectBuffer(Buf, SizeOf(Buf)); +end; + +function TCCM.GetStandardAuthenticationTagBitLengths: TStandardBitLengths; +begin + SetLength(Result, 7); + Result := [32, 48, 64, 80, 96, 112, 128]; +end; + +procedure TCCM.SetAuthenticationTagLength(const Value: UInt32); +begin + if not (Value in [32, 48, 64, 80, 96, 112, 128]) then + raise EDECAuthLengthException.Create(sWrongCCMAuthLength); + + FCalcAuthenticationTagLength := Value shr 3; + + SetLength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); +end; + +procedure TCCM.Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); +begin + Assert(Length(InitVector) > 0, 'No init vector specified'); + + if (Length(InitVector) < 7) or (Length(InitVector) > 13) then + raise EDECNonceLengthException.Create(sWrongNonceLength); + + inherited; + + FOrigInitVector := InitVector; +end; + + +procedure TCCM.UpdateWithEncDecBuf(buf: PUInt8Array; Size: Integer); +begin + inherited; + +end; + +procedure TCCM.InitAuth; +begin + inherited; + +end; + +procedure TCCM.LocEncodeDecode(Source, Dest: Pointer; Size: Integer); +begin + inherited; + +end; + +procedure TCCM.Burn; +begin + inherited; + +end; + +procedure TCCM.FinalizeMAC(authLen, encDecBufSize: Int64); +begin + inherited; + +end; + +end. diff --git a/Source/DECCipherModesGCM.pas b/Source/DECCipherModesGCM.pas index 0e819637..c87009b8 100644 --- a/Source/DECCipherModesGCM.pas +++ b/Source/DECCipherModesGCM.pas @@ -26,7 +26,8 @@ interface {$ELSE} System.SysUtils, {$ENDIF} - DECTypes; + DECTypes, + DECAuthenticatedCipherModesBase; type /// @@ -47,72 +48,53 @@ interface /// P16ByteArray = ^T16ByteArray; - /// - /// A methopd of this type needs to be supplied for encrypting or decrypting - /// a block via this GCM algorithm. The method is implemented as a parameter, - /// to avoid the need to bring TGCM in the inheritance chain. TGCM thus can - /// be used for composition instead of inheritance. - /// - /// - /// Data to be encrypted - /// - /// - /// In this memory the encrypted result will be written - /// - /// - /// Size of source in byte - /// - TEncodeDecodeMethod = procedure(Source, Dest: Pointer; Size: Integer) of Object; - /// /// Galois Counter Mode specific methods /// - TGCM = class(TObject) - private + TGCM = class(TAuthenticatedCipherModesBase) + strict private + const cGCMBlkSize = 16; + strict private /// /// Empty value? /// nullbytes : T128; - /// - /// Table with precalculated values - /// - FM : array[0..15,0..255] of T128; /// - /// Required for creating the table and encryption at least + /// if flag is set no more encoding is allowed /// - FH : T128; + fIsLastBlock : boolean; + /// - /// Calculated in initialization + /// One reserve buffer for the GCM intermediate blocks /// - FY : T128; + FData : Array[0..cGCMBlkSize-1] of Byte; + /// - /// Calculated in initialization + /// Current index of non encoded fdata bytes /// - FE_K_Y0 : T128; + FDataIdx : integer; /// - /// The data which shall be authenticated in parallel to the encryption + /// Table with precalculated values /// - FDataToAuthenticate : TBytes; + FM : array[0..15,0..255] of T128; + /// - /// Length of the authentication tag to generate in byte - /// - FCalcAuthenticationTagLength : UInt32; + FGHash : T128; + /// - /// Generated authentication tag + /// Required for creating the table and encryption at least /// - FCalcAuthenticationTag : TBytes; + FH : T128; /// - /// Expected authentication tag value, will be compared with actual value - /// when decryption finished. + /// Calculated in initialization /// - FExpectedAuthenticationTag : TBytes; - + FY : T128; /// - /// Reference to the encode method of the actual cipher used + /// Calculated in initialization /// - FEncryptionMethod : TEncodeDecodeMethod; + FE_K_Y0 : T128; /// /// XOR implementation for unsigned 128 bit numbers @@ -159,7 +141,7 @@ TGCM = class(TObject) /// /// Result of the XOR operation /// - procedure XOR_ArrayWithT128(const x: TBytes; XIndex, Count: UInt64; y: T128; var Result: TBytes); inline; + procedure XOR_ArrayWithT128(x: PUInt8Array; XIndex, Count: UInt64; y: T128; Result: PUInt8Array); inline; /// /// XORs all elements of the precalculated matrix with the value passed @@ -214,22 +196,9 @@ TGCM = class(TObject) procedure INCR(var Y : T128); /// - /// Defines the length of the resulting authentication value in bit. - /// - /// - /// Sets the length of Authenticaton_tag in bit, values as per specification - /// are: 128, 120, 112, 104, or 96 bit. For certain applications, they - /// may be 64 or 32 as well, but the use of these two tag lengths - /// constrains the length of the input data and the lifetime of the key. - /// - procedure SetAuthenticationTagLength(const Value: UInt32); - /// - /// Returns the length of the calculated authehtication value in bit - /// - /// - /// Length of the calculated authentication value in bit - /// - function GetAuthenticationTagBitLength: UInt32; + // ########################################### + // #### blocked version of GaloisHash functions + // ########################################### /// /// Calculates the hash value @@ -238,6 +207,9 @@ TGCM = class(TObject) /// Specifys the data for which an authentication value shall be /// calculated. It is allowed to be nil. /// + /// + /// Length of the data to authenticate in byte + /// /// /// Encrypted data used in the calculation /// @@ -247,8 +219,18 @@ TGCM = class(TObject) /// /// Calculated raw hash value which will later get returned as AuthenticatedTag /// - function CalcGaloisHash(AuthenticatedData, Ciphertext : TBytes; CiphertextSize: - Integer): T128; + function CalcGaloisHash(AuthenticatedData: PUInt8Array; AuthLen: integer; + Ciphertext: PUInt8Array; CiphertextSize: Integer): T128; + + + + /// + /// Finalizes the Hash using the Authdata length and accumulated CipherText length. + /// + /// + /// Calculated raw hash value which will later get returned as AuthenticatedTag + /// + /// /// Encrypts a T128 value using the encryption method specified on init @@ -259,51 +241,77 @@ TGCM = class(TObject) /// /// Encrypted value /// - function EncodeT128(Value: T128): T128; - public + function EncodeT128(Value: T128): T128; inline; + strict protected /// - /// Should be called when starting encryption/decryption in order to - /// initialize internal tables etc. + /// Defines the length of the resulting authentication value in bit. /// - /// - /// Encryption method of the cypher used - /// - /// - /// Initialization vector + /// + /// Sets the length of Authenticaton_tag in bit, values as per specification + /// are: 128, 120, 112, 104, or 96 bit. For certain applications, they + /// may be 64 or 32 as well, but the use of these two tag lengths + /// constrains the length of the input data and the lifetime of the key. /// - procedure Init(EncryptionMethod : TEncodeDecodeMethod; - InitVector : TBytes); + procedure SetAuthenticationTagLength(const Value: UInt32); override; + + /// - /// Encodes a block of data using the supplied cipher + /// Finalizes the Poly1305 calculation + /// The last block is padded and one additional block containing + /// the processed length + the legnth processed AuthenticationBytes + /// is created and fed into the polynom. + /// After this call the MAC is valid. /// - /// - /// Plain text to encrypt - /// - /// - /// Ciphertext after encryption + procedure FinalizeMAC( authLen, encDecBufLen : int64); override; + + /// + /// Initializes the Galois Hash function internal data and starts + /// with the DataToAuthenticate field. + /// + procedure InitAuth; override; + + /// + /// Updates the hash with a given cipher text. Internally the ciphertext length + /// field is also updated + /// + /// + /// Pointer the data that updates the hash. /// - /// - /// Number of bytes to encrypt + /// + /// Length of the buffer /// - procedure EncodeGCM(Source, - Dest : TBytes; - Size : Integer); + procedure UpdateWithEncDecBuf(buf : PUInt8Array; Size : Integer); override; + /// - /// Decodes a block of data using the supplied cipher + /// Encoding/Decoding routine - For some methods it is sufficient to just call + /// the given encoding routine (poly1305, chacha handles that internally) - some need to update the cipher (e.g. aes gcm) /// /// - /// Encrypted ciphertext to decrypt + /// Pointer the data that updates the hash. /// /// - /// Plaintext after decryption + /// Pointer the data that updates the hash. /// - /// - /// Number of bytes to decrypt + /// + /// Length of the buffer /// - procedure DecodeGCM(Source, - Dest : TBytes; - Size : Integer); + procedure LocEncodeDecode(Source, Dest: Pointer; Size: Integer); override; + + procedure Burn; override; + public + /// + /// Should be called when starting encryption/decryption in order to + /// initialize internal tables etc. + /// + /// + /// Encryption method of the cypher used + /// + /// + /// Initialization vector + /// + procedure Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); override; /// /// Returns a list of authentication tag lengths explicitely specified by /// the official specification of the standard. @@ -311,42 +319,19 @@ TGCM = class(TObject) /// /// List of bit lengths /// - function GetStandardAuthenticationTagBitLengths:TStandardBitLengths; - - /// - /// The data which shall be authenticated in parallel to the encryption - /// - property DataToAuthenticate : TBytes - read FDataToAuthenticate - write FDataToAuthenticate; - /// - /// Sets the length of AuthenticatonTag in bit, values as per official - /// specification are: 128, 120, 112, 104, or 96 bit. For certain - /// applications, they may be 64 or 32 as well, but the use of these two - /// tag lengths constrains the length of the input data and the lifetime - /// of the key. - /// - property AuthenticationTagBitLength : UInt32 - read GetAuthenticationTagBitLength - write SetAuthenticationTagLength; - /// - /// Calculated authentication value - /// - property CalculatedAuthenticationTag : TBytes - read FCalcAuthenticationTag - write FCalcAuthenticationTag; - - /// - /// Expected authentication tag value, will be compared with actual value - /// when decryption finished. - /// - property ExpectedAuthenticationTag : TBytes - read FExpectedAuthenticationTag - write FExpectedAuthenticationTag; + function GetStandardAuthenticationTagBitLengths:TStandardBitLengths; override; end; implementation +uses Math; + +function TGCM.EncodeT128(Value: T128): T128; +begin + FEncryptionMethod(@Value[0], @Result[0], 16); +end; + + function TGCM.XOR_T128(const x, y : T128): T128; begin Result[0] := x[0] xor y[0]; @@ -359,7 +344,7 @@ function TGCM.XOR_PointerWithT128(const x : Pointer; y : T128): T128; Result[1] := P128(x)^[1] xor y[1]; end; -procedure TGCM.XOR_ArrayWithT128(const x: TBytes; XIndex, Count: UInt64; y: T128; var Result: TBytes); +procedure TGCM.XOR_ArrayWithT128(x: PUInt8Array; XIndex, Count: UInt64; y: T128; Result: PUInt8Array); var i : integer; by : P16ByteArray; @@ -367,7 +352,7 @@ procedure TGCM.XOR_ArrayWithT128(const x: TBytes; XIndex, Count: UInt64; y: T128 by := @y[0]; for i := 0 to Count-1 do begin - Result[XIndex] := x[XIndex] xor by[i]; + Result^[XIndex] := x^[XIndex] xor by[i]; inc(XIndex); end; end; @@ -506,11 +491,7 @@ procedure TGCM.Init(EncryptionMethod : TEncodeDecodeMethod; b : ^Byte; OldH : T128; begin - Assert(Assigned(EncryptionMethod), 'No encryption method specified'); - - // Clear calculated authentication value - if (Length(FCalcAuthenticationTag) > 0) then - FillChar(FCalcAuthenticationTag[0], Length(FCalcAuthenticationTag), #0); + inherited; FEncryptionMethod := EncryptionMethod; @@ -518,7 +499,7 @@ procedure TGCM.Init(EncryptionMethod : TEncodeDecodeMethod; Nullbytes[1] := 0; OldH := FH; - EncryptionMethod(@Nullbytes[0], @FH[0], 16); + FEncryptionMethod(@Nullbytes[0], @FH[0], 16); // Only generate the table when not already generated if (OldH[0] <> FH[0]) or (OldH[1] <> FH[1]) then @@ -533,70 +514,145 @@ procedure TGCM.Init(EncryptionMethod : TEncodeDecodeMethod; b^ := 1; end else - FY := CalcGaloisHash(nil, InitVector, length(InitVector)); + FY := CalcGaloisHash(nil, 0, @InitVector[0], length(InitVector)); FEncryptionMethod(@FY[0], @FE_K_Y0[0], 16); end; -function TGCM.CalcGaloisHash(AuthenticatedData, Ciphertext : TBytes; - CiphertextSize: Integer): T128; -var - AuthCipherLength : T128; - x : T128; - n : Uint64; +procedure TGCM.InitAuth; +var authLen : integer; +begin + inherited; + + FillChar(fData, sizeof(fData), 0); + FDataIdx := 0; + + FGHash := nullbytes; + if Length(FDataToAuthenticate) > 0 then + begin + authLen := Length(FDataToAuthenticate); + UpdateWithEncDecBuf(@FDataToAuthenticate[0], authLen); + // this block needs to be padded if the authentication buffer is not a multiple of 16 + authLen := 16 - (authLen mod 16); + if authLen <> 16 then + UpdateWithEncDecBuf(@nullbytes, authLen); + end; + + fIsLastBlock := False; +end; - procedure encode(data : TBytes; dataSize: Integer); - var - i, mod_d, div_d, len_d : UInt64; - hdata : T128; - begin - len_d := dataSize; - if (len_d > 0) then - begin - n := 0; - div_d := len_d div 16; - if div_d > 0 then - begin - for i := 0 to div_d-1 do - begin - x := poly_mult_H(XOR_PointerWithT128(@data[n], x )); - inc(n, 16); - end; - end; +procedure TGCM.LocEncodeDecode(Source, Dest: Pointer; Size: Integer); +var i, j : integer; + div_len_plain : integer; - mod_d := len_d mod 16; - if mod_d > 0 then - begin - hdata := nullbytes; - Move(data[n], hdata[0], mod_d); - x := poly_mult_H(XOR_T128(hdata, x)); - end; +begin + if fIsLastBlock then + raise Exception.Create('Already last block processed. Call the encode only with a blocksize of 16 bytes'); + i := 0; + div_len_plain := Size div 16; + + for j := 1 to div_len_plain do + begin + INCR(FY); + + P128(@PUInt8Array(Dest)^[i])^ := XOR_PointerWithT128(@PUInt8Array(Source)^[i], EncodeT128(FY)); + + inc(i,16); + end; + + // is it the last block? + if i < Size then + begin + fIsLastBlock := True; + INCR(FY); + XOR_ArrayWithT128(Source, i, Size - i, EncodeT128(FY), Dest); end; - end; +end; +procedure TGCM.FinalizeMAC(authLen, encDecBufLen: int64); +var res : T128; + AuthCipherLength : T128; + x : T128; begin - x := nullbytes; - encode(AuthenticatedData, length(AuthenticatedData)); - Assert(length(Ciphertext) >= CiphertextSize); - encode(Ciphertext, CiphertextSize); - SetAuthenticationCipherLength(AuthCipherLength, length(AuthenticatedData) shl 3, CiphertextSize shl 3); + // last block::: + if FDataIdx > 0 then + begin + x := nullbytes; + Move(fData[0], x, FDataIdx); + FGHash := poly_mult_H(XOR_T128(x, FGHash)); + fDataIdx := 0; + end; + + // update hash with the lengths... + SetAuthenticationCipherLength(AuthCipherLength, authLen shl 3, encDecBufLen shl 3); + res := XOR_T128(poly_mult_H(XOR_T128(AuthCipherLength, FGHash)), FE_K_Y0); + + // copy and burn + if Length(FCalcAuthenticationTag) > 0 then + Move(res, FCalcAuthenticationTag[0], Min(sizeof(res), length(FCalcAuthenticationTag))); + res := nullbytes; + FillChar(FData, sizeof(fData), 0); +end; - Result := poly_mult_H(XOR_T128(AuthCipherLength, x)); +procedure TGCM.UpdateWithEncDecBuf(buf: PUInt8Array; Size: Integer); +var i, div_d, len_d : integer; + n : integer; +begin + n := 0; + if FDataIdx > 0 then + begin + if cGCMBlkSize - fDataIdx > Size then + begin + Move(buf^[0], fData[FDataIdx], size); + inc(FDataIdx, size); + exit; + end + else + begin + // encode one block + n := cGCMBlkSize - fDataIdx; + Move( buf^[0], fData[fDataIdx], n); + FGHash := poly_mult_H(XOR_PointerWithT128(@fData[0], FGHash )); + FDataIdx := 0; + end; + + end; + + len_d := size - n; + if (len_d >= cGCMBlkSize) then + begin + div_d := len_d div cGCMBlkSize; + for i := 0 to div_d - 1 do + begin + FGHash := poly_mult_H(XOR_PointerWithT128(@buf^[n], FGHash )); + inc(n, cGCMBlkSize); + end; + end; + + if n < size then + begin + Move(buf^[n], fData[fDataIdx], size - n); + inc(FDataIdx, size - n); + end; end; -procedure TGCM.DecodeGCM(Source, Dest: TBytes; Size: Integer); +(* +procedure TGCM.Encode(Source, Dest: PUInt8Array; Size: Integer); var - i, j, BlockCount : UInt64; - a_tag : T128; + i, j, div_len_plain : UInt64; + AuthTag : T128; + pDataToAuth : PUInt8Array; begin i := 0; - BlockCount := Size div 16; + div_len_plain := Size div 16; - for j := 1 to BlockCount do + for j := 1 to div_len_plain do begin INCR(FY); - P128(@Dest[i])^ := XOR_PointerWithT128(@Source[i], EncodeT128(FY)); - inc(i, 16); + + P128(@Dest^[i])^ := XOR_PointerWithT128(@Source^[i], EncodeT128(FY)); + + inc(i,16); end; if i < Size then @@ -605,61 +661,67 @@ procedure TGCM.DecodeGCM(Source, Dest: TBytes; Size: Integer); XOR_ArrayWithT128(Source, i, UInt64(Size)-i, EncodeT128(FY), Dest); end; - a_tag := XOR_T128(CalcGaloisHash(DataToAuthenticate, Source, Size), FE_K_Y0); - + pDataToAuth := nil; + if Length(DataToAuthenticate) > 0 then + pDataToAuth := @DataToAuthenticate[0]; + AuthTag := XOR_T128(CalcGaloisHash(pDataToAuth, Length(DataToAuthenticate), @Dest[0], Size), FE_K_Y0); Setlength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); if (FCalcAuthenticationTagLength > 0) then - Move(a_tag[0], FCalcAuthenticationTag[0], FCalcAuthenticationTagLength); - - // Check for correct authentication result is in Done of DECCipherModes - // if not IsEqual(FExpectedAuthenticationTag, FCalcAuthenticationTag) then - // raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); - - // In difference to the NIST recommendation we do not discard plaintext if - // authentication failed to make data recovery possible. But since we throw - // an exception the user will get notified that there's something wrong - // if not IsEqual(authenticaton_tag, ba_tag) then - // SetLength(plaintext, 0); // NIST FAIL => pt='' + Move(AuthTag[0], FCalcAuthenticationTag[0], FCalcAuthenticationTagLength); end; -procedure TGCM.EncodeGCM(Source, Dest: TBytes; Size: Integer); +*) + +(* +procedure TGCM.EncodeGCMBlk(Ciphertext, Dest : PUInt8Array; + CiphertextSize : Integer; + lastBlock: boolean); var - i, j, div_len_plain : UInt64; + i, j, div_len_plain : integer; AuthTag : T128; begin + // len = 0 -> first block. Init the hash + if FCipherLen = 0 then + BeginCalcGaloisHash; + + if not lastBlock and (CiphertextSize mod 16 <> 0) then + raise Exception.Create('Only multiple of 16bytes are allowed in block mode'); + i := 0; - div_len_plain := Size div 16; + div_len_plain := CiphertextSize div 16; for j := 1 to div_len_plain do begin INCR(FY); - P128(@Dest[i])^ := XOR_PointerWithT128(@Source[i], EncodeT128(FY)); + P128(@Dest^[i])^ := XOR_PointerWithT128(@Ciphertext^[i], EncodeT128(FY)); inc(i,16); end; - if i < Size then + if lastBlock then begin - INCR(FY); - XOR_ArrayWithT128(Source, i, UInt64(Size)-i, EncodeT128(FY), Dest); - end; + if i < CiphertextSize then + begin + INCR(FY); + XOR_ArrayWithT128(Ciphertext, i, CiphertextSize-i, EncodeT128(FY), Dest); + end; - AuthTag := XOR_T128(CalcGaloisHash(DataToAuthenticate, Dest, Size), FE_K_Y0); - Setlength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); - if (FCalcAuthenticationTagLength > 0) then - Move(AuthTag[0], FCalcAuthenticationTag[0], FCalcAuthenticationTagLength); -end; + UpdateGaloisHash(Dest, CiphertextSize); -function TGCM.EncodeT128(Value: T128): T128; -begin - FEncryptionMethod(@Value[0], @Result[0], 16); + //AuthTag := XOR_T128(CalcGaloisHash(DataToAuthenticate, Dest, Size), FE_K_Y0); + AuthTag := XOR_T128(FinishGaloisHash, FE_K_Y0); + Setlength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); + if (FCalcAuthenticationTagLength > 0) then + Move(AuthTag[0], FCalcAuthenticationTag[0], FCalcAuthenticationTagLength); + end + else + begin + UpdateGaloisHash(Dest, CiphertextSize); + end; end; -function TGCM.GetAuthenticationTagBitLength: UInt32; -begin - Result := FCalcAuthenticationTagLength shl 3; -end; +*) function TGCM.GetStandardAuthenticationTagBitLengths: TStandardBitLengths; begin @@ -667,66 +729,58 @@ function TGCM.GetStandardAuthenticationTagBitLengths: TStandardBitLengths; Result := [96, 104, 112, 120, 128]; end; -// -//function decrypt( const key, IV : TBytes; out plaintext : TBytes; const authenticated_data, -//ciphertext : TBytes; len_auth_tag : integer; const authenticaton_tag : TBytes ) : boolean; -//var -// i, j, div_len_ciph, len_ciph : Uint64; -// a_tag, E_K_Y0, Y, H : T128; -// bY : array[0..15] of byte absolute Y[0]; -// ba_Tag : TBytes; -// -// function equal( const a, b : TBytes ):boolean; -// begin -// if length(a) <> length(b) then Result := false -// else -// Result := CompareMem( @a[0], @b[0], length(a) ); -// end; -// -//begin -// len_auth_tag := len_auth_tag shr 3; -// -// E_Init( key ); -// H := E_Cipher( nullbytes ); -// Table_M_8Bit(H); -// -// len_ciph := length( ciphertext ); -// SetLength( plaintext, len_ciph ); -// -// if length(IV) = 12 then -// begin -// Y[1] := 0; -// Move( IV[0], Y[0], 12 ); -// bY[15] := 1; -// end -// else -// Y := CalcGaloisHash( H, nil, IV ); -// -// E_K_Y0 := E_Cipher( y ); -// -// i := 0; -// div_len_ciph := len_ciph div 16; -// for j := 1 to div_len_ciph do -// begin -// INCR( Y ); -// P128(@plaintext[i])^ := XOR_128_n( @ciphertext[i], E_cipher( Y ) ); -// inc(i,16); -// end; -// -// if i < len_ciph then -// begin -// INCR( Y ); -// XOR_128_n_l( ciphertext, i, len_ciph-i, E_cipher( Y ), plaintext ); -// end; -// -// a_tag := XOR_128( CalcGaloisHash( H, authenticated_data, ciphertext ), E_K_Y0 ); -// -// Setlength( ba_tag, len_auth_tag ); -// Move( a_tag[0], ba_tag[0], len_auth_tag ); -// -// Result := equal( authenticaton_tag, ba_tag ); -// if not Result then SetLength( plaintext, 0 ); // NIST FAIL => pt='' -//end; -// +procedure TGCM.Burn; +begin + inherited; + + FH := nullbytes; +end; + +function TGCM.CalcGaloisHash(AuthenticatedData : PUInt8Array; AuthLen : integer; Ciphertext : PUInt8Array; + CiphertextSize: Integer): T128; +var + AuthCipherLength : T128; + x : T128; + n : Uint64; + + procedure encode(data : PUInt8Array; dataSize: Integer); + var + i, mod_d, div_d, len_d : UInt64; + hdata : T128; + begin + len_d := dataSize; + if (len_d > 0) then + begin + n := 0; + div_d := len_d div 16; + if div_d > 0 then + begin + for i := 0 to div_d-1 do + begin + x := poly_mult_H(XOR_PointerWithT128(@data^[n], x )); + inc(n, 16); + end; + end; + + mod_d := len_d mod 16; + if mod_d > 0 then + begin + hdata := nullbytes; + Move(data^[n], hdata[0], mod_d); + x := poly_mult_H(XOR_T128(hdata, x)); + end; + end; + end; + +begin + x := nullbytes; + if AuthLen > 0 then + encode(@AuthenticatedData[0], AuthLen); + //Assert(length(Ciphertext) >= CiphertextSize); + encode(Ciphertext, CiphertextSize); + SetAuthenticationCipherLength(AuthCipherLength, AuthLen shl 3, CiphertextSize shl 3); + + Result := poly_mult_H(XOR_T128(AuthCipherLength, x)); +end; end. diff --git a/Source/DECCipherModesPoly1305.pas b/Source/DECCipherModesPoly1305.pas new file mode 100644 index 00000000..90307f39 --- /dev/null +++ b/Source/DECCipherModesPoly1305.pas @@ -0,0 +1,582 @@ +{***************************************************************************** + The DEC team (see file NOTICE.txt) licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. A copy of this licence is found in the root directory + of this project in the file LICENCE.txt or alternatively at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*****************************************************************************} + +unit DECCipherModesPoly1305; + +interface + +{$INCLUDE DECOptions.inc} + +uses + {$IFDEF FPC} + SysUtils, + {$ELSE} + System.SysUtils, + {$ENDIF} + DECTypes, DECAuthenticatedCipherModesBase; + +// ########################################### +// #### The implementation follows the openssl poly1305 one +// on https://github.com/openssl/openssl/blob/master/crypto/poly1305/poly1305.c +// the avx optimization is based on https://github.com/Sreyosi/Improved-SIMD-Implementation-of-Poly1305/ +type + T32ByteArray = Array[0..31] of Byte; // 0 - 16: key, 17-32 nonce +type + TPoly1305 = class(TAuthenticatedCipherModesBase) + private + const POLY1305_BLOCK_SIZE = 16; + POLY1305_DIGEST_SIZE = 16; + POLY1305_KEY_SIZE = 32; + type + TPoly1305Nonce = Array[0..3] of UInt32; + TPoly1305BlockMethod = procedure ( pData : PByteArray; size : integer ) of Object; + TPoly1305EmitMethod = procedure( var mac: TBlock16Byte ) of Object; + TPoly1305PadAndFinalize = procedure( authLen, encDecBufLen : int64) of Object; + THArr = Array[0..4] of UInt32; + PHArr = ^THArr; + TRArr = Array[0..3] of UInt32; + PRArr = ^TRArr; + TPoly1305State = Array[0..160] of Byte; + private + /// + /// avx buffer for h and R (may be extended in future fo for SSE, AVX) + /// + fPoly1305State : TPoly1305State; + + /// + /// H and R values. These point ot the fPoly1305State buffer + /// + FH : PHArr; + FR : PRArr; + + /// + /// Initialization vector and nonce - initialized from the 32Byte init vector + /// + fIV : T32ByteArray; + FNonce : TPoly1305Nonce; + + /// + /// Internal state variables - number of remaining bytes, block size and intermediate buffer + /// + fNum : integer; + fPolyBlockSize : integer; + fData : Array[0..2*POLY1305_BLOCK_SIZE - 1] of Byte; // for both the sse and pas version + + /// + /// #bytes of encrypted data + /// + fPolyInitComplete : boolean; + + /// + /// Reference to the actual poly block function. For future SSE, AVX use + /// + fPolyBlkFunc : TPoly1305BlockMethod; + fPadAndFinalizeFunc : TPoly1305PadAndFinalize; + + function U8ToU32( pData : PByteArray ) : UInt32; inline; + procedure U32ToU8(pData : PByteArray; value : UInt32); inline; + + /// + /// Poly1305 blocks function + /// + procedure Poly1305Blocks( pData : PByteArray; size : integer; padBit : UInt32 ); + + /// + /// Finaly MAC creating function + /// + procedure Poly1305Emit( var mac : TBlock16Byte; const nonce : TPoly1305Nonce ); + procedure PadAndFinalizePAS( authLen, encDecBufLen : int64); + protected + // ########################################### + // #### Authentication block functions + procedure UpdatePoly( pData : PByteArray; size : integer); + procedure InitInternal(const InitVector : T32ByteArray); + procedure Finalize; + + /// + /// Finalizes the Poly1305 calculation + /// The last block is padded and one additional block containing + /// the processed length + the legnth processed AuthenticationBytes + /// is created and fed into the polynom. + /// After this call the MAC is valid. + /// + procedure FinalizeMAC( authLen, encDecBufLen : int64); override; + procedure InitAuth; override; + procedure UpdateWithEncDecBuf(buf : PUInt8Array; Size : Integer); override; + + procedure Burn; override; + + public + constructor Create; + + /// + /// Should be called when starting encryption/decryption in order to + /// initialize internal tables etc. + /// + /// + /// Encryption method of the cypher used + /// + /// + /// Initialization vector + /// + procedure Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); override; + end; + +implementation + +{$R-}{$Q-} + +//CONSTANT_TIME_CARRY(a,b) ( \ +// (a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1) \ +// ) +function ConstTimeCarray32(a, b : UInt32 ) : UInt32; inline; +begin + Result := (a xor ( (a xor b) or ((a - b) xor b))) shr 31; +end; + + +{ TPoly1305 } + +procedure TPoly1305.U32ToU8(pData: PByteArray; value: UInt32); +begin + pData^[0] := Byte(value); + pData^[1] := Byte(value shr 8); + pData^[2] := Byte(value shr 16); + pData^[3] := Byte(value shr 24); +end; + +function TPoly1305.U8ToU32(pData: PByteArray): UInt32; +begin + Result := (UInt32(pData^[0]) and $ff) or + ((UInt32(pData^[1]) and $ff) shl 8) or + ((UInt32(pData^[2]) and $ff) shl 16) or + ((UInt32(pData^[3]) and $ff) shl 24); +end; + + +procedure TPoly1305.InitAuth; +var aLen : integer; + vec : TBytes; +begin + InitInternal(fIV); + + aLen := Length(FDataToAuthenticate); + // update the polynom with the unencrypted authentication data + if aLen > 0 then + begin + // pad to blocksize if ncessary + if aLen mod POLY1305_BLOCK_SIZE <> 0 then + begin + aLen := aLen + POLY1305_BLOCK_SIZE - aLen mod POLY1305_BLOCK_SIZE; + SetLength(vec, aLen); + Move(FDataToAuthenticate[0], vec[0], Length(FDataToAuthenticate)); + end + else + vec := FDataToAuthenticate; + fPolyBlkFunc( @vec[0], Length(vec)); + end; +end; + + +procedure TPoly1305.Burn; +begin + inherited; + + FillChar(fPoly1305State, sizeof(fPoly1305State), 0); + FillChar(FNonce, sizeof(FNonce), 0); + FillChar(fIV, sizeof(fIV), 0); + FillChar(fData, sizeof(fData), 0); + fNum := 0; +end; + +function AlignPtr64( A : Pointer ) : Pointer; +begin + Result := A; + if (NativeUint(A) and $3F) <> 0 then + Result := Pointer( NativeUint(Result) + $40 - NativeUint(Result) and $3F ); +end; + + +constructor TPoly1305.Create; +begin + inherited Create; + + FCalcAuthenticationTagLength := sizeof(TBlock16Byte); + FH := @fPoly1305State[0]; + FR := @fPoly1305State[sizeof(THarr)]; + + // for future use -> here is a good place to add sse AVX functions + fPadAndFinalizeFunc := PadAndFinalizePAS; + fPolyBlkFunc := UpdatePoly; + fPolyBlockSize := POLY1305_BLOCK_SIZE; +end; + +procedure TPoly1305.Finalize; +var mac : TBlock16Byte; +begin + if fNum > 0 then + begin + fData[fNum] := 1; // padbit.. + inc(fNum); + while fNum < Length(fData) do + begin + fData[fNum] := 0; + inc(fNum); + end; + + Poly1305Blocks(@fData[0], POLY1305_BLOCK_SIZE, 0); + fNum := 0; + end; + + Poly1305Emit(mac, FNonce); + + SetLength(FCalcAuthenticationTag, sizeof(mac)); + Move(mac, FCalcAuthenticationTag[0], sizeof(mac)); + + FillChar(mac, sizeof(mac), 0); +end; + +procedure TPoly1305.Init(EncryptionMethod: TEncodeDecodeMethod; + InitVector: TBytes); +begin + inherited; + + // the poly1305 format needs to be initialized correctly from the outside! + // for chacha20 one needs to set initialize the chacha block with the key, + // 96bit nonce and counter to 0 -> the first 32bytes of that chacha scrambled block + // defines the iv + if Length(InitVector) <> ( Length(fIV) ) then + raise Exception.Create('The initVector must be 32Bytes long!'); + + // in this library this only works for chacha since it has an internal counter + // don't know how to deal with aes here... + // build the poly1305 iv from the first 256 bits + FillChar( fIV, sizeof(fIV), 0); + Move( initVector[0], fIV, Length(initVector)); +end; + +procedure TPoly1305.InitInternal(const InitVector: T32ByteArray); +begin + fPolyInitComplete := True; + + FillChar(FH^, sizeof(FH^), 0); + + ///* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ +// st->r[0] = U8TOU32(&key[0]) & 0x0fffffff; +// st->r[1] = U8TOU32(&key[4]) & 0x0ffffffc; +// st->r[2] = U8TOU32(&key[8]) & 0x0ffffffc; +// st->r[3] = U8TOU32(&key[12]) & 0x0ffffffc; + FR^[0] := U8ToU32(@initVector[0]) and $0fffffff; + FR^[1] := U8ToU32(@initVector[4]) and $0ffffffc; + FR^[2] := U8ToU32(@initVector[8]) and $0ffffffc; + FR^[3] := U8ToU32(@initVector[12]) and $0ffffffc; + + + FNonce[0] := U8ToU32(@initVector[16]); + FNonce[1] := U8ToU32(@initVector[20]); + FNonce[2] := U8ToU32(@initVector[24]); + FNonce[3] := U8ToU32(@initVector[28]); + + fNum := 0; +end; + +procedure TPoly1305.FinalizeMAC( authLen, encDecBufLen : int64); +begin + inherited; + + fPadAndFinalizeFunc(authLen, encDecBufLen); +end; + +procedure TPoly1305.PadAndFinalizePAS( authLen, encDecBufLen : int64); +var lens : Array[0..1] of Int64; +begin + // pad the last block with 0 + if fNum > 0 then + begin + fData[fNum] := 0; + inc(fNum); + while fNum < Length(fData) do + begin + fData[fNum] := 0; + inc(fNum); + end; + + Poly1305Blocks(@fData[0], POLY1305_BLOCK_SIZE, 1); + fNum := 0; + end; + + + // finalize with the tag with the lengths! + lens[0] := authLen; + lens[1] := encDecBufLen; + Poly1305Blocks(@lens[0], POLY1305_BLOCK_SIZE, 1); + + Finalize; +end; + +procedure TPoly1305.Poly1305Blocks(pData: PByteArray; size: integer; + padBit: UInt32); +var r0, r1, r2, r3 : UInt32; + s1, s2, s3 : UInt32; + h0, h1, h2, h3, h4, c : UInt32; + d0, d1, d2, d3 : UInt64; +begin + //r0 = st->r[0]; +// r1 = st->r[1]; +// r2 = st->r[2]; +// r3 = st->r[3]; + r0 := FR^[0]; + r1 := FR^[1]; + r2 := FR^[2]; + r3 := FR^[3]; + + //s1 = r1 + (r1 >> 2); +// s2 = r2 + (r2 >> 2); +// s3 = r3 + (r3 >> 2); + s1 := r1 + (r1 shr 2); + s2 := r2 + (r2 shr 2); + s3 := r3 + (r3 shr 2); + + //h0 = st->h[0]; +// h1 = st->h[1]; +// h2 = st->h[2]; +// h3 = st->h[3]; +// h4 = st->h[4]; + h0 := FH^[0]; + h1 := FH^[1]; + h2 := FH^[2]; + h3 := FH^[3]; + h4 := FH^[4]; + + while size >= POLY1305_BLOCK_SIZE do + begin + ///* h += m[i] */ +// h0 = (u32)(d0 = (u64)h0 + U8TOU32(inp + 0)); +// h1 = (u32)(d1 = (u64)h1 + (d0 >> 32) + U8TOU32(inp + 4)); +// h2 = (u32)(d2 = (u64)h2 + (d1 >> 32) + U8TOU32(inp + 8)); +// h3 = (u32)(d3 = (u64)h3 + (d2 >> 32) + U8TOU32(inp + 12)); +// h4 += (u32)(d3 >> 32) + padbit; + d0 := UInt64(h0) + U8ToU32(pData); + h0 := UInt32(d0); + d1 := UInt64(h1) + d0 shr 32 + U8ToU32(@pData^[4]); // the delphi compiler seems to be intelligent enough to replace the shift by accessing the high 4 bytes + h1 := UInt32(d1); + d2 := UInt64(h2) + d1 shr 32 + U8ToU32(@pData^[8]); + h2 := UInt32(d2); + d3 := UInt64(h3) + d2 shr 32 + U8ToU32(@pData^[12]); + h3 := UInt32(d3); + h4 := h4 + padbit + UInt32( d3 shr 32); + +// /* h *= r "%" p, where "%" stands for "partial remainder" */ + //d0 = ((u64)h0 * r0) + +// ((u64)h1 * s3) + +// ((u64)h2 * s2) + +// ((u64)h3 * s1); + d0 := UInt64(h0)*r0 + UInt64(h1)*s3 + UInt64(h2)*s2 + UInt64(h3)*s1; + +// d1 = ((u64)h0 * r1) + +// ((u64)h1 * r0) + +// ((u64)h2 * s3) + +// ((u64)h3 * s2) + +// (h4 * s1); + d1 := UInt64(h0)*r1 + UInt64(h1)*r0 + UInt64(h2)*s3 + UInt64(h3)*s2 + h4*s1; + +// d2 = ((u64)h0 * r2) + +// ((u64)h1 * r1) + +// ((u64)h2 * r0) + +// ((u64)h3 * s3) + +// (h4 * s2); + d2 := UInt64(h0)*r2 + UInt64(h1)*r1 + UInt64(h2)*r0 + UInt64(h3)*s3 + h4*s2; + +// d3 = ((u64)h0 * r3) + +// ((u64)h1 * r2) + +// ((u64)h2 * r1) + +// ((u64)h3 * r0) + +// (h4 * s3); +// h4 = (h4 * r0); +// + d3 := UInt64(h0)*r3 + UInt64(h1)*r2 + UInt64(h2)*r1 + UInt64(h3)*r0 + h4*s3; + h4 := h4*r0; + + //* last reduction step: */ + // /* a) h4:h0 = h4<<128 + d3<<96 + d2<<64 + d1<<32 + d0 */ +// h0 = (u32)d0; +// h1 = (u32)(d1 += d0 >> 32); +// h2 = (u32)(d2 += d1 >> 32); +// h3 = (u32)(d3 += d2 >> 32); +// h4 += (u32)(d3 >> 32); + h0 := UInt32(d0); + d1 := d1 + d0 shr 32; + h1 := UInt32(d1); + d2 := d2 + d1 shr 32; + h2 := UInt32(d2); + d3 := d3 + d2 shr 32; + h3 := UInt32(d3); + h4 := h4 + UInt32(d3 shr 32); + + //* b) (h4:h0 += (h4:h0>>130) * 5) %= 2^130 */ +// c = (h4 >> 2) + (h4 & ~3U); +// h4 &= 3; +// h0 += c; +// h1 += (c = CONSTANT_TIME_CARRY(h0,c)); +// h2 += (c = CONSTANT_TIME_CARRY(h1,c)); +// h3 += (c = CONSTANT_TIME_CARRY(h2,c)); +// h4 += CONSTANT_TIME_CARRY(h3,c); + c := (h4 shr 2) + (h4 and (not UInt32(3))); + h4 := h4 and 3; + h0 := h0 + c; + c := ConstTimeCarray32(h0, c); + h1 := h1 + c; + c := ConstTimeCarray32(h1, c); + h2 := h2 + c; + c := ConstTimeCarray32(h2, c); + h3 := h3 + c; + h4 := h4 + ConstTimeCarray32(h3, c); + + inc(PByte(pData), POLY1305_BLOCK_SIZE); + dec(size, POLY1305_BLOCK_SIZE); + end; + + FH^[0] := h0; + FH^[1] := h1; + FH^[2] := h2; + FH^[3] := h3; + FH^[4] := h4; +end; + +procedure TPoly1305.Poly1305Emit(var mac: TBlock16Byte; + const nonce: TPoly1305Nonce); +var h0, h1, h2, h3, h4 : UInt32; + g0, g1, g2, g3, g4 : UInt32; + t: UInt64; + mask : UInt32; +begin + // h0 = st->h[0]; + // h1 = st->h[1]; + //h2 = st->h[2]; +// h3 = st->h[3]; +// h4 = st->h[4]; + h0 := FH^[0]; + h1 := FH^[1]; + h2 := FH^[2]; + h3 := FH^[3]; + h4 := FH^[4]; + + // /* compare to modulus by computing h + -p */ +// g0 = (u32)(t = (u64)h0 + 5); +// g1 = (u32)(t = (u64)h1 + (t >> 32)); +// g2 = (u32)(t = (u64)h2 + (t >> 32)); +// g3 = (u32)(t = (u64)h3 + (t >> 32)); +// g4 = h4 + (u32)(t >> 32); + t := UInt64(h0) + 5; + g0 := UInt32(t); + t := UInt64(h1) + t shr 32; + g1 := UInt32(t); + t := UInt64(h2) + t shr 32; + g2 := UInt32(t); + t := UInt64(h3) + t shr 32; + g3 := UInt32(t); + g4 := h4 + UInt32( t shr 32 ); + + //* if there was carry into 131st bit, h3:h0 = g3:g0 */ + //mask = 0 - (g4 >> 2); +// g0 &= mask; +// g1 &= mask; +// g2 &= mask; +// g3 &= mask; +// mask = ~mask; +// h0 = (h0 & mask) | g0; +// h1 = (h1 & mask) | g1; +// h2 = (h2 & mask) | g2; +// h3 = (h3 & mask) | g3; + mask := UInt32( -(g4 shr 2) ); + g0 := g0 and mask; + g1 := g1 and mask; + g2 := g2 and mask; + g3 := g3 and mask; + mask := not mask; + h0 := (h0 and mask) or g0; + h1 := (h1 and mask) or g1; + h2 := (h2 and mask) or g2; + h3 := (h3 and mask) or g3; + + // /* mac = (h + nonce) % (2^128) */ + //h0 = (u32)(t = (u64)h0 + nonce[0]); +// h1 = (u32)(t = (u64)h1 + (t >> 32) + nonce[1]); +// h2 = (u32)(t = (u64)h2 + (t >> 32) + nonce[2]); +// h3 = (u32)(t = (u64)h3 + (t >> 32) + nonce[3]); + t := UInt64(h0) + nonce[0]; + h0 := UInt32(t); + t := UInt64(h1) + t shr 32 + nonce[1]; + h1 := UInt32(t); + t := UInt64(h2) + t shr 32 + nonce[2]; + h2 := UInt32(t); + t := UInt64(h3) + t shr 32 + nonce[3]; + h3 := UInt32(t); + + U32ToU8(@mac[0], h0); + U32ToU8(@mac[4], h1); + U32ToU8(@mac[8], h2); + U32ToU8(@mac[12], h3); +end; + +procedure TPoly1305.UpdatePoly(pData: PByteArray; size: integer); +var num : integer; + rem : integer; +begin + num := fNum; + + if num <> 0 then + begin + rem := POLY1305_BLOCK_SIZE - num; + if size >= rem then + begin + Move( pData^, fData[num], rem); + Poly1305Blocks(@fData[0], POLY1305_BLOCK_SIZE, 1); + inc( PByte(pData), rem); + dec( size, rem); + end + else + begin + //* Still not enough data to process a block. */ + move( pData^, fData[num], size ); + inc(fNum, size); + exit; + end; + end; + + rem := size mod POLY1305_BLOCK_SIZE; + size := size - rem; + + if size >= POLY1305_BLOCK_SIZE then + begin + Poly1305Blocks(pData, size, 1); + inc(PByte(pData), size); + end; + + if rem > 0 then + Move( pData^, fData[0], rem ); + + fNum := rem; +end; + +procedure TPoly1305.UpdateWithEncDecBuf(buf: PUInt8Array; Size: Integer); +begin + UpdatePoly(PByteArray(buf), size); +end; + +end. diff --git a/Source/DECCiphers.pas b/Source/DECCiphers.pas index d91593ad..6237f0d0 100644 --- a/Source/DECCiphers.pas +++ b/Source/DECCiphers.pas @@ -20,8 +20,13 @@ interface {$INCLUDE DECOptions.inc} -uses - DECCipherBase, DECCipherFormats, DECUtil, DECTypes; +uses {$IFDEF FPC} + SysUtils, + {$ELSE} + System.SysUtils, + {$ENDIF} + DECCipherBase, DECCipherFormats, DECUtil, DECTypes, DECCipherMOdesPoly1305, + System.Types; type // Cipher Classes @@ -201,6 +206,16 @@ TCipher_TEAN = class; /// TCipher_XTEA_DEC52 = class; + /// + /// ChaCha20 cipher. + /// + TCipher_ChaCha20 = class; + + /// + /// XChaCha20 cipher + /// + TCipher_XChaCha20 = class; + // Definitions needed for Skipjack algorithm PSkipjackTab = ^TSkipjackTab; TSkipjackTab = array[0..255] of Byte; @@ -365,8 +380,19 @@ TCipher_RC6 = class(TDECFormattedCipher) end; TCipher_Rijndael = class(TDECFormattedCipher) + protected + + /// + /// Blocksize in LongWords + /// + const Rijndael_Blocks = 4; // don't change this! + /// + /// Maximum number of rounds allowed. + /// + Rijndael_Rounds = 14; private FRounds: Integer; + /// /// Calculates the key used for encoding. Implemented is the "new AES /// conform key scheduling". @@ -394,6 +420,7 @@ TCipher_Rijndael = class(TDECFormattedCipher) procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; public + class var UseAESAsm : boolean; class function Context: TCipherContext; override; /// /// Gets the number of rounds/times the algorithm is being applied to the @@ -477,6 +504,77 @@ TCipher_AES256 = class(TCipher_AES) class function Context: TCipherContext; override; end; + TChaChaMode = (cmSpeed, cmBalance, cmSecure); // number of rounds... (4, 12, 20) default is 20 + TChaChaMtx = Array[0..15] of LongWord; + PChaChaMtx = ^TChaChaMtx; + TChaChaCpuMode = (cmPas, cmSSE, cmAVX); + TChaChaAVXMtx = Array[0..31] of LongWord; + PChaChaAVXMtx = ^TChaChaAVXMtx; + + TCipher_ChaCha20 = class(TDECFormattedCipher) + private + type + TChaChaKey = Array[0..7] of LongWord; // key - always 256 bit + TChaChaNonce = Array[0..1] of LongWord; // nonce - 96 bit, one longword is the counter + + type + // double the size -> two blocks at once + TChaChaEncodeBlkFunc = procedure(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); register; {$IFDEF FPC} assembler; {$ENDIF} + + protected + fInpChaChaMTX : PChaChaMtx; + fOutChaChaMtx : PChaChaAVXMtx; + + fChaChaBlkLen : integer; + fChaChaIdx : integer; + fChaChaMode : TChaChaMode; + fNumChaChaRounds : integer; + fFullBlockFunc : TChaChaEncodeBlkFunc; + + procedure ChaChaQuarterRound( var a, b, c, d : LongWord ); + procedure PasChaChaDoubleQuarterRound(mtx : PChaChaMtx); // one column and row round + + procedure InitChaChaBlk; + {$IFNDEF PUREPASCAL} + procedure SSEChaChaDoubleQuarterRound(mtx : PChaChaMtx); register; {$IFDEF FPC} assembler; {$ENDIF} + {$ENDIF} + procedure SetChaChaMode(const Value: TChaChaMode); + protected + procedure DoInit(const Key; Size: Integer); override; + procedure DoEncode(Source, Dest: Pointer; Size: Integer); override; + procedure DoDecode(Source, Dest: Pointer; Size: Integer); override; + procedure OnAfterInitVectorInitialization(const OriginalInitVector: TBytes); override; + + // some internal test functions + function TestChaChaMtx( const expectedMtx : TChaChaMtx ) : boolean; + public + property ChaChaMode : TChaChaMode read fChaChaMode write SetChaChaMode; + + procedure AfterConstruction; override; + + /// + /// Provides meta data about the cipher algorithm used like key size. + /// + class function Context: TCipherContext; override; + + /// + /// Set to true if the routine shall use SSE instructinos to build the chacha matrix + /// + class var CpuMode : TChaChaCpuMode; + end; + + // based on the draft: https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 + TCipher_XChaCha20 = class(TCipher_ChaCha20) + private + fHChaCha : Array[0..22] of LongWord; + fPHChaCha : PChaChaMtx; + + procedure HChaCha( iv : TBytes ); + protected + procedure OnAfterInitVectorInitialization(const OriginalInitVector: TBytes); override; + public + end; + TCipher_Square = class(TDECFormattedCipher) protected /// @@ -1020,12 +1118,7 @@ implementation {$IFOPT R+}{$DEFINE RESTORE_RANGECHECKS}{$R-}{$ENDIF} uses - {$IFDEF FPC} - SysUtils, - {$ELSE} - System.SysUtils, - {$ENDIF} - DECData, DECDataCipher; + DECData, DECDataCipher, DECCPUSupport; { TCipher_Null } @@ -2748,21 +2841,549 @@ procedure TCipher_RC6.DoDecode(Source, Dest: Pointer; Size: Integer); { TCipher_Rijndael } class function TCipher_Rijndael.Context: TCipherContext; -const - // don't change this! - Rijndael_Blocks = 4; - Rijndael_Rounds = 14; begin Result.KeySize := 32; Result.BlockSize := Rijndael_Blocks * 4; Result.BufferSize := Rijndael_Blocks * 4; - Result.AdditionalBufferSize := (Rijndael_Rounds + 1) * Rijndael_Blocks * SizeOf(UInt32) * 2; + Result.AdditionalBufferSize := (Rijndael_Rounds + 1) * Rijndael_Blocks * SizeOf(UInt32) * 2 + $20; // add additional spare memory for alignment Result.NeedsAdditionalBufferBackup := False; Result.MinRounds := 1; Result.MaxRounds := 1; Result.CipherType := [ctSymmetric, ctBlock]; end; +{$IF defined(X86ASM) or defined(X64ASM)} + +// ########################################### +// #### AES assembler functions +// #### Routines are based on the intel whitepaper: +// #### https://www.intel.com/content/dam/develop/external/us/en/documents/aes-wp-2012-09-22-v01-165683.pdf +// ########################################### + +// assumes registerd preloaded - use only in within BuildASMKey128 +procedure KeyExpand128; register; +asm + pshufd xmm2, xmm2, $ff; + movapd xmm3, xmm1; + pslldq xmm3, $04; + pxor xmm1, xmm3; + movapd xmm3, xmm1; + pslldq xmm3, $04; + pxor xmm1, xmm3; + movapd xmm3, xmm1; + pslldq xmm3, $04; + pxor xmm1, xmm3; + pxor xmm1, xmm2; + {$IFDEF X64ASM} + movdqu [rdx], xmm1; + add rdx, $10; + {$ELSE} + movdqu [edx], xmm1; + add edx, $10; + {$ENDIF} + +end; + +procedure BuildAsmKey128( key : PByte; dest : PLongWord ); register; +// eax : key, edx: dest +// rcx : key, rdx : dest +asm + xorpd xmm2, xmm2; + // key is 128bit + // 10 rounds to be filled + {$IFDEF X64ASM} + movdqu xmm1, [rcx]; + movdqu [rdx], xmm1; + add rdx, 16; + {$ELSE} + movdqu xmm1, [eax]; + movdqu [edx], xmm1; + add edx, 16; + {$ENDIF} + + aeskeygenassist xmm2, xmm1, $1; + call KeyExpand128; + aeskeygenassist xmm2, xmm1, $2; + call KeyExpand128 + aeskeygenassist xmm2, xmm1, $4 + call KeyExpand128 + aeskeygenassist xmm2, xmm1, $8 + call KeyExpand128 + aeskeygenassist xmm2, xmm1, $10 + call KeyExpand128 + aeskeygenassist xmm2, xmm1, $20 + call KeyExpand128 + aeskeygenassist xmm2, xmm1, $40 + call KeyExpand128 + aeskeygenassist xmm2, xmm1, $80 + call KeyExpand128 + aeskeygenassist xmm2, xmm1, $1b + call KeyExpand128 + aeskeygenassist xmm2, xmm1, $36 + call KeyExpand128 +end; + + +// only call with BuildasmKey192 - it assumes preloaded registers xmm0, xmm1, xmm2 +// xmm3 is used for intermediate results +procedure KeyExpand192; register; +asm + pshufd xmm1, xmm1, $55; + movapd xmm3, xmm0; + pslldq xmm3, $04; + pxor xmm0, xmm3; + + pslldq xmm3, $04; + pxor xmm0, xmm3; + + pslldq xmm3, $04; + pxor xmm0, xmm3; + + pxor xmm0, xmm1; + pshufd xmm1, xmm0, $FF; + + movapd xmm3, xmm2; + pslldq xmm3, $04; + + pxor xmm2, xmm3; + pxor xmm2, xmm1; +end; + +procedure BuildAsmKey196( key : PByte; dest : PLongWord); register; +// eax: key, edx : dest +// rcx: key, rdx : dest; +asm + // load key + xorpd xmm2, xmm2; + + {$IFDEF X64ASM} + movupd xmm0, [rcx]; + movsd xmm2, [rcx + 16]; + movupd [rdx], xmm0; + {$ELSE} + movupd xmm0, [eax]; + movsd xmm2, [eax + 16]; + movupd [edx], xmm0; + {$ENDIF} + + movapd xmm4, xmm2; + + aeskeygenassist xmm1, xmm2, $01; + call KeyExpand192; + + shufpd xmm4, xmm0, 0; + {$IFDEF X64ASM} + movupd [rdx + 16], xmm4; + {$ELSE} + movupd [edx + 16], xmm4; + {$ENDIF} + movapd xmm4, xmm0; + shufpd xmm4, xmm2, 1; + {$IFDEF X64ASM} + movupd [rdx + 32], xmm4; + {$ELSE} + movupd [edx + 32], xmm4; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $02; + call KeyExpand192; + {$IFDEF X64ASM} + movupd [rdx + 48], xmm0; + {$ELSE} + movupd [edx + 48], xmm0; + {$ENDIF} + movapd xmm4, xmm2; + aeskeygenassist xmm1, xmm2, $04; + call KeyExpand192; + shufpd xmm4, xmm0, 0; + {$IFDEF X64ASM} + movupd [rdx + 64], xmm4; + {$ELSE} + movupd [edx + 64], xmm4; + {$ENDIF} + + movapd xmm4, xmm0; + shufpd xmm4, xmm2, 1; + {$IFDEF X64ASM} + movupd [rdx + 80], xmm4; + {$ELSE} + movupd [edx + 80], xmm4; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $08; + call KeyExpand192; + {$IFDEF X64ASM} + movupd [rdx + 96], xmm0; + {$ELSE} + movupd [edx + 96], xmm0; + {$ENDIF} + movapd xmm4, xmm2; + + aeskeygenassist xmm1, xmm2, $10; + call KeyExpand192; + shufpd xmm4, xmm0, 0; + {$IFDEF X64ASM} + movupd [rdx + 112], xmm4; + {$ELSE} + movupd [edx + 112], xmm4; + {$ENDIF} + + movapd xmm4, xmm0; + shufpd xmm4, xmm2, 1; + {$IFDEF X64ASM} + movupd [rdx + 128], xmm4; + {$ELSE} + movupd [edx + 128], xmm4; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $20; + call KeyExpand192; + {$IFDEF X64ASM} + movupd [rdx + 144], xmm0; + {$ELSE} + movupd [edx + 144], xmm0; + {$ENDIF} + movapd xmm4, xmm2; + + aeskeygenassist xmm1, xmm2, $40; + call KeyExpand192; + + shufpd xmm4, xmm0, 0; + {$IFDEF X64ASM} + movupd [rdx + 160], xmm4; + {$ELSE} + movupd [edx + 160], xmm4; + {$ENDIF} + + movapd xmm4, xmm0; + shufpd xmm4, xmm2, 1; + {$IFDEF X64ASM} + movupd [rdx + 176], xmm4; + {$ELSE} + movupd [edx + 176], xmm4; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $80; + call KeyExpand192; + {$IFDEF X64ASM} + movupd [rdx + 192], xmm0; + {$ELSE} + movupd [edx + 192], xmm0; + {$ENDIF} +end; + +// for the 256 bit key expand functions we assume that xmm0 - xmm2 are +// prefilled and are used (aka not used as parameters) +// xmm3 and xmm4 are used as intermediate registers +procedure KeyExpand256_1; register; +asm + pshufd xmm1, xmm1, $FF; + movapd xmm3, xmm0; + pslldq xmm3, $04; + pxor xmm0, xmm3; + + pslldq xmm3, $04; + pxor xmm0, xmm3; + + pslldq xmm3, $04; + pxor xmm0, xmm3; + pxor xmm0, xmm1; +end; + +// no parameter given here -> xmm01 to xmm3 represent temp1 to temp4 +procedure KeyExpand256_2; register; +asm + aeskeygenassist xmm3, xmm0, $00; + pshufd xmm1, xmm3, $AA; + movapd xmm3, xmm2; + pslldq xmm3, $04; + pxor xmm2, xmm3; + pslldq xmm3, $04; + + pxor xmm2, xmm3; + pslldq xmm3, $04; + + pxor xmm2, xmm3; + pxor xmm2, xmm1; +end; + +procedure BuildAsmKey256( key : PByte; dest : PLongWord); register; +asm +// eax = key, edx = dest +// rcx = key, rdx = dest + + // load key + {$IFDEF X64ASM} + movupd xmm0, [rcx]; + movupd xmm2, [rcx + 16]; + + movupd [rdx], xmm0; + movupd [rdx + 16], xmm2; + + {$ELSE} + movupd xmm0, [eax]; + movupd xmm2, [eax + 16]; + + movupd [edx], xmm0; + movupd [edx + 16], xmm2; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $1; + call KeyExpand256_1; + {$IFDEF X64ASM} + movupd [rdx + 32], xmm0; + {$ELSE} + movupd [edx + 32], xmm0; + {$ENDIF} + call KeyExpand256_2; + {$IFDEF X64ASM} + movupd [rdx + 48], xmm2; + {$ELSE} + movupd [edx + 48], xmm2; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $2; + call KeyExpand256_1; + {$IFDEF X64ASM} + movupd [rdx + 64], xmm0; + {$ELSE} + movupd [edx + 64], xmm0; + {$ENDIF} + call KeyExpand256_2; + {$IFDEF X64ASM} + movupd [rdx + 80], xmm2; + {$ELSE} + movupd [edx + 80], xmm2; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $4; + call KeyExpand256_1; + {$IFDEF X64ASM} + movupd [rdx + 96], xmm0; + {$ELSE} + movupd [edx + 96], xmm0; + {$ENDIF} + call KeyExpand256_2; + {$IFDEF X64ASM} + movupd [rdx + 112], xmm2; + {$ELSE} + movupd [edx + 112], xmm2; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $8; + call KeyExpand256_1; + {$IFDEF X64ASM} + movupd [rdx + 128], xmm0; + {$ELSE} + movupd [edx + 128], xmm0; + {$ENDIF} + call KeyExpand256_2; + {$IFDEF X64ASM} + movupd [rdx + 144], xmm2; + {$ELSE} + movupd [edx + 144], xmm2; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $10; + call KeyExpand256_1; + {$IFDEF X64ASM} + movupd [rdx + 160], xmm0; + {$ELSE} + movupd [edx + 160], xmm0; + {$ENDIF} + call KeyExpand256_2; + {$IFDEF X64ASM} + movupd [rdx + 176], xmm2; + {$ELSE} + movupd [edx + 176], xmm2; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $20; + call KeyExpand256_1; + {$IFDEF X64ASM} + movupd [rdx + 192], xmm0; + {$ELSE} + movupd [edx + 192], xmm0; + {$ENDIF} + call KeyExpand256_2; + {$IFDEF X64ASM} + movupd [rdx + 208], xmm2; + {$ELSE} + movupd [edx + 208], xmm2; + {$ENDIF} + + aeskeygenassist xmm1, xmm2, $40; + call KeyExpand256_1; + {$IFDEF X64ASM} + movupd [rdx + 224], xmm0; + {$ELSE} + movupd [edx + 224], xmm0; + {$ENDIF} + call KeyExpand256_2; + {$IFDEF X64ASM} + movupd [rdx + 240], xmm2; + {$ELSE} + movupd [edx + 240], xmm2; + {$ENDIF} +end; + +procedure BuildASMDecodeKey( encodeKey : PLongWord; decodeKey : PLongWord; numRounds : integer); register; +// eax = encodeKey, edx = decodeKey, ecx = numRounds +// rcx = encodeKey, rdx = decodeKey, r8 = numRounds +asm +// store in reverse order for iterative access in the decode routine! + {$IFDEF X64ASM} + movdqu xmm0, [rcx]; + lea rdx, [rdx + 8*r8]; // mult by 16 is not possible -> do it twice + lea rdx, [rdx + 8*r8]; + movdqu [rdx], xmm0; + + add rcx, 16; + sub rdx, 16; + dec r8d; + + @decLoop: + movdqu xmm0, [rcx]; + aesimc xmm0, xmm0; + movdqu [rdx], xmm0; + + add rcx, 16; + sub rdx, 16; + dec r8d; + jg @decLoop; + + movdqu xmm0, [rcx]; + movdqu [rdx], xmm0; + {$ELSE} + movdqu xmm0, [eax]; + lea edx, [edx + 8*ecx]; // mult by 16 is not possible -> do it twice + lea edx, [edx + 8*ecx]; + movdqu [edx], xmm0; + + add eax, 16; + sub edx, 16; + dec ecx; + + @decLoop: + movdqu xmm0, [eax]; + aesimc xmm0, xmm0; + movdqu [edx], xmm0; + + add eax, 16; + sub edx, 16; + + // decrement ecx and test + loop @decLoop; + + movdqu xmm0, [eax]; + movdqu [edx], xmm0; + {$ENDIF} +end; + + +// ########################################### +// #### AES assembler encode/decode +// ########################################### + +{$REGION 'ASM encode/decode'} +procedure AESEncode( Source, Dest : Pointer; numRounds : integer; key : PLongWord ); register; +asm + {$IFDEF X64ASM} + movupd xmm1, [rcx]; + movdqa xmm2, [r9]; + pxor xmm1, xmm2; + add r9, 16; + + dec r8d; + + @aesloop: + movdqa xmm2, [r9]; + aesenc xmm1, xmm2; + add r9, 16; + + dec r8d; + jg @aesloop; + + movdqa xmm2, [r9]; + aesenclast xmm1, xmm2; + movupd [rdx], xmm1; + {$ELSE} + push edi; + + movupd xmm1, [eax]; + mov edi, key; + movdqa xmm2, [edi]; + pxor xmm1, xmm2; + add edi, 16; + + dec ecx; + + @aesloop: + movdqa xmm2, [edi]; + aesenc xmm1, xmm2; + add edi, 16; + + dec ecx; + jg @aesloop; + + movdqa xmm2, [edi]; + aesenclast xmm1, xmm2; + movupd [edx], xmm1; + pop edi; + {$ENDIF} +end; + +procedure AESDecode( Source, Dest : Pointer; numRounds : integer; key : PLongWord ); register; +asm + {$IFDEF X64ASM} + movupd xmm1, [rcx]; + movdqa xmm2, [r9]; + pxor xmm1, xmm2; + add r9, 16; + + dec r8d; + + @aesloop: + movdqa xmm2, [r9]; + aesdec xmm1, xmm2; + add r9, 16; + + dec r8d; + jg @aesloop; + + movdqa xmm2, [r9]; + aesdeclast xmm1, xmm2; + movupd [rdx], xmm1; + {$ELSE} + push edi; + + movupd xmm1, [eax]; + mov edi, key; + movdqa xmm2, [edi]; + pxor xmm1, xmm2; + add edi, 16; + + dec ecx; + + @aesloop: + movdqa xmm2, [edi]; + aesdec xmm1, xmm2; + add edi, 16; + + dec ecx; + jg @aesloop; + + movdqa xmm2, [edi]; + aesdeclast xmm1, xmm2; + movupd [edx], xmm1; + pop edi; + {$ENDIF} +end; + +{$ENDREGION} + +{$IFEND} + procedure TCipher_Rijndael.DoInit(const Key; Size: Integer); {$REGION OldKeyShedule} { @@ -2853,6 +3474,9 @@ procedure TCipher_Rijndael.DoInit(const Key; Size: Integer); end; } {$ENDREGION} +{$IF defined(X86ASM) or defined(X64ASM)} +var pBuf : PUInt32Array; +{$IFEND} begin if Size <= 16 then FRounds := 10 @@ -2861,10 +3485,29 @@ procedure TCipher_Rijndael.DoInit(const Key; Size: Integer); FRounds := 12 else FRounds := 14; - FillChar(FAdditionalBuffer^, 32, 0); - Move(Key, FAdditionalBuffer^, Size); - BuildEncodeKey(Size); - BuildDecodeKey; + + {$IF defined(X86ASM) or defined(X64ASM)} + if UseAESAsm and TDEC_CPUSupport.AES then + begin + pBuf := AlignPtr32( FAdditionalBuffer ); + case Size of + 16: BuildAsmKey128(@key, PLongWord(pBuf)); + 24: BuildAsmKey196(@key, PLongWord(pBuf)); + 32: BuildAsmKey256(@key, PLongWord(pBuf)); + end; + + // build inverse decode key - utilize the aesimc opcode + BuildASMDecodeKey( PLongWord(pBuf), @(pBuf^[Rijndael_Rounds*Rijndael_Blocks]), fRounds); + end + else + {$IFEND} + begin + FillChar(FAdditionalBuffer^, 32, 0); + Move(Key, FAdditionalBuffer^, Size); + + BuildEncodeKey(Size); + BuildDecodeKey; + end; inherited; end; @@ -2965,12 +3608,50 @@ procedure TCipher_Rijndael.DoEncode(Source, Dest: Pointer; Size: Integer); begin Assert(Size = Context.BlockSize); + {$IF defined(X86ASM) or defined(X64ASM)} + if UseAESAsm and (TDEC_CPUSupport.AES) then + begin + AESEncode(Source, Dest, fRounds, AlignPtr32( FAdditionalBuffer ) ); + exit; + end; + {$IFEND} + P := FAdditionalBuffer; A1 := PUInt32Array(Source)[0]; B1 := PUInt32Array(Source)[1]; C1 := PUInt32Array(Source)[2]; D1 := PUInt32Array(Source)[3]; + //i := frounds; +// asmP := @fAsmEncKey[0]; +// asm +// push edx; +// push ecx; +// mov ecx, source; +// movupd xmm1, [ecx]; +// mov ecx, asmP; +// movupd xmm2, [ecx]; +// pxor xmm1, xmm2; +// add ecx, 16; +// +// mov edx, i; +// dec edx; +// +// aesloop: +// movupd xmm2, [ecx]; +// aesenc xmm1, xmm2; +// add ecx, 16; +// +// dec edx; +// jg aesloop; +// +// movupd xmm2, [ecx]; +// aesenclast xmm1, xmm2; +// movupd pp, xmm1; +// pop ecx; +// pop edx; +// end; + for I := 2 to FRounds do begin A2 := A1 xor P[0]; @@ -3030,6 +3711,14 @@ procedure TCipher_Rijndael.DoDecode(Source, Dest: Pointer; Size: Integer); begin Assert(Size = Context.BlockSize); + {$IF defined(X86ASM) or defined(X64ASM)} + if UseAESAsm and TDEC_CPUSupport.AES then + begin + AESDecode(Source, Dest, fRounds, @(PUInt32Array(AlignPtr32( FAdditionalBuffer ))^[Rijndael_Rounds*Rijndael_Blocks]) ); + exit; + end; + {$IFEND} + P := Pointer(PByte(FAdditionalBuffer) + FAdditionalBufferSize shr 1 + FRounds * 16); // for Pointer Math A1 := PUInt32Array(Source)[0]; B1 := PUInt32Array(Source)[1]; @@ -6786,12 +7475,1058 @@ procedure TCipher_XTEA_DEC52.DoDecode(Source, Dest: Pointer; Size: Integer); PUInt32Array(Dest)[1] := Y; end; +{ TCipher_ChaCha20 } + +{$IFDEF PUREPASCAL} +function rol(value: LongWord; Bits: Byte): LongWord; +begin + Result := (value shl Bits) or (value shr (32 - bits)); +end; +{$ELSE} +function rol(value: LongWord; Bits: Byte): LongWord; assembler; +{$IFDEF FPC} +begin +{$ENDIF} +asm + {$IFdef X64ASM} + mov eax, ecx; + mov cl, dl; + rol eax, cl; + {$ELSE} + xchg cl,dl + rol eax, cl + {$ENDIF} +end; +{$IFDEF FPC} +end; +{$ENDIF} +{$ENDIF} + +procedure TCipher_ChaCha20.ChaChaQuarterRound(var a, b, c, d: LongWord); +begin + // ########################################### + // #### + // a += b; d ^= a; d <<<= 16; + // c += d; b ^= c; b <<<= 12; + // a += b; d ^= a; d <<<= 8; + // c += d; b ^= c; b <<<= 7; + a := a + b; + d := d xor a; + d := rol(d, 16); + + c := c + d; + b := b xor c; + b := rol(b, 12); + + a := a + b; + d := d xor a; + d := rol(d, 8); + + c := c + d; + b := b xor c; + b := rol(b, 7); +end; + + +class function TCipher_ChaCha20.Context: TCipherContext; +begin + Result.KeySize := 256; + Result.BlockSize := 1; + Result.BufferSize := 16; + Result.AdditionalBufferSize := $40 + 3*sizeof(TChaChaMtx); + Result.NeedsAdditionalBufferBackup := False; + Result.MinRounds := 1; + Result.MaxRounds := 1; + Result.CipherType := [ctSymmetric, ctStream]; +end; + + +procedure TCipher_ChaCha20.DoDecode(Source, Dest: Pointer; Size: Integer); +begin + // should be the same + DoEncode( Source, Dest, size ); + FState := csDecode; +end; + +procedure TCipher_ChaCha20.DoEncode(Source, Dest: Pointer; Size: Integer); +var pChaCha : PByte; + + procedure TryEncodeFullBlocks; + begin + // ########################################### + // #### Full block version -> + if fChaChaIdx = 0 then + begin + while size >= sizeof(TChaChaAVXMtx) do + begin + fFullBlockFunc(fOutChaChaMtx, Source, Dest); + + inc(PByte(Source), sizeof(TChaChaAVXMtx)); + inc(PByte(Dest), sizeof(TChaChaAVXMtx)); + dec(size, sizeof(TChaChaAVXMtx)); + + InitChaChaBlk; + end; + end; + end; +begin + FState := csEncode; + pChaCha := PByte(fOutChaChaMtx); + inc(pChaCha, fChaChaIdx); + + TryEncodeFullBlocks; + + // ########################################### + // #### Single byte version + while size > 0 do + begin + if fChaChaIdx = fChaChaBlkLen then + begin + InitChaChaBlk; + pChaCha := PByte(fOutChaChaMtx); + + if size >= sizeof(TChaChaAVXMtx) then + begin + TryEncodeFullBlocks; + if size = 0 then + break; + end; + end; + + PByte(dest)^ := PByte(Source)^ xor pChaCha^; + + inc(pChaCha); + inc(PByte(dest)); + inc(PByte(source)); + inc(fChaChaIdx); + + dec(size); + end; +end; + +procedure TCipher_ChaCha20.OnAfterInitVectorInitialization( + const OriginalInitVector: TBytes); +var iv : TBytes; +begin + if FInitVectorSize <> 12 then + raise EDECException.Create('Nonce is not 96 bit.'); + + fInpChaChaMTX^[12] := 0; // counter + Move( FInitializationVector^, fInpChaChaMTX^[13], 3*sizeof(longword)); + + // special care in case of poly1305: + if FMode = cmPoly1305 then + begin + FBufferSize := 0; + // according to RFC7539 (chapter 2.6) we create the R and S (the IV vector) value as: + // block counter is 0 key and nonce (96 or 64 bits) + // build iv by applying the key/nonce pair on the first "block" which results + // in an 512bit vector -> use the first 256 bit as IV and discard the remaining one + // -> update the counter to 1 and setup the next block + + SetLength(iv, 32); + FillChar(iv[0], 32, 0); + + // init with count 0 + fInpChaChaMTX^[12] := 0; + InitChaChaBlk; + DoEncode(@iv[0], @iv[0], Length(iv)); + + inherited OnAfterInitVectorInitialization( iv ); + + // dismiss the remaining block -> + // first block was for the polynom... increment block number for the rest + fChaChaIdx := sizeof(TChaChaMtx); + + // setup complete -> We are ready to encrypt... + end + else + inherited; +end; + +procedure TCipher_ChaCha20.DoInit(const Key; Size: Integer); +// from chacha-prng.h +const cChaChaConst : Array[0..15] of AnsiChar = 'expand 32-byte k'; +begin + inherited; + + if size <> 32 then + raise EDECException.Create('Given ChaCha key size is not 256 bit'); + + // allocate for the AVX case -> 2 cha cha matrices at once + fInpChaChaMtx := AlignPtr32(FAdditionalBuffer); + fOutChaChaMTX := PChaChaAVXMtx( fInpChaChaMtx ); + inc(PByte(fOutChaChaMTX), sizeof(TChaChaMtx)); + + Move(cChaChaConst[0], fInpChaChaMTX^[0], sizeof(cChaChaConst)); + Move(key, fInpChaChaMTX^[4], 32); + + fChaChaBlkLen := sizeof(TChaChaAvxMtx);// 2*Length(fInpChaChaMTX^)*sizeof(fInpChaChaMTX^[0]); + fChaChaIdx := fChaChaBlkLen; +end; + +procedure FullBlockPas(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); register; +var i, j : integer; +begin + // xor the complete block + for i := 0 to 7 do + begin + j := i shl 2; + PChaChaAVXMtx(Dest)^[j + 0] := PChaChaAVXMtx(Source)^[j + 0] xor ChaChaMtx^[j + 0]; + PChaChaAVXMtx(Dest)^[j + 1] := PChaChaAVXMtx(Source)^[j + 1] xor ChaChaMtx^[j + 1]; + PChaChaAVXMtx(Dest)^[j + 2] := PChaChaAVXMtx(Source)^[j + 2] xor ChaChaMtx^[j + 2]; + PChaChaAVXMtx(Dest)^[j + 3] := PChaChaAVXMtx(Source)^[j + 3] xor ChaChaMtx^[j + 3]; + end; +end; + +procedure TCipher_ChaCha20.SetChaChaMode(const Value: TChaChaMode); +begin + fChaChaMode := Value; + + // secure would be 20 rounds + case fChaChaMode of + cmSpeed: fNumChaChaRounds := 4; + cmBalance: fNumChaChaRounds := 6; + cmSecure: fNumChaChaRounds := 10; + end; +end; + +// ########################################### +// #### AVX chacha assembler code +// ########################################### + +{$IFNDEF PUREPASCAL} + +{$IFDEF X86ASM} + +procedure FullBlockSSE(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); register; {$IFDEF FPC}assembler;{$ENDIF} +// eax = ChaChaMtx, edx = source, ecx = dest +asm + movapd xmm0, [eax]; + movupd xmm1, [edx]; + xorpd xmm0, xmm1; + movupd [ecx], xmm0; + + movapd xmm0, [eax + 16]; + movupd xmm1, [edx + 16]; + xorpd xmm0, xmm1; + movupd [ecx + 16], xmm0; + + movapd xmm0, [eax + 32]; + movupd xmm1, [edx + 32]; + xorpd xmm0, xmm1; + movupd [ecx + 32], xmm0; + + movapd xmm0, [eax + 48]; + movupd xmm1, [edx + 48]; + xorpd xmm0, xmm1; + movupd [ecx + 48], xmm0; + + movapd xmm0, [eax + 64]; + movupd xmm1, [edx + 64]; + xorpd xmm0, xmm1; + movupd [ecx + 64], xmm0; + + movapd xmm0, [eax + 80]; + movupd xmm1, [edx + 80]; + xorpd xmm0, xmm1; + movupd [ecx + 80], xmm0; + + movapd xmm0, [eax + 96]; + movupd xmm1, [edx + 96]; + xorpd xmm0, xmm1; + movupd [ecx + 96], xmm0; + + movapd xmm0, [eax + 112]; + movupd xmm1, [edx + 112]; + xorpd xmm0, xmm1; + movupd [ecx + 112], xmm0; +end; + +procedure FullBlockAVX(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); register; {$IFDEF FPC}assembler;{$ENDIF} +// eax = ChaChaMtx, edx = source, ecx = dest +asm + {$IFDEF AVXSUP}vmovapd ymm0, [eax]; {$ELSE}db $C5,$FD,$28,$00;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm1, [edx]; {$ELSE}db $C5,$FD,$10,$0A;{$ENDIF} + {$IFDEF AVXSUP}vxorpd ymm0, ymm1, ymm0; {$ELSE}db $C5,$F5,$57,$C0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd [ecx], ymm0; {$ELSE}db $C5,$FD,$11,$01;{$ENDIF} + + {$IFDEF AVXSUP}vmovapd ymm0, [eax + 32]; {$ELSE}db $C5,$FD,$28,$40,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm1, [edx + 32]; {$ELSE}db $C5,$FD,$10,$4A,$20;{$ENDIF} + {$IFDEF AVXSUP}vxorpd ymm0, ymm1, ymm0; {$ELSE}db $C5,$F5,$57,$C0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd [ecx + 32], ymm0; {$ELSE}db $C5,$FD,$11,$41,$20;{$ENDIF} + + {$IFDEF AVXSUP}vmovapd ymm0, [eax + 64]; {$ELSE}db $C5,$FD,$28,$40,$40;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm1, [edx + 64]; {$ELSE}db $C5,$FD,$10,$4A,$40;{$ENDIF} + {$IFDEF AVXSUP}vxorpd ymm0, ymm1, ymm0; {$ELSE}db $C5,$F5,$57,$C0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd [ecx + 64], ymm0; {$ELSE}db $C5,$FD,$11,$41,$40;{$ENDIF} + + {$IFDEF AVXSUP}vmovapd ymm0, [eax + 96]; {$ELSE}db $C5,$FD,$28,$40,$60;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm1, [edx + 96]; {$ELSE}db $C5,$FD,$10,$4A,$60;{$ENDIF} + {$IFDEF AVXSUP}vxorpd ymm0, ymm1, ymm0; {$ELSE}db $C5,$F5,$57,$C0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd [ecx + 96], ymm0; {$ELSE}db $C5,$FD,$11,$41,$60;{$ENDIF} + + {$IFDEF AVXSUP}vzeroupper; {$ELSE}db $C5,$F8,$77;{$ENDIF} +end; + + +{$ENDIF} +{$IFDEF X64ASM} +procedure FullBlockSSE(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); +// rcx = ChaChaMtx, rdx = source, r8 = dest +asm + {$IFDEF UNIX} + // Linux uses a diffrent ABI -> copy over the registers so they meet with winABI + // The parameters are passed in the following order: + // RDI, RSI, RDX, RCX, r8, r9 -> mov to RCX, RDX, R8, R9, width and height + mov r8, rdx; + mov r9, rcx; + mov rcx, rdi; + mov rdx, rsi; + {$ENDIF} + + movapd xmm0, [rcx]; + movupd xmm1, [rdx]; + xorpd xmm0, xmm1; + movupd [r8], xmm0; + + movapd xmm0, [rcx + 16]; + movupd xmm1, [rdx + 16]; + xorpd xmm0, xmm1; + movupd [r8 + 16], xmm0; + + movapd xmm0, [rcx + 32]; + movupd xmm1, [rdx + 32]; + xorpd xmm0, xmm1; + movupd [r8 + 32], xmm0; + + movapd xmm0, [rcx + 48]; + movupd xmm1, [rdx + 48]; + xorpd xmm0, xmm1; + movupd [r8 + 48], xmm0; + + movapd xmm0, [rcx + 64]; + movupd xmm1, [rdx + 64]; + xorpd xmm0, xmm1; + movupd [r8 + 64], xmm0; + + movapd xmm0, [rcx + 80]; + movupd xmm1, [rdx + 80]; + xorpd xmm0, xmm1; + movupd [r8 + 80], xmm0; + + movapd xmm0, [rcx + 96]; + movupd xmm1, [rdx + 96]; + xorpd xmm0, xmm1; + movupd [r8 + 96], xmm0; + + movapd xmm0, [rcx + 112]; + movupd xmm1, [rdx + 112]; + xorpd xmm0, xmm1; + movupd [r8 + 112], xmm0; +end; + +procedure FullBlockAVX(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); +// rcx = ChaChaMtx, rdx = source, r8 = dest +asm + {$IFDEF UNIX} + // Linux uses a diffrent ABI -> copy over the registers so they meet with winABI + // The parameters are passed in the following order: + // RDI, RSI, RDX, RCX, r8, r9 -> mov to RCX, RDX, R8, R9, width and height + mov r8, rdx; + mov r9, rcx; + mov rcx, rdi; + mov rdx, rsi; + {$ENDIF} + + {$IFDEF AVXSUP}vmovapd ymm0, [rcx]; {$ELSE}db $C5,$FD,$28,$01;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm1, [rdx]; {$ELSE}db $C5,$FD,$10,$0A;{$ENDIF} + {$IFDEF AVXSUP}vxorpd ymm0, ymm1, ymm0; {$ELSE}db $C5,$F5,$57,$C0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd [r8], ymm0; {$ELSE}db $C4,$C1,$7D,$11,$00;{$ENDIF} + + {$IFDEF AVXSUP}vmovapd ymm0, [rcx + 32]; {$ELSE}db $C5,$FD,$28,$41,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm1, [rdx + 32]; {$ELSE}db $C5,$FD,$10,$4A,$20;{$ENDIF} + {$IFDEF AVXSUP}vxorpd ymm0, ymm1, ymm0; {$ELSE}db $C5,$F5,$57,$C0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd [r8 + 32], ymm0; {$ELSE}db $C4,$C1,$7D,$11,$40,$20;{$ENDIF} + + {$IFDEF AVXSUP}vmovapd ymm0, [rcx + 64]; {$ELSE}db $C5,$FD,$28,$41,$40;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm1, [rdx + 64]; {$ELSE}db $C5,$FD,$10,$4A,$40;{$ENDIF} + {$IFDEF AVXSUP}vxorpd ymm0, ymm1, ymm0; {$ELSE}db $C5,$F5,$57,$C0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd [r8 + 64], ymm0; {$ELSE}db $C4,$C1,$7D,$11,$40,$40;{$ENDIF} + + {$IFDEF AVXSUP}vmovapd ymm0, [rcx + 96]; {$ELSE}db $C5,$FD,$28,$41,$60;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm1, [rdx + 96]; {$ELSE}db $C5,$FD,$10,$4A,$60;{$ENDIF} + {$IFDEF AVXSUP}vxorpd ymm0, ymm1, ymm0; {$ELSE}db $C5,$F5,$57,$C0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd [r8 + 96], ymm0; {$ELSE}db $C4,$C1,$7D,$11,$40,$60;{$ENDIF} + + {$IFDEF AVXSUP}vzeroupper; {$ELSE}db $C5,$F8,$77;{$ENDIF} +end; +{$ENDIF} + +const cShuf16 : Array[0..31] of byte = (3, 0, 1, 2, + 7, 4, 5, 6, + 11, 8, 9, 10, + 15, 12, 13, 14, + 3, 0, 1, 2, + 7, 4, 5, 6, + 11, 8, 9, 10, + 15, 12, 13, 14); + +{$IFDEF X86ASM} + +procedure AVXChaChaDoubleQuarterRound( chachaMtx : PChaChaAVXMtx ); {$IFDEF FPC} assembler; {$ELSE} register; {$ENDIF} +asm + lea ecx, cShuf16; + {$IFDEF AVXSUP}vmovdqu ymm5, [ecx]; {$ELSE}db $C5,$FE,$6F,$29;{$ENDIF} + + // move the matrix to xmm0 to xmm3 + {$IFDEF AVXSUP}vmovdqa ymm0, [eax]; {$ELSE}db $C5,$FD,$6F,$00;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa ymm1, [eax + 32]; {$ELSE}db $C5,$FD,$6F,$48,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa ymm2, [eax + 64]; {$ELSE}db $C5,$FD,$6F,$50,$40;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa ymm3, [eax + 96]; {$ELSE}db $C5,$FD,$6F,$58,$60;{$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= 16 + {$IFDEF AVXSUP}vpaddd ymm0, ymm0, ymm1; {$ELSE}db $C5,$FD,$FE,$C1;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm3, ymm3, ymm0; {$ELSE}db $C5,$E5,$EF,$D8;{$ENDIF} + {$IFDEF AVXSUP}vpshufhw ymm3, ymm3, $B1; {$ELSE}db $C5,$FE,$70,$DB,$B1;{$ENDIF} // 10 11 00 01 + {$IFDEF AVXSUP}vpshuflw ymm3, ymm3, $B1; {$ELSE}db $C5,$FF,$70,$DB,$B1;{$ENDIF} + + // v2 += v3; v1 ^= v2; v1 <<<= (12, 12, 12, 12); + {$IFDEF AVXSUP}vpaddd ymm2, ymm2, ymm3; {$ELSE}db $C5,$ED,$FE,$D3;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm1, ymm1, ymm2; {$ELSE}db $C5,$F5,$EF,$CA;{$ENDIF} + // rotate is x << n | x >> 32 - n + {$IFDEF AVXSUP}vpslld ymm4, ymm1, 12; {$ELSE}db $C5,$DD,$72,$F1,$0C;{$ENDIF} + {$IFDEF AVXSUP}vpsrld ymm1, ymm1, 20; {$ELSE}db $C5,$F5,$72,$D1,$14;{$ENDIF} // 32 - 12 + {$IFDEF AVXSUP}vpor ymm1, ymm1, ymm4; {$ELSE}db $C5,$F5,$EB,$CC;{$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= ( 8, 8, 8, 8); + {$IFDEF AVXSUP}vpaddd ymm0, ymm0, ymm1; {$ELSE}db $C5,$FD,$FE,$C1;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm3, ymm3, ymm0; {$ELSE}db $C5,$E5,$EF,$D8;{$ENDIF} + {$IFDEF AVXSUP}vpshufb ymm3, ymm3, ymm5; {$ELSE}db $C4,$E2,$65,$00,$DD;{$ENDIF} + + // v2 += v3; v1 ^= v2; v1 <<<= ( 7, 7, 7, 7); + {$IFDEF AVXSUP}vpaddd ymm2, ymm2, ymm3; {$ELSE}db $C5,$ED,$FE,$D3;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm1, ymm1, ymm2; {$ELSE}db $C5,$F5,$EF,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpslld ymm4, ymm1, 7; {$ELSE}db $C5,$DD,$72,$F1,$07;{$ENDIF} + {$IFDEF AVXSUP}vpsrld ymm1, ymm1, 25; {$ELSE}db $C5,$F5,$72,$D1,$19;{$ENDIF} // 32 - 7 + {$IFDEF AVXSUP}vpor ymm1, ymm1, ymm4; {$ELSE}db $C5,$F5,$EB,$CC;{$ENDIF} + + // v1 >>>= 32; v2 >>>= 64; v3 >>>= 96; + + // palignr is actually a sse3 opcode but ok... + {$IFDEF AVXSUP}vmovapd ymm4, ymm1; {$ELSE}db $C5,$FD,$29,$CC;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm1, ymm1, ymm4, 4; {$ELSE}db $C4,$E3,$75,$0F,$CC,$04;{$ENDIF} + {$IFDEF AVXSUP}vmovapd ymm4, ymm2; {$ELSE}db $C5,$FD,$29,$D4;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm2, ymm2, ymm4, 8; {$ELSE}db $C4,$E3,$6D,$0F,$D4,$08;{$ENDIF} + {$IFDEF AVXSUP}vmovapd ymm4, ymm3; {$ELSE}db $C5,$FD,$29,$DC;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm3, ymm3, ymm4, 12; {$ELSE}db $C4,$E3,$65,$0F,$DC,$0C;{$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= 16 + {$IFDEF AVXSUP}vpaddd ymm0, ymm0, ymm1; {$ELSE}db $C5,$FD,$FE,$C1;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm3, ymm3, ymm0; {$ELSE}db $C5,$E5,$EF,$D8;{$ENDIF} + {$IFDEF AVXSUP}vpshufhw ymm3, ymm3, $B1; {$ELSE}db $C5,$FE,$70,$DB,$B1;{$ENDIF} // 10 11 00 01 + {$IFDEF AVXSUP}vpshuflw ymm3, ymm3, $B1; {$ELSE}db $C5,$FF,$70,$DB,$B1;{$ENDIF} + + // v2 += v3; v1 ^= v2; v1 <<<= (12, 12, 12, 12); + {$IFDEF AVXSUP}vpaddd ymm2, ymm2, ymm3; {$ELSE}db $C5,$ED,$FE,$D3;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm1, ymm1, ymm2; {$ELSE}db $C5,$F5,$EF,$CA;{$ENDIF} + // rotate is x << n | x >> 32 - n + {$IFDEF AVXSUP}vpslld ymm4, ymm1, 12; {$ELSE}db $C5,$DD,$72,$F1,$0C;{$ENDIF} + {$IFDEF AVXSUP}vpsrld ymm1, ymm1, 20; {$ELSE}db $C5,$F5,$72,$D1,$14;{$ENDIF} // 32 - 12 + {$IFDEF AVXSUP}vpor ymm1, ymm1, ymm4; {$ELSE}db $C5,$F5,$EB,$CC;{$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= ( 8, 8, 8, 8); + {$IFDEF AVXSUP}vpaddd ymm0, ymm0, ymm1; {$ELSE}db $C5,$FD,$FE,$C1;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm3, ymm3, ymm0; {$ELSE}db $C5,$E5,$EF,$D8;{$ENDIF} + {$IFDEF AVXSUP}vpshufb ymm3, ymm3, ymm5; {$ELSE}db $C4,$E2,$65,$00,$DD;{$ENDIF} + + // v2 += v3; v1 ^= v2; v1 <<<= ( 7, 7, 7, 7); + {$IFDEF AVXSUP}vpaddd ymm2, ymm2, ymm3; {$ELSE}db $C5,$ED,$FE,$D3;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm1, ymm1, ymm2; {$ELSE}db $C5,$F5,$EF,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpslld ymm4, ymm1, 7; {$ELSE}db $C5,$DD,$72,$F1,$07;{$ENDIF} + {$IFDEF AVXSUP}vpsrld ymm1, ymm1, 25; {$ELSE}db $C5,$F5,$72,$D1,$19;{$ENDIF} // 32 - 7 + {$IFDEF AVXSUP}vpor ymm1, ymm1, ymm4; {$ELSE}db $C5,$F5,$EB,$CC;{$ENDIF} + + // v1 <<<= 32; v2 <<<= 64; v3 <<<= 96; Return + {$IFDEF AVXSUP}vmovapd ymm4, ymm1; {$ELSE}db $C5,$FD,$29,$CC;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm1, ymm1, ymm4, 12; {$ELSE}db $C4,$E3,$75,$0F,$CC,$0C;{$ENDIF} + {$IFDEF AVXSUP}vmovapd ymm4, ymm2; {$ELSE}db $C5,$FD,$29,$D4;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm2, ymm2, ymm4, 8; {$ELSE}db $C4,$E3,$6D,$0F,$D4,$08;{$ENDIF} + {$IFDEF AVXSUP}vmovapd ymm4, ymm3; {$ELSE}db $C5,$FD,$29,$DC;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm3, ymm3, ymm4, 4; {$ELSE}db $C4,$E3,$65,$0F,$DC,$04;{$ENDIF} + + // move back + {$IFDEF AVXSUP}vmovdqa [eax], ymm0; {$ELSE}db $C5,$FD,$7F,$00;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 32], ymm1; {$ELSE}db $C5,$FD,$7F,$48,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 64], ymm2; {$ELSE}db $C5,$FD,$7F,$50,$40;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 96], ymm3; {$ELSE}db $C5,$FD,$7F,$58,$60;{$ENDIF} + {$IFDEF AVXSUP}vzeroupper; {$ELSE}db $C5,$F8,$77;{$ENDIF} +end; + +// realign the chacha matrix such that further access to it is linear +procedure AVXRealingAndAddMtx( chaChaMtx : PChaChaAVXMtx; inpChaCha : PChaChaMtx ); {$IFDEF FPC} assembler; {$ELSE} register; {$ENDIF} +asm + // store second matrix + {$IFDEF AVXSUP}vmovdqa xmm0, [eax + 16]; {$ELSE}db $C5,$F9,$6F,$40,$10;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm1, [eax + 48]; {$ELSE}db $C5,$F9,$6F,$48,$30;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm2, [eax + 80]; {$ELSE}db $C5,$F9,$6F,$50,$50;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm3, [eax + 112]; {$ELSE}db $C5,$F9,$6F,$58,$70;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm0, xmm0, [edx]; {$ELSE}db $C5,$F9,$FE,$02;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm1, xmm1, [edx + 16]; {$ELSE}db $C5,$F1,$FE,$4A,$10;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm2, xmm2, [edx + 32]; {$ELSE}db $C5,$E9,$FE,$52,$20;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm3, xmm3, [edx + 48]; {$ELSE}db $C5,$E1,$FE,$5A,$30;{$ENDIF} + + // move positions + {$IFDEF AVXSUP}vmovapd xmm5, [eax]; {$ELSE}db $C5,$F9,$28,$28;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm5, xmm5, [edx]; {$ELSE}db $C5,$D1,$FE,$2A;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax], xmm5; {$ELSE}db $C5,$F9,$7F,$28;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm5, [eax + 32]; {$ELSE}db $C5,$F9,$6F,$68,$20;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm5, xmm5, [edx + 16]; {$ELSE}db $C5,$D1,$FE,$6A,$10;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 16], xmm5; {$ELSE}db $C5,$F9,$7F,$68,$10;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm5, [eax + 64]; {$ELSE}db $C5,$F9,$6F,$68,$40;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm5, xmm5, [edx + 32]; {$ELSE}db $C5,$D1,$FE,$6A,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 32], xmm5; {$ELSE}db $C5,$F9,$7F,$68,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm5, [eax + 96]; {$ELSE}db $C5,$F9,$6F,$68,$60;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm5, xmm5, [edx + 48]; {$ELSE}db $C5,$D1,$FE,$6A,$30;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 48], xmm5; {$ELSE}db $C5,$F9,$7F,$68,$30;{$ENDIF} + + // append second matrix + {$IFDEF AVXSUP}vmovdqa [eax + 64], xmm0; {$ELSE}db $C5,$F9,$7F,$40,$40;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 80], xmm1; {$ELSE}db $C5,$F9,$7F,$48,$50;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 96], xmm2; {$ELSE}db $C5,$F9,$7F,$50,$60;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [eax + 112], xmm3; {$ELSE}db $C5,$F9,$7F,$58,$70;{$ENDIF} + + {$IFDEF AVXSUP}vzeroupper; {$ELSE}db $C5,$F8,$77;{$ENDIF} +end; +{$ENDIF} + +{$IFDEF X64ASM} + +procedure AVXChaChaDoubleQuarterRound( chachaMtx : PChaChaAVXMtx ); +var dYMM4, dYMM5 : Array[0..4] of int64; +{$IFDEF FPC} +begin +{$ENDIF} +asm + {$IFDEF UNIX} + // Linux uses a diffrent ABI -> copy over the registers so they meet with winABI + // The parameters are passed in the following order: + // RDI, RSI, RDX, RCX, r8, r9 -> mov to RCX, RDX, R8, R9, width and height + // in our case only rdi to rcx + mov rcx, rdi; + {$ENDIF} + {$IFDEF AVXSUP}vmovupd dYMM4, ymm4; {$ELSE}db $C5,$FD,$11,$65,$D8;{$ENDIF} + {$IFDEF AVXSUP}vmovupd dYMM5, ymm5; {$ELSE}db $C5,$FD,$11,$6D,$B8;{$ENDIF} + + // 64bit version + lea rdx, [rip + cShuf16]; + {$IFDEF AVXSUP}vmovdqu ymm5, [rdx]; {$ELSE}db $C5,$FE,$6F,$2A;{$ENDIF} + + // move the matrix to xmm0 to xmm3 + {$IFDEF AVXSUP}vmovdqa ymm0, [rcx]; {$ELSE}db $C5,$FD,$6F,$01;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa ymm1, [rcx + 32]; {$ELSE}db $C5,$FD,$6F,$49,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa ymm2, [rcx + 64]; {$ELSE}db $C5,$FD,$6F,$51,$40;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa ymm3, [rcx + 96]; {$ELSE}db $C5,$FD,$6F,$59,$60;{$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= 16 + {$IFDEF AVXSUP}vpaddd ymm0, ymm0, ymm1; {$ELSE}db $C5,$FD,$FE,$C1;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm3, ymm3, ymm0; {$ELSE}db $C5,$E5,$EF,$D8;{$ENDIF} + {$IFDEF AVXSUP}vpshufhw ymm3, ymm3, $B1; {$ELSE}db $C5,$FE,$70,$DB,$B1;{$ENDIF} // 10 11 00 01 + {$IFDEF AVXSUP}vpshuflw ymm3, ymm3, $B1; {$ELSE}db $C5,$FF,$70,$DB,$B1;{$ENDIF} + + // v2 += v3; v1 ^= v2; v1 <<<= (12, 12, 12, 12); + {$IFDEF AVXSUP}vpaddd ymm2, ymm2, ymm3; {$ELSE}db $C5,$ED,$FE,$D3;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm1, ymm1, ymm2; {$ELSE}db $C5,$F5,$EF,$CA;{$ENDIF} + // rotate is x << n | x >> 32 - n + {$IFDEF AVXSUP}vpslld ymm4, ymm1, 12; {$ELSE}db $C5,$DD,$72,$F1,$0C;{$ENDIF} + {$IFDEF AVXSUP}vpsrld ymm1, ymm1, 20; {$ELSE}db $C5,$F5,$72,$D1,$14;{$ENDIF} // 32 - 12 + {$IFDEF AVXSUP}vpor ymm1, ymm1, ymm4; {$ELSE}db $C5,$F5,$EB,$CC;{$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= ( 8, 8, 8, 8); + {$IFDEF AVXSUP}vpaddd ymm0, ymm0, ymm1; {$ELSE}db $C5,$FD,$FE,$C1;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm3, ymm3, ymm0; {$ELSE}db $C5,$E5,$EF,$D8;{$ENDIF} + {$IFDEF AVXSUP}vpshufb ymm3, ymm3, ymm5; {$ELSE}db $C4,$E2,$65,$00,$DD;{$ENDIF} + + // v2 += v3; v1 ^= v2; v1 <<<= ( 7, 7, 7, 7); + {$IFDEF AVXSUP}vpaddd ymm2, ymm2, ymm3; {$ELSE}db $C5,$ED,$FE,$D3;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm1, ymm1, ymm2; {$ELSE}db $C5,$F5,$EF,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpslld ymm4, ymm1, 7; {$ELSE}db $C5,$DD,$72,$F1,$07;{$ENDIF} + {$IFDEF AVXSUP}vpsrld ymm1, ymm1, 25; {$ELSE}db $C5,$F5,$72,$D1,$19;{$ENDIF} // 32 - 7 + {$IFDEF AVXSUP}vpor ymm1, ymm1, ymm4; {$ELSE}db $C5,$F5,$EB,$CC;{$ENDIF} + + // v1 >>>= 32; v2 >>>= 64; v3 >>>= 96; + + // palignr is actually a sse3 opcode but ok... + {$IFDEF AVXSUP}vmovapd ymm4, ymm1; {$ELSE}db $C5,$FD,$29,$CC;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm1, ymm1, ymm4, 4; {$ELSE}db $C4,$E3,$75,$0F,$CC,$04;{$ENDIF} + {$IFDEF AVXSUP}vmovapd ymm4, ymm2; {$ELSE}db $C5,$FD,$29,$D4;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm2, ymm2, ymm4, 8; {$ELSE}db $C4,$E3,$6D,$0F,$D4,$08;{$ENDIF} + {$IFDEF AVXSUP}vmovapd ymm4, ymm3; {$ELSE}db $C5,$FD,$29,$DC;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm3, ymm3, ymm4, 12; {$ELSE}db $C4,$E3,$65,$0F,$DC,$0C;{$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= 16 + {$IFDEF AVXSUP}vpaddd ymm0, ymm0, ymm1; {$ELSE}db $C5,$FD,$FE,$C1;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm3, ymm3, ymm0; {$ELSE}db $C5,$E5,$EF,$D8;{$ENDIF} + {$IFDEF AVXSUP}vpshufhw ymm3, ymm3, $B1; {$ELSE}db $C5,$FE,$70,$DB,$B1;{$ENDIF} // 10 11 00 01 + {$IFDEF AVXSUP}vpshuflw ymm3, ymm3, $B1; {$ELSE}db $C5,$FF,$70,$DB,$B1;{$ENDIF} + + // v2 += v3; v1 ^= v2; v1 <<<= (12, 12, 12, 12); + {$IFDEF AVXSUP}vpaddd ymm2, ymm2, ymm3; {$ELSE}db $C5,$ED,$FE,$D3;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm1, ymm1, ymm2; {$ELSE}db $C5,$F5,$EF,$CA;{$ENDIF} + // rotate is x << n | x >> 32 - n + {$IFDEF AVXSUP}vpslld ymm4, ymm1, 12; {$ELSE}db $C5,$DD,$72,$F1,$0C;{$ENDIF} + {$IFDEF AVXSUP}vpsrld ymm1, ymm1, 20; {$ELSE}db $C5,$F5,$72,$D1,$14;{$ENDIF} // 32 - 12 + {$IFDEF AVXSUP}vpor ymm1, ymm1, ymm4; {$ELSE}db $C5,$F5,$EB,$CC;{$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= ( 8, 8, 8, 8); + {$IFDEF AVXSUP}vpaddd ymm0, ymm0, ymm1; {$ELSE}db $C5,$FD,$FE,$C1;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm3, ymm3, ymm0; {$ELSE}db $C5,$E5,$EF,$D8;{$ENDIF} + {$IFDEF AVXSUP}vpshufb ymm3, ymm3, ymm5; {$ELSE}db $C4,$E2,$65,$00,$DD;{$ENDIF} + + // v2 += v3; v1 ^= v2; v1 <<<= ( 7, 7, 7, 7); + {$IFDEF AVXSUP}vpaddd ymm2, ymm2, ymm3; {$ELSE}db $C5,$ED,$FE,$D3;{$ENDIF} + {$IFDEF AVXSUP}vpxor ymm1, ymm1, ymm2; {$ELSE}db $C5,$F5,$EF,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpslld ymm4, ymm1, 7; {$ELSE}db $C5,$DD,$72,$F1,$07;{$ENDIF} + {$IFDEF AVXSUP}vpsrld ymm1, ymm1, 25; {$ELSE}db $C5,$F5,$72,$D1,$19;{$ENDIF} // 32 - 7 + {$IFDEF AVXSUP}vpor ymm1, ymm1, ymm4; {$ELSE}db $C5,$F5,$EB,$CC;{$ENDIF} + + // v1 <<<= 32; v2 <<<= 64; v3 <<<= 96; Return + {$IFDEF AVXSUP}vmovapd ymm4, ymm1; {$ELSE}db $C5,$FD,$29,$CC;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm1, ymm1, ymm4, 12; {$ELSE}db $C4,$E3,$75,$0F,$CC,$0C;{$ENDIF} + {$IFDEF AVXSUP}vmovapd ymm4, ymm2; {$ELSE}db $C5,$FD,$29,$D4;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm2, ymm2, ymm4, 8; {$ELSE}db $C4,$E3,$6D,$0F,$D4,$08;{$ENDIF} + {$IFDEF AVXSUP}vmovapd ymm4, ymm3; {$ELSE}db $C5,$FD,$29,$DC;{$ENDIF} + {$IFDEF AVXSUP}vpalignr ymm3, ymm3, ymm4, 4; {$ELSE}db $C4,$E3,$65,$0F,$DC,$04;{$ENDIF} + + // move back + {$IFDEF AVXSUP}vmovdqa [rcx], ymm0; {$ELSE}db $C5,$FD,$7F,$01;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 32], ymm1; {$ELSE}db $C5,$FD,$7F,$49,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 64], ymm2; {$ELSE}db $C5,$FD,$7F,$51,$40;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 96], ymm3; {$ELSE}db $C5,$FD,$7F,$59,$60;{$ENDIF} + + // cleanup registers + {$IFDEF AVXSUP}vmovupd ymm4, dYMM4; {$ELSE}db $C5,$FD,$10,$65,$D8;{$ENDIF} + {$IFDEF AVXSUP}vmovupd ymm5, dYMM5; {$ELSE}db $C5,$FD,$10,$6D,$B8;{$ENDIF} + {$IFDEF AVXSUP}vzeroupper; {$ELSE}db $C5,$F8,$77;{$ENDIF} +end; +{$IFDEF FPC} +end; +{$ENDIF} + +// realign the chacha matrix such that further access to it is linear +procedure AVXRealingAndAddMtx( chaChaMtx : PChaChaAVXMtx; inpChaCha : PChaChaMtx ); +var dXMM4, dXMM5 : Array[0..2] of Double; +{$IFDEF FPC} +begin +{$ENDIF} +asm + {$IFDEF UNIX} + // Linux uses a diffrent ABI -> copy over the registers so they meet with winABI + // The parameters are passed in the following order: + // RDI, RSI -> mov to RCX, RDX + mov rcx, rdi; + mov rdx, rsi; + {$ENDIF} + {$IFDEF AVXSUP}vmovupd dXMM4, xmm4; {$ELSE}db $C5,$F9,$11,$65,$E0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd dXMM5, xmm5; {$ELSE}db $C5,$F9,$11,$6D,$D0;{$ENDIF} + + // store second matrix + {$IFDEF AVXSUP}vmovdqa xmm0, [rcx + 16]; {$ELSE}db $C5,$F9,$6F,$41,$10;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm1, [rcx + 48]; {$ELSE}db $C5,$F9,$6F,$49,$30;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm2, [rcx + 80]; {$ELSE}db $C5,$F9,$6F,$51,$50;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm3, [rcx + 112]; {$ELSE}db $C5,$F9,$6F,$59,$70;{$ENDIF} + + {$IFDEF AVXSUP}vpaddd xmm0, xmm0, [rdx]; {$ELSE}db $C5,$F9,$FE,$02;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm1, xmm1, [rdx + 16]; {$ELSE}db $C5,$F1,$FE,$4A,$10;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm2, xmm2, [rdx + 32]; {$ELSE}db $C5,$E9,$FE,$52,$20;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm3, xmm3, [rdx + 48]; {$ELSE}db $C5,$E1,$FE,$5A,$30;{$ENDIF} + + + // move positions + {$IFDEF AVXSUP}vmovapd xmm5, [rcx]; {$ELSE}db $C5,$F9,$28,$29;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm5, xmm5, [rdx]; {$ELSE}db $C5,$D1,$FE,$2A;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx], xmm5; {$ELSE}db $C5,$F9,$7F,$29;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm5, [rcx + 32]; {$ELSE}db $C5,$F9,$6F,$69,$20;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm5, xmm5, [rdx + 16]; {$ELSE}db $C5,$D1,$FE,$6A,$10;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 16], xmm5; {$ELSE}db $C5,$F9,$7F,$69,$10;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm5, [rcx + 64]; {$ELSE}db $C5,$F9,$6F,$69,$40;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm5, xmm5, [rdx + 32]; {$ELSE}db $C5,$D1,$FE,$6A,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 32], xmm5; {$ELSE}db $C5,$F9,$7F,$69,$20;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm5, [rcx + 96]; {$ELSE}db $C5,$F9,$6F,$69,$60;{$ENDIF} + {$IFDEF AVXSUP}vpaddd xmm5, xmm5, [rdx + 48]; {$ELSE}db $C5,$D1,$FE,$6A,$30;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 48], xmm5; {$ELSE}db $C5,$F9,$7F,$69,$30;{$ENDIF} + + // append second matrix + {$IFDEF AVXSUP}vmovdqa [rcx + 64], xmm0; {$ELSE}db $C5,$F9,$7F,$41,$40;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 80], xmm1; {$ELSE}db $C5,$F9,$7F,$49,$50;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 96], xmm2; {$ELSE}db $C5,$F9,$7F,$51,$60;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa [rcx + 112], xmm3; {$ELSE}db $C5,$F9,$7F,$59,$70;{$ENDIF} + + // cleanup registers + {$IFDEF AVXSUP}vmovupd xmm4, dXMM4; {$ELSE}db $C5,$F9,$10,$65,$E0;{$ENDIF} + {$IFDEF AVXSUP}vmovupd xmm5, dXMM5; {$ELSE}db $C5,$F9,$10,$6D,$D0;{$ENDIF} + + {$IFDEF AVXSUP}vzeroupper; {$ELSE}db $C5,$F8,$77;{$ENDIF} +end; +{$IFDEF FPC} +end; +{$ENDIF} + +{$ENDIF} + +{$ENDIF} // PUREPASCAL + +procedure TCipher_ChaCha20.AfterConstruction; +begin + inherited; + + // default is poly1305!! + Mode := cmPoly1305; + SetChaChaMode( cmSecure ); + {$IFDEF PUREPASCAL} + fFullBlockFunc := FullBlockPas; + {$ELSE} + case CpuMode of + cmSSE: if TDEC_CPUSupport.SSE3 then + fFullBlockFunc := FullBlockSSE; + cmAVX: if TDEC_CPUSupport.AVX2 then + fFullBlockFunc := FullBlockAVX; + else + fFullBlockFunc := FullBlockPas; + end; + {$ENDIF} +end; + + +// ########################################### +// #### ChaChaBlock init +// ########################################### +procedure TCipher_ChaCha20.InitChaChaBlk; +var i : integer; + m1, m2 : PChaChaMtx; +begin + if fChaChaIdx >= fChaChaBlkLen then + begin + {$IFNDEF PUREPASCAL} + if CpuMode = cmAVX then + begin + // move the input matrix so we have nicely aligned memory for the quarter round + for i := 0 to 3 do + begin + Move(fInpChaChaMtx^[4*i], fOutChaChaMtx^[8*i], 4*sizeof(LongWord)); + Move(fInpChaChaMtx^[4*i], fOutChaChaMtx^[8*i + 4], 4*sizeof(LongWord)); + end; + + // update index in the "second" matrix - this one is always odd so no further check + inc(fOutChaChaMtx^[3*8 + 4]); + + for i := 0 to fNumChaChaRounds - 1 do + AVXChaChaDoubleQuarterRound(fOutChaChaMtx); + // undo the alignment so both matrices are adjacent again (not intermittent as used for the rounds) + AVXRealingAndAddMtx(fOutChaChaMtx, fInpChaChaMTX); + + // increment the one value that is off by one from the input matrix + inc(fOutChaChaMtx^[16 + 12]); + + // increment input matrix by 2 + inc(fInpChaChaMTX^[12], 2); + end + else + {$ENDIF} + begin + // ########################################### + // #### Create two chacha matrices in one go + m1 := PChaChaMtx(fOutChaChaMtx); + m2 := m1; + inc(m2); + Move(fInpChaChaMTX^, m1^, sizeof(TChaChaMtx)); + Move(fInpChaChaMTX^, m2^, sizeof(TChaChaMtx)); + inc(m2^[12]); + + {$IFNDEF PUREPASCAL} + if cpuMode = cmSSE then + begin + for i := 0 to fNumChaChaRounds - 1 do + begin + SSEChaChaDoubleQuarterRound(m1); + SSEChaChaDoubleQuarterRound(m2); + end; + end + else + {$ENDIF} + begin + for i := 0 to fNumChaChaRounds - 1 do + begin + PasChaChaDoubleQuarterRound(m1); + PasChaChaDoubleQuarterRound(m2); + end; + + end; + for i := 0 to High(fInpChaChaMTX^) do + inc(m1^[i], fInpChaChaMTX^[i]); + inc(fInpChaChaMTX^[12]); + for i := 0 to High(fInpChaChaMTX^) do + inc(m2^[i], fInpChaChaMTX^[i]); + inc(fInpChaChaMTX^[12]); + end; + + fChaChaIdx := 0; + + // is this here for xchacha? + if fInpChaChaMTX^[12] <= 1 then + raise EDECException.Create('Counter overflow!'); +// inc(fInpChaChaMTX^[13]); + end; +end; + +procedure TCipher_ChaCha20.PasChaChaDoubleQuarterRound(mtx : PChaChaMtx); +begin + ChaChaQuarterRound( mtx^[0], mtx^[4], mtx^[8], mtx^[12]); + ChaChaQuarterRound( mtx^[1], mtx^[5], mtx^[9], mtx^[13]); + ChaChaQuarterRound( mtx^[2], mtx^[6], mtx^[10], mtx^[14]); + ChaChaQuarterRound( mtx^[3], mtx^[7], mtx^[11], mtx^[15]); + ChaChaQuarterRound( mtx^[0], mtx^[5], mtx^[10], mtx^[15]); + ChaChaQuarterRound( mtx^[1], mtx^[6], mtx^[11], mtx^[12]); + ChaChaQuarterRound( mtx^[2], mtx^[7], mtx^[8], mtx^[13]); + ChaChaQuarterRound( mtx^[3], mtx^[4], mtx^[9], mtx^[14]); +end; + +{$IFNDEF PUREPASCAL} + +(* +// https://eprint.iacr.org/2013/759.pdf +Algorithm 5: DOUBLEQUARTERROUND (optimized for 128-bit vectors) +Input: v0, v1, v2, v3 (state matrix as four 4x32-bit vectors, each vector includes one row) +Output: v0, v1, v2, v3 (updated state matrix) +Flow + v0 += v1; v3 ^= v0; v3 <<<= (16, 16, 16, 16); + v2 += v3; v1 ^= v2; v1 <<<= (12, 12, 12, 12); + v0 += v1; v3 ^= v0; v3 <<<= ( 8, 8, 8, 8); + v2 += v3; v1 ^= v2; v1 <<<= ( 7, 7, 7, 7); + v1 >>>= 32; v2 >>>= 64; v3 >>>= 96; + v0 += v1; v3 ^= v0; v3 <<<= (16, 16, 16, 16); + v2 += v3; v1 ^= v2; v1 <<<= (12, 12, 12, 12); + v0 += v1; v3 ^= v0; v3 <<<= ( 8, 8, 8, 8); + v2 += v3; v1 ^= v2; v1 <<<= ( 7, 7, 7, 7); + v1 <<<= 32; v2 <<<= 64; v3 <<<= 96; Return +*) +const cShuf8 : Array[0..15] of byte = (3, 0, 1, 2, + 7, 4, 5, 6, + 11, 8, 9, 10, + 15, 12, 13, 14 ); + +procedure TCipher_ChaCha20.SSEChaChaDoubleQuarterRound(mtx : PChaChaMtx); +// 32Bit: ecx = self, edx = mtx +// 64bit: rcx = self, rdx = mtx +{$IFDEF CPUX64} +var dXMM4, dXMM5 : Array[0..1] of Int64; +{$ENDIF} +asm + {$IFDEF CPUX64} + // rcx seems to have "self" as reference + {$IFDEF UNIX} + // Linux uses a diffrent ABI -> copy over the registers so they meet with winABI + // The parameters are passed in the following order: + // RDI, RSI, RDX, RCX, r8, r9 -> mov to RCX, RDX, R8, R9, width and height + // in our case only rdi to rcx + mov rdx, rsi; + {$ENDIF} + movupd dXMM4, xmm4; + movupd dXMM5, xmm5; + + // 64bit version + movdqu xmm5, [rip + cShuf8]; + + // move the matrix to xmm0 to xmm3 + movdqa xmm0, [rdx]; + movdqa xmm1, [rdx + 16]; + movdqa xmm2, [rdx + 32]; + movdqa xmm3, [rdx + 48]; + {$ELSE} + movdqu xmm5, cShuf8; + + // move the matrix to xmm0 to xmm3 + mov edx, mtx; + movdqa xmm0, [edx]; + movdqa xmm1, [edx + 16]; + movdqa xmm2, [edx + 32]; + movdqa xmm3, [edx + 48]; + {$ENDIF} + + // v0 += v1; v3 ^= v0; v3 <<<= 16 + paddd xmm0, xmm1; + pxor xmm3, xmm0; + pshufhw xmm3, xmm3, $B1; // 10 11 00 01 + pshuflw xmm3, xmm3, $B1; + + // v2 += v3; v1 ^= v2; v1 <<<= (12, 12, 12, 12); + paddd xmm2, xmm3; + pxor xmm1, xmm2; + // rotate is x << n | x >> 32 - n + movapd xmm4, xmm1; + pslld xmm4, 12; + psrld xmm1, 20; // 32 - 12 + por xmm1, xmm4; + + // v0 += v1; v3 ^= v0; v3 <<<= ( 8, 8, 8, 8); + paddd xmm0, xmm1; + pxor xmm3, xmm0; + pshufb xmm3, xmm5; + + // v2 += v3; v1 ^= v2; v1 <<<= ( 7, 7, 7, 7); + paddd xmm2, xmm3; + pxor xmm1, xmm2; + movapd xmm4, xmm1; + pslld xmm4, 7; + psrld xmm1, 25; // 32 - 7 + por xmm1, xmm4; + + // v1 >>>= 32; v2 >>>= 64; v3 >>>= 96; + + // palignr is actually a sse3 opcode but ok... + movapd xmm4, xmm1; + palignr xmm1, xmm4, 4; + movapd xmm4, xmm2; + palignr xmm2, xmm4, 8; + movapd xmm4, xmm3; + palignr xmm3, xmm4, 12; + + + // v0 += v1; v3 ^= v0; v3 <<<= 16 + paddd xmm0, xmm1; + pxor xmm3, xmm0; + pshufhw xmm3, xmm3, $B1; // 10 11 00 01 + pshuflw xmm3, xmm3, $B1; + + // v2 += v3; v1 ^= v2; v1 <<<= (12, 12, 12, 12); + paddd xmm2, xmm3; + pxor xmm1, xmm2; + // rotate is x << n | x >> 32 - n + movapd xmm4, xmm1; + pslld xmm4, 12; + psrld xmm1, 20; // 32 - 12 + por xmm1, xmm4; + + // v0 += v1; v3 ^= v0; v3 <<<= ( 8, 8, 8, 8); + paddd xmm0, xmm1; + pxor xmm3, xmm0; + pshufb xmm3, xmm5; + + // v2 += v3; v1 ^= v2; v1 <<<= ( 7, 7, 7, 7); + paddd xmm2, xmm3; + pxor xmm1, xmm2; + movapd xmm4, xmm1; + pslld xmm4, 7; + psrld xmm1, 25; // 32 - 7 + por xmm1, xmm4; + + // v1 <<<= 32; v2 <<<= 64; v3 <<<= 96; Return + movapd xmm4, xmm1; + palignr xmm1, xmm4, 12; + movapd xmm4, xmm2; + palignr xmm2, xmm4, 8; + movapd xmm4, xmm3; + palignr xmm3, xmm4, 4; + + // move back + {$IFDEF CPUX64} + movdqa [rdx], xmm0; + movdqa [rdx + 16], xmm1; + movdqa [rdx + 32], xmm2; + movdqa [rdx + 48], xmm3; + + // cleanup registers + movupd xmm4, dXMM4; + movupd xmm5, dXMM5; + {$ELSE} + movdqa [edx], xmm0; + movdqa [edx + 16], xmm1; + movdqa [edx + 32], xmm2; + movdqa [edx + 48], xmm3; + {$ENDIF} +end; + +{$ENDIF} + {$IFDEF RESTORE_RANGECHECKS}{$R+}{$ENDIF} {$IFDEF RESTORE_OVERFLOWCHECKS}{$Q+}{$ENDIF} +function TCipher_ChaCha20.TestChaChaMtx( + const expectedMtx: TChaChaMtx): boolean; +begin + Result := CompareMem(fOutChaChaMtx, @expectedMtx, sizeof(TChaChaMtx)); +end; + + +{ TCipher_XChaCha20 } + +procedure TCipher_XChaCha20.HChaCha(iv: TBytes); +var i : integer; +begin + // inpmatrix is initialized with the original key + fPHChaCha := AlignPtr32( @fHChaCha[0] ); + Move( fInpChaChaMTX^, fPHChaCha^, sizeof(fPHChaCha^)); + + // copy over the iv -> 128 bit + // create the HChaChaMatrix in fPHChaCha + Move(iv[0], fPHChaCha^[12], 4*sizeof(LongWord)); + + {$IFNDEF PUREPASCAL} + if cpuMode = cmSSE then + begin + for i := 0 to fNumChaChaRounds - 1 do + SSEChaChaDoubleQuarterRound(fPHChaCha); + end + else + {$ENDIF} + begin + for i := 0 to fNumChaChaRounds - 1 do + PasChaChaDoubleQuarterRound(fPHChaCha); + end; +end; + + +procedure TCipher_XChaCha20.OnAfterInitVectorInitialization( + const OriginalInitVector: TBytes); +begin + // RFC point 2.3 and 2.3.1: + + if length(OriginalInitVector) <> 24 then //192 div 8 + raise EDECException.Create('IV vector needs to be 192 bits long'); + + // update iv -> use the first 16 bytes! + HChaCha(OriginalInitVector); + + // extract subkey -> overwrite key + + // subkey is the first row and the last row!! + Move(fPHChaCha^[0], fInpChaChaMTX^[4], 4*sizeof(LongWord)); + Move(fPHChaCha^[12], fInpChaChaMTX^[8], 4*sizeof(LongWord)); + + // update IV -> the last 8 bytes + Move(OriginalInitVector[16], FInitializationVector[4], 2*sizeof(LongWord)); + PLongWord(@FInitializationVector[0])^ := 0; // per definition the these bytes are zero + + // truncate iv length + FInitVectorSize := 3*sizeof(longword); + + // int chacha with these values + // note: the inherted routine may not overwrite the key part and needs + // to initialize the nonce with the "tampered" iv + inherited; + + // restore the iv vector size + FInitVectorSize := 24; + + // burn + FillChar(fHChaCha, sizeof(fHChaCha), 0); +end; + initialization SetDefaultCipherClass(TCipher_Null); + TCipher_ChaCha20.CpuMode := cmPas; + {$IFNDEF ManualRegisterCipherClasses} TCipher_Null.RegisterClass(TDECCipher.ClassList); TCipher_Blowfish.RegisterClass(TDECCipher.ClassList); @@ -6820,6 +8555,9 @@ initialization TCipher_3Way.RegisterClass(TDECCipher.ClassList); TCipher_Cast128.RegisterClass(TDECCipher.ClassList); TCipher_Gost.RegisterClass(TDECCipher.ClassList); + TCipher_ChaCha20.RegisterClass(TDECCipher.ClassList); + TCipher_XChaCha20.RegisterClass(TDECCipher.ClassList); + // Explicitely not registered, as this is an alias for Gost only // TCipher_Magma.RegisterClass(TDECCipher.ClassList); TCipher_Misty.RegisterClass(TDECCipher.ClassList); @@ -6843,6 +8581,17 @@ initialization {$ENDIF} {$ENDIF} + if TDEC_CPUSupport.AVX2 + then + TCipher_ChaCha20.CpuMode := cmAVX + else if TDEC_CPUSupport.SSE3 + then + TCipher_ChaCha20.CpuMode := cmSSE + else + TCipher_ChaCha20.CpuMode := cmPas; + + TCipher_Rijndael.UseAESAsm := TDEC_CPUSupport.AES; + finalization end. diff --git a/Source/DECOptions.inc b/Source/DECOptions.inc index da05d4bd..a76838bc 100644 --- a/Source/DECOptions.inc +++ b/Source/DECOptions.inc @@ -73,29 +73,39 @@ // Automatically register all hash classes {.$DEFINE ManualRegisterHashClasses} (* default off *) +{$DEFINE ASSEMBLER} + // if the compiler does not support assembler turn usage off and even if restrict // it to Windows, as those non Windows platforms which actually do support ASM // in Delphi do not use Intel x86 ASM -{$IFDEF FPC } +{$IFNDEF FPC } {$IF defined(CPUX86_64) or defined(CPUAMD64) or defined(CPUIA64) } {$ifndef CPUX64} {$define CPUX64} {$endif} - {$else}{$if defined(CPU386) or defined(CPUI386) } + {$IFEND} + + {$if defined(CPU386) or defined(CPUI386) } {$ifndef CPUX32} {$define CPUX32} {$endif} - {$ELSE} - {$IFNDEF ASSEMBLER } - {$DEFINE NO_ASM} (* default ON *) - {$ELSE} - {$IFDEF WINDOWS} - {.$DEFINE NO_ASM} (* default OFF *) - {$ELSE} - {$DEFINE NO_ASM} (* default ON *) - {$ENDIF} - {$ENDIF} - {$ENDIF}{$endif} + {$IFEND} + + {$IFNDEF ASSEMBLER} + {$DEFINE NO_ASM} + {$ENDIF} + {$IFDEF UNIX} + {$DEFINE NO_ASM} + {$ENDIF} + // {$IFNDEF ASSEMBLER } +// {$DEFINE NO_ASM} (* default ON *) +// {$ELSE} +// {$IFDEF WINDOWS} +// {.$DEFINE NO_ASM} (* default OFF *) +// {$ELSE} +// {$DEFINE NO_ASM} (* default ON *) +// {$ENDIF} +// {$ENDIF} {$ELSE} // Turn ASM off for FPC as we do not know enough about ASM support on FPC {$DEFINE NO_ASM} @@ -193,16 +203,16 @@ {$IFNDEF PUREPASCAL} // ignored by FPC (already in PurePascal mode as defined in FPC block above) + {$DEFINE PUREPASCAL} {$IFDEF CPUX86} {$DEFINE X86ASM} - {$ELSE !CPUX86} - {$IFDEF CPUX64} - {$DEFINE X64ASM} - {$ELSE !CPUX64} - {$DEFINE PUREPASCAL} - {$ENDIF !CPUX64} + {$UNDEF PUREPASCAL} {$ENDIF} -{$ENDIF !PUREPASCAL} + {$IFDEF CPUX64} + {$DEFINE X64ASM} + {$UNDEF PUREPASCAL} + {$ENDIF} +{$ENDIF} //------------------------------------------------------------------------------ // Delphi and C++ Builder diff --git a/Source/DECTypes.pas b/Source/DECTypes.pas index 9c7ec0b2..9fe62d5c 100644 --- a/Source/DECTypes.pas +++ b/Source/DECTypes.pas @@ -53,6 +53,11 @@ interface PUInt64Array = ^TUInt64Array; TUInt64Array = array[0..1023] of UInt64; + /// + /// AES works on 16 byte blocks, some others too + /// + TBlock16Byte = Array[0..15] of UInt8; + /// /// Declared here because it is used by Blowfish cipher and BCrypt hash /// diff --git a/Source/DECUtil.pas b/Source/DECUtil.pas index a47882c1..14cb71a6 100644 --- a/Source/DECUtil.pas +++ b/Source/DECUtil.pas @@ -281,6 +281,17 @@ function StringToBytes(const Str: string): TBytes; inline; /// function IsEqual(const a, b : TBytes ):Boolean; +/// +/// Returns the 32Byte aligned address of pointer A +/// +/// /// +/// Pointer to input memory block +/// +/// /// +/// Returns the fir +/// +function AlignPtr32( A : Pointer ) : Pointer; + implementation uses @@ -680,4 +691,12 @@ function IsEqual(const a, b : TBytes):Boolean; Result := true; end; +function AlignPtr32( A : Pointer ) : Pointer; +begin + Result := A; + if (NativeUint(A) and $1F) <> 0 then + Result := Pointer( NativeUint(Result) + $20 - NativeUint(Result) and $1F ); +end; + + end. diff --git a/Source/_DECCipherModesGCM.pas b/Source/_DECCipherModesGCM.pas new file mode 100644 index 00000000..d378e895 --- /dev/null +++ b/Source/_DECCipherModesGCM.pas @@ -0,0 +1,857 @@ +{***************************************************************************** + The DEC team (see file NOTICE.txt) licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. A copy of this licence is found in the root directory + of this project in the file LICENCE.txt or alternatively at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*****************************************************************************} +unit DECCipherModesGCM; + +interface + +{$INCLUDE DECOptions.inc} + +uses + {$IFDEF FPC} + SysUtils, + {$ELSE} + System.SysUtils, + {$ENDIF} + DECTypes; + +type + /// + /// 128 bit unsigned integer + /// + T128 = array[0..1] of UInt64; + /// + /// pointer to an 128 bit unsigned integer + /// + P128 = ^T128; + + /// + /// Array of 16 bytes + /// + T16ByteArray = array[0..15] of Byte; + /// + /// Pointer to an array of 16 bytes + /// + P16ByteArray = ^T16ByteArray; + + /// + /// A methopd of this type needs to be supplied for encrypting or decrypting + /// a block via this GCM algorithm. The method is implemented as a parameter, + /// to avoid the need to bring TGCM in the inheritance chain. TGCM thus can + /// be used for composition instead of inheritance. + /// + /// + /// Data to be encrypted + /// + /// + /// In this memory the encrypted result will be written + /// + /// + /// Size of source in byte + /// + TEncodeDecodeMethod = procedure(Source, Dest: Pointer; Size: Integer) of Object; + + /// + /// Galois Counter Mode specific methods + /// + TGCM = class(TObject) + private + /// + /// Empty value? + /// + nullbytes : T128; + /// + /// Table with precalculated values + /// + FM : array[0..15,0..255] of T128; + + /// + /// Required for creating the table and encryption at least + /// + FH : T128; + /// + /// Calculated in initialization + /// + FY : T128; + /// + /// Calculated in initialization + /// + FE_K_Y0 : T128; + + /// + /// The data which shall be authenticated in parallel to the encryption + /// + FDataToAuthenticate : TBytes; + /// + /// Length of the authentication tag to generate in byte + /// + FCalcAuthenticationTagLength : UInt32; + /// + /// Generated authentication tag + /// + FCalcAuthenticationTag : TBytes; + /// + /// Expected authentication tag value, will be compared with actual value + /// when decryption finished. + /// + FExpectedAuthenticationTag : TBytes; + + /// + /// Reference to the encode method of the actual cipher used + /// + FEncryptionMethod : TEncodeDecodeMethod; + + /// + /// XOR implementation for unsigned 128 bit numbers + /// + /// + /// First number to xor + /// + /// + /// Second number to xor the first with + /// + /// + /// x xor y + /// + function XOR_T128(const x, y: T128): T128; inline; + /// + /// XOR implementation for a pointer and an unsigned 128 bit number + /// + /// + /// Pointer on a T128 typed number to xor with y + /// + /// + /// Second number to xor the first with + /// + /// + /// x xor y + /// + function XOR_PointerWithT128(const x: Pointer; y: T128 ): T128; inline; + /// + /// XORs the bytes given in a byte array with a T128 number given + /// + /// + /// Bytes which shall be XORed with the T128 number + /// + /// + /// Starting index within x from which onwards to XOR + /// + /// + /// Number of bytes from x beginning at XIndex to XOR + /// + /// + /// Value to XOR the bytes from y with. XOR is done bytewise for each + /// byte of y + /// + /// + /// Result of the XOR operation + /// + procedure XOR_ArrayWithT128(const x: TBytes; XIndex, Count: UInt64; y: T128; var Result: TBytes); overload; //inline; + procedure XOR_ArrayWithT128(const x: PUInt8Array; XIndex, Count: UInt64; y: T128; Result: PUInt8Array); overload; + + /// + /// XORs all elements of the precalculated matrix with the value passed + /// + /// + /// Value who's two parts shall be XORed with the two parts of the + /// matrix each. + /// + /// + /// result of the XOR Operation + /// + function poly_mult_H(const hx: T128) : T128; inline; + + /// + /// Encodes the 64 bit lengths of DataToAuthenticate and of the cipher + /// text into a T128 value, swapping the bytes in the process. + /// + /// + /// Result of the operation + /// + /// + /// Length of the data to authenticate in byte + /// + /// + /// Length of the ciphertext in byte + /// + procedure SetAuthenticationCipherLength(var x : T128; + AuthDataLength, CipherTextLength : UInt64); inline; + + /// + /// Calculates a table with precalculated values which speeds up + /// operations later. The initialized table is the FM field. + /// + /// + /// Start value for the precalculation + /// + procedure GenerateTableM8Bit(const H: T128); //inline; + /// + /// Performs a right shift of 1 of all bytes in an 128 bit variable + /// + /// + /// Variable on which the right shift is being performed + /// + procedure ShiftRight(var rx: T128); //inline; + + /// + /// Incremepts the last 4 bytes of the index 0 part + /// + /// + /// Value to increment, this is the return value as well. + /// + procedure INCR(var Y : T128); + + /// + /// Defines the length of the resulting authentication value in bit. + /// + /// + /// Sets the length of Authenticaton_tag in bit, values as per specification + /// are: 128, 120, 112, 104, or 96 bit. For certain applications, they + /// may be 64 or 32 as well, but the use of these two tag lengths + /// constrains the length of the input data and the lifetime of the key. + /// + procedure SetAuthenticationTagLength(const Value: UInt32); + /// + /// Returns the length of the calculated authehtication value in bit + /// + /// + /// Length of the calculated authentication value in bit + /// + function GetAuthenticationTagBitLength: UInt32; + + /// + /// Calculates the hash value + /// + /// + /// Specifys the data for which an authentication value shall be + /// calculated. It is allowed to be nil. + /// + /// + /// Encrypted data used in the calculation + /// + /// + /// Length of the ciphertext in bytes. Use when reading part of array. + /// + /// + /// Calculated raw hash value which will later get returned as AuthenticatedTag + /// + function CalcGaloisHash(AuthenticatedData, Ciphertext : TBytes; CiphertextSize: + Integer): T128; overload; + + /// + /// Calculates the hash value + /// + /// + /// Specifys the data for which an authentication value shall be + /// calculated. It is allowed to be nil. + /// + /// + /// Encrypted data used in the calculation + /// + /// + /// Length of the ciphertext in bytes. Use when reading part of array. + /// + /// + /// Calculated raw hash value which will later get returned as AuthenticatedTag + /// + function CalcGaloisHash(AuthenticatedData: TBytes; Ciphertext : PUInt8Array; CiphertextSize: + Integer): T128; overload; + + /// + /// Encrypts a T128 value using the encryption method specified on init + /// + /// + /// Value to be encrypted + /// + /// + /// Encrypted value + /// + function EncodeT128(Value: T128): T128; + public + /// + /// Should be called when starting encryption/decryption in order to + /// initialize internal tables etc. + /// + /// + /// Encryption method of the cypher used + /// + /// + /// Initialization vector + /// + procedure Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); +// /// +// /// Encodes a block of data using the supplied cipher +// /// +// /// +// /// Plain text to encrypt +// /// +// /// +// /// Ciphertext after encryption +// /// +// /// +// /// Number of bytes to encrypt +// /// +// procedure EncodeGCM(Source, +// Dest : TBytes; +// Size : Integer); + /// + /// Encodes a block of data using the supplied cipher + /// + /// + /// Plain text to encrypt + /// + /// + /// Ciphertext after encryption + /// + /// + /// Number of bytes to encrypt + /// + procedure EncodeGCM(Source, + Dest : PUInt8Array; + Size : Integer); + /// + /// Decodes a block of data using the supplied cipher + /// + /// + /// Encrypted ciphertext to decrypt + /// + /// + /// Plaintext after decryption + /// + /// + /// Number of bytes to decrypt + /// + procedure DecodeGCM(Source, + Dest : TBytes; + Size : Integer); + + /// + /// Returns a list of authentication tag lengths explicitely specified by + /// the official specification of the standard. + /// + /// + /// List of bit lengths + /// + function GetStandardAuthenticationTagBitLengths:TStandardBitLengths; + + /// + /// The data which shall be authenticated in parallel to the encryption + /// + property DataToAuthenticate : TBytes + read FDataToAuthenticate + write FDataToAuthenticate; + /// + /// Sets the length of AuthenticatonTag in bit, values as per official + /// specification are: 128, 120, 112, 104, or 96 bit. For certain + /// applications, they may be 64 or 32 as well, but the use of these two + /// tag lengths constrains the length of the input data and the lifetime + /// of the key. + /// + property AuthenticationTagBitLength : UInt32 + read GetAuthenticationTagBitLength + write SetAuthenticationTagLength; + /// + /// Calculated authentication value + /// + property CalculatedAuthenticationTag : TBytes + read FCalcAuthenticationTag + write FCalcAuthenticationTag; + + /// + /// Expected authentication tag value, will be compared with actual value + /// when decryption finished. + /// + property ExpectedAuthenticationTag : TBytes + read FExpectedAuthenticationTag + write FExpectedAuthenticationTag; + end; + +implementation + +function TGCM.XOR_T128(const x, y : T128): T128; +begin + Result[0] := x[0] xor y[0]; + Result[1] := x[1] xor y[1]; +end; + +function TGCM.XOR_PointerWithT128(const x : Pointer; y : T128): T128; +begin + Result[0] := P128(x)^[0] xor y[0]; + Result[1] := P128(x)^[1] xor y[1]; +end; + +procedure TGCM.XOR_ArrayWithT128(const x: TBytes; XIndex, Count: UInt64; y: T128; var Result: TBytes); +var + i : integer; + by : P16ByteArray; +begin + by := @y[0]; + for i := 0 to Count-1 do + begin + Result[XIndex] := x[XIndex] xor by[i]; + inc(XIndex); + end; +end; + +procedure TGCM.XOR_ArrayWithT128(const x: PUInt8Array; XIndex, Count: UInt64; y: T128; Result: PUInt8Array); +var + i : integer; + by : P16ByteArray; +begin + by := @y[0]; + for i := 0 to Count-1 do + begin + Result^[XIndex] := x^[XIndex] xor by[i]; + inc(XIndex); + end; +end; + +function TGCM.poly_mult_H(const hx : T128): T128; +var + i : integer; + x : P16ByteArray; +begin + x := @hx[0]; + Result := FM[0, x[0]]; + + for i := 1 to 15 do + begin + Result[0] := Result[0] xor FM[i, x[i]][0]; + Result[1] := Result[1] xor FM[i, x[i]][1]; + end; +end; + +procedure TGCM.SetAuthenticationCipherLength(var x : T128; + AuthDataLength, CipherTextLength : UInt64); +var + i : integer; + hx : P16ByteArray; +begin + hx := @x[0]; + // al: + x := nullbytes; + i := 7; + + repeat + hx[i] := AuthDataLength mod 256; + AuthDataLength := AuthDataLength shr 8; + dec(i); + until AuthDataLength = 0; + + // cl: + i := 15; + + repeat + hx[i] := CipherTextLength mod 256; + CipherTextLength := CipherTextLength shr 8; + dec(i); + until CipherTextLength = 0; +end; + +procedure TGCM.GenerateTableM8Bit(const H : T128); +var + hbit, hbyte, i, j : integer; + HP : T128; + bHP : P16ByteArray; + mask : byte; +begin + HP := H; + bHP := @HP[0]; + for hbyte := 0 to 15 do + begin + mask := 128; + for hbit := 0 to 7 do + begin + FM[hbyte, mask] := HP; + + if (bHP[15] and 1 = 0) then + ShiftRight(HP) + else + begin + ShiftRight(HP); + bHP[0] := bHP[0] xor $e1; + end; + + mask := mask shr 1; + end; + end; + + for hbyte := 0 to 15 do + begin + i := 2; + + while i <= 128 do + begin + for j := 1 to i-1 do + FM[hbyte, i+j] := XOR_T128(FM[hbyte, i], FM[hbyte, j]); + i := i*2; + end; + + FM[hbyte, 0] := nullbytes; + end; +end; + +procedure TGCM.ShiftRight(var rx : T128); +var + x : P16ByteArray; + i : integer; +begin + x := @rx[0]; + + for i := 15 downto 1 do + x[i] := (x[i] shr 1) or ((x[i-1] and 1) shl 7); + + x[0] := x[0] shr 1; +end; + +procedure TGCM.SetAuthenticationTagLength(const Value: UInt32); +begin + FCalcAuthenticationTagLength := Value shr 3; + SetLength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); +end; + +procedure TGCM.INCR(var Y : T128); +var + bY : P16ByteArray; +begin + bY := @Y[0]; + + {$IFOPT Q+}{$DEFINE RESTORE_OVERFLOWCHECKS}{$Q-}{$ENDIF} + {$Q-} + inc(bY[15]); + if bY[15] = 0 then + begin + inc(bY[14]); + + if bY[14] = 0 then + begin + inc(bY[13]); + + if bY[13] = 0 then + inc(bY[12]); + end; + end; + {$IFDEF RESTORE_OVERFLOWCHECKS}{$Q+}{$ENDIF} +end; + +procedure TGCM.Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); +var + b : ^Byte; + OldH : T128; +begin + Assert(Assigned(EncryptionMethod), 'No encryption method specified'); + + // Clear calculated authentication value + if (Length(FCalcAuthenticationTag) > 0) then + FillChar(FCalcAuthenticationTag[0], Length(FCalcAuthenticationTag), #0); + + FEncryptionMethod := EncryptionMethod; + + Nullbytes[0] := 0; + Nullbytes[1] := 0; + + OldH := FH; + EncryptionMethod(@Nullbytes[0], @FH[0], 16); + + // Only generate the table when not already generated + if (OldH[0] <> FH[0]) or (OldH[1] <> FH[1]) then + GenerateTableM8Bit(FH); + + if length(InitVector) = 12 then + begin + FY[1] := 0; + Move(InitVector[0], FY[0], 12); + b := @FY[0]; + inc(b, 15); + b^ := 1; + end + else + FY := CalcGaloisHash(nil, InitVector, length(InitVector)); + + FEncryptionMethod(@FY[0], @FE_K_Y0[0], 16); +end; + +function TGCM.CalcGaloisHash(AuthenticatedData, Ciphertext : TBytes; + CiphertextSize: Integer): T128; +var + AuthCipherLength : T128; + x : T128; + n : Uint64; + + procedure encode(data : TBytes; dataSize: Integer); + var + i, mod_d, div_d, len_d : UInt64; + hdata : T128; + begin + len_d := dataSize; + if (len_d > 0) then + begin + n := 0; + div_d := len_d div 16; + if div_d > 0 then + begin + for i := 0 to div_d-1 do + begin + x := poly_mult_H(XOR_PointerWithT128(@data[n], x )); + inc(n, 16); + end; + end; + + mod_d := len_d mod 16; + if mod_d > 0 then + begin + hdata := nullbytes; + Move(data[n], hdata[0], mod_d); + x := poly_mult_H(XOR_T128(hdata, x)); + end; + end; + end; + +begin + x := nullbytes; + encode(AuthenticatedData, length(AuthenticatedData)); + Assert(length(Ciphertext) >= CiphertextSize); + encode(Ciphertext, CiphertextSize); + SetAuthenticationCipherLength(AuthCipherLength, length(AuthenticatedData) shl 3, CiphertextSize shl 3); + + Result := poly_mult_H(XOR_T128(AuthCipherLength, x)); +end; + +function TGCM.CalcGaloisHash(AuthenticatedData: TBytes; Ciphertext : PUInt8Array; + CiphertextSize: Integer): T128; +var + AuthCipherLength : T128; + x : T128; + n : Uint64; + + procedure encode(data : PUInt8Array; dataSize: Integer); + var + i, mod_d, div_d, len_d : UInt64; + hdata : T128; + begin + len_d := dataSize; + if (len_d > 0) then + begin + n := 0; + div_d := len_d div 16; + if div_d > 0 then + begin + for i := 0 to div_d-1 do + begin + x := poly_mult_H(XOR_PointerWithT128(@data^[n], x )); + inc(n, 16); + end; + end; + + mod_d := len_d mod 16; + if mod_d > 0 then + begin + hdata := nullbytes; + Move(data^[n], hdata[0], mod_d); + x := poly_mult_H(XOR_T128(hdata, x)); + end; + end; + end; + +begin + x := nullbytes; + + if (length(AuthenticatedData) > 0) then + encode(@AuthenticatedData[0], length(AuthenticatedData)); +// Assert(length(Ciphertext) >= CiphertextSize); + encode(Ciphertext, CiphertextSize); + SetAuthenticationCipherLength(AuthCipherLength, length(AuthenticatedData) shl 3, CiphertextSize shl 3); + + Result := poly_mult_H(XOR_T128(AuthCipherLength, x)); +end; + +procedure TGCM.DecodeGCM(Source, Dest: TBytes; Size: Integer); +var + i, j, BlockCount : UInt64; + a_tag : T128; +begin + i := 0; + BlockCount := Size div 16; + + for j := 1 to BlockCount do + begin + INCR(FY); + P128(@Dest[i])^ := XOR_PointerWithT128(@Source[i], EncodeT128(FY)); + inc(i, 16); + end; + + if i < Size then + begin + INCR(FY); + XOR_ArrayWithT128(Source, i, UInt64(Size)-i, EncodeT128(FY), Dest); + end; + + a_tag := XOR_T128(CalcGaloisHash(DataToAuthenticate, Source, Size), FE_K_Y0); + + Setlength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); + if (FCalcAuthenticationTagLength > 0) then + Move(a_tag[0], FCalcAuthenticationTag[0], FCalcAuthenticationTagLength); + + // Check for correct authentication result is in Done of DECCipherModes + // if not IsEqual(FExpectedAuthenticationTag, FCalcAuthenticationTag) then + // raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); + + // In difference to the NIST recommendation we do not discard plaintext if + // authentication failed to make data recovery possible. But since we throw + // an exception the user will get notified that there's something wrong + // if not IsEqual(authenticaton_tag, ba_tag) then + // SetLength(plaintext, 0); // NIST FAIL => pt='' +end; + +//procedure TGCM.EncodeGCM(Source, Dest: TBytes; Size: Integer); +//var +// i, j, div_len_plain : UInt64; +// AuthTag : T128; +//begin +// i := 0; +// div_len_plain := Size div 16; +// +// for j := 1 to div_len_plain do +// begin +// INCR(FY); +// +// P128(@Dest[i])^ := XOR_PointerWithT128(@Source[i], EncodeT128(FY)); +// +// inc(i,16); +// end; +// +// if i < Size then +// begin +// INCR(FY); +// XOR_ArrayWithT128(Source, i, UInt64(Size)-i, EncodeT128(FY), Dest); +// end; +// +// AuthTag := XOR_T128(CalcGaloisHash(DataToAuthenticate, Dest, Size), FE_K_Y0); +// Setlength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); +// if (FCalcAuthenticationTagLength > 0) then +// Move(AuthTag[0], FCalcAuthenticationTag[0], FCalcAuthenticationTagLength); +//end; + +procedure TGCM.EncodeGCM(Source, Dest: PUInt8Array; Size: Integer); +var + i, j, div_len_plain : UInt64; + AuthTag : T128; +begin + i := 0; + div_len_plain := Size div 16; + + for j := 1 to div_len_plain do + begin + INCR(FY); + + P128(@Dest[i])^ := XOR_PointerWithT128(@Source[i], EncodeT128(FY)); + + inc(i,16); + end; + + if i < Size then + begin + INCR(FY); + XOR_ArrayWithT128(Source, i, UInt64(Size)-i, EncodeT128(FY), Dest); + end; + + AuthTag := XOR_T128(CalcGaloisHash(DataToAuthenticate, Dest, Size), FE_K_Y0); + Setlength(FCalcAuthenticationTag, FCalcAuthenticationTagLength); + if (FCalcAuthenticationTagLength > 0) then + Move(AuthTag[0], FCalcAuthenticationTag[0], FCalcAuthenticationTagLength); +end; + +function TGCM.EncodeT128(Value: T128): T128; +begin + FEncryptionMethod(@Value[0], @Result[0], 16); +end; + +function TGCM.GetAuthenticationTagBitLength: UInt32; +begin + Result := FCalcAuthenticationTagLength shl 3; +end; + +function TGCM.GetStandardAuthenticationTagBitLengths: TStandardBitLengths; +begin + SetLength(Result, 5); + Result := [96, 104, 112, 120, 128]; +end; + +// +//function decrypt( const key, IV : TBytes; out plaintext : TBytes; const authenticated_data, +//ciphertext : TBytes; len_auth_tag : integer; const authenticaton_tag : TBytes ) : boolean; +//var +// i, j, div_len_ciph, len_ciph : Uint64; +// a_tag, E_K_Y0, Y, H : T128; +// bY : array[0..15] of byte absolute Y[0]; +// ba_Tag : TBytes; +// +// function equal( const a, b : TBytes ):boolean; +// begin +// if length(a) <> length(b) then Result := false +// else +// Result := CompareMem( @a[0], @b[0], length(a) ); +// end; +// +//begin +// len_auth_tag := len_auth_tag shr 3; +// +// E_Init( key ); +// H := E_Cipher( nullbytes ); +// Table_M_8Bit(H); +// +// len_ciph := length( ciphertext ); +// SetLength( plaintext, len_ciph ); +// +// if length(IV) = 12 then +// begin +// Y[1] := 0; +// Move( IV[0], Y[0], 12 ); +// bY[15] := 1; +// end +// else +// Y := CalcGaloisHash( H, nil, IV ); +// +// E_K_Y0 := E_Cipher( y ); +// +// i := 0; +// div_len_ciph := len_ciph div 16; +// for j := 1 to div_len_ciph do +// begin +// INCR( Y ); +// P128(@plaintext[i])^ := XOR_128_n( @ciphertext[i], E_cipher( Y ) ); +// inc(i,16); +// end; +// +// if i < len_ciph then +// begin +// INCR( Y ); +// XOR_128_n_l( ciphertext, i, len_ciph-i, E_cipher( Y ), plaintext ); +// end; +// +// a_tag := XOR_128( CalcGaloisHash( H, authenticated_data, ciphertext ), E_K_Y0 ); +// +// Setlength( ba_tag, len_auth_tag ); +// Move( a_tag[0], ba_tag[0], len_auth_tag ); +// +// Result := equal( authenticaton_tag, ba_tag ); +// if not Result then SetLength( plaintext, 0 ); // NIST FAIL => pt='' +//end; +// + +end. diff --git a/Source/x86_64/DECUtil.inc b/Source/x86_64/DECUtil.inc index 838a1346..0cbecc72 100644 --- a/Source/x86_64/DECUtil.inc +++ b/Source/x86_64/DECUtil.inc @@ -6,9 +6,8 @@ {$define SwapUInt32_asm} function SwapUInt32(Source: UInt32): UInt32; asm - MOV RAX, Source - BSWAP RAX - SHR RAX, 32 + MOV EAX, Source + BSWAP EAX end; {$endif} diff --git a/Unit Tests/DECDUnitTestSuite.dpr b/Unit Tests/DECDUnitTestSuite.dpr index 44ec045b..fdf107d2 100644 --- a/Unit Tests/DECDUnitTestSuite.dpr +++ b/Unit Tests/DECDUnitTestSuite.dpr @@ -40,7 +40,38 @@ uses TestDECHashSHA3 in 'Tests\TestDECHashSHA3.pas', TestDECCipherModesGCM in 'Tests\TestDECCipherModesGCM.pas', TestDECZIPHelper in 'Tests\TestDECZIPHelper.pas', - TestDECCipherPaddings in 'Tests\TestDECCipherPaddings.pas'; + TestDECCipherPaddings in 'Tests\TestDECCipherPaddings.pas', + DECBaseClass in '..\Source\DECBaseClass.pas', + DECCipherBase in '..\Source\DECCipherBase.pas', + DECCipherFormats in '..\Source\DECCipherFormats.pas', + DECCipherInterface in '..\Source\DECCipherInterface.pas', + TestDECCipherModesCCM in 'Tests\TestDECCipherModesCCM.pas', + DECCipherModes in '..\Source\DECCipherModes.pas', + DECCipherPaddings in '..\Source\DECCipherPaddings.pas', + DECCiphers in '..\Source\DECCiphers.pas', + DECCRC in '..\Source\DECCRC.pas', + DECData in '..\Source\DECData.pas', + DECDataCipher in '..\Source\DECDataCipher.pas', + DECDataHash in '..\Source\DECDataHash.pas', + DECFormat in '..\Source\DECFormat.pas', + DECFormatBase in '..\Source\DECFormatBase.pas', + DECHash in '..\Source\DECHash.pas', + AuthenticatedCiphersCommonTestData in 'Tests\AuthenticatedCiphersCommonTestData.pas', + DECAuthenticatedCipherModesBase in '..\Source\DECAuthenticatedCipherModesBase.pas', + DECCipherModesCCM in '..\Source\DECCipherModesCCM.pas', + DECCipherModesPoly1305 in '..\Source\DECCipherModesPoly1305.pas', + DECHashAuthentication in '..\Source\DECHashAuthentication.pas', + DECHashBase in '..\Source\DECHashBase.pas', + DECHashBitBase in '..\Source\DECHashBitBase.pas', + DECHashInterface in '..\Source\DECHashInterface.pas', + DECRandom in '..\Source\DECRandom.pas', + DECTypes in '..\Source\DECTypes.pas', + DECUtil in '..\Source\DECUtil.pas', + DECUtilRawByteStringHelper in '..\Source\DECUtilRawByteStringHelper.pas', + DECZIPHelper in '..\Source\DECZIPHelper.pas', + DECCipherModesGCM in '..\Source\DECCipherModesGCM.pas', + TestDECChaChaPoly1305 in 'Tests\TestDECChaChaPoly1305.pas', + DECCPUSupport in '..\Source\DECCPUSupport.pas'; {$R *.RES} diff --git a/Unit Tests/DECDUnitTestSuite.dproj b/Unit Tests/DECDUnitTestSuite.dproj index 48958ad9..b08d731b 100644 --- a/Unit Tests/DECDUnitTestSuite.dproj +++ b/Unit Tests/DECDUnitTestSuite.dproj @@ -1,7 +1,7 @@  {4117BDAD-9849-4F6E-8968-BB6B92C8AE7B} - 20.2 + 20.3 DECDUnitTestSuite.dpr True Debug @@ -112,6 +112,8 @@ .\..\Compiled\DCU_IDE$(ProductVersion)_$(Platform)_$(Config) 3 /L /LL65535 + ASSEMBLER;$(DCC_Define) + none true @@ -162,6 +164,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Base @@ -215,15 +249,43 @@ DECDUnitTestSuite.dpr - Embarcadero C++Builder-Package für Office 2000-Server - Embarcadero C++Builder-Package für Office XP-Server - Microsoft Office 2000 Beispiele für gekapselte Komponenten für Automatisierungsserver - Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server + Microsoft Office 2000 Beispiele für gekapselte Komponenten für Automatisierungsserver + Microsoft Office XP Beispiele für gekapselte Komponenten für Automation Server + + + DECDUnitTestSuite.exe + true + + + + + DECDUnitTestSuite.exe + true + + + + + DECDUnitTestSuite.rsm + true + + + + + .\ + true + + + + + .\ + true + + 1 @@ -338,6 +400,16 @@ 1 + + + res\values-v35 + 1 + + + res\values-v35 + 1 + + res\drawable-anydpi-v26 diff --git a/Unit Tests/DECDUnitXTestSuite.dproj b/Unit Tests/DECDUnitXTestSuite.dproj index 6563539a..461a00bb 100644 --- a/Unit Tests/DECDUnitXTestSuite.dproj +++ b/Unit Tests/DECDUnitXTestSuite.dproj @@ -1,7 +1,7 @@  {FEE36113-01B3-4DE2-B2BC-B4858EAD04A3} - 20.2 + 20.3 DECDUnitXTestSuite.dpr True Debug @@ -105,7 +105,7 @@ $(BDS)\bin\delphi_PROJECTICON.ico - package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34 + package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=35 Debug android-support-v4.dex.jar;cloud-messaging.dex.jar;fmx.dex.jar;google-analytics-v2.dex.jar;google-play-billing.dex.jar;google-play-licensing.dex.jar;google-play-services.dex.jar DBXSqliteDriver;RESTComponents;DBXInterBaseDriver;emsclientfiredac;tethering;DataSnapFireDAC;bindcompfmx;FmxTeeUI;FireDACIBDriver;fmx;FireDACDBXDriver;dbexpress;IndyCore;dsnap;emsclient;DataSnapCommon;FireDACCommon;RESTBackendComponents;soapserver;bindengine;CloudService;FireDACCommonDriver;DataSnapClient;inet;IndyIPCommon;bindcompdbx;IndyIPServer;IndySystem;fmxFireDAC;FireDAC;FireDACSqliteDriver;FMXTee;soaprtl;DbxCommonDriver;xmlrtl;soapmidas;DataSnapNativeClient;FireDACDSDriver;rtl;DbxClientDriver;CustomIPTransport;bindcomp;IndyIPClient;dbxcds;dsnapxml;DataSnapProviderClient;dbrtl;IndyProtocols;$(DCC_UsePackage) @@ -117,7 +117,7 @@ $(BDS)\bin\Artwork\Android\FM_LauncherIcon_192x192.png - package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=34 + package=com.embarcadero.$(MSBuildProjectName);label=$(MSBuildProjectName);versionCode=1;versionName=1.0.0;persistent=False;restoreAnyVersion=False;installLocation=auto;largeHeap=False;theme=TitleBar;hardwareAccelerated=true;apiKey=;minSdkVersion=23;targetSdkVersion=35 Debug true Base @@ -194,6 +194,7 @@ + Base @@ -361,6 +362,16 @@ 1 + + + res\values-v35 + 1 + + + res\values-v35 + 1 + + res\drawable-anydpi-v26 diff --git a/Unit Tests/Data/chacha20_poly1305_test.json b/Unit Tests/Data/chacha20_poly1305_test.json new file mode 100644 index 00000000..e6253fdb --- /dev/null +++ b/Unit Tests/Data/chacha20_poly1305_test.json @@ -0,0 +1,3710 @@ +{ + "algorithm" : "CHACHA20-POLY1305", + "numberOfTests" : 300, + "header" : [ + "Test vectors of type AeadTest test authenticated encryption with", + "additional data. The test vectors are intended for testing both", + "encryption and decryption." + ], + "notes" : { + }, + "schema" : "aead_test_schema.json", + "testGroups" : [ + { + "ivSize" : 96, + "keySize" : 256, + "tagSize" : 128, + "type" : "AeadTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.8r12" + }, + "tests" : [ + { + "tcId" : 1, + "comment" : "RFC 7539", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "070000004041424344454647", + "aad" : "50515253c0c1c2c3c4c5c6c7", + "msg" : "4c616469657320616e642047656e746c656d656e206f662074686520636c617373206f66202739393a204966204920636f756c64206f6666657220796f75206f6e6c79206f6e652074697020666f7220746865206675747572652c2073756e73637265656e20776f756c642062652069742e", + "ct" : "d31a8d34648e60db7b86afbc53ef7ec2a4aded51296e08fea9e2b5a736ee62d63dbea45e8ca9671282fafb69da92728b1a71de0a9e060b2905d6a5b67ecd3b3692ddbd7f2d778b8c9803aee328091b58fab324e4fad675945585808b4831d7bc3ff4def08e4b7a9de576d26586cec64b6116", + "tag" : "1ae10b594f09e26a7e902ecbd0600691", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 2, + "comment" : "", + "key" : "80ba3192c803ce965ea371d5ff073cf0f43b6a2ab576b208426e11409c09b9b0", + "iv" : "4da5bf8dfd5852c1ea12379d", + "aad" : "", + "msg" : "", + "ct" : "", + "tag" : "76acb342cf3166a5b63c0c0ea1383c8d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 3, + "comment" : "", + "key" : "7a4cd759172e02eb204db2c3f5c746227df584fc1345196391dbb9577a250742", + "iv" : "a92ef0ac991dd516a3c6f689", + "aad" : "bd506764f2d2c410", + "msg" : "", + "ct" : "", + "tag" : "906fa6284b52f87b7359cbaa7563c709", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 4, + "comment" : "", + "key" : "cc56b680552eb75008f5484b4cb803fa5063ebd6eab91f6ab6aef4916a766273", + "iv" : "99e23ec48985bccdeeab60f1", + "aad" : "", + "msg" : "2a", + "ct" : "3a", + "tag" : "cac27dec0968801e9f6eded69d807522", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 5, + "comment" : "", + "key" : "46f0254965f769d52bdb4a70b443199f8ef207520d1220c55e4b70f0fda620ee", + "iv" : "ab0dca716ee051d2782f4403", + "aad" : "91ca6c592cbcca53", + "msg" : "51", + "ct" : "c4", + "tag" : "168310ca45b1f7c66cad4e99e43f72b9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 6, + "comment" : "", + "key" : "2f7f7e4f592bb389194989743507bf3ee9cbde1786b6695fe6c025fd9ba4c100", + "iv" : "461af122e9f2e0347e03f2db", + "aad" : "", + "msg" : "5c60", + "ct" : "4d13", + "tag" : "91e8b61efb39c122195453077b22e5e2", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 7, + "comment" : "", + "key" : "c8833dce5ea9f248aa2030eacfe72bffe69a620caf793344e5718fe0d7ab1a58", + "iv" : "61546ba5f1720590b6040ac6", + "aad" : "88364fc8060518bf", + "msg" : "ddf2", + "ct" : "b60d", + "tag" : "ead0fd4697ec2e5558237719d02437a2", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 8, + "comment" : "", + "key" : "bd8ed7fb0d607522f04d0b12d42c92570bccc5ba2486953d70ba2e8193f6225a", + "iv" : "d2ab0abb50a8e9fba25429e1", + "aad" : "", + "msg" : "201221", + "ct" : "3cf470", + "tag" : "a27a69c9d7ee84586f11388c6884e63a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 9, + "comment" : "", + "key" : "1c8b59b17a5ceced31bde97d4cefd9aaaa63362e096e863ec1c89580bca79b7a", + "iv" : "94f32a6dff588f2b5a2ead45", + "aad" : "6c8cf2ab3820b695", + "msg" : "453f95", + "ct" : "610925", + "tag" : "a8a7883eb7e40bc40e2e5922ae95ddc3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 10, + "comment" : "", + "key" : "e4912cb75a1174345f1a457366f18885fe8460b06478e04be2f7fb4ec9c113e5", + "iv" : "7aa5ad8bf5254762171ec869", + "aad" : "", + "msg" : "9e4c1d03", + "ct" : "fe6849aa", + "tag" : "99ad07871b25c27defc31a541bd5c418", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 11, + "comment" : "", + "key" : "e05777ef3d989ace7d2abfba452bfded54801dbd5c66e91c0c2ef00479d85572", + "iv" : "b7f526e3fd71cf5720961aec", + "aad" : "15d93a96d0e6c5a9", + "msg" : "17bfda03", + "ct" : "f4710e51", + "tag" : "b957c6a37b6a4c94996c002186d63b2b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 12, + "comment" : "", + "key" : "1a4c4f39abe890e62345c947bcf7de7c2e33bd5ceeda0a0abf0e7ef935ddf3ee", + "iv" : "9447bf85d5b97d8aee0f8e51", + "aad" : "", + "msg" : "c15a593bd0", + "ct" : "f711647ff1", + "tag" : "22b12dc38cb79629f84cdbdc2425c09d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 13, + "comment" : "", + "key" : "800e9a24791700c9609736695ba2a8b99b2d57f1c3bfb61ed49db1c6c5219583", + "iv" : "3dbe876bd880ec8ea2017043", + "aad" : "96224835610b782b", + "msg" : "a7bfd041e3", + "ct" : "d171f046ea", + "tag" : "d179b1b9c4184378df009019dbb8c249", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 14, + "comment" : "", + "key" : "208c2c376c9430433db20e1a6b7ba817f8ffbfa6827f26759ccede42e591d3ec", + "iv" : "27fb58ec6a21e84696cb8830", + "aad" : "", + "msg" : "af104b5ccd0e", + "ct" : "9351b1b1b082", + "tag" : "560785509f60f26b681933d9cdbfd29f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 15, + "comment" : "", + "key" : "2eb168e53b07ab04355ea792fe11a6be2ce9c39cfe15a997076b1e38c17ad620", + "iv" : "b5965470c383fd29fe7eaee7", + "aad" : "6d52feb2509f7fbf", + "msg" : "6fdf2927e169", + "ct" : "41abff7b71cc", + "tag" : "9b5174297c03cf8902d1f706fd008902", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 16, + "comment" : "", + "key" : "55568158d3a6483f1f7021eab69b703f614251cadc1af5d34a374fdbfc5adac7", + "iv" : "3c4e654d663fa4596dc55bb7", + "aad" : "", + "msg" : "ab85e9c1571731", + "ct" : "5dfe3440dbb3c3", + "tag" : "ed7a434e2602d394281e0afa9fb7aa42", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 17, + "comment" : "", + "key" : "e3c09e7fab1aefb516da6a33022a1dd4eb272c80d540c5da52a730f34d840d7f", + "iv" : "58389375c69ee398de948396", + "aad" : "84e46be8c0919053", + "msg" : "4ee5cda20d4290", + "ct" : "4bd47212941ce3", + "tag" : "185f1408ee7fbf18f5abad6e2253a1ba", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 18, + "comment" : "", + "key" : "51e4bf2bad92b7aff1a4bc05550ba81df4b96fabf41c12c7b00e60e48db7e152", + "iv" : "4f07afedfdc3b6c2361823d3", + "aad" : "", + "msg" : "be3308f72a2c6aed", + "ct" : "8e9439a56eeec817", + "tag" : "fbe8a6ed8fabb1937539dd6c00e90021", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 19, + "comment" : "", + "key" : "1131c1418577a054de7a4ac551950f1a053f9ae46e5b75fe4abd5608d7cddadd", + "iv" : "b4ea666ee119563366484a78", + "aad" : "66c0ae70076cb14d", + "msg" : "a4c9c2801b71f7df", + "ct" : "b9b910433af052b0", + "tag" : "4530f51aeee024e0a445a6328fa67a18", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 20, + "comment" : "", + "key" : "e1094967f86d893cdfe2e2e6d5c7ee4dfef67da3c9c5d64e6ad7c1577dcb38c5", + "iv" : "8092fc245b3326cddbd1424c", + "aad" : "", + "msg" : "c37aa791ddd6accf91", + "ct" : "d9d897a9c1c5bb9f01", + "tag" : "085a430373058f1a12a0d589fd5be68b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 21, + "comment" : "", + "key" : "236f9baee4f9da15beeca40ff4af7c760f254a64bc3a3d7f4fad557e61b68586", + "iv" : "f1ca81338629587acf9372bf", + "aad" : "8c32f47a386152ec", + "msg" : "d7f26d5252e1765f5b", + "ct" : "8fdb429d47761cbf8e", + "tag" : "8ef647ed334fdebbc2bef80be02884e0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 22, + "comment" : "", + "key" : "4de207a3b70c51e5f23048eed5a5da9bb65e917a69aa93e7c8b4a815cd9724de", + "iv" : "4c15a71dc6791a8c005ad502", + "aad" : "", + "msg" : "f2c54b6b5e490da18659", + "ct" : "700d35adf5100a22a1de", + "tag" : "102d992ffaff599b5bddddeb2dfb399b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 23, + "comment" : "", + "key" : "6d667fd79e5fb725f50343dccc4863227c75ee3f7a578476e3e9f32598d81559", + "iv" : "6220527aba88e27f766658b2", + "aad" : "e1e27ccddb3cb407", + "msg" : "0c8c5a252681f2b5b4c0", + "ct" : "04aad66c60e0bf8ebba9", + "tag" : "c15f69a4d2aef97d7748756ff49d894b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 24, + "comment" : "", + "key" : "8f4bd94ef73e75d1e068c30b37ead576c5344e093ece1330e9101c82f793cf05", + "iv" : "ec1e2967f0f6979e5f5b07fb", + "aad" : "", + "msg" : "b89812b34d9bced4a0ba07", + "ct" : "1c3d53baaa36eaa1d8ec4d", + "tag" : "4d94ebf960f12433bec43aa86d7e6e6d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 25, + "comment" : "", + "key" : "2aa3bc7033351cac51364cdaf6ffac2c20f64046e1550a7b1c65f41800599019", + "iv" : "28cce57a5db2cd206321e340", + "aad" : "a9bc350eaf2e6e3d", + "msg" : "83016823123484b56095b0", + "ct" : "1c8578f8e75203d0336a52", + "tag" : "5910f7a9d5e4df05d7248bd7a8d65e63", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 26, + "comment" : "", + "key" : "99b62bd5afbe3fb015bde93f0abf483957a1c3eb3ca59cb50b39f7f8a9cc51be", + "iv" : "9a59fce26df0005e07538656", + "aad" : "", + "msg" : "42baae5978feaf5c368d14e0", + "ct" : "ff7dc203b26c467a6b50db33", + "tag" : "578c0f2758c2e14e36d4fc106dcb29b4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 27, + "comment" : "", + "key" : "85f35b6282cff440bc1020c8136ff27031110fa63ec16f1e825118b006b91257", + "iv" : "58dbd4ad2c4ad35dd906e9ce", + "aad" : "a506e1a5c69093f9", + "msg" : "fdc85b94a4b2a6b759b1a0da", + "ct" : "9f8816de0994e938d9e53f95", + "tag" : "d086fc6c9d8fa915fd8423a7cf05072f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 28, + "comment" : "", + "key" : "faf4bfe8019a891c74901b17f4f48cee5cd065d55fdea60118aaf6c4319a0ea5", + "iv" : "b776c3fddba7c81362ce6e1b", + "aad" : "", + "msg" : "8dadff8d60c8e88f604f274833", + "ct" : "e6b33a74a4ac443bd93f9c1b94", + "tag" : "0c115172bdb02bbad3130fff22790d60", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 29, + "comment" : "", + "key" : "841020d1606edcfc536abfb1a638a7b958e21efc10c386ac45a18493450afd5f", + "iv" : "6d62f159731b140eb18ce074", + "aad" : "5a8e1c7aa39810d5", + "msg" : "d6af138f701b801e60c85ffd5c", + "ct" : "b0a7500aca45bb15f01ece4389", + "tag" : "0160e83adbec7f6a2ee2ff0215f9ef00", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 30, + "comment" : "", + "key" : "470f9ce3d2250bd60cbbefdb2e6a1178c012299b5590639c7797b6024fa703d8", + "iv" : "a9ea4d619fe405d04cba7d7a", + "aad" : "", + "msg" : "6ca67dd023fba6507b9f9a1f667e", + "ct" : "d3017e0bb1705b380b34cc333450", + "tag" : "5708e72ca2bd354f487f82f67fbc3acb", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 31, + "comment" : "", + "key" : "e4b97e91e4c8e85eb7ce0a7f30bf8a0abf4468251e4c6386c0e7aacb8e879aa8", + "iv" : "0e23c942a0c9fb526586eead", + "aad" : "eaaaeab26957f9a1", + "msg" : "b84b3f74cd23064bb426fe2ced2b", + "ct" : "52e9672b416d84d97033796072d0", + "tag" : "e83839dc1fd9b8b9d1444c40e488d493", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 32, + "comment" : "", + "key" : "67119627bd988eda906219e08c0d0d779a07d208ce8a4fe0709af755eeec6dcb", + "iv" : "68ab7fdbf61901dad461d23c", + "aad" : "", + "msg" : "51f8c1f731ea14acdb210a6d973e07", + "ct" : "0b29638e1fbdd6df53970be2210042", + "tag" : "2a9134087d67a46e79178d0a93f5e1d2", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 33, + "comment" : "", + "key" : "e6f1118d41e4b43fb58221b7ed79673834e0d8ac5c4fa60bbc8bc4893a58894d", + "iv" : "d95b3243afaef714c5035b6a", + "aad" : "6453a53384632212", + "msg" : "97469da667d6110f9cbda1d1a20673", + "ct" : "32db66c4a3819d81557455e5980fed", + "tag" : "feae30dec94e6ad3a9eea06a0d703917", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 34, + "comment" : "", + "key" : "59d4eafb4de0cfc7d3db99a8f54b15d7b39f0acc8da69763b019c1699f87674a", + "iv" : "2fcb1b38a99e71b84740ad9b", + "aad" : "", + "msg" : "549b365af913f3b081131ccb6b825588", + "ct" : "e9110e9f56ab3ca483500ceabab67a13", + "tag" : "836ccabf15a6a22a51c1071cfa68fa0c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 35, + "comment" : "", + "key" : "b907a45075513fe8a8019edee3f2591487b2a030b03c6e1d771c862571d2ea1e", + "iv" : "118a6964c2d3e380071f5266", + "aad" : "034585621af8d7ff", + "msg" : "55a465644f5b650928cbee7c063214d6", + "ct" : "e4b113cb775945f3d3a8ae9ec141c00c", + "tag" : "7c43f16ce096d0dc27c95849dc383b7d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 36, + "comment" : "", + "key" : "3b2458d8176e1621c0cc24c0c0e24c1e80d72f7ee9149a4b166176629616d011", + "iv" : "45aaa3e5d16d2d42dc03445d", + "aad" : "", + "msg" : "3ff1514b1c503915918f0c0c31094a6e1f", + "ct" : "02cc3acb5ee1fcdd12a03bb857976474d3", + "tag" : "d83b7463a2c3800fe958c28eaa290813", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 37, + "comment" : "", + "key" : "f60c6a1b625725f76c7037b48fe3577fa7f7b87b1bd5a982176d182306ffb870", + "iv" : "f0384fb876121410633d993d", + "aad" : "9aaf299eeea78f79", + "msg" : "63858ca3e2ce69887b578a3c167b421c9c", + "ct" : "35766488d2bc7c2b8d17cbbb9abfad9e6d", + "tag" : "1f391e657b2738dda08448cba2811ceb", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 38, + "comment" : "", + "key" : "37ceb574ccb0b701dd11369388ca27101732339f49d8d908ace4b23af0b7ce89", + "iv" : "37270b368f6b1e3e2ca51744", + "aad" : "", + "msg" : "f26991537257378151f4776aad28ae8bd16b", + "ct" : "b621d76a8dacff00b3f840cdf26c894cc5d1", + "tag" : "e0a21716ed94c0382fa9b0903d15bb68", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 39, + "comment" : "", + "key" : "68888361919bc10622f45df168e5f6a03bd8e884c0611bea2f34c1882ed9832b", + "iv" : "bfd6ff40f2df8ca7845980cc", + "aad" : "b8373438ddb2d6c3", + "msg" : "ff97f2eefb3401ac31fc8dc1590d1a92cbc1", + "ct" : "e0a745186c1a7b147f74faff2a715df5c19d", + "tag" : "917baf703e355d4d950e6c05fe8f349f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 40, + "comment" : "", + "key" : "1b35b856b5a86d3403d28fc2103a631d42deca5175cdb0669a5e5d90b2caafc5", + "iv" : "2343de88be6c7196d33b8694", + "aad" : "", + "msg" : "21ef185c3ae9a96fa5eb473878f4d0b242781d", + "ct" : "d6e0ed54fccef30bd605d72da3320e249a9cb5", + "tag" : "c68bc6724ec803c43984ce42f6bd09ff", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 41, + "comment" : "", + "key" : "d6484e3973f6be8c83ed3208d5be5cfa06fda72fbfdc5b19d09be3f4e4eba29d", + "iv" : "1af1d90e877e11a496efa3df", + "aad" : "cc4efd8364fb114a", + "msg" : "7335ab04b03e706109ec3ee835db9a246ea0ad", + "ct" : "29e54d608237c3c3609dba16e6edf43842d72f", + "tag" : "d3365fdcd506aaaa5368661e80e9d99b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 42, + "comment" : "", + "key" : "422add37849d6e4c3dfd8020dc6a07e8a249788f3d6a83b9cb4d802362c97542", + "iv" : "1e7e67be948de7352ffdb727", + "aad" : "", + "msg" : "d7f5e611dd3a2750fb843fc1b6b93087310dc87d", + "ct" : "7fe606652d858f595ec2e706754fa3d933fcc834", + "tag" : "78d59235aa5d03a4c32590e590c04d22", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 43, + "comment" : "", + "key" : "cdccfe3f46d782ef47df4e72f0c02d9c7f774def970d23486f11a57f54247f17", + "iv" : "376187894605a8d45e30de51", + "aad" : "956846a209e087ed", + "msg" : "e28e0e9f9d22463ac0e42639b530f42102fded75", + "ct" : "14f707c446988a4903775ec7acec6da114d43112", + "tag" : "987d4b147c490d43d376a198cab383f0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 44, + "comment" : "", + "key" : "e79dfc6d2fc465b8439e1c5baccb5d8ef2853899fc19753b397e6c25b35e977e", + "iv" : "f9d6320d7ce51d8ed0677d3a", + "aad" : "", + "msg" : "4f543e7938d1b878dacaeec81dce4899974816813b", + "ct" : "1003f13ea1329cbb187316f64c3ff3a87cf5b96661", + "tag" : "d2323ad625094bec84790d7958d5583f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 45, + "comment" : "", + "key" : "1d7b8f1d96a1424923aef8a984869d4a777a110990ba465627acf80396c7f376", + "iv" : "50ba1962cdc32a5a2d36e640", + "aad" : "093053e20261daab", + "msg" : "5d3efd5767f3c12efd08af9a44e028ae68c9eff843", + "ct" : "2d48b0834e9ffe3046103ef7a214f02e8e4d33360e", + "tag" : "d533ad089be229ea606ec0f3fa22eb33", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 46, + "comment" : "", + "key" : "dd433e28cfbcb5de4ab36a02bf38686d83208771a0e63dcd08b4df1a07ac47a1", + "iv" : "c9cc0a1afc38ec6c30c38c68", + "aad" : "", + "msg" : "8a3e17aba9606dd49e3b1a4d9e5e42f1742373632489", + "ct" : "e9917ff3e64bbe1783579375e75ea823976b35539949", + "tag" : "074a890669b25105434c75beed3248db", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 47, + "comment" : "", + "key" : "a60924101b42ac24154a88de42142b2334cf599176caf4d1226f712dd9172930", + "iv" : "8ba77644b08d65d5e9f31942", + "aad" : "b2a4e12a19a61c75", + "msg" : "c949957e66439deee4b2ac1d4a6c98a6c527b90f52ab", + "ct" : "db4c700513818972b0dc0e531b1c281ca03e40c60dea", + "tag" : "63f4478bba2af469a7a4dc3b4f141360", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 48, + "comment" : "", + "key" : "1aa42027836965b1e6086fa137f9cf7f1ff48676696829bd281ff81c8ea0a4a9", + "iv" : "4b3dca84ecc407f424f281a9", + "aad" : "", + "msg" : "37252a3eb5c8960f0567e503a9035783b3d0a19a4b9a47", + "ct" : "b5f14617491fc923b683e2cc9562d043dd5986b97dbdbd", + "tag" : "972ce54713c05c4bb4d088c0a30cacd3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 49, + "comment" : "", + "key" : "5d40db0cc18ef2e42815d3b6245a466a0b30a0f93e318ac10edde3bf8ad98160", + "iv" : "acad618039b317470d21621b", + "aad" : "413036411af75745", + "msg" : "959dde1ef3129b27702c558849e466f2baca1a45bdf4b2", + "ct" : "b7ca3879f95140bf6a97b3212218b7bf864a51e5bb0b3e", + "tag" : "fe558fb570145470ea693eb76eb73171", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 50, + "comment" : "", + "key" : "0212a8de5007ed87b33f1a7090b6114f9e08cefd9607f2c276bdcfdbc5ce9cd7", + "iv" : "e6b1adf2fd58a8762c65f31b", + "aad" : "", + "msg" : "10f1ecf9c60584665d9ae5efe279e7f7377eea6916d2b111", + "ct" : "42f26c56cb4be21d9d8d0c80fc99dde00d75f38074bfe764", + "tag" : "54aa7e13d48fff7d7557039457040a3a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 51, + "comment" : "", + "key" : "c5bc09565646e7edda954f1f739223dada20b95c44ab033d0fae4b0283d18be3", + "iv" : "6b282ebecc541bcd7834ed55", + "aad" : "3e8bc5ade182ff08", + "msg" : "9222f9018e54fd6de1200806a9ee8e4cc904d29f25cba193", + "ct" : "123032437b4bfd6920e8f7e7e0087ae4889ebe7a0ad0e900", + "tag" : "3cf68f179550da63d3b96c2d55411865", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 52, + "comment" : "", + "key" : "9460b3c44ed86e70f3bda66385e1ca10b0c1677ef4f1360532830d17535f996f", + "iv" : "abfaf42e0dba884efcf07823", + "aad" : "", + "msg" : "5c5cce881b93fb7a1b7939af1ffc5f84d3280ada778cca0953", + "ct" : "1d218c9f1f9f02f248a6f976a7557057f37d9393d9f213c1f3", + "tag" : "bc88344c6fdc898feed394fb28511316", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 53, + "comment" : "", + "key" : "c111d6d5d78a071b15ab37cc8c3819199387ab7c1933aa97b1489f6584ba8e2a", + "iv" : "85f18ad8ff72cafee2452ab8", + "aad" : "84cdff939391c022", + "msg" : "6989c646a10b7c76f4d9f7d574da40e152013cf0dd78f5aa8a", + "ct" : "9715d344e8d3f3a3eaa98a9cea57c0cd717c6ef5076027c9ec", + "tag" : "3056ff5ee0aa8636bb639984edb5236b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 54, + "comment" : "", + "key" : "8a1b1e699a0c4a3e610b10902daedab1bf1ea0d505c47d7842cbcee0d3b1b6e6", + "iv" : "a6f9a8d335fa84c3b27dcd2a", + "aad" : "", + "msg" : "ee6a15fc183108f0877e7f2b8a9615f4b3fc36e1c83440f66aad", + "ct" : "9089bbdb8bcfd124e227bf75c4bfe1cba2004a274fc31aa32358", + "tag" : "fd2e21c64a019621c68594826cd7b1cd", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 55, + "comment" : "", + "key" : "74b384e6e013ec4172ed7a28a10fb9bb79b4be2a24f6999e3d3caa28e64a8656", + "iv" : "ebc19fc9ecb2339908ea3836", + "aad" : "85073f2edc13d3a1", + "msg" : "3aa9f7372f056e5a0729752d9a37132d6dd07c56792e1c7582a9", + "ct" : "796ffb70ab43e7fa79f95583e384524727bb3e47fc45b969f714", + "tag" : "c3322b4445de5f3c9f18dcc847cc94c3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 56, + "comment" : "", + "key" : "77d824795d2029f0eb0e0baab5cfeb32f7e93474913a7f95c737a667a3c33314", + "iv" : "f3307430f492d2b8a72d3a81", + "aad" : "", + "msg" : "0c4179a497d8fdd72796fb725692b805d63b7c718359cf10518aee", + "ct" : "49c81d17d67d7ba9954f497d0b0ddc21f3f839c9d2cc198d30bc2c", + "tag" : "50009899e5b2a9726c8f3556cadfbe84", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 57, + "comment" : "", + "key" : "bec5eac68f893951cbd7d1ecd3ee6611130dd9c3f80cddf95111d07d5edd76d1", + "iv" : "342ada4f0c115124b222df80", + "aad" : "73365f6d80edb1d8", + "msg" : "481433d8b1cd38af4a750e13a64b7a4e8507682b3517595938a20e", + "ct" : "4c129fc13cbdd9d3fe81ac755bf4fbea2fdd7e0aca0505a6ee9637", + "tag" : "9cede1d30a03db5d55265d3648bc40d4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 58, + "comment" : "", + "key" : "a59c1e13064df8f2b8df77a492b0ca2eae921b52a84b305a3a9a51408a9ecb69", + "iv" : "9544d41ece0c92ef01cfac2d", + "aad" : "", + "msg" : "1c35b898821ba55c2617c25df9e6df2a8002b384902186cd69dfd20e", + "ct" : "a6fa8f57ddc81d6099f667dd62402b6a5d5b7d05a329298029113169", + "tag" : "bb24e38b31dbbc3e575b9e3ee076af2a", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 59, + "comment" : "", + "key" : "084b5d7365f1a8fec6365939ed741e6ea5893e0318d82ab47500a97d77aaa041", + "iv" : "829f005e980f0a6e2f983eaa", + "aad" : "770f6e6e89a3fe8e", + "msg" : "7510016efadc385a71ed689ceb590c8ea9cc1e81b793338bddf5f10c", + "ct" : "fd42cb5cf894f879e3cf751662aaa58a2288cc53548802becaf42359", + "tag" : "188329438afe1cd7225d0478aa90c773", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 60, + "comment" : "", + "key" : "5a7f850a1d9aafa77d59ae1b731965e8aaec6352280fc76a7b5e23ef3610cfe4", + "iv" : "4946a0d6adea93b82d4332e5", + "aad" : "", + "msg" : "3c161d791f624fb0388e808f0f69ed790dbe4cbd089ebac46627bcf01d", + "ct" : "402302b56140c4dcc39774732c55883de124ce4bf0a0261cfa1569e2cf", + "tag" : "e830bfe933a96786cff2dd72b82c4bd5", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 61, + "comment" : "", + "key" : "e6d5a4246f6f05618b59c8f9ec3ac8068cc0d3f351c571aa52b09cb251f9c2f6", + "iv" : "2f90a65e9e48725de6ffc727", + "aad" : "f2415377ad283fd8", + "msg" : "964fc9e0e8355947aa1c2caadd7b3dbef82a1024e623606fac436ef573", + "ct" : "d052932bad6e6c4f835f02019e52d7ff807dc2a5aac2040883c79dd3d5", + "tag" : "655f93396b4d755dc4475721665fed91", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 62, + "comment" : "", + "key" : "09e822123adbb1ed89b79a58619c64853992f8371d46338712f6c91ab11a68bb", + "iv" : "a797205a6cacdd7e47a4789d", + "aad" : "", + "msg" : "80b71bbe833629841bd3aeaeb9db6123e51d367b436fe9d2d3454b62cfad", + "ct" : "83f5c77396cabd28dfcc002cba0756d4ea5455e0261d847d5708aac21e8d", + "tag" : "705a05820a21f381d244d40e58d2f16b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 63, + "comment" : "", + "key" : "625735fe7f8fc81b0c1edc3d08a78b41268f87a3c68488b674222630c1d587a5", + "iv" : "9d8cdf289dddd09afdc1b02f", + "aad" : "200a9c95946ff05c", + "msg" : "67ae1882d0b1c1b2485bec98115ecf53b9b438deb1d0400531705038873a", + "ct" : "209b7539385c8b19ecd0fd8b5011b2996e316f1942064e68edfa363acbcd", + "tag" : "fa2f454b9fa2608f780f7c6f9b780fe1", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 64, + "comment" : "", + "key" : "2eb51c469aa8eb9e6c54a8349bae50a20f0e382711bba1152c424f03b6671d71", + "iv" : "04a9be03508a5f31371a6fd2", + "aad" : "", + "msg" : "b053999286a2824f42cc8c203ab24e2c97a685adcc2ad32662558e55a5c729", + "ct" : "45c7d6b53acad4abb68876a6e96a48fb59524d2c92c9d8a189c9fd2db91746", + "tag" : "566d3ca10e311b695f3eae1551652493", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 65, + "comment" : "", + "key" : "7f5b74c07ed1b40fd14358fe2ff2a740c116c7706510e6a437f19ea49911cec4", + "iv" : "470a339ecb3219b8b81a1f8b", + "aad" : "374618a06ea98a48", + "msg" : "f45206abc25552b2abc9ab7fa243035fedaaddc3b2293956f1ea6e7156e7eb", + "ct" : "46a80c4187024720084627580080dde5a3f4a11093a7076ed6f3d326bc7b70", + "tag" : "534d4aa2835a52e72d14df0e4f47f25f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 66, + "comment" : "", + "key" : "e1731d5854e1b70cb3ffe8b786a2b3ebf0994370954757b9dc8c7bc5354634a3", + "iv" : "72cfd90ef3026ca22b7e6e6a", + "aad" : "", + "msg" : "b9c554cbc36ac18ae897df7beecac1dbeb4eafa156bb60ce2e5d48f05715e678", + "ct" : "ea29afa49d36e8760f5fe19723b9811ed5d519934a440f5081ac430b953b0e21", + "tag" : "222541af46b86533c6b68d2ff108a7ea", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 67, + "comment" : "", + "key" : "27d860631b0485a410702fea61bc873f3442260caded4abde25b786a2d97f145", + "iv" : "262880d475f3dac5340dd1b8", + "aad" : "2333e5ce0f93b059", + "msg" : "6b2604996cd30c14a13a5257ed6cffd3bc5e29d6b97eb1799eb335e281ea451e", + "ct" : "6dad637897544d8bf6be9507ed4d1bb2e954bc427e5de729daf50762846ff2f4", + "tag" : "7b997d93c982189d7095dc794c746232", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 68, + "comment" : "", + "key" : "5155dee9aade1cc61ee7e3f92660f7590f5e5ba82f1b59b850e3fa453d2fa6b3", + "iv" : "c26c4b3bfdb97ee6b0f63ca1", + "aad" : "", + "msg" : "2734e08eff8f5c4f84fa0c207f49c7fd78af1ad5123ff81f83f500edf4eda09edf", + "ct" : "f5982b601c7a18fc72a65b218c44974dc564d8314cbe6f87fcf6c6cfbe618b34b1", + "tag" : "c43632f55760b5d1ed37556a94d049b5", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 69, + "comment" : "", + "key" : "573f08ebbe0cce4ac9618e8c3b224bea0a32f055c6996838a32f527ca3c3b695", + "iv" : "ad8050dc6d122dce3e5639ed", + "aad" : "e99698241c599b5f", + "msg" : "668d5e3f95fe030daf432a5fc5837af3a79c81e94b28d8204c5ee262ab3c9908a7", + "ct" : "eaf6810e6ec1cb7a2918856257d1aa3d51a827879146c6337ecf535e9c89b149c5", + "tag" : "a2950c2f394a3466c345f796323c1aa7", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 70, + "comment" : "", + "key" : "cf0d40a4644e5f51815165d5301b22631f4544c49a1878e3a0a5e8e1aae0f264", + "iv" : "e74a515e7e2102b90bef55d2", + "aad" : "", + "msg" : "973d0c753826bae466cf9abb3493152e9de7819e2bd0c71171346b4d2cebf8041aa3cedc0dfd7b467e26228bc86c9a", + "ct" : "fba78ae4f9d808a62e3da40be2cb7700c3613d9eb2c529c652e76a432c658d27095f0eb8f940c324981ea935e507f9", + "tag" : "8f046956db3a512908bd7afc8f2ab0a9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 71, + "comment" : "", + "key" : "6cbfd71c645d184cf5d23c402bdb0d25ec54898c8a0273d42eb5be109fdcb2ac", + "iv" : "d4d807341683825b31cd4d95", + "aad" : "b3e4064683b02d84", + "msg" : "a98995504df16f748bfb7785ff91eeb3b660ea9ed3450c3d5e7b0e79ef653659a9978d75542ef91c456762215640b9", + "ct" : "a1ffed80761829ecce242e0e88b138049016bca018da2b6e19986b3e318cae8d806198fb4c527cc39350ebddeac573", + "tag" : "c4cbf0befda0b70242c640d7cd02d7a3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 72, + "comment" : "", + "key" : "5b1d1035c0b17ee0b0444767f80a25b8c1b741f4b50a4d3052226baa1c6fb701", + "iv" : "d61040a313ed492823cc065b", + "aad" : "", + "msg" : "d096803181beef9e008ff85d5ddc38ddacf0f09ee5f7e07f1e4079cb64d0dc8f5e6711cd4921a7887de76e2678fdc67618f1185586bfea9d4c685d50e4bb9a82", + "ct" : "9a4ef22b181677b5755c08f747c0f8d8e8d4c18a9cc2405c12bb51bb1872c8e8b877678bec442cfcbb0ff464a64b74332cf072898c7e0eddf6232ea6e27efe50", + "tag" : "9ff3427a0f32fa566d9ca0a78aefc013", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 73, + "comment" : "", + "key" : "97d635c4f47574d9998a90875da1d3a284b755b2d39297a5725235190e10a97e", + "iv" : "d31c21aba175b70de4ebb19c", + "aad" : "7193f623663321a2", + "msg" : "94ee166d6d6ecf8832437136b4ae805d428864359586d9193a25016293edba443c58e07e7b7195ec5bd84582a9d56c8d4a108c7d7ce34e6c6f8ea1bec0567317", + "ct" : "5fbbdecc34be201614f636031eeb42f1cace3c79a12cffd871ee8e73820c829749f1abb4294367849fb6c2aa56bda8a3078f723d7c1c852024b017b58973fb1e", + "tag" : "09263da7b4cb921452f97dca40f580ec", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 74, + "comment" : "", + "key" : "fe6e55bdaed1f7284ca5fc0f8c5f2b8df56dc0f49e8ca66a41995e783351f901", + "iv" : "17c86a8abbb7e003acde2799", + "aad" : "", + "msg" : "b429eb80fb8fe8baeda0c85b9c333458e7c2992e558475069d12d45c22217564121588032297eff56783742a5fc22d7410ffb29d66098661d76f126c3c27689e43b37267cac5a3a6d3ab49e391da29cd3054a5692e2807e4c3ea46c8761d50f592", + "ct" : "d0102f6c258bf49742cec34cf2d0fedf23d105fb4c84cf98515e1bc9a64f8ad5be8f0721bde50645d00083c3a263a31053b760245f52ae2866a5ec83b19f61be1d30d5c5d9fecc4cbbe08fd385813a2aa39a00ff9c10f7f23702add1e4b2ffa31c", + "tag" : "41865fc71de12b19612127ce49993bb0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 75, + "comment" : "", + "key" : "aabc063474e65c4c3e9bdc480dea97b45110c8618846ff6b15bdd2a4a5682c4e", + "iv" : "46362f45d6379e63e5229460", + "aad" : "a11c40b603767330", + "msg" : "ceb534ce50dc23ff638ace3ef63ab2cc2973eeada80785fc165d06c2f5100ff5e8ab2882c475afcd05ccd49f2e7d8f55ef3a72e3dc51d6852b8e6b9e7aece57be6556b0b6d9413e33fc5fc24a9a205ad59574bb39d944a92dc47970d84a6ad3176", + "ct" : "7545391b51de01d5c53dfaca777909063e58edee4bb1227e7110ac4d2620c2aec2f848f56deeb037a8dced75afa8a6c890e2dee42f950bb33d9e2424d08a505d899563973ed38870f3de6ee2adc7fe072c366c14e2cf7ca62fb3d36bee11685461", + "tag" : "b70d44ef8c66c5c7bbf10dcadd7facf6", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 76, + "comment" : "", + "key" : "d7addd3889fadf8c893eee14ba2b7ea5bf56b449904869615bd05d5f114cf377", + "iv" : "8a3ad26b28cd13ba6504e260", + "aad" : "", + "msg" : "c877a76bf595560772167c6e3bcc705305db9c6fcbeb90f4fea85116038bc53c3fa5b4b4ea0de5cc534fbe1cf9ae44824c6c2c0a5c885bd8c3cdc906f12675737e434b983e1e231a52a275db5fb1a0cac6a07b3b7dcb19482a5d3b06a9317a54826cea6b36fce452fa9b5475e2aaf25499499d8a8932a19eb987c903bd8502fe", + "ct" : "294a764c03353f5f4f6e93cd7e977480d6c343071db0b7c1f0db1e95b85e6053f0423168a9c7533268db9a194e7665359d14489bc47172a9f21370e89b0bd0e5ef9661738de282572bcc3e541247626e57e75dec0f91ac5c530bd1a53271842996dcd04d865321b1ecb6e7630114fe780291b8dc3e5d0abc8e65b1c5493e9af0", + "tag" : "f2b974ca0f14fb9f92014bff18573cff", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 77, + "comment" : "", + "key" : "80be86fb6fc49bc73428cab576f6ad72ff6aca04001b8b1c57a7128be73900aa", + "iv" : "903188433c1ce8971aa19b9d", + "aad" : "0587af8530ad0547", + "msg" : "67ce499cd8ed68bd717dfe61c60f27d260b1c163a72e8cc8597253d3d987c2dbe1bff2e44d9bd4765d3e53d9c3f8eb3b90e751f47c7157bdc1142bc33f5833ac1cd1262cbb239066b334a4ed99ae82c74f2b49540f1a614bc239d8fc5add8c178184e41281f6e66c5c3117fd953547f7c829425b5082aa69686847eaf5784692", + "ct" : "2b90b4f3de280c44913d1984bdd5dfa0566c6a14a058659a9b623277b0bb6e82101e79395d12e643f62d9a822bae497907493e4f8213fcf99da8a78fdf867af36bc8b0931c1886b4f0ae5729986494dbd59737e956cd8f226c7c522689d082f023894d54acab0c4d609f3746a67369bb8876008f7fd3dc6681c5fb9d728c5911", + "tag" : "f005ebe1c1ada75a9cee8d630881d5b8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 78, + "comment" : "", + "key" : "7d00b48095adfa3272050607b264185002ba99957c498be022770f2ce2f3143c", + "iv" : "87345f1055fd9e2102d50656", + "aad" : "02", + "msg" : "e5ccaa441bc814688f8f6e8f28b500b2", + "ct" : "7e72f5a185af16a611921b438f749f0b", + "tag" : "1242c670732334029adfe1c5001651e4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 79, + "comment" : "", + "key" : "6432717f1db85e41ac7836bce25185a080d5762b9e2b18444b6ec72c3bd8e4dc", + "iv" : "87a3163ec0598ad95b3aa713", + "aad" : "b648", + "msg" : "02cde168fba3f544bbd0332f7adeada8", + "ct" : "85f29a719557cdd14d1f8fffab6d9e60", + "tag" : "732ca32becd515a1ed353f542e999858", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 80, + "comment" : "", + "key" : "7afa0f59dfcb5ad3a76490c5c804327c8d052be737a60fa8bcbf0a2c36630a43", + "iv" : "25b7bdf4a6dcbf7c9a3ec2b3", + "aad" : "8b71ac", + "msg" : "623e6ba6d3166a338bfcc7af90a230c8", + "ct" : "d46e8265a8c6a25393dd956bb44397ad", + "tag" : "e28f3ad9e3ef4a3d94ee07bf538eaafb", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 81, + "comment" : "", + "key" : "2ec25b0ec7ac244224e9c7fc2fa5d3ef17809e19fd6e954158dd0d72738a4cc8", + "iv" : "6fb0d1417cdfff4df37db08c", + "aad" : "3a5ddf40", + "msg" : "a1c933768a6d573ebf68a99e5e18dae8", + "ct" : "2d3cb2d9303491e264f2904f0e0753f4", + "tag" : "6c1db959362d217b2322b466536bfea0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 82, + "comment" : "", + "key" : "0a2cf52371cf9d9f95b10108fc82b4fd6110a8ba9a88a26083685ad29826891a", + "iv" : "2538fc67afb9eab333f83290", + "aad" : "9eec540bb0", + "msg" : "0d8c691d044a3978d790432dc71d69f8", + "ct" : "a988c03c71b956ff086d0470d706bd34", + "tag" : "b35d7cbf2beb894b0c746e0730429e15", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 83, + "comment" : "", + "key" : "307e886b38bb18b445f8a2c6d6f8932492a9cea8d041ba72eb5efdfa70d0b8d2", + "iv" : "a071be999151e2a1c41c81e9", + "aad" : "56e014d97c74", + "msg" : "9aba22b495cb7ec887ddaa62019aa14d", + "ct" : "32bf95d4c195dbaf58d9af4001c6e57d", + "tag" : "4393808703d67a90870578046cd8b525", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 84, + "comment" : "", + "key" : "dacd51a8a8e4d5905b4cbb947ef4013eb296889353f3c9ee35f5577b26737a51", + "iv" : "3fa378a1befdddd61ae68cf4", + "aad" : "bb5a3812f0aefd", + "msg" : "e148313883a77da121124d06b1c77dca", + "ct" : "2a207ca7e9da6b13a229604304d87eb1", + "tag" : "8a6b6afec87d93ec6e8dbe13d84c0f8c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 85, + "comment" : "", + "key" : "7b5fbbb202c16108fd13066446853a850d8b34e9da40519580da446a922f9162", + "iv" : "aa077a5ce9161bde8d8edc40", + "aad" : "f94bb92c1c668a695b", + "msg" : "da471cd6935a0ca8307ddedc6b959962", + "ct" : "548a5ca0ae49211cdf30bbdcb1352d31", + "tag" : "204dacb98f8c8908cc5ea22bb23f901f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 86, + "comment" : "", + "key" : "1ffd101eb97531f6faa821ec4d5c5702725dd033d3b830bb760c4ef27ba983df", + "iv" : "598114e8cf7fbdea8ad29683", + "aad" : "2155627ec15a978fbcb2", + "msg" : "28668ca8db535c7e8eb27491ad0fb7cb", + "ct" : "28cedac24f14caa326c7fe401f68a87c", + "tag" : "2bf1b2c43d3039f8f5ce359c1102f879", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 87, + "comment" : "", + "key" : "d2d0a973d5951af352cbee57ac9dab1c284c99af3b992ce015f219506f64888d", + "iv" : "9acd213570ce9bb9d886c6ef", + "aad" : "37ad668d4d4fe889949763", + "msg" : "3f3f0076250352e1b6b5c12cfa12625e", + "ct" : "7256e856872ad3a54b34a2a6bdca8838", + "tag" : "3b12e4586e45223f78a6eea811efb863", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 88, + "comment" : "", + "key" : "adcc520b381382237d05a6400a7dfbcd0771b6aa9edb7966131ddef6af21f1be", + "iv" : "9183cdf3a8ba7397b6b2d5d5", + "aad" : "b334375415f6215c0bf89a9a", + "msg" : "958295619cf1b36f0b474663c0bc79eb", + "ct" : "852c141b4239a31feeda03550d70a2be", + "tag" : "5fc59287b92d3fcf7d66f13defb11b0d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 89, + "comment" : "", + "key" : "bd534f7adeca466844fb3ba34658be807f15c5291ed6026860a24f179b712c89", + "iv" : "412c3e13ee1f7864bd15ce39", + "aad" : "2866afff0bcc6135dc63af88c8", + "msg" : "d92f8ce5d8d0ad2eb5f11af02ef63949", + "ct" : "89d6d089c4a255952aca11b24a01ff95", + "tag" : "f88fa4531204da315e7317970240ce9e", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 90, + "comment" : "", + "key" : "910ade7d324d2c9688439e1f142e0e5f9d130ff832e507fe1985e5a26452a6d0", + "iv" : "9be090dba93deff27adf99ee", + "aad" : "ea2575f123268e936c8e4c8c1bb8", + "msg" : "6e356094ed9d9a7053c7906c48ba3d9f", + "ct" : "01ffb343c757b27843d8a900a36ce39d", + "tag" : "a315541b7d6313c6fddf64b303d71d60", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 91, + "comment" : "", + "key" : "8e34cf73d245a1082a920b86364eb896c4946467bcb3d58929fcb36690e6394f", + "iv" : "6f573aa86baa492ba46596df", + "aad" : "bd4cd02fc7502bbdbdf6c9a3cbe8f0", + "msg" : "16ddd23ff53f3d23c06334487040eb47", + "ct" : "c1b295936d56fadac03e5f742bff73a1", + "tag" : "39c457dbab66382babb3b55800cda5b8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 92, + "comment" : "", + "key" : "cb5575f5c7c45c91cf320b139fb594237560d0a3e6f865a67d4f633f2c08f016", + "iv" : "1a6518f02ede1da6809266d9", + "aad" : "89cce9fb47441d07e0245a66fe8b778b", + "msg" : "623b7850c321e2cf0c6fbcc8dfd1aff2", + "ct" : "c84c9bb7c61c1bcb17772a1c500c5095", + "tag" : "dbadf7a5138ca03459a2cd65831e092f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 93, + "comment" : "", + "key" : "a5569e729a69b24ba6e0ff15c4627897436824c941e9d00b2e93fddc4ba77657", + "iv" : "564dee49ab00d240fc1068c3", + "aad" : "d19f2d989095f7ab03a5fde84416e00c0e", + "msg" : "87b3a4d7b26d8d3203a0de1d64ef82e3", + "ct" : "94bc80621ed1e71b1fd2b5c3a15e3568", + "tag" : "333511861796978401598b963722f5b3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 94, + "comment" : "", + "key" : "56207465b4e48e6d04630f4a42f35cfc163ab289c22a2b4784f6f9290330bee0", + "iv" : "df8713e87ec3dbcfad14d53e", + "aad" : "5e6470facd99c1d81e37cd44015fe19480a2a4d3352a4ff560c0640fdbda", + "msg" : "e601b38557797da2f8a4106a089d1da6", + "ct" : "299b5d3f3d03c087209a16e285143111", + "tag" : "4b454ed198de117e83ec49fa8d8508d6", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 95, + "comment" : "", + "key" : "077433022ab34d380fc192fc24c2edc6301fec6f24442f572a1087ff2e05b39a", + "iv" : "28adcbc74364f26dd4b3108b", + "aad" : "e0100eb116cdc5e22a3b9f9b4126c149595e75107f6e237c69e82960052270", + "msg" : "03c874eeaaa6fa9f0da62c758fb0ad04", + "ct" : "1e9687b35fbc8eaa1825ed3847798f76", + "tag" : "0788bf70fd04030ecd1c96d0bc1fcd5d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 96, + "comment" : "", + "key" : "3937986af86dafc1ba0c4672d8abc46c207062682d9c264ab06d6c5807205130", + "iv" : "8df4b15a888c33286a7b7651", + "aad" : "ba446f6f9a0ced22450feb10737d9007fd69abc19b1d4d9049a5551e86ec2b37", + "msg" : "dc9e9eaf11e314182df6a4eba17aec9c", + "ct" : "605bbf90aeb974f6602bc778056f0dca", + "tag" : "38ea23d99054b46b42ffe004129d2204", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 97, + "comment" : "", + "key" : "36372abcdb78e0279646ac3d176b9674e9154eecf0d5469c651ec7e16b4c1199", + "iv" : "be40e5f1a11817a0a8fa8949", + "aad" : "d41a828d5e71829247021905402ea257dccbc3b80fcd5675056b68bb59e62e8873", + "msg" : "81ce84ede9b35859cc8c49a8f6be7dc6", + "ct" : "7b7ce0d824809a70de32562ccf2c2bbd", + "tag" : "15d44a00ce0d19b4231f921e22bc0a43", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 98, + "comment" : "", + "key" : "9f1479ed097d7fe529c11f2f5add9aaff4a1ca0b68997a2cb7f79749bd90aaf4", + "iv" : "84c87dae4eee27730ec35d12", + "aad" : "3f2dd49bbf09d69a78a3d80ea2566614fc379474196c1aae84583da73d7ff85c6f42ca42056a9792cc1b9fb3c7d261", + "msg" : "a66747c89e857af3a18e2c79500087ed", + "ct" : "ca82bff3e2f310ccc976672c4415e69b", + "tag" : "57638c62a5d85ded774f913c813ea032", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 99, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000000000000000000000000000000", + "msg" : "65b63bf074b7283992e24b1ac0df0d22b555dbe2254d94a43f1de748d3cc6f0d", + "ct" : "0000000000000000000000000000000000000000000000000000000000000000", + "tag" : "39f4fce3026d83789ffd1ee6f2cd7c4f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 100, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000000000000000000000000000000", + "msg" : "65b63bf074b7283992e24b1ac0df0d22b555dbe2254d94a43f1de748d3cc6f0d20c142fe898fbbe668d4324394434c1b18b58ead710aed9c31db1f2a8a1f1bb2", + "ct" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "tag" : "f5eaa804605c3a4785f9d7f13b6f67d6", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 101, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000000000000000000000000000000", + "msg" : "65b63bf074b7283992e24b1ac0df0d22b555dbe2254d94a43f1de748d3cc6f0d20c142fe898fbbe668d4324394434c1b18b58ead710aed9c31db1f2a8a1f1bb24405c183af94ee1ad630cd931158a6213d48c8fff10d0a1f9ef760188e658802aad55e41a1d99069a18db55c56af7c10a6f21ecc8af9b7ce0a7ea0b67426e925", + "ct" : "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "tag" : "9b5c43a78d954e8a3c659eebc13d5d55", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 102, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffffffffffffffffffffffffffffff", + "msg" : "9a49c40f8b48d7c66d1db4e53f20f2dd4aaa241ddab26b5bc0e218b72c3390f2", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "37e3399d9ca696799f08f4f72bc0cdd8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 103, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffffffffffffffffffffffffffffff", + "msg" : "9a49c40f8b48d7c66d1db4e53f20f2dd4aaa241ddab26b5bc0e218b72c3390f2df3ebd0176704419972bcdbc6bbcb3e4e74a71528ef51263ce24e0d575e0e44d", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "3d52710bec86d4ea9fea2ff269549191", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 104, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffffffffffffffffffffffffffffff", + "msg" : "9a49c40f8b48d7c66d1db4e53f20f2dd4aaa241ddab26b5bc0e218b72c3390f2df3ebd0176704419972bcdbc6bbcb3e4e74a71528ef51263ce24e0d575e0e44dbbfa3e7c506b11e529cf326ceea759dec2b737000ef2f5e061089fe7719a77fd552aa1be5e266f965e724aa3a95083ef590de13375064831f5815f498bd916da", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "51356329e280b12d55d3d98f0a580cbe", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 105, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000080000000800000008000000080", + "msg" : "65b63b7074b728b992e24b9ac0df0da2b555db62254d94243f1de7c8d3cc6f8d", + "ct" : "0000008000000080000000800000008000000080000000800000008000000080", + "tag" : "c152a4b90c548c71dc479edeaf9211bf", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 106, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000080000000800000008000000080", + "msg" : "65b63b7074b728b992e24b9ac0df0da2b555db62254d94243f1de7c8d3cc6f8d20c1427e898fbb6668d432c394434c9b18b58e2d710aed1c31db1faa8a1f1b32", + "ct" : "00000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080", + "tag" : "40ef6383052d91c2e4b4611b0e32c5ff", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 107, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000080000000800000008000000080", + "msg" : "65b63b7074b728b992e24b9ac0df0da2b555db62254d94243f1de7c8d3cc6f8d20c1427e898fbb6668d432c394434c9b18b58e2d710aed1c31db1faa8a1f1b324405c103af94ee9ad630cd131158a6a13d48c87ff10d0a9f9ef760988e658882aad55ec1a1d990e9a18db5dc56af7c90a6f21e4c8af9b74e0a7ea0367426e9a5", + "ct" : "0000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080", + "tag" : "ae9b542541e84fc74542eed6be638fee", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 108, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "80000000800000008000000080000000", + "msg" : "e5b63bf0f4b7283912e24b1a40df0d223555dbe2a54d94a4bf1de74853cc6f0d", + "ct" : "8000000080000000800000008000000080000000800000008000000080000000", + "tag" : "10fee3ecfba9cdf797bae37a626ec83b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 109, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "80000000800000008000000080000000", + "msg" : "e5b63bf0f4b7283912e24b1a40df0d223555dbe2a54d94a4bf1de74853cc6f0da0c142fe098fbbe6e8d4324314434c1b98b58eadf10aed9cb1db1f2a0a1f1bb2", + "ct" : "80000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000", + "tag" : "7490795bdbbbf5d0aecb9a4f65aa379f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 110, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "80000000800000008000000080000000", + "msg" : "e5b63bf0f4b7283912e24b1a40df0d223555dbe2a54d94a4bf1de74853cc6f0da0c142fe098fbbe6e8d4324314434c1b98b58eadf10aed9cb1db1f2a0a1f1bb2c405c1832f94ee1a5630cd939158a621bd48c8ff710d0a1f1ef760180e6588022ad55e4121d99069218db55cd6af7c1026f21ecc0af9b7ce8a7ea0b6f426e925", + "ct" : "8000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000800000008000000080000000", + "tag" : "1d1096a8ca9e2bda2762c41d5b16f62f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 111, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffff7fffffff7fffffff7fffffff7f", + "msg" : "9a49c48f8b48d7466d1db4653f20f25d4aaa249ddab26bdbc0e218372c339072", + "ct" : "ffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7f", + "tag" : "af8492c792bf8d8062be74ff6efb3869", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 112, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffff7fffffff7fffffff7fffffff7f", + "msg" : "9a49c48f8b48d7466d1db4653f20f25d4aaa249ddab26bdbc0e218372c339072df3ebd8176704499972bcd3c6bbcb364e74a71d28ef512e3ce24e05575e0e4cd", + "ct" : "ffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7f", + "tag" : "f24db68c46b67d6f402fa6c897913368", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 113, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffff7fffffff7fffffff7fffffff7f", + "msg" : "9a49c48f8b48d7466d1db4653f20f25d4aaa249ddab26bdbc0e218372c339072df3ebd8176704499972bcd3c6bbcb364e74a71d28ef512e3ce24e05575e0e4cdbbfa3efc506b116529cf32eceea7595ec2b737800ef2f56061089f67719a777d552aa13e5e266f165e724a23a950836f590de1b3750648b1f5815fc98bd9165a", + "ct" : "ffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7f", + "tag" : "43f651ab2e2eb0f04bf689a40d32da24", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 114, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "7fffffff7fffffff7fffffff7fffffff", + "msg" : "1a49c40f0b48d7c6ed1db4e5bf20f2ddcaaa241d5ab26b5b40e218b7ac3390f2", + "ct" : "7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff", + "tag" : "60d95294a3694cfaa64b2f63bc1f82ec", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 115, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "7fffffff7fffffff7fffffff7fffffff", + "msg" : "1a49c40f0b48d7c6ed1db4e5bf20f2ddcaaa241d5ab26b5b40e218b7ac3390f25f3ebd01f6704419172bcdbcebbcb3e4674a71520ef512634e24e0d5f5e0e44d", + "ct" : "7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff", + "tag" : "beaca0b47027196176186d944019c1c8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 116, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "7fffffff7fffffff7fffffff7fffffff", + "msg" : "1a49c40f0b48d7c6ed1db4e5bf20f2ddcaaa241d5ab26b5b40e218b7ac3390f25f3ebd01f6704419172bcdbcebbcb3e4674a71520ef512634e24e0d5f5e0e44d3bfa3e7cd06b11e5a9cf326c6ea759de42b737008ef2f5e0e1089fe7f19a77fdd52aa1bede266f96de724aa3295083efd90de133f506483175815f490bd916da", + "ct" : "7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff7fffffff", + "tag" : "d4811028a577d4dd69d6b35d717f73e3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 117, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000000ffffffff00000000ffffffff", + "msg" : "65b63bf08b48d7c692e24b1a3f20f2ddb555dbe2dab26b5b3f1de7482c3390f2", + "ct" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", + "tag" : "10fb61272b555bee104f5a71818716d6", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 118, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000000ffffffff00000000ffffffff", + "msg" : "65b63bf08b48d7c692e24b1a3f20f2ddb555dbe2dab26b5b3f1de7482c3390f220c142fe7670441968d432436bbcb3e418b58ead8ef5126331db1f2a75e0e44d", + "ct" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", + "tag" : "4756764e59583504182877d8c33120f0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 119, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "00000000ffffffff00000000ffffffff", + "msg" : "65b63bf08b48d7c692e24b1a3f20f2ddb555dbe2dab26b5b3f1de7482c3390f220c142fe7670441968d432436bbcb3e418b58ead8ef5126331db1f2a75e0e44d4405c183506b11e5d630cd93eea759de3d48c8ff0ef2f5e09ef76018719a77fdaad55e415e266f96a18db55ca95083efa6f21ecc750648310a7ea0b68bd916da", + "ct" : "00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff", + "tag" : "95a2b12a4a280089d4bd4f904253e754", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 120, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffffff00000000ffffffff00000000", + "msg" : "9a49c40f74b728396d1db4e5c0df0d224aaa241d254d94a4c0e218b7d3cc6f0d", + "ct" : "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000", + "tag" : "60dcd45974bebe032eb7b86c9d063452", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 121, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffffff00000000ffffffff00000000", + "msg" : "9a49c40f74b728396d1db4e5c0df0d224aaa241d254d94a4c0e218b7d3cc6f0ddf3ebd01898fbbe6972bcdbc94434c1be74a7152710aed9cce24e0d58a1f1bb2", + "ct" : "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000", + "tag" : "f0e6a3c1f28ad92d0dbc900be291d877", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 122, + "comment" : "", + "key" : "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffffff00000000ffffffff00000000", + "msg" : "9a49c40f74b728396d1db4e5c0df0d224aaa241d254d94a4c0e218b7d3cc6f0ddf3ebd01898fbbe6972bcdbc94434c1be74a7152710aed9cce24e0d58a1f1bb2bbfa3e7caf94ee1a29cf326c1158a621c2b73700f10d0a1f61089fe78e658802552aa1bea1d990695e724aa356af7c10590de1338af9b7cef5815f497426e925", + "ct" : "ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000", + "tag" : "57eff4a525eeff2ebd7a28eb894282be", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 123, + "comment" : "Flipped bit 0 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f5409bb729039d0814ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 124, + "comment" : "Flipped bit 1 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f6409bb729039d0814ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 125, + "comment" : "Flipped bit 7 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "74409bb729039d0814ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 126, + "comment" : "Flipped bit 8 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4419bb729039d0814ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 127, + "comment" : "Flipped bit 31 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409b3729039d0814ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 128, + "comment" : "Flipped bit 32 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb728039d0814ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 129, + "comment" : "Flipped bit 33 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb72b039d0814ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 130, + "comment" : "Flipped bit 63 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d8814ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 131, + "comment" : "Flipped bit 64 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d0815ac514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 132, + "comment" : "Flipped bit 77 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d08148c514054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 133, + "comment" : "Flipped bit 80 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d0814ac504054323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 134, + "comment" : "Flipped bit 96 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d0814ac514055323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 135, + "comment" : "Flipped bit 97 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d0814ac514056323f44", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 136, + "comment" : "Flipped bit 120 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d0814ac514054323f45", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 137, + "comment" : "Flipped bit 121 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d0814ac514054323f46", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 138, + "comment" : "Flipped bit 126 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d0814ac514054323f04", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 139, + "comment" : "Flipped bit 127 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d0814ac514054323fc4", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 140, + "comment" : "Flipped bit 63 and 127 in tag expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "f4409bb729039d8814ac514054323fc4", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 141, + "comment" : "Tag changed to all zero expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 142, + "comment" : "tag change to all 1 expected tag:f4409bb729039d0814ac514054323f44", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "", + "ct" : "", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 143, + "comment" : "Flipped bit 0 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "28914007a6119dd3f109bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 144, + "comment" : "Flipped bit 1 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "2b914007a6119dd3f109bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 145, + "comment" : "Flipped bit 7 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "a9914007a6119dd3f109bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 146, + "comment" : "Flipped bit 8 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29904007a6119dd3f109bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 147, + "comment" : "Flipped bit 31 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914087a6119dd3f109bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 148, + "comment" : "Flipped bit 32 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a7119dd3f109bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 149, + "comment" : "Flipped bit 33 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a4119dd3f109bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 150, + "comment" : "Flipped bit 63 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119d53f109bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 151, + "comment" : "Flipped bit 64 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f009bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 152, + "comment" : "Flipped bit 77 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f129bba21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 153, + "comment" : "Flipped bit 80 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f109baa21ce9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 154, + "comment" : "Flipped bit 96 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f109bba21de9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 155, + "comment" : "Flipped bit 97 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f109bba21ee9a7d6", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 156, + "comment" : "Flipped bit 120 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f109bba21ce9a7d7", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 157, + "comment" : "Flipped bit 121 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f109bba21ce9a7d4", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 158, + "comment" : "Flipped bit 126 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f109bba21ce9a796", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 159, + "comment" : "Flipped bit 127 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119dd3f109bba21ce9a756", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 160, + "comment" : "Flipped bit 63 and 127 in tag expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "29914007a6119d53f109bba21ce9a756", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 161, + "comment" : "Tag changed to all zero expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 162, + "comment" : "tag change to all 1 expected tag:29914007a6119dd3f109bba21ce9a7d6", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995a", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 163, + "comment" : "Flipped bit 0 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "67405a16e8b44eba92aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 164, + "comment" : "Flipped bit 1 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "64405a16e8b44eba92aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 165, + "comment" : "Flipped bit 7 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "e6405a16e8b44eba92aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 166, + "comment" : "Flipped bit 8 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66415a16e8b44eba92aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 167, + "comment" : "Flipped bit 31 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a96e8b44eba92aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 168, + "comment" : "Flipped bit 32 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e9b44eba92aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 169, + "comment" : "Flipped bit 33 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16eab44eba92aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 170, + "comment" : "Flipped bit 63 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44e3a92aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 171, + "comment" : "Flipped bit 64 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba93aa47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 172, + "comment" : "Flipped bit 77 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba928a47f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 173, + "comment" : "Flipped bit 80 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba92aa46f5cea52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 174, + "comment" : "Flipped bit 96 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba92aa47f5cfa52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 175, + "comment" : "Flipped bit 97 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba92aa47f5cca52b7a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 176, + "comment" : "Flipped bit 120 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba92aa47f5cea52b7b", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 177, + "comment" : "Flipped bit 121 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba92aa47f5cea52b78", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 178, + "comment" : "Flipped bit 126 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba92aa47f5cea52b3a", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 179, + "comment" : "Flipped bit 127 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44eba92aa47f5cea52bfa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 180, + "comment" : "Flipped bit 63 and 127 in tag expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "66405a16e8b44e3a92aa47f5cea52bfa", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 181, + "comment" : "Tag changed to all zero expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "00000000000000000000000000000000", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 182, + "comment" : "tag change to all 1 expected tag:66405a16e8b44eba92aa47f5cea52b7a", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b", + "aad" : "000102", + "msg" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20", + "ct" : "d03bcb3ca52d48d1d203b1e7b1a5995af1a0466a61bb386a2e12d189a2c4ea15e9", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "invalid", + "flags" : [] + }, + { + "tcId" : 183, + "comment" : "edge case for poly1305 key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "dc8ce708bf26aab862d97e1b42f31ef38c382cf07174142ea564920612997b1c2e38aca2438b588d5459493e97e7fa330ff9bc3b9458297ba0967d86ed090b435103478f2869b93ee29c837e95fb6b9903f3b735b7345428eb93b3db1d9b5187cebb889aa177d83e4f63fc9a5c0596eed939883d06aacdfdea44fdecdf5cb7fc", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "c296436246c3a7c4b3ba09ab2a6a0889", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 184, + "comment" : "edge case for poly1305 key:278de313ffffffdfffe9acbf3ea59357c4e16a5bc120d346af4a8cf694a84374", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "0001020304050607051e9373", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "931227274a89d0b3aade7fac62c96262c1e77b8dafd248f10ad37c6ccb69cb7131b041593c8bb8c3db38f39dd8a124c424fce4389dede1d3cb9d46cf95970aea9856b6e313d756197baf4fcb58df275bca8a2188f9e8a1ad04354ede542ddc30e8b735b2f5905f5811799282be94ae842ec126c55d2e667235e9acf1d48798f0", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "99a3b0fff6fdcbcce9dc5820f2a64861", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 185, + "comment" : "edge case for poly1305 key:0050799fe9e74fcffcffffcfd21aa8b5cb5aa2c6ab347b6886eedaca4bfff3c0", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "0001020304050607048c3c5f", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "0df91f31230e8941e700a752fef08c897c511ed618fdf8a378a1f439013b40a48d4634c27d9ada7c0bb6f3fa92e341425903d7ecd0c49bee4c77e84b11f1c721922308642885b813fae364da32eaf120d6a43a74fb1632443667bfea6eef1be73eb1c3c0b5a57cee8dc4feed4a1fb9ae02f7b1695588c3c878451cb6ee0cb3dc", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "eaff8f47ef9268fd0d94e8a9c4b78d24", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 186, + "comment" : "edge case for poly1305 key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "1fde9b9ec8b247d42bbee2016d6715ba428a85431430eada56a2c5dc944b6aa6cef0b056a2eecc51d30838e640615e1458e0943e30f91ba41b4362fa9ed6037b21d14da7b4f76f9f68fa8903138d563ce2590af1201c7cfec2290cfce98a822ebb8d1ed9dc4e20d241755aff91cdfd10fdb69efa0d5c8082692601cbfbb955c7", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "86ed21fda080a7d13981078d86b3e3cd", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 187, + "comment" : "edge case for poly1305 key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "66115e67ecd3d4178c4c60e713ab4e5e66f8d1f971da17437a2b5e04fbca1671e847139a5f4e3f8e92d7a3b71eb4ff0e50354c0c1580af3662d5f8151e3f7e8264a0085c32ddfcbeb01a8be4c34d53319800ac4ef9d4e4014524bc7cd3387242e774f4d1a7a0521e42ec44844d0bd8b9d73fec959212fd7e8eacf4d984996d9b", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "34f9e0faa515eee0e784e6ef2678befa", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 188, + "comment" : "edge case for poly1305 key:0000003059ffce96438a246ff9536787d92bc40eafa0241a2972780ef6ca1ef8", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060726c6961b", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "e97244259af5a379238da0cad2a5f493655ec0e5024fd553bbb3deb66a94036d106c3d513407b2dd1cc5936c4c9c1e4f4b37b54dec261c601dc99e90680e23e2dc5c9a8d503d8bea49a8cdca3706bfd2a3daa0afb19a70fd3d355fc37c13f3f9e5c8d0864a5f80a780b36d4698ec2ce9ccc27b97ecbe672e41628ebd773acb81", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "3c94b9fe60bdb35c6b7b73b765083492", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 189, + "comment" : "edge case for poly1305 key:3fa0ea9c030000a036217d42e775ad189b96e24ee591952e2922ff151334b9ec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "0001020304050607013da060", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "9453aa159c3d87f17e21e88adabc37e553b904d00eefc66b8e0905e23576fbdc9c7bea9777f3b8368481932534b3344d309e6307cddfe7b3549300dd9cda7efe9d43c8a115912a392904079ee92bcd33099f7022ea94c1e7353b89bfc54de3ceb56f529a1a608bb5a970e1359609d1f56806b37f8605f4c27451da6066fc557a", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "2b11cf9f8db8490d409fc62afd7379f3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 190, + "comment" : "edge case for poly1305 key:a556cb502baf395b020000f03c5108fb1cf76df1b8a8f724e877bd3c588d3285", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060707db33de", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "2e1836640d810c2709fb83ccf1aef3a971085d1bbfb58a425abf75ccec70b3abde0e80539e83a82546e7372a19481547053308dd7842675e9c4f61302426da0d71c1da3102031030ed928152be009b15b52f71b5911991d39f68a8658d99729df2bbef31c8989f9604558df9f2aba4b3766c58aaef3548de545ec1f080225a88", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "c9c8366920f88381407712cec61e6607", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 191, + "comment" : "edge case for poly1305 key:0c327fbcc564555545d4fe75020000d0a65799f363ec51b1c5c427b4a04af190", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060702a11942", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "0ecb4d85c956b5268c9b35a8c63b4e9d3e5cb72b64ef98773841b947bd7d59ef7d0eb0e1c050d49a5424ce7deb527d76087e4746674c958965df32d9e5fb03b46501706128d481217aaeae2f78f9259273358a2954cac0bc2fbfe77447d1d387b9314c6541b69f1270b3438b1042b2b4663e62ba4d49c07ac6f163034afa80af", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "2373cfa2ab24446ad5a236167b8027fe", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 192, + "comment" : "edge case for poly1305 key:415f08302f210340240d0e903e2b01205ba43e106aebd7e2481016b31118b1ae", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506073c0df637", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "2e8e45e903bfab32f2f0d49d9a3e449bef6f4093e2722cdab2cf935c1822b830fb5a4056516d560dfc8638c9a57d2927200a56f0b67153271d498e8f08dc888c61ef634f7ae40f4608f96f92fea5a1e5bd45131120098dc5de0378e58f2ddb46fa4aa5adb38fe006bb19b69146382f77a79e06214def547cfb5ce37a7008b9b6", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "5f93946478d8081e7247f414ad39a515", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 193, + "comment" : "edge case for poly1305 key:feffff1ff6b87403fd6435b09775bc92491a0ae62c5842a30e3b82710cc2dad1", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "00000000101112130bc672c3", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "3619cb470af86dceceb6940f2d9abb34c9a9131476053387445ffebbe240d4f9818377855652f46a8219c7f71c3554f8acef8258de4b7d17c0f3d353ac981cc6a13287be1e6b41dc6d133df4ababebdf43d665ce7a4a5c982a0b139cb8202eebc74173e3224a440e4c37d2b595f384290e939ba016df0d49b36cdb4bd91c39", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "133fe62391744d11ce44594b96c53baf", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 194, + "comment" : "edge case for poly1305 key:bf358f18ffffffbf4b62ed6e1f53790785c4dabdfc72e2a219d377a682c85f38", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "000000001011121303e9b9a4", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "af205bda819f7451be0f28667d4b01b59ff2daa8173cab52046c3c9e0d989889c5e021ef7afd06e9ce6cc30e3a6ebab509134ba10d10e570c55587c13eee53e73be54804c8539ffbf23b35922b1ca37b9e9bc24ee204837ca5a294ce05d12600c7eff6aee32270db2feff47dc5a04176169e15850628e6035f78994f9f5603", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "e3451adb9d23a7710a1aafba26f56387", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 195, + "comment" : "edge case for poly1305 key:d0b7b3a352a4010ffeffffbfe8cc66dc6e5e7451dc61762c5753174fed88e746", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "00000000101112130700b982", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "68c67272036fb652a0182eeb4781358e4704a4a702fd731bf3b3ea994717989e7d9104e0ae81732a8c7e9a82b3d31d541761a366b67c3396f1a6c67e293ddb65a59e42541dda144dc6c78388cfca982e23350958ac5b3d54a1722fd64733577862e1879c9e9445ebdec5315d1706db7ebbedd4c779935e72057e5b0ecde081", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "b0bb8a55ff5f52a5043c6e7795847557", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 196, + "comment" : "edge case for poly1305 key:7bee33931a4157a8cb701becfeffff4fbe7e69f19cd065313bb49a252628dd3d", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "0000000010111213019836bb", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "c483b7334ebe2e879b0c3f9db4fcd9f5219062360d6ce44cdae0f94e04c8345ea7e3ae33855118741dcafe0de4ae98c4e43af7b12b04ee8ab175625823ac040e5abac4403f1d45238adcb8c0cf44bd56917f9f5d93974c82b56951986a9c0450bd9047b5a616e814526ad0580e3ecd8189c9fef2cdb979a22ad3a01930fbd1", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "f4fc25f4c5543a9afee9819e2904fb68", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 197, + "comment" : "edge case for poly1305 key:7cb5fbdffb40ff5f3c7de74f655ffc1fac03013a7fe468440b861ebe0ab1650a", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "00000000101112131d59f288", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "bc7f4f15fd1e4c1399740836670abe39a05707be19956ce169b32321759e0f213ae19ad34aa612b3a29f02c4bbac9f785a55a3adfe419ab891bbe0acee9921322ea21002c9dd3dcdd13a7f8554dddc10f9b529ce94be7050937dab76557b7eb17c685aad8f0797e39d62553988989aab1d9764fe431cc1d4c595062ce93ce9", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "5e67a7b8733e0e4b01ac2178a205ae7e", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 198, + "comment" : "edge case for poly1305 key:00000090e6e328c242cde5c83e3d8262d467f2bcd53d3755c781f3c6a2cb0648", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "00000000101112130552a411", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "eaccaa778935ef249e0900149dd889462d2a061486ba102b8caebe465f3959fb3119ebb5689676ffdd6d851a26739e772b54a2f5f473ea9c7e58ccbc4cfc953e8c420b2175d9dd519265630bb79bd87a601b113231a8b16ce54c331347ec04c2b1c9160f38207aa46e96feb06dee883eb422fa14908df300bb1a1ef758c408", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "177a77fce114a4349c4f8d5ec825d06f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 199, + "comment" : "edge case for poly1305 key:9e98d64e000000505a07183c5c68c63c14c9266dd37ff86aafc22ddbdb355617", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "00000000101112130c807a72", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "a76c330e015060a17e64cb7b6d753f201f75be8759fd7539fb92b22aef54c9d3029dba0c15cbf7c95135888319c6b2e6276da21e0c351fd522b29aabb5883a3291d6f427de773b124390ef6fd96621ffbc42dfbf7a34da272cbc9ccb1a498d078033d1ac3bf7e92715948b06d69d5c5039e9164ba9c3a02219ec5908206b3b", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "623c7d4424f5497aedfd1339cf8cecce", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 200, + "comment" : "edge case for poly1305 key:1048a92e65f5e63102000080d9ae08de4319a7c45fdbe707b9ec1b7e0d635161", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "00000000101112130397a143", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "228a7e15bcce13051de9145f77f7f4ff7921828b4f99efc4ff55ee0d9344955b69ec2d4798b0517f0273c4456ae5ffc5929cbe74ddb0da51d4f2b4df7578a31240c88ae922c3c5eca7b97d72d497062050a587447c562b343d5c71921944872f9fd06b8f34b3eb5d4341f5ff8a907dd7c2e1676b81252726ba54814da51eab", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "1c18b69354b189731a1a83fe8f0d57c9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 201, + "comment" : "edge case for poly1305 key:01517a2ceb89bbfb5741f7d9000000401a65b132ad661072a00ffe7defbb18a5", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "000000001011121308cb0f3f", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "c7d843188ab193dfef5c4daf583f952cd4b195f240fa2e704d021723023c123371a41e87dfc6e6c3874a42f331cf035988a38c72ba2da854b1208f98bf8cc29948169481ab3a402d5fcc7ff78f9e31925576dc3938074b8c5b27960e3afc750ad686563688b7441787288d5256c1301d563b7744843bd1ab4eff5be6f1653d", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "2045815b8211b9a2995effe0b8ed9868", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 202, + "comment" : "edge case for poly1305 key:bc90156087e0125006d90c30babd0590427bff19de1f2e7d0757a79528731138", + "key" : "9de836aa579585081f330a7c4036e20e38ef15eff3945184d231867f505fffdf", + "iv" : "00000000101112130d8fcf4e", + "aad" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "msg" : "cfc3db8631c81c69023a3c8a9ad66c35053685144c4fa2a9510add72e211dad9ca5b982e4c194591fdb74116280311d1299ad81227258cb52f079bbcb12aff161d278dec33a326d71276b3de01a8327ee7f45f94179dff18a3fe643e56c30cfd03871c8110ab00f6612b9e17a4647360d7847bb63a3122613c2e7cdddd08ae", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "1ae2ed84ea9774d78d782bf8d972a8b8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 203, + "comment" : "edge case for tag", + "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffffffffffffffffffffffffffffff415771fda4fbcc55c377f73203e60226", + "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "000102030405060708090a0b0c0d0e0f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 204, + "comment" : "edge case for tag", + "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "iv" : "000102030405060708090a0b", + "aad" : "f1ffffffffffffffffffffffffffffff615af39eddb5fcd2519190d5507d3b06", + "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "00000000000000000000000000000000", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 205, + "comment" : "edge case for tag", + "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "iv" : "000102030405060708090a0b", + "aad" : "b5ffffffffffffffffffffffffffffff764e5d82ce7da0d44148484fd96a6107", + "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "ffffffffffffffffffffffffffffffff", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 206, + "comment" : "edge case for tag", + "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "iv" : "000102030405060708090a0b", + "aad" : "fdffffffffffffffffffffffffffffff2bdbf16d8ea4d39dab8dcb3d4bc4e104", + "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "00000080000000800000008000000080", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 207, + "comment" : "edge case for tag", + "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "iv" : "000102030405060708090a0b", + "aad" : "a9ffffffffffffffffffffffffffffffaccd5eb31d8fc909e84b0de7de23bb08", + "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "ffffff7fffffff7fffffff7fffffff7f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 208, + "comment" : "edge case for tag", + "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "iv" : "000102030405060708090a0b", + "aad" : "d2ffffffffffffffffffffffffffffffdd4b933e7b1a7ed93cc7c050db71dc03", + "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "01000000010000000100000001000000", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 209, + "comment" : "edge case for tag", + "key" : "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f", + "iv" : "000102030405060708090a0b", + "aad" : "ffffffffffffffffffffffffffffffffa08164425d7642e9e90fc8d5c32d2cf6", + "msg" : "e48caf8a76183327c9561a4651c07c822ccd1642c06607d0d4bc0afb4de15915dbfa3b0b422e77e15c64bf6247031f15fdb643117809821870000adf83834da5", + "ct" : "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", + "tag" : "ffffffff000000000000000000000000", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 210, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "c68ce708bf26aab862d97e1b42f31ef37bb66f8090c149e452ec7f20327eb2ea2e38aca2438b588d5459493e97e7fa330ff9bc23c897df6b00af86931d6c81555103478f2869b93ee29c837e95fb6b9903f3b72debfba2384baa48ceedfedb91", + "ct" : "e5ffffffffffffffffffffffffffffff0871bc8f1e4aa235087712d9df183609ffffffffffffffffffffffffffffffffffffffe7a33009ef5fc604ea0f9a75e9ffffffffffffffffffffffffffffffffffffffe7a33009ef5fc604ea0f9a75e9", + "tag" : "3572162777262c518eef573b720e8e64", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 211, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "c78ce708bf26aab862d97e1b42f31ef376209eef141691fba5d10eaf581affe62e38aca2438b588d5459493e97e7fa330e73d2dc3bbd954989cb8433b7d6597b5103478f2869b93ee29c837e95fb6b990279d9d218d1e81ac2ce4a6e474403bf", + "ct" : "e4ffffffffffffffffffffffffffffff05e74de09a9d7a2aff4a6356b57c7b05fffffffffffffffffffffffffffffffffe759118501a43cdd6a2064aa520adc7fffffffffffffffffffffffffffffffffe759118501a43cdd6a2064aa520adc7", + "tag" : "347216375f5b7b5c4e6bff4912fd9473", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 212, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "fc8ce708bf26aab862d97e1b42f31ef38b79403dfaabc0d8c18d23a3469c13e62e38aca2438b588d5459493e97e7fa330a4b941e6b66fcc2ed7d8cb3e8cc7ffc5103478f2869b93ee29c837e95fb6b9906419f10480a8191a67842ee185e2538", + "ct" : "dffffffffffffffffffffffffffffffff8be933274202b099b164e5aabfa9705fffffffffffffffffffffffffffffffffa4dd7da00c12a46b2140ecafa3a8b40fffffffffffffffffffffffffffffffffa4dd7da00c12a46b2140ecafa3a8b40", + "tag" : "30721677ff2eb8894e5a9d8492b7b0af", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 213, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "fa8ce708bf26aab862d97e1b42f31ef39bcbb8da477d580d772de4229bba7de22938aca2438b588d5459493e97e7fa331e9dedf9dd64a0681bac2969549425bc5603478f2869b93ee29c837e95fb6b991297e6f7fe08dd3b50a9e734a4067f78", + "ct" : "d9ffffffffffffffffffffffffffffffe80c6bd5c9f6b3dc2db689db76dcf901f8ffffffffffffffffffffffffffffffee9bae3db6c376ec44c5ab104662d100f8ffffffffffffffffffffffffffffffee9bae3db6c376ec44c5ab104662d100", + "tag" : "2b7216c7873744c20ec5e2cdb260d3fa", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 214, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "ee8ce708bf26aab862d97e1b42f31ef3b9f55bd56e0fd74b46063a96354cfbee3238aca2438b588d5459493e97e7fa3320c78886a6f6292d6cc5fbddb546a2b04d03478f2869b93ee29c837e95fb6b992ccd8388859a547e27c0358045d4f874", + "ct" : "cdffffffffffffffffffffffffffffffca3288dae0843c9a1c9d576fd82a7f0de3ffffffffffffffffffffffffffffffd0c1cb42cd51ffa933ac79a4a7b0560ce3ffffffffffffffffffffffffffffffd0c1cb42cd51ffa933ac79a4a7b0560c", + "tag" : "22721657b0130d28cf1ec65153c41182", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 215, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "ef8ce708bf26aab862d97e1b42f31ef3b46fca24d353ff5e49eac51540e840ea3038aca2438b588d5459493e97e7fa333d311e572202011a75e948586fe268b44f03478f2869b93ee29c837e95fb6b99313b1559016e7c493eec86059f703270", + "ct" : "ccffffffffffffffffffffffffffffffc7a8192b5dd8148f1371a8ecad8ec409e1ffffffffffffffffffffffffffffffcd375d9349a5d79e2a80ca217d149c08e1ffffffffffffffffffffffffffffffcd375d9349a5d79e2a80ca217d149c08", + "tag" : "2172166798485c338f9a6d60f3b21891", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 216, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f59d56151de28bef83505f6d89c0b0f7f75b2fa8e6dce386075db283ec85ee62555baffad423af25f66069bb69fb6f4d", + "ct" : "d6ee4ee25d3bdea81e76de8934cc51fb849cfca7685708575dc6df7a01e36a81849cfca7685708575dc6df7a01e36a81", + "tag" : "831312cbb0f165dc3e8ff52125f48640", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 217, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f717f8d5b28032d5c8e8061cd44d71e4f2d55de772fe7a91ce85e410db3e2d8d50d5ddb5400136323fb83f285e40aca2", + "ct" : "d464e022f259679255ce87f8694190e881128ee8fc759140941e89e93658a96e81128ee8fc759140941e89e93658a96e", + "tag" : "821312db9826b5e7fe0a9d30c5e28d4f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 218, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f28ce708bf26aab862d97e1b42f31ef3e68a922c9219d30f07554d7d99f2bde92c38aca2438b588d5459493e97e7fa33e24c07dd98f9b253ab0c318d9b14f6b15303478f2869b93ee29c837e95fb6b99ee460cd3bb95cf00e009ffd06b86ac75", + "ct" : "d1ffffffffffffffffffffffffffffff954d41231c9238de5dce20847494390afdffffffffffffffffffffffffffffff124a4419f35e64d7f465b3f489e2020dfdffffffffffffffffffffffffffffff124a4419f35e64d7f465b3f489e2020d", + "tag" : "c1045769d487d545cef3f0d34b7a8733", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 219, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "dc8ce708bf26aab862d97e1b42f31ef32e6784d857df07543d0dc72f179935fbede8c8baf01ee2044b162cbb343b355acc29d82327cd93f2bfd918034ed5c42a", + "ct" : "ffffffffffffffffffffffffffffffff5da057d7d954ec856796aad6faffb1183c2f9be74c6a4576e0b09a7a5c2330963c2f9be74c6a4576e0b09a7a5c233096", + "tag" : "64e7efd24516a83e2c87e06a76e2dea3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 220, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f78ce708bf26aab862d97e1b42f31ef34c6ead26f84a0225d557745d32fc72e72c38aca2438b588d5459493e97e7fa3364db334b69bee579383e61ae742c71bb5303478f2869b93ee29c837e95fb6b9968d138454ad2982a733baff384be2b7f", + "ct" : "d4ffffffffffffffffffffffffffffff3fa97e2976c1e9f48fcc19a4df9af604fdffffffffffffffffffffffffffffff94dd708f021933fd6757e3d766da8507fdffffffffffffffffffffffffffffff94dd708f021933fd6757e3d766da8507", + "tag" : "e6cc6729d79ba558cd73b03cba54d660", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 221, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f08ce708bf26aab862d97e1b42f31ef34fd8c3757c9f2938dc3b07d85898bfe22a38aca2438b588d5459493e97e7fa336155412415cbdd760142b62c2ec83fbf5503478f2869b93ee29c837e95fb6b996d5f4a2a36a7a0254a477871de5a657b", + "ct" : "d3ffffffffffffffffffffffffffffff3c1f107af214c2e986a06a21b5fe3b01fbffffffffffffffffffffffffffffff915302e07e6c0bf25e2b34553c3ecb03fbffffffffffffffffffffffffffffff915302e07e6c0bf25e2b34553c3ecb03", + "tag" : "e5cc6739bfd0f4638def574b5a43dd6f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 222, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f28ce708bf26aab862d97e1b42f31ef3df03ca84082f7f70ad8e4004cabd2ce42b38aca2438b588d5459493e97e7fa3328fd413caab1d02bf1c65753aa2ad3b95403478f2869b93ee29c837e95fb6b9924f74a3289ddad78bac3990e5ab8897d", + "ct" : "d1ffffffffffffffffffffffffffffffacc4198b86a494a1f7152dfd27dba807faffffffffffffffffffffffffffffffd8fb02f8c11606afaeafd52ab8dc2705faffffffffffffffffffffffffffffffd8fb02f8c11606afaeafd52ab8dc2705", + "tag" : "0fca702228817d53ee64d142b192e665", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 223, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f38ce708bf26aab862d97e1b42f31ef31ffc31ae69399394b8c338674c3dfde92938aca2438b588d5459493e97e7fa33477ec8cf3ea3d4d5d76d85ad2b7f0bb85603478f2869b93ee29c837e95fb6b994b74c3c11dcfa9869c684bf0dbed517c", + "ct" : "d0ffffffffffffffffffffffffffffff6c3be2a1e7b27845e258559ea15b790af8ffffffffffffffffffffffffffffffb7788b0b55040251880407d43989ff04f8ffffffffffffffffffffffffffffffb7788b0b55040251880407d43989ff04", + "tag" : "efc3b035ded6b460bfce6f494955e677", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 224, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "2bfd0d56ece98771756d60d9d9106cd0c6fc106936c7ef347c078fd71c54228164fc903b0438a3978d3a54ef992aa3ae", + "ct" : "088e15a1ac30d236e84be13d641c8ddcb53bc366b84c04e5269ce22ef132a662b53bc366b84c04e5269ce22ef132a662", + "tag" : "345fc9fe573c136c1be83730500ce662", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 225, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f68ce708bf26aab862d97e1b42f31ef37cc2255decdf8e0fe1373591da0e28e42838aca2438b588d5459493e97e7fa33e291fb4838019c51dfb7141515bb53b15703478f2869b93ee29c837e95fb6b99ee9bf0461b6de10294b2da48e5290975", + "ct" : "d5ffffffffffffffffffffffffffffff0f05f652625465debbac58683768ac07f9ffffffffffffffffffffffffffffff1297b88c53a64ad580de966c074da70df9ffffffffffffffffffffffffffffff1297b88c53a64ad580de966c074da70d", + "tag" : "336f97a5faa995a2a03781b591588da8", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 226, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "c68ce708bf26aab862d97e1b42f31ef37ab66f8090c149e452ec7f20327eb2ea0438aca2438b588d5459493e97e7fa338d2613ea0ef8b656b247373ecec015bc7b03478f2869b93ee29c837e95fb6b99812c18e42d94cb05f942f9633e524f78", + "ct" : "e5ffffffffffffffffffffffffffffff0971bc8f1e4aa235087712d9df183609d5ffffffffffffffffffffffffffffff7d20502e655f60d2ed2eb547dc36e100d5ffffffffffffffffffffffffffffff7d20502e655f60d2ed2eb547dc36e100", + "tag" : "9351c680c8a5d34882d42145e89745c4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 227, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "c68ce708bf26aab862d97e1b42f31ef374b66f8090c149e452ec7f20327eb2ea2e38aca2438b588d5459493e97e7fa33acd9ec859e0866620cc24c8a97d5d9f55103478f2869b93ee29c837e95fb6b99a0d3e78bbd641b3147c782d767478331", + "ct" : "e5ffffffffffffffffffffffffffffff0771bc8f1e4aa235087712d9df183609ffffffffffffffffffffffffffffffff5cdfaf41f5afb0e653abcef385232d49ffffffffffffffffffffffffffffffff5cdfaf41f5afb0e653abcef385232d49", + "tag" : "d79266cd25a784599a0a8e31fc84d604", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 228, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f78ce708bf26aab862d97e1b42f31ef34251cd29b0aaa960557c9ea2828334e4e4e231db0a27fac9ec9e744886eb0133c5232142ddf48b3f185140f0fc05f043", + "ct" : "d4ffffffffffffffffffffffffffffff31961e263e2142b10fe7f35b6fe5b00735256286b6535dbb4738c289eef304ff35256286b6535dbb4738c289eef304ff", + "tag" : "9d671d407d7660459d5d582d83915efe", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 229, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "f58ce708bf26aab862d97e1b42f31ef373bd9f01bf3331b12e31dd14cf11feee1d38aca2438b588d5459493e97e7fa33625c6965f61a1c36118c747076d5b7b76203478f2869b93ee29c837e95fb6b996e56626bd57661655a89ba2d8647ed73", + "ct" : "d6ffffffffffffffffffffffffffffff007a4c0e31b8da6074aab0ed22777a0dccffffffffffffffffffffffffffffff925a2aa19dbdcab24ee5f6096423430bccffffffffffffffffffffffffffffff925a2aa19dbdcab24ee5f6096423430b", + "tag" : "7b207c2c3278c64f0d6b913fe371fe63", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 230, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "dc8ce708bf26aab862d97e1b42f31ef3ec0933f0bfb91218cea0d74e061f559e2d38aca2438b588d5459493e97e7fa338d5b67e0acee534ce2d9791487b1ecb25203478f2869b93ee29c837e95fb6b9981516cee8f822e1fa9dcb7497723b676", + "ct" : "ffffffffffffffffffffffffffffffff9fcee0ff3132f9c9943bbab7eb79d17dfcffffffffffffffffffffffffffffff7d5d2424c74985c8bdb0fb6d9547180efcffffffffffffffffffffffffffffff7d5d2424c74985c8bdb0fb6d9547180e", + "tag" : "3672162bb1f3ff537ece013f1aca4f68", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 231, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "dc8ce708bf26aab862d97e1b42f31ef3ee83a14f48db696291080edfcc898b882b38aca2438b588d5459493e97e7fa338ad5f6b0283a8b39ebedce92785da9b65403478f2869b93ee29c837e95fb6b9986dffdbe0b56f66aa0e800cf88cff372", + "ct" : "ffffffffffffffffffffffffffffffff9d447240c65082b3cb93632621ef0f6bfaffffffffffffffffffffffffffffff7ad3b574439d5dbdb4844ceb6aab5d0afaffffffffffffffffffffffffffffff7ad3b574439d5dbdb4844ceb6aab5d0a", + "tag" : "3572163b99284f5f3e4aa94dbab85677", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 232, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "dc8ce708bf26aab862d97e1b42f31ef3e87dd08ed4e4e04c5877616cbb02cabb2938aca2438b588d5459493e97e7fa33874f0401d457e336f4311f1152f957ba5603478f2869b93ee29c837e95fb6b998b450f0ff73b9e65bf34d14ca26b0d7e", + "ct" : "ffffffffffffffffffffffffffffffff9bba03815a6f0b9d02ec0c9556644e58f8ffffffffffffffffffffffffffffff774947c5bff035b2ab589d68400fa306f8ffffffffffffffffffffffffffffff774947c5bff035b2ab589d68400fa306", + "tag" : "3472164b815d9e6afec5505c5aa75d86", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 233, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "c88ce708bf26aab862d97e1b42f31ef36be436e346f8f2b32f4cbbaef95150ef0438aca2438b588d5459493e97e7fa332fb76b5132e930f6d0acf70875e977b57b03478f2869b93ee29c837e95fb6b9923bd605f11854da59ba93955857b2d71", + "ct" : "ebffffffffffffffffffffffffffffff1823e5ecc873196275d7d6571437d40cd5ffffffffffffffffffffffffffffffdfb12895594ee6728fc57571671f8309d5ffffffffffffffffffffffffffffffdfb12895594ee6728fc57571671f8309", + "tag" : "3a7216d7ee1da018ce8412f251656b19", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 234, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "c58ce708bf26aab862d97e1b42f31ef3783cf9302c7d22914b38aca2e7d374ef1d38aca2438b588d5459493e97e7fa33228f2d23597640d574f8e20c4f6b6bb56203478f2869b93ee29c837e95fb6b992e85262d7a1a3d863ffd2c51bff93171", + "ct" : "e6ffffffffffffffffffffffffffffff0bfb2a3fa2f6c94011a3c15b0ab5f00cccffffffffffffffffffffffffffffffd2896ee732d196512b9160755d9d9f09ccffffffffffffffffffffffffffffffd2896ee732d196512b9160755d9d9f09", + "tag" : "367216178ff1dc45ce73b02cd21f8755", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 235, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "dc8ce708bf26aab862d97e1b42f31ef35db72f89d1402b1a0373ff0a9c5cd44b6d67af40798f5455501792953248ec234ca6bfd9ae5c25a3a4d8a62d48a61d53", + "ct" : "ffffffffffffffffffffffffffffffff2e70fc865fcbc0cb59e892f3713a50a8bca0fc1dc5fbf327fbb124545a50e9efbca0fc1dc5fbf327fbb124545a50e9ef", + "tag" : "0b4961c9525ea2f2cdad6273e1c7824c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 236, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "dc8ce708bf26aab862d97e1b42f31ef35f215ec87d62a264cadb519b4ac90a7668d1dd03e56eda6399ac7803e7dd22114910cd9a32bdab956d634cbb9d33d361", + "ct" : "ffffffffffffffffffffffffffffffff2ce68dc7f3e949b590403c62a7af8e95b9168e5e591a7d11320acec28fc527ddb9168e5e591a7d11320acec28fc527dd", + "tag" : "0a4961d93a93f1fd8d290a8281b6895b", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 237, + "comment" : "edge case intermediate sums in poly1305. poly_key:ffffffefeb344f6bc37ba77ea2ee06dfe8c7f4ae10810422124fc5e1bd7fe301", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060710abb165", + "aad" : "ffffffff", + "msg" : "dc8ce708bf26aab862d97e1b42f31ef3d15ad590dd0f40ba18acd168f6ac777a0f38aca2438b588d5459493e97e7fa33932a097f1d39a04ad30f1b6c650260bf7003478f2869b93ee29c837e95fb6b999f2002713e55dd19980ad53195903a7b", + "ct" : "ffffffffffffffffffffffffffffffffa29d069f5384ab6b4237bc911bcaf399deffffffffffffffffffffffffffffff632c4abb769e76ce8c66991577f49403deffffffffffffffffffffffffffffff632c4abb769e76ce8c66991577f49403", + "tag" : "3572161355240943de9406292a64c551", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 238, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "40115e67ecd3d4178c4c60e713ab4e5e390ef93aeb61aa307f141323c38e0685fa47139a5f4e3f8e92d7a3b71eb4ff0e259445f4ffc31bce540190edd6ad207876a0085c32ddfcbeb01a8be4c34d5331eda1a5b6139750f973f0d4841baa2cb8", + "ct" : "d9ffffffffffffffffffffffffffffffa009d73c6544428cfac0b2d8c7bbef0bedffffffffffffffffffffffffffffff8a5ef60715bc4b07c92b9707376da105edffffffffffffffffffffffffffffff8a5ef60715bc4b07c92b9707376da105", + "tag" : "19532d9fa0b5fbd582aaeda830602f1d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 239, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "49115e67ecd3d4178c4c60e713ab4e5ee02b87aeae8c3da8895f8cb0f6b9cc80f447139a5f4e3f8e92d7a3b71eb4ff0ecc4b7b803a5f8f4647df169080fe567a78a0085c32ddfcbeb01a8be4c34d5331047e9bc2d60bc471602e52f94df95aba", + "ct" : "d0ffffffffffffffffffffffffffffff792ca9a820a9d5140c8b2d4bf28c250ee3ffffffffffffffffffffffffffffff6381c873d020df8fdaf5117a613ed707e3ffffffffffffffffffffffffffffff6381c873d020df8fdaf5117a613ed707", + "tag" : "adbd2cafc8c8f0e51250e7b81c9d0a2d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 240, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "43eadae036f733ea9b5b7eb22aee395db6f51a4d10bc2460810c229651556acf384ad82e3e280cad69f0df25b42b83b0", + "ct" : "da047b7825db1802e8e8e1aac6ba88fc2ff2344b9e99ccdc04d8836d556083412ff2344b9e99ccdc04d8836d55608341", + "tag" : "973e270a7afcab75348e14dbe19c5156", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 241, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "66115e67ecd3d4178c4c60e713ab4e5e891b797521ba925b24090aaf6c4482bae847139a5f4e3f8e92d7a3b71eb4ff0e6d50c32d05a946cb8cea57c9f1442cb164a0085c32ddfcbeb01a8be4c34d5331a565236fe9fd0dfcab1b13a03c432071", + "ct" : "ffffffffffffffffffffffffffffffff101c5773af9f7ae7a1ddab5468716b34ffffffffffffffffffffffffffffffffc29a70deefd6160211c050231084adccffffffffffffffffffffffffffffffffc29a70deefd6160211c050231084adcc", + "tag" : "e17c273f31758e752322ae4869c1bfbb", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 242, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "6a115e67ecd3d4178c4c60e713ab4e5e519cccebf72573dbee8c12f74255d18c0add1035861ffc0b7f40079b969f8c63b2af4fa3ccd16cb38f425c3996140def", + "ct" : "f3ffffffffffffffffffffffffffffffc89be2ed79009b676b58b30c466038021d65fc5026ae3c7a12685bd377d48c921d65fc5026ae3c7a12685bd377d48c92", + "tag" : "a22390224c5db0f01696743d870725c5", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 243, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "e235b8c21384557085c3f2eb2a8fa36058cffd2af743dacf96b4ae4d51b4e488d6703f49d9d7f2027e4853feb4ca0df7", + "ct" : "7bdb195a00a87e98f6706df3c6db12c1c1c8d32c7966327313600fb655810d06c1c8d32c7966327313600fb655810d06", + "tag" : "437d1efad21b0865a541b5cab62e2a44", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 244, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "66115e67ecd3d4178c4c60e713ab4e5e8fab58574a322bac6f394474e4ce7eaec347139a5f4e3f8e92d7a3b71eb4ff0e71532dfb0e9141b00983394722829e7c4fa0085c32ddfcbeb01a8be4c34d5331b966cdb9e2c50a872e727d2eef8592bc", + "ct" : "ffffffffffffffffffffffffffffffff16ac7651c417c310eaede58fe0fb9720d4ffffffffffffffffffffffffffffffde999e08e4ee117994a93eadc3421f01d4ffffffffffffffffffffffffffffffde999e08e4ee117994a93eadc3421f01", + "tag" : "acf4ffa20c0d06d61a18e9a8d4c84d1d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 245, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "61115e67ecd3d4178c4c60e713ab4e5e5efe679ba17384c55eb8cc193666fe8d04608c3503d217aa3f90a9b0e1b3b313bc12d3a3491c8712cf92f212e138329f", + "ct" : "f8ffffffffffffffffffffffffffffffc7f9499d2f566c79db6c6de23253170313d86050a363d7db52b8f5f800f8b3e213d86050a363d7db52b8f5f800f8b3e2", + "tag" : "cd466d06e75b7fd18d5fe21d9227d9a7", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 246, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "9064b88a282052a1ee44df05ad213da679f8d1f971da17437a2b5e04fbca167151b2650ec945fec70588bc65a616a5f24f354c0c1580af3662d5f8151e3f7e82dd557ec8a4d63df7274594367bef09cd", + "ct" : "098a19123b0c79499df7401d41758c07e0ffffffffffffffffffffffffffffff460a896b69f43eb668a0e02d475da503e0ffffffffffffffffffffffffffffff460a896b69f43eb668a0e02d475da503", + "tag" : "ce8a3d4d887d95613d829b538ed01196", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 247, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "43115e67ecd3d4178c4c60e713ab4e5eeef67bd4795b74015a3493905d544a86e847139a5f4e3f8e92d7a3b71eb4ff0e3197be28eff843592bd8fc8d578421d664a0085c32ddfcbeb01a8be4c34d5331f9a25e6a03ac086e0c29b8e49a832d16", + "ct" : "daffffffffffffffffffffffffffffff77f155d2f77e9cbddfe0326b5961a308ffffffffffffffffffffffffffffffff9e5d0ddb05871390b6f2fb67b644a0abffffffffffffffffffffffffffffffff9e5d0ddb05871390b6f2fb67b644a0ab", + "tag" : "08289f5199df476fe90475cb95225566", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 248, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "6b115e67ecd3d4178c4c60e713ab4e5e1e34412ab0a056e809d5d4b92be1128a4b2a651a62aeab26cf437fb195407574f3583a8c28603b9e3f41241395cbf4f8", + "ct" : "f2ffffffffffffffffffffffffffffff87336f2c3e85be548c0175422fd4fb045c92897fc21f6b57a26b23f9740b75855c92897fc21f6b57a26b23f9740b7585", + "tag" : "06df93f651ea5cc56911f30d3e58f997", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 249, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "3fe606108f35869df4c7aa0128464a1265f8d1f971da17437a2b5e04fbca1671fdbe843a0ad9be25055992ab6dcbc9f153354c0c1580af3662d5f8151e3f7e8271599ffc674a7d152794baf8b03265ce", + "ct" : "a608a7889c19ad7587743519c412fbb3fcffffffffffffffffffffffffffffffea06685faa687e546871cee38c80c900fcffffffffffffffffffffffffffffffea06685faa687e546871cee38c80c900", + "tag" : "9264fc0f47febb30661254daf9a06189", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 250, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "6e8eb98cf7fffe4cd683568cf892991564f8d1f971da17437a2b5e04fbca1671c70f5d8b30c64bf2e6d1d613f40e0bf052354c0c1580af3662d5f8151e3f7e824be8464d5d5588c2c41cfe4029f7a7cf", + "ct" : "f7601814e4d3d5a4a530c99414c628b4fdffffffffffffffffffffffffffffffd0b7b1ee90778b838bf98a5b15450b01fdffffffffffffffffffffffffffffffd0b7b1ee90778b838bf98a5b15450b01", + "tag" : "69a124fc7f96e220d1a031ced5527279", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 251, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "4f115e67ecd3d4178c4c60e713ab4e5e4156269fe3da101eeb0abf8dda20fe8fff47139a5f4e3f8e92d7a3b71eb4ff0e6aece983e64f97e43ff5295bc884fa7773a0085c32ddfcbeb01a8be4c34d5331a2d909c10a1bdcd318046d320583f6b7", + "ct" : "d6ffffffffffffffffffffffffffffffd85108996dfff8a26ede1e76de151701e8ffffffffffffffffffffffffffffffc5265a700c30c72da2df2eb129447b0ae8ffffffffffffffffffffffffffffffc5265a700c30c72da2df2eb129447b0a", + "tag" : "3ea8f9b2012321e63d5fb5bc2c5d332d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 252, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "66115e67ecd3d4178c4c60e713ab4e5e18f125ef374c1454b680e23427e7dc69e447139a5f4e3f8e92d7a3b71eb4ff0e858b08eb1d581570a7cd1e48593b757568a0085c32ddfcbeb01a8be4c34d53314dbee8a9f10c5e47803c5a21943c79b5", + "ct" : "ffffffffffffffffffffffffffffffff81f60be9b969fce8335443cf23d235e7f3ffffffffffffffffffffffffffffff2a41bb18f72745b93ae719a2b8fbf408f3ffffffffffffffffffffffffffffff2a41bb18f72745b93ae719a2b8fbf408", + "tag" : "dfaf8a3a15d45e7f4c3430048d8589f0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 253, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "b02ab747a310d6a3bbdb97018a3be8b341f8d1f971da17437a2b5e04fbca1671b7a338bc3423895f0fd96cdb27a787f277354c0c1580af3662d5f8151e3f7e823b44237a59b04a6f2d144488fa5e2bcd", + "ct" : "29c416dfb03cfd4bc8680819666f5912d8ffffffffffffffffffffffffffffffa01bd4d99492492e62f13093c6ec8703d8ffffffffffffffffffffffffffffffa01bd4d99492492e62f13093c6ec8703", + "tag" : "3408eb2b13a9b76befcedf699422d61f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 254, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "40115e67ecd3d4178c4c60e713ab4e5e380ef93aeb61aa307f141323c38e0685f647139a5f4e3f8e92d7a3b71eb4ff0e3f769a30e8951ff2fb365fa780fdde7e7aa0085c32ddfcbeb01a8be4c34d5331f7437a7204c154c5dcc71bce4dfad2be", + "ct" : "d9ffffffffffffffffffffffffffffffa109d73c6544428cfac0b2d8c7bbef0be1ffffffffffffffffffffffffffffff90bc29c302ea4f3b661c584d613d5f03e1ffffffffffffffffffffffffffffff90bc29c302ea4f3b661c584d613d5f03", + "tag" : "09f4f2a3936d7461a67ce022176bb8dd", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 255, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "40115e67ecd3d4178c4c60e713ab4e5e060ef93aeb61aa307f141323c38e0685ee47139a5f4e3f8e92d7a3b71eb4ff0e2bca70bfcdf1171ab611d12bed5d627a62a0085c32ddfcbeb01a8be4c34d5331e3ff90fd21a55c2d91e09542205a6eba", + "ct" : "d9ffffffffffffffffffffffffffffff9f09d73c6544428cfac0b2d8c7bbef0bf9ffffffffffffffffffffffffffffff8400c34c278e47d32b3bd6c10c9de307f9ffffffffffffffffffffffffffffff8400c34c278e47d32b3bd6c10c9de307", + "tag" : "2eb2679aadfd824a5fd8fa2e4a55a65c", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 256, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "56115e67ecd3d4178c4c60e713ab4e5e6c7e1312c6774fae7d1e5d0cc609028ff547139a5f4e3f8e92d7a3b71eb4ff0e81c9e61cbeeed5546b1ce5d8fef21a7a79a0085c32ddfcbeb01a8be4c34d533149fc065e52ba9e634ceda1b133f516ba", + "ct" : "cffffffffffffffffffffffffffffffff5793d144852a712f8cafcf7c23ceb01e2ffffffffffffffffffffffffffffff2e0355ef5491859df636e2321f329b07e2ffffffffffffffffffffffffffffff2e0355ef5491859df636e2321f329b07", + "tag" : "5e89349f6b011cd6e24ee6ac2f590c21", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 257, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "2ea8410b4dca8c9d5369a033d8db61e46cf8d1f971da17437a2b5e04fbca1671f0f58e8bba6cf1a52146273d8fe0c4fc5a354c0c1580af3662d5f8151e3f7e827c12954dd7ff3295038b0f6e521968c3", + "ct" : "b746e0935ee6a77520da3f2b348fd045f5ffffffffffffffffffffffffffffffe74d62ee1add31d44c6e7b756eabc40df5ffffffffffffffffffffffffffffffe74d62ee1add31d44c6e7b756eabc40d", + "tag" : "b24537fcb0dcb6200b0285cafc9c3a7d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 258, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "17059a7c8883a28b90bd94ae44d1543662f8d1f971da17437a2b5e04fbca1671a23018bf8e68e413e99ac2d4ab3f8df154354c0c1580af3662d5f8151e3f7e822ed70379e3fb2723cb57ea8776c621ce", + "ct" : "8eeb3be49baf8963e30e0bb6a885e597fbffffffffffffffffffffffffffffffb588f4da2ed9246284b29e9c4a748d00fbffffffffffffffffffffffffffffffb588f4da2ed9246284b29e9c4a748d00", + "tag" : "43300400ea36e720361153ce0c5d637d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 259, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "aaa1b258fd4b54b497b520806a66d7aa68f8d1f971da17437a2b5e04fbca167199132a234a8c789bf8544547940ec3f35e354c0c1580af3662d5f8151e3f7e8215f431e5271fbbabda996d1449f76fcc", + "ct" : "334f13c0ee677f5ce406bf988632660bf1ffffffffffffffffffffffffffffff8eabc646ea3db8ea957c190f7545c302f1ffffffffffffffffffffffffffffff8eabc646ea3db8ea957c190f7545c302", + "tag" : "d79a0310124adc30c6b64cdef8993e8d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 260, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "4c115e67ecd3d4178c4c60e713ab4e5ebb5357ed314ad740b9910fad6f01d781f047139a5f4e3f8e92d7a3b71eb4ff0ec8042b414fdd1bba3a6c936b7ed678797ca0085c32ddfcbeb01a8be4c34d53310031cb03a389508d1d9dd702b3d174b9", + "ct" : "d5ffffffffffffffffffffffffffffff225479ebbf6f3ffc3c45ae566b343e0fe7ffffffffffffffffffffffffffffff67ce98b2a5a24b73a74694819f16f904e7ffffffffffffffffffffffffffffff67ce98b2a5a24b73a74694819f16f904", + "tag" : "e6022cc3ba20e3f9065fdfcc43a9dc40", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 261, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "66115e67ecd3d4178c4c60e713ab4e5ef64296975af7fced168181f76c6508e1c947139a5f4e3f8e92d7a3b71eb4ff0e4975060f7ddef4a098699333b30fbf7c45a0085c32ddfcbeb01a8be4c34d53318140e64d918abf97bf98d75a7e08b3bc", + "ct" : "ffffffffffffffffffffffffffffffff6f45b891d4d214519355200c6850e16fdeffffffffffffffffffffffffffffffe6bfb5fc97a1a469054394d952cf3e01deffffffffffffffffffffffffffffffe6bfb5fc97a1a469054394d952cf3e01", + "tag" : "353e304fd8553286b26e0d59942fe7cd", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 262, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "9841cfc927a57dc491ab35427ff935e66ef8d1f971da17437a2b5e04fbca1671a683c8f9f9e6780fda4940ddedd76bf258354c0c1580af3662d5f8151e3f7e822a64d33f9475bb3ff884688e302ec7cd", + "ct" : "01af6e513489562ce218aa5a93ad8447f7ffffffffffffffffffffffffffffffb13b249c5957b87eb7611c950c9c6b03f7ffffffffffffffffffffffffffffffb13b249c5957b87eb7611c950c9c6b03", + "tag" : "0aeb04ecf7def40c42025bbae5509169", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 263, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "42115e67ecd3d4178c4c60e713ab4e5e0b61bf9b7caf83cc34da625593514289e847139a5f4e3f8e92d7a3b71eb4ff0e696a5c7fb9da9cd4a39c8591086db42d64a0085c32ddfcbeb01a8be4c34d5331a15fbc3d558ed7e3846dc1f8c56ab8ed", + "ct" : "dbffffffffffffffffffffffffffffff9266919df28a6b70b10ec3ae9764ab07ffffffffffffffffffffffffffffffffc6a0ef8c53a5cc1d3eb6827be9ad3550ffffffffffffffffffffffffffffffffc6a0ef8c53a5cc1d3eb6827be9ad3550", + "tag" : "8fc4f77a6ee052a4c314780b8df9a2d0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 264, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "4b115e67ecd3d4178c4c60e713ab4e5ef28e4d0f20ca1644470c9cdac6000887ed47139a5f4e3f8e92d7a3b71eb4ff0e1464775bacd5c69fe26e1a74968ea27e61a0085c32ddfcbeb01a8be4c34d5331dc51971940818da8c59f5e1d5b89aebe", + "ct" : "d2ffffffffffffffffffffffffffffff6b896309aeeffef8c2d83d21c235e109faffffffffffffffffffffffffffffffbbaec4a846aa96567f441d9e774e2303faffffffffffffffffffffffffffffffbbaec4a846aa96567f441d9e774e2303", + "tag" : "232ff78a96f347b453ba711b79367ee0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 265, + "comment" : "edge case intermediate sums in poly1305. poly_key:946aff9f2a13f56f92a5f9cfee3cdb1fef6d98d5a55ab563cb28620cd57f19d2", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "00010203040506072dd4cd40", + "aad" : "ffffffff", + "msg" : "4d115e67ecd3d4178c4c60e713ab4e5e6ee628fc4b5830184cd293364a213e84fe47139a5f4e3f8e92d7a3b71eb4ff0e29db953ad5458fea61f013ea1854fe7572a0085c32ddfcbeb01a8be4c34d5331e1ee75783911c4dd46015783d553f2b5", + "ct" : "d4fffffffffffffffffffffffffffffff7e106fac57dd8a4c90632cd4e14d70ae9ffffffffffffffffffffffffffffff861126c93f3adf23fcda1400f9947f08e9ffffffffffffffffffffffffffffff861126c93f3adf23fcda1400f9947f08", + "tag" : "e00d2e8bae5d09c28e9bf59409545d09", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 266, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "19de9b9ec8b247d42bbee2016d6715babc286fd979807951b183a188930ad15edcf0b056a2eecc51d30838e640615e14890e659fd3028c904e65018fdfd6038333d14da7b4f76f9f68fa8903138d563c33b7fb50c3e7ebca970f6f89a88a82d6", + "ct" : "f9ffffffffffffffffffffffffffffff015d1565924f6c7418de9babf8be4407edffffffffffffffffffffffffffffff2e110e5e1c0468cbaad99c8abeffff07edffffffffffffffffffffffffffffff2e110e5e1c0468cbaad99c8abeffff07", + "tag" : "47e5d4294239db73b836c04070ff5b2d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 267, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1fde9b9ec8b247d42bbee2016d6715ba839f811ad0310c77052f45320b0d9560c4f0b056a2eecc51d30838e640615e1470d6b14fd209fedf261fd1d250d3478d2bd14da7b4f76f9f68fa8903138d563cca6f2f80c2ec9985ff75bfd4278fc6d8", + "ct" : "ffffffffffffffffffffffffffffffff3eeafba63bfe1952ac727f1160b90039f5ffffffffffffffffffffffffffffffd7c9da8e1d0f1a84c2a34cd731fabb09f5ffffffffffffffffffffffffffffffd7c9da8e1d0f1a84c2a34cd731fabb09", + "tag" : "232c882f7a1a2f808ccf26496cff5b3d", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 268, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "97311cd6e2d25a7b4eaa16f0a61ca6246b8a85431430eada56a2c5dc944b6aa695136310b6b6b5c17c9f8c02ba7d0aeb71e0943e30f91ba41b4362fa9ed6037b7a329ee1a0af160fc76d3de7e99102c3", + "ct" : "771078b7d59fe2509aeb0b0e34844c61d6ffffffffffffffffffffffffffffffa41c2cb9eba7866f50684b1b05e3ab00d6ffffffffffffffffffffffffffffffa41c2cb9eba7866f50684b1b05e3ab00", + "tag" : "d71bc70d5adc74e7dfd89406fc15f044", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 269, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "34de9b9ec8b247d42bbee2016d6715ba74cf7e9d82b7e8ed9ec965f6ea310951dc104940e08a4222556828eba459f65a4a006d28729d95d79d2372f77aeeab35", + "ct" : "d4ffffffffffffffffffffffffffffffc9ba04216978fdc837945fd581859c08ed1f06e9bd9b718c799feff21bc757b1ed1f06e9bd9b718c799feff21bc757b1", + "tag" : "21e63987d494673f3040ae9de2bc0da0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 270, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "e72b83514e5e50509070359c1cac7e1c428a85431430eada56a2c5dc944b6aa6dad35950d8a9b55a472f9bb8860a526358e0943e30f91ba41b4362fa9ed6037b35f2a4a1ceb01694fcdd2a5dd5e65a4b", + "ct" : "070ae7307913e87b443128628e349459ffffffffffffffffffffffffffffffffebdc16f985b886f46bd85ca13994f388ffffffffffffffffffffffffffffffffebdc16f985b886f46bd85ca13994f388", + "tag" : "e4fb945d6a2d0b947834317cc415f024", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 271, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "8c6165f445443588041b6e044fb6baae728a85431430eada56a2c5dc944b6aa6881a54c09516a1f1cae7b9dd71130ee168e0943e30f91ba41b4362fa9ed6037b673ba931830f023f7115083822ff06c9", + "ct" : "6c40019572098da3d05a73fadd2e50ebcfffffffffffffffffffffffffffffffb9151b69c807925fe6107ec4ce8daf0acfffffffffffffffffffffffffffffffb9151b69c807925fe6107ec4ce8daf0a", + "tag" : "c0424863a20e5fa04ccd9784c015f034", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 272, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "18e36174545fa7ec9ea9f05d7057c5ca638a85431430eada56a2c5dc944b6aa6434e1c5e71005b690ca5cb8d580b89ed79e0943e30f91ba41b4362fa9ed6037bac6fe1af6719f8a7b7577a680be781c5", + "ct" : "f8c2051563121fc74ae8eda3e2cf2f8fdeffffffffffffffffffffffffffffff724153f72c1168c720520c94e7952806deffffffffffffffffffffffffffffff724153f72c1168c720520c94e7952806", + "tag" : "aa7293ffe5db30a31f2581e0e7ae56ed", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 273, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "12de9b9ec8b247d42bbee2016d6715ba54305dff6b61c40b775c352d025c1a56d7f0b056a2eecc51d30838e640615e14bce574e9e11afedbdca021e53bb9188338d14da7b4f76f9f68fa8903138d563c065cea26f1ff998105ca4fe34ce599d6", + "ct" : "f2ffffffffffffffffffffffffffffffe945274380aed12ede010f0e69e88f0fe6ffffffffffffffffffffffffffffff1bfa1f282e1c1a80381cbce05a90e407e6ffffffffffffffffffffffffffffff1bfa1f282e1c1a80381cbce05a90e407", + "tag" : "42e5d43d1e808e79f017144d4498c235", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 274, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1fde9b9ec8b247d42bbee2016d6715badf0599194b0ce890cc1d8eb383b57f38dcf0b056a2eecc51d30838e640615e1435df81077d068077ce805ea592f6f88833d14da7b4f76f9f68fa8903138d563c8f661fc86de3e72d17ea30a3e5aa79dd", + "ct" : "ffffffffffffffffffffffffffffffff6270e3a5a0c3fdb56540b490e801ea61edffffffffffffffffffffffffffffff92c0eac6b200642c2a3cc3a0f3df040cedffffffffffffffffffffffffffffff92c0eac6b200642c2a3cc3a0f3df040c", + "tag" : "6cf2f9230af8679e7ecb19421362fce3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 275, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "39de9b9ec8b247d42bbee2016d6715ba4092e1f9a22c8b18184d805c128ade57c7f0b056a2eecc51d30838e640615e1464fe8b9bdd215a620973affefe93398528d14da7b4f76f9f68fa8903138d563cde471554cdc43d38d019c1f889cfb8d0", + "ct" : "d9fffffffffffffffffffffffffffffffde79b4549e39e3db110ba7f793e4b0ef6ffffffffffffffffffffffffffffffc3e1e05a1227be39edcf32fb9fbac501f6ffffffffffffffffffffffffffffffc3e1e05a1227be39edcf32fb9fbac501", + "tag" : "6d46d2230a9848d518f9d94bb2c49caa", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 276, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "12de9b9ec8b247d42bbee2016d6715ba327f3a1befb4287c17450391ed0eb854d6f0b056a2eecc51d30838e640615e141460d3545c29ddc790711b8e7533698539d14da7b4f76f9f68fa8903138d563caed94d9b4cccba9d491b7588026fe8d0", + "ct" : "f2ffffffffffffffffffffffffffffff8f0a40a7047b3d59be1839b286ba2d0de7ffffffffffffffffffffffffffffffb37fb895932f399c74cd868b141a9501e7ffffffffffffffffffffffffffffffb37fb895932f399c74cd868b141a9501", + "tag" : "74dda12e0558877bc0e40c3eace0af29", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 277, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1bde9b9ec8b247d42bbee2016d6715ba85b67664ee49fa347fbfd2dd92007c57def0b056a2eecc51d30838e640615e14fb27ee075b3c0f0f682babdde63dad8731d14da7b4f76f9f68fa8903138d563c419e70c84bd96855b141c5db91612cd2", + "ct" : "fbffffffffffffffffffffffffffffff38c30cd80586ef11d6e2e8fef9b4e90eefffffffffffffffffffffffffffffff5c3885c6943aeb548c9736d887145103efffffffffffffffffffffffffffffff5c3885c6943aeb548c9736d887145103", + "tag" : "502455343d39db87947d7346a8e0af39", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 278, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "36de9b9ec8b247d42bbee2016d6715ba1132811b2f18321ba99b12432c7f865aa3352cd2d7ac70b4c6f5419767926e20352508ba45bba7410ebe1b8bb925334f", + "ct" : "d6ffffffffffffffffffffffffffffffac47fba7c4d7273e00c6286047cb1303923a637b8abd431aea02868ed80ccfcb923a637b8abd431aea02868ed80ccfcb", + "tag" : "14fba149d1c0edc8aa665851126b5afd", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 279, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1fde9b9ec8b247d42bbee2016d6715baf999461058f6d7733e5cd0d1639d9025cbf0b056a2eecc51d30838e640615e14520a0da50439db00e289e1791342068e24d14da7b4f76f9f68fa8903138d563ce8b3936a14dcbc5a3be38f7f641e87db", + "ct" : "ffffffffffffffffffffffffffffffff44ec3cacb339c2569701eaf20829057cfafffffffffffffffffffffffffffffff5156664cb3f3f5b06357c7c726bfa0afafffffffffffffffffffffffffffffff5156664cb3f3f5b06357c7c726bfa0a", + "tag" : "bf7fbd422cbf0e700fd1605be8fd212f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 280, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "15de9b9ec8b247d42bbee2016d6715bacc1629a40cd11eafdf04138b45afe458eff0b056a2eecc51d30838e640615e14340ac9b45a5896a418a8cee8032e078f00d14da7b4f76f9f68fa8903138d563c8eb3577b4abdf1fec1c2a0ee747286da", + "ct" : "f5ffffffffffffffffffffffffffffff71635318e71e0b8a765929a82e1b7101deffffffffffffffffffffffffffffff9315a275955e72fffc1453ed6207fb0bdeffffffffffffffffffffffffffffff9315a275955e72fffc1453ed6207fb0b", + "tag" : "c6f23204865b0adde0070037d6538dd3", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 281, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "31de9b9ec8b247d42bbee2016d6715baff746ef53ec3357cbc3c3ce4ab1d2d51ed9eb456dc9d9b59f656a5d2d974d26a7b8e903e4e8a4cac3e1dffce07c38f05", + "ct" : "d1ffffffffffffffffffffffffffffff42011449d50c2059156106c7c0a9b808dc91fbff818ca8f7daa162cb66ea7381dc91fbff818ca8f7daa162cb66ea7381", + "tag" : "8cff61b7b3919ed6bde72b36e0d31326", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 282, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "19de9b9ec8b247d42bbee2016d6715babf286fd979807951b183a188930ad15ecef0b056a2eecc51d30838e640615e1464413d71939b9cb0a4d32ef115da9e1021d14da7b4f76f9f68fa8903138d563cdef8a3be837efbea7db940f762861f45", + "ct" : "f9ffffffffffffffffffffffffffffff025d1565924f6c7418de9babf8be4407ffffffffffffffffffffffffffffffffc35e56b05c9d78eb406fb3f474f36294ffffffffffffffffffffffffffffffffc35e56b05c9d78eb406fb3f474f36294", + "tag" : "369cf17011cae47539e2723f010cf980", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 283, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "19de9b9ec8b247d42bbee2016d6715babd286fd979807951b183a188930ad15ee3f0b056a2eecc51d30838e640615e14f25e78fe1b53ae416d1fbc698522618f0cd14da7b4f76f9f68fa8903138d563c48e7e6310bb6c91bb475d26ff27ee0da", + "ct" : "f9ffffffffffffffffffffffffffffff005d1565924f6c7418de9babf8be4407d2ffffffffffffffffffffffffffffff5541133fd4554a1a89a3216ce40b9d0bd2ffffffffffffffffffffffffffffff5541133fd4554a1a89a3216ce40b9d0b", + "tag" : "532eb8e272a8d171378b0d42dff2bed9", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 284, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "32de9b9ec8b247d42bbee2016d6715ba258d5d3e441683f546beba2e23755f5ccef0b056a2eecc51d30838e640615e149d13fdf8fa899836fa5c410d4ccd25ea21d14da7b4f76f9f68fa8903138d563c27aa6337ea6cff6c23362f0b3b91a4bf", + "ct" : "d2ffffffffffffffffffffffffffffff98f82782afd996d0efe3800d48c1ca05ffffffffffffffffffffffffffffffff3a0c9639358f7c6d1ee0dc082de4d96effffffffffffffffffffffffffffffff3a0c9639358f7c6d1ee0dc082de4d96e", + "tag" : "d1be7426cd12446fe52e8d45331e0835", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 285, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1fde9b9ec8b247d42bbee2016d6715bad64add2aa3c5a30a31d9e65e90f93ad1cbf0b056a2eecc51d30838e640615e14de9aeab86144d5464811b2373ba4cc8324d14da7b4f76f9f68fa8903138d563c6423747771a1b21c917bdc314cf84dd6", + "ct" : "ffffffffffffffffffffffffffffffff6b3fa796480ab62f9884dc7dfb4daf88faffffffffffffffffffffffffffffff79858179ae42311dacad2f325a8d3007faffffffffffffffffffffffffffffff79858179ae42311dacad2f325a8d3007", + "tag" : "62630c18de8c10876adb9f30f300963f", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 286, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1fde9b9ec8b247d42bbee2016d6715bacc3492272b8a4b112a4e7d7ccf092692cef0b056a2eecc51d30838e640615e1430ce678e9375b2af0b82c2d2fbd7928c21d14da7b4f76f9f68fa8903138d563c8a77f9418390d5f5d2e8acd48c8b13d9", + "ct" : "ffffffffffffffffffffffffffffffff7141e89bc0455e348313475fa4bdb3cbffffffffffffffffffffffffffffffff97d10c4f5c7356f4ef3e5fd79afe6e08ffffffffffffffffffffffffffffffff97d10c4f5c7356f4ef3e5fd79afe6e08", + "tag" : "feb6412b9031f076eddcd9426fff5b31", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 287, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "34de9b9ec8b247d42bbee2016d6715ba722b6549c9df0f4b04b5f7432203fa54cef0b056a2eecc51d30838e640615e1487de186cd28e43544c73de628fd1d60e21d14da7b4f76f9f68fa8903138d563c3d6786a3c26b240e9519b064f88d575b", + "ct" : "d4ffffffffffffffffffffffffffffffcf5e1ff522101a6eade8cd6049b76f0dffffffffffffffffffffffffffffffff20c173ad1d88a70fa8cf4367eef82a8affffffffffffffffffffffffffffffff20c173ad1d88a70fa8cf4367eef82a8a", + "tag" : "dafdf430c8124483c175404b6bff5b41", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 288, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "3dde9b9ec8b247d42bbee2016d6715bac5629699cfd4d9036cef478ed705be5650f575882c3800f757ea6e0f8c6d47acc6e551e0be2fd7029fa1341352da1ac3", + "ct" : "ddffffffffffffffffffffffffffffff7817ec25241bcc26c5b27dadbcb12b0f61fa3a21712933597b1da91633f3e64761fa3a21712933597b1da91633f3e647", + "tag" : "f8800c5b6283dddfc41f935c01bd0d24", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 289, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1fde9b9ec8b247d42bbee2016d6715ba66d624f288f52941ca24865ce96f0d9736ff33a27c23f4976fc74f1fcd82f5cca0ef17caee342362a78c15031335a8a3", + "ct" : "ffffffffffffffffffffffffffffffffdba35e4e633a3c646379bc7f82db98ce07f07c0b2132c73943308806721c542707f07c0b2132c73943308806721c5427", + "tag" : "38bfb8318c627d86c34bab1f1ebd0db0", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 290, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "f4ebbe3fca96bc4885b35582c43e0eb3588a85431430eada56a2c5dc944b6aa6b4570e8446e886bcbff82a24f49be5ed42e0943e30f91ba41b4362fa9ed6037b5b76f37550f12572040a9bc1a777edc5", + "ct" : "14cada5efddb046351f2487c56a6e4f6e5ffffffffffffffffffffffffffffff8558412d1bf9b512930fed3d4b054406e5ffffffffffffffffffffffffffffff8558412d1bf9b512930fed3d4b054406", + "tag" : "af7293eb09957d9de7432dd41316f0e4", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 291, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1ade9b9ec8b247d42bbee2016d6715ba571a3fca3cda7def4c93d4a382ca3a57eaf0b056a2eecc51d30838e640615e1476cddbee2f185776174f6df3bbe5b38105d14da7b4f76f9f68fa8903138d563ccc7445213ffd302cce2503f5ccb932d4", + "ct" : "faffffffffffffffffffffffffffffffea6f4576d71568cae5ceee80e97eaf0edbffffffffffffffffffffffffffffffd1d2b02fe01eb32df3f3f0f6dacc4f05dbffffffffffffffffffffffffffffffd1d2b02fe01eb32df3f3f0f6dacc4f05", + "tag" : "e178b0d5eb9bc551fa645c49f9f17667", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 292, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "1fde9b9ec8b247d42bbee2016d6715babe31a501536a7c91e4a102cc27cdfe09d2f0b056a2eecc51d30838e640615e14dd9416a12e2f81bdee023d462feef7833dd14da7b4f76f9f68fa8903138d563c672d886e3ecae6e73768534058b276d6", + "ct" : "ffffffffffffffffffffffffffffffff0344dfbdb8a569b44dfc38ef4c796b50e3ffffffffffffffffffffffffffffff7a8b7d60e12965e60abea0434ec70b07e3ffffffffffffffffffffffffffffff7a8b7d60e12965e60abea0434ec70b07", + "tag" : "bdbf63db237d195ecefdc251f5f17677", + "result" : "valid", + "flags" : [] + }, + { + "tcId" : 293, + "comment" : "edge case intermediate sums in poly1305. poly_key:dc46b3c53be153ccd4986678ffffffafe484c316c93f64195da65a2742fd3fec", + "key" : "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f", + "iv" : "000102030405060703e76f6f", + "aad" : "ffffffff", + "msg" : "3ede9b9ec8b247d42bbee2016d6715ba8567a7fde812a3aa2f552a33c1718c58e2f0b056a2eecc51d30838e640615e14bb8729fd148f23b2a916b7f40f2f29810dd14da7b4f76f9f68fa8903138d563c013eb732046a44e8707cd9f27873a8d4", + "ct" : "deffffffffffffffffffffffffffffff3812dd4103ddb68f86081010aac51901d3ffffffffffffffffffffffffffffff1c98423cdb89c7e94daa2af16e06d505d3ffffffffffffffffffffffffffffff1c98423cdb89c7e94daa2af16e06d505", + "tag" : "b4ccb422bc5f7264aff73f3675ff5b19", + "result" : "valid", + "flags" : [] + } + ] + }, + { + "ivSize" : 0, + "keySize" : 256, + "tagSize" : 128, + "type" : "AeadTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.8r12" + }, + "tests" : [ + { + "tcId" : 294, + "comment" : "invalid nonce size", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "", + "aad" : "", + "msg" : "", + "ct" : "", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "ivSize" : 64, + "keySize" : 256, + "tagSize" : 128, + "type" : "AeadTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.8r12" + }, + "tests" : [ + { + "tcId" : 295, + "comment" : "invalid nonce size", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "0001020304050607", + "aad" : "", + "msg" : "", + "ct" : "", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "ivSize" : 88, + "keySize" : 256, + "tagSize" : 128, + "type" : "AeadTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.8r12" + }, + "tests" : [ + { + "tcId" : 296, + "comment" : "invalid nonce size", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a", + "aad" : "", + "msg" : "", + "ct" : "", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "ivSize" : 104, + "keySize" : 256, + "tagSize" : 128, + "type" : "AeadTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.8r12" + }, + "tests" : [ + { + "tcId" : 297, + "comment" : "invalid nonce size", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b0c", + "aad" : "", + "msg" : "", + "ct" : "", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "ivSize" : 112, + "keySize" : 256, + "tagSize" : 128, + "type" : "AeadTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.8r12" + }, + "tests" : [ + { + "tcId" : 298, + "comment" : "invalid nonce size", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b0c0d", + "aad" : "", + "msg" : "", + "ct" : "", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "ivSize" : 128, + "keySize" : 256, + "tagSize" : 128, + "type" : "AeadTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.8r12" + }, + "tests" : [ + { + "tcId" : 299, + "comment" : "invalid nonce size", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b0c0d0e0f", + "aad" : "", + "msg" : "", + "ct" : "", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + }, + { + "ivSize" : 160, + "keySize" : 256, + "tagSize" : 128, + "type" : "AeadTest", + "source" : { + "name" : "google-wycheproof", + "version" : "0.8r12" + }, + "tests" : [ + { + "tcId" : 300, + "comment" : "invalid nonce size", + "key" : "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f", + "iv" : "000102030405060708090a0b0c0d0e0f10111213", + "aad" : "", + "msg" : "", + "ct" : "", + "tag" : "", + "result" : "invalid", + "flags" : [] + } + ] + } + ] +} diff --git a/Unit Tests/Tests/AuthenticatedCiphersCommonTestData.pas b/Unit Tests/Tests/AuthenticatedCiphersCommonTestData.pas new file mode 100644 index 00000000..a76938a9 --- /dev/null +++ b/Unit Tests/Tests/AuthenticatedCiphersCommonTestData.pas @@ -0,0 +1,153 @@ +{***************************************************************************** + The DEC team (see file NOTICE.txt) licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. A copy of this licence is found in the root directory of + this project in the file LICENCE.txt or alternatively at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*****************************************************************************} + +/// +/// Common definitions used by all authenticated cipher modes tests, if possible. +/// The file loading for the individual algorithms has to be implemented in the +/// individual test unit for the algorith, because NIST doesn't use a 100% +/// identical file format for CCM and GCM. +/// +unit AuthenticatedCiphersCommonTestData; + +interface + +uses + Generics.Collections; + +type + /// + /// Test data for one single authenticated cipher test, all in HexL + /// + TSingleAuthenticatedTestData = record + /// + /// Encryption/decryption key + /// + CryptKey : RawByteString; + /// + /// Initialization vecotr + /// + InitVector : RawByteString; + /// + /// Plain Text: text to be encrypted, given in HexL + /// + PT : RawByteString; + /// + /// Additional Authenticated Data: the data which shall be authenticated + /// but not encrypted. + /// + AAD : RawByteString; + /// + /// Cipher Text: encrypted text, given in HexL + /// + CT : RawByteString; + /// + /// Calculated authenticated "tag" value + /// + TagResult : RawByteString; + /// + /// Used additional authenticated data for testing authentication failures. + /// Only filled when present in test data file. + /// + ModifiedAAD: RawByteString; + /// + /// Used ciphertext data for testing authentication failures. + /// Only filled when present in test data file. + /// + ModifiedCT: RawByteString; + + /// + /// Sets all fields and array entries to default values + /// + procedure Clear; + end; + + /// + /// Test data for one single GCM test + /// + TAuthenticatedCipherTestSetEntry = record + /// + /// Length of the encryption/decryption key in bit, determines the + /// algorithm used in case of AES (AES128, AES192, AES256) + /// + Keylen : UInt16; + /// + /// Length of the initialization vector in bit + /// + IVlen : UInt16; + /// + /// Length of the ? in bit + /// + PTlen : UInt16; + /// + /// Length of the ? in bit + /// + AADlen : UInt16; + /// + /// Length of the "tag" resulting from the authentication part in bit + /// + Taglen : UInt16; + + /// + /// The test data files provided contains one test for the meta data + /// specified above. This array holds the test data. + /// + TestData : array of TSingleAuthenticatedTestData; + + /// + /// Sets all fields and array entries to default values + /// + procedure Clear; + end; + + /// + /// List of loaded authentication cipher test vectors + /// + TAuthenticatedTestDataList = TList; + +implementation + +{ TSingleAuthenticatedTestData } + +procedure TSingleAuthenticatedTestData.Clear; +begin + CryptKey := ''; + InitVector := ''; + PT := ''; + AAD := ''; + CT := ''; + TagResult := ''; + ModifiedAAD := ''; + ModifiedCT := ''; +end; + +{ TAuthenticatedCipherTestSetEntry } + +procedure TAuthenticatedCipherTestSetEntry.Clear; +var + i : Integer; +begin + Keylen := 0; + IVlen := 0; + PTlen := 0; + AADlen := 0; + Taglen := 0; + + for i := Low(TestData) to High(TestData) do + TestData[i].Clear; +end; + +end. diff --git a/Unit Tests/Tests/TestDECCRC.pas b/Unit Tests/Tests/TestDECCRC.pas index 94c8da07..5a6c9d41 100644 --- a/Unit Tests/Tests/TestDECCRC.pas +++ b/Unit Tests/Tests/TestDECCRC.pas @@ -1027,7 +1027,7 @@ initialization {$IFDEF DUnitX} TDUnitX.RegisterTestFixture(TestCRC); {$ELSE} - RegisterTest(TestCRC.Suite); + RegisterTest('DEC CRC', TestCRC.Suite); {$ENDIF} end. diff --git a/Unit Tests/Tests/TestDECChaChaPoly1305.pas b/Unit Tests/Tests/TestDECChaChaPoly1305.pas new file mode 100644 index 00000000..f3e7c1dc --- /dev/null +++ b/Unit Tests/Tests/TestDECChaChaPoly1305.pas @@ -0,0 +1,602 @@ +unit TestDECChaChaPoly1305; + +interface + +uses {$IFDEF DUnitX} + DUnitX.TestFramework,DUnitX.DUnitCompatibility, + {$ELSE} + TestFramework, + {$ENDIF} + System.SysUtils, Generics.Collections, System.Math, + DECBaseClass, System.JSON, + DECCipherBase, DECCipherModes, DECCipherFormats, DECCiphers; + + +type +// Testmethods for class TDECCipher + {$IFDEF DUnitX} [TestFixture] {$ENDIF} + TestChaCha20Poly1305 = class(TTestCase) + private + type + TJsonTestCase = record + key : TBytes; + iv : TBytes; + msg : TBytes; + aad : TBytes; + tag : TBytes; + enc : TBytes; + isValid : boolean; + end; + TTestEnumerator = class(TEnumerable) + private + fTests : TList; + protected + function DoGetEnumerator: TEnumerator; override; + public + constructor Create(const aTestFile : string); + destructor Destroy; override; + end; + private + fTests : TTestEnumerator; + + function IterTests : TTestEnumerator; + public + destructor Destroy; override; + published + procedure TestPoly1305; + procedure TestChaCha20_Poly1305_KeySetup; + procedure TestChaCha20_Poly1305_AEAD; + procedure TestChaChaEncodeDecodeSpeed; + + procedure TestXChaCha_Poly1305_AEAD; + // test suite code + procedure TestEncode; + procedure TestDecode; + end; +implementation + +uses DECCipherModesPoly1305, System.Diagnostics, classes, DECFormat, DECTypes, + System.JSON.Readers; + + +// ########################################### +// #### +// ########################################### + +{ TestTDECGCM } +type + THackChaChaCipher = class(TCipher_chacha20); + + +procedure TestChaCha20Poly1305.TestChaCha20_Poly1305_KeySetup; +// test vector of chapter 2.6.2 in RFC 7538 +const cKey : TBytes = [$80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $8a, $8b, $8c, $8d, $8e, $8f, + $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9a, $9b, $9c, $9d, $9e, $9f]; + cNonce : TBytes = [$00, $00, $00, $00, $00, $01, $02, $03, $04, $05, $06, $07]; + + cChaChaMtx : TChaChaMtx = ($8ba0d58a, $cc815f90, $27405081, $7194b24a, + $37b633a8, $a50dfde3, $e2b8db08, $46a6d1fd, + $7da03782, $9183a233, $148ad271, $b46773d1, + $3cc1875a, $8607def1, $ca5c3086, $7085eb87); + + +var chaCha : TCipher_ChaCha20; + cpuMode : TChaChaCpuMode; +begin + for cpuMode in [cmPas, cmSSE, cmAVX] do + begin + TCipher_ChaCha20.CpuMode := cpuMode; + chaCha := TCipher_ChaCha20.Create; + try + chaCha.Mode := cmPoly1305; + chaCha.Init( cKey, cNonce ); + Check( THackChaChaCipher(chaCha).TestChaChaMtx(cChaChaMtx), 'Initialization failed'); + finally + chaCha.Free; + end; + end; +end; + +procedure TestChaCha20Poly1305.TestChaChaEncodeDecodeSpeed; +var startStop : TStopWatch; + encBuf : TBytes; + decBuf_pas, decBuf_SSe, decBuf_AVX, testDecode : TBytes; + i : Integer; + chaCha : TCipher_ChaCha20; + cpuMode : TChaChaCpuMode; + +const cKey : TBytes = [$80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $8a, $8b, $8c, $8d, $8e, $8f, + $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9a, $9b, $9c, $9d, $9e, $9f]; + + cNonce : TBytes = [$07, $00, $00, $00, $40, $43, $41, $43, $44, $45, $46, $47]; + +procedure EncodeBuf( var dest : TBytes ); +var i : integer; +begin + for i := 0 to 3 do + begin + chaCha := TCipher_ChaCha20.Create; + try + chaCha.Mode := cmECBx; + chaCha.Init(cKey, cNonce); + + dest := chaCha.EncodeBytes(encBuf); + finally + chaCha.Free; + end; + end; + +end; + +begin + SetLength(encBuf, 10000000); + + for i := 0 to Length(encBuf) - 1 do + encBuf[i] := Byte(Random(255)); + + + SetLength(decBuf_pas, Length(encBuf)); + SetLength(decBuf_sse, Length(encBuf)); + SetLength(decBuf_avx, Length(encBuf)); + SetLength(testDecode, Length(encBuf)); + + // ########################################### + // #### Perform encryption of all 3 types + // + TCipher_ChaCha20.CpuMode := cmPas; + startStop.Reset; + startStop.Start; + EncodeBuf( decbuf_pas ); + startStop.Stop; + Status( Format( 'Pas Encoding took %dms', [startStop.ElapsedMilliseconds])); + + TCipher_ChaCha20.CpuMode := cmSSE; + startStop.Reset; + startStop.Start; + EncodeBuf( decbuf_sse ); + startStop.Stop; + Status( Format( 'SSE Encoding took %dms', [startStop.ElapsedMilliseconds])); + + TCipher_ChaCha20.CpuMode := cmAVX; + startStop.Reset; + startStop.Start; + EncodeBuf( decbuf_avx ); + startStop.Stop; + Status( Format( 'AVX Encoding took %dms', [startStop.ElapsedMilliseconds])); + + + Check( CompareMem( @decbuf_pas[0], @decBuf_sse[0], Length(decBuf_sse)), 'SSE encoding failed'); + Check( CompareMem( @decbuf_pas[0], @decBuf_sse[0], Length(decBuf_sse)), 'avx encoding failed'); + + + // test decode + for cpuMode in [cmPas, cmSSE, cmAVX] do + begin + TCipher_ChaCha20.CpuMode := cpuMode; + chaCha := TCipher_ChaCha20.Create; + try + chaCha.Mode := cmECBx; + chaCha.Init(cKey, cNonce); + + testDecode := chaCha.DecodeBytes(decbuf_sse); + finally + chaCha.Free; + end; + + Check( CompareMem( @encBuf[0], @testDecode[0], Length(testDecode)), 'Dencoding failed'); + end; +end; + +procedure TestChaCha20Poly1305.TestDecode; +var aTest : TJsonTestCase; + chacha : TCipher_ChaCha20; + decode : TBytes; + isValid : boolean; +begin + isValid := False; // satisfy compiler + for aTest in IterTests do + begin + try + chacha := TCipher_ChaCha20.Create; + try + chacha.DataToAuthenticate := aTest.aad; + chacha.ExpectedAuthenticationResult := aTest.tag; + chaCha.Init( aTest.key, aTest.iv ); + + decode := chaCha.DecodeBytes(aTest.enc); + chaCha.Done; + isValid := True; + finally + chacha.Free; + end; + + Check( Length(decode) = Length(aTest.msg), 'Decoding length test failed'); + if Length(decode) <> 0 then + Check( Comparemem(@decode[0], @aTest.msg[0], Length(decode) ), 'Decoding failed' ); + except + // tests marked as "invalid" (or not "valid") raise an exception + // -> the test does not fail if the result is different to "valid" + on E : EDECException do + begin + isValid := False; + end; + else + raise; + end; + + Check( not (isValid xor aTest.isValid), 'Test failed'); + end; +end; + +procedure TestChaCha20Poly1305.TestEncode; +var aTest : TJsonTestCase; + chacha : TCipher_ChaCha20; + encode : TBytes; + isValid : boolean; +begin + isValid := False; // satisfy compiler + for aTest in IterTests do + begin + try + chacha := TCipher_ChaCha20.Create; + try + chacha.DataToAuthenticate := aTest.aad; + chacha.ExpectedAuthenticationResult := aTest.tag; + chaCha.Init( aTest.key, aTest.iv ); + + encode := chaCha.EncodeBytes(aTest.msg); + chaCha.Done; + isValid := True; + finally + chacha.Free; + end; + + Check( Length(encode) = Length(aTest.enc), 'Decoding length test failed'); + if Length(encode) <> 0 then + Check( Comparemem(@encode[0], @aTest.enc[0], Length(encode) ), 'Encoding failed' ); + except + // tests marked as "invalid" (or not "valid") raise an exception + // -> the test does not fail if the result is different to "valid" + on E : EDECException do + begin + isValid := False; + end; + else + raise; + end; + + Check( not (isValid xor aTest.isValid), 'Test failed'); + end; +end; + +type + THackPly1305 = class(TPoly1305); + +procedure TestChaCha20Poly1305.TestPoly1305; +const// cKey : Array of Byte = [$85, $d6, $be, $78, $57, $55, $6d, $33, $7f, $44, $52, $fe, $42, $d5, $06, $a8, $01, $0, +// $3, $80, $8a, $fb, $0d, $b2, $fd, $4a, $bf, $f6, $af, $41, $49, $f5, $1b ]; + + // original test vector from rfc7539 + cMsg : AnsiString = 'Cryptographic Forum Research Group'; // without trailing #0! + cS : Array of BYte = [$01, $03, $80, $8a, $fb, $0d, $b2, $fd, $4a, $bf, $f6, $af, $41, $49, $f5, $1b]; + cR : Array of Byte = [$85, $d6, $be, $78, $57, $55, $6d, $33, $7f, $44, $52, $fe, $42, $d5, $06, $a8]; + cTag : Array of Byte = [$a8, $06, $1d, $c1, $30, $51, $36, $c6, $c2, $2b, $8b, $af, $0c, $01, $27, $a9]; + +// cKey1 : Array of Byte = [$ec, $07, $4c, $83, $55, $80, $74, $17, $01, $42, $5b, $62, $32, $35, $ad, $d6]; + cR1 : Array of BYte = [$85, $1f, $c4, $0c, $34, $67, $ac, $0b, $e0, $5c, $c2, $04, $04, $f3, $f7, $00]; + cS1 : Array of BYte = [$ec, $07, $4c, $83, $55, $80, $74, $17, $01, $42, $5b, $62, $32, $35, $ad, $d6]; + cMsg1 : Array of Byte = [$f3, $f6]; + cTag1 : Array of BYte = [$88, $C3, $44, $37, $C6, $87, $7A, $3E, $90, $C1, $F8, $08, $58, $C3, $92, $F8]; + +var poly : TPoly1305; + iv : T32ByteArray; + msg : TBytes; + calcTag : TBytes; + // ctx : PPoly1305Ctx; +procedure InvData( data : PByte; len : integer ); +var tmp : byte; + pEnd : PByte; +begin + pEnd := data; + inc(pEnd, len - 1); + while pEnd > data do + begin + tmp := pEnd^; + pEnd^ := data^; + data^ := tmp; + + inc(data); + dec(pEnd); + end; +end; +begin + // test vector from https://datatracker.ietf.org/doc/html/rfc7539.html#page-15 + // RFC 7538 + FillChar(iv[0], Length(iv), 0); + Move( cR1[0], iv[0], Length(cr)); + Move( cS1[0], iv[16], Length(cS1)); + + //InvData( @iv[0], 16); + //invData( @iv[16], 16); + SetLength(msg, length(cMsg1)); + Move(cMsg1[0], msg[0], Length(msg)); + //InvData( @msg[0], Length(msg)); + + poly := TPoly1305.Create; + try + THackPly1305(poly).InitInternal(iv); + THackPly1305(poly).UpdatePoly(@msg[0], Length(msg)); + THackPly1305(poly).Finalize; + + calcTag := poly.CalculatedAuthenticationTag; + finally + poly.Free; + end; + + Check(Length(cTag) = Length(calcTag), 'MAC length is wrong'); + Check( CompareMem(@cTag1[0], @calcTag[0], Length(calcTag)), 'Polynom calculated tag does not match'); + + // ########################################### + // #### second test + FillChar(iv[0], Length(iv), 0); + Move( cR[0], iv[0], Length(cr)); + Move( cS[0], iv[16], Length(cS1)); + + SetLength(msg, length(cMsg)); + Move(cMsg[1], msg[0], Length(msg)); + + poly := TPoly1305.Create; + try + THackPly1305(poly).InitInternal(iv); + THackPly1305(poly).UpdatePoly(@msg[0], Length(msg)); + THackPly1305(poly).Finalize; + + calcTag := poly.CalculatedAuthenticationTag; + finally + poly.Free; + end; + + Check(Length(cTag) = Length(calcTag), 'MAC length is wrong'); + Check( CompareMem(@cTag[0], @calcTag[0], Length(calcTag)), 'Polynom calculated tag does not match'); +end; + + +function TestChaCha20Poly1305.IterTests: TTestEnumerator; +begin + if not Assigned(fTests) then + fTests := TTestEnumerator.Create('..\..\Unit Tests\Data\chacha20_poly1305_test.json'); + + Result := fTests; +end; + +procedure TestChaCha20Poly1305.TestXChaCha_Poly1305_AEAD; +// is actually the same test vector as for chacha20_poly1305 +const cMsg : AnsiString = 'Ladies and Gentlemen of the class of ''99: If I could offer you only one tip for the future, sunscreen would be it.'; + cAAD : TBytes = [$50, $51, $52, $53, $c0, $c1, $c2, $c3, $c4, $c5, $c6, $c7]; + + cKey : TBytes = [$80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $8a, $8b, $8c, $8d, $8e, $8f, + $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9a, $9b, $9c, $9d, $9e, $9f]; + + cNonce : TBytes = [$40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4a, $4b, $4c, $4d, $4e, $4f, $50, $51, $52, $53, $54, $55, $56, $57]; + + cTag : TBytes = [$c0, $87, $59, $24, $c1, $c7, $98, $79, $47, $de, $af, $d8, $78, $0a, $cf, $49]; + + cCipherText : TBytes = [$bd, $6d, $17, $9d, $3e, $83, $d4, $3b, $95, $76, $57, $94, $93, $c0, $e9, $39, + $57, $2a, $17, $00, $25, $2b, $fa, $cc, $be, $d2, $90, $2c, $21, $39, $6c, $bb, + $73, $1c, $7f, $1b, $0b, $4a, $a6, $44, $0b, $f3, $a8, $2f, $4e, $da, $7e, $39, + $ae, $64, $c6, $70, $8c, $54, $c2, $16, $cb, $96, $b7, $2e, $12, $13, $b4, $52, + $2f, $8c, $9b, $a4, $0d, $b5, $d9, $45, $b1, $1b, $69, $b9, $82, $c1, $bb, $9e, + $3f, $3f, $ac, $2b, $c3, $69, $48, $8f, $76, $b2, $38, $35, $65, $d3, $ff, $f9, + $21, $f9, $66, $4c, $97, $63, $7d, $a9, $76, $88, $12, $f6, $15, $c6, $8b, $13, + $b5, $2e ]; +var chaCha : TCipher_XChaCha20; + msg : TBytes; + encr : TBytes; + encrTag : TBytes; + decr : TBytes; + decodeTag : TBytes; + cpuMode : TChaChaCpuMode; +begin + for cpuMode in [cmPas, cmSSE, cmAVX] do + begin + TCipher_XChaCha20.CpuMode := cpuMode; + + SetLength(msg, Length(cMsg)); + Move( cMsg[1], msg[0], Length(msg)); + + + chaCha := TCipher_XChaCha20.Create; + try + chaCha.Mode := cmPoly1305; + chaCha.DataToAuthenticate := cAAD; + chaCha.Init(cKey, cNonce); + encr := chaCha.EncodeBytes(msg); + chaCha.Done; + + encrTag := chaCha.CalculatedAuthenticationResult; + finally + chaCha.Free; + end; + + Check( Length(cCipherText) = Length(encr), 'Encryption length is wrong'); + Check( CompareMem( @cCipherText[0], @encr[0], Length(encr) ), 'Encryption failed'); + + + Check( Length(cTag) = Length(encrTag), 'Tag length is wrong'); + Check( CompareMem( @encrTag[0], @cTag[0], Length(cTag)), 'Calculated Tag is wrong'); + + // ########################################### + // #### Test decode + chaCha := TCipher_XChaCha20.Create; + try + chaCha.Mode := cmPoly1305; + chaCha.ExpectedAuthenticationResult := encrTag; + chaCha.DataToAuthenticate := cAAD; + + chaCha.Init(cKey, cNonce); + decr := chaCha.DecodeBytes(encr); + chaCha.Done; + + decodeTag := chaCha.CalculatedAuthenticationResult + finally + chaCha.Free; + end; + + Check( Length(cTag) = Length(decodeTag), 'Tag length is wrong'); + Check( CompareMem( @decodeTag[0], @cTag[0], Length(cTag)), 'Calculated Tag is wrong'); + end; +end; + + +destructor TestChaCha20Poly1305.Destroy; +begin + fTests.Free; + + inherited; +end; + +procedure TestChaCha20Poly1305.TestChaCha20_Poly1305_AEAD; +const cMsg : AnsiString = 'Ladies and Gentlemen of the class of ''99: If I could offer you only one tip for the future, sunscreen would be it.'; + cAAD : TBytes = [$50, $51, $52, $53, $c0, $c1, $c2, $c3, $c4, $c5, $c6, $c7]; + + cKey : TBytes = [$80, $81, $82, $83, $84, $85, $86, $87, $88, $89, $8a, $8b, $8c, $8d, $8e, $8f, + $90, $91, $92, $93, $94, $95, $96, $97, $98, $99, $9a, $9b, $9c, $9d, $9e, $9f]; + + cNonce : TBytes = [$07, $00, $00, $00, $40, $41, $42, $43, $44, $45, $46, $47]; + + cTag : TBytes = [$1a, $e1, $0b, $59, $4f, $09, $e2, $6a, $7e, $90, $2e, $cb, $d0, $60, $06, $91]; + + cCipherText : TBytes = [$d3, $1a, $8d, $34, $64, $8e, $60, $db, $7b, $86, $af, $bc, $53, $ef, $7e, $c2, + $a4, $ad, $ed, $51, $29, $6e, $08, $fe, $a9, $e2, $b5, $a7, $36, $ee, $62, $d6, + $3d, $be, $a4, $5e, $8c, $a9, $67, $12, $82, $fa, $fb, $69, $da, $92, $72, $8b, + $1a, $71, $de, $0a, $9e, $06, $0b, $29, $05, $d6, $a5, $b6, $7e, $cd, $3b, $36, + $92, $dd, $bd, $7f, $2d, $77, $8b, $8c, $98, $03, $ae, $e3, $28, $09, $1b, $58, + $fa, $b3, $24, $e4, $fa, $d6, $75, $94, $55, $85, $80, $8b, $48, $31, $d7, $bc, + $3f, $f4, $de, $f0, $8e, $4b, $7a, $9d, $e5, $76, $d2, $65, $86, $ce, $c6, $4b, + $61, $16 ]; + +var chaCha : TCipher_ChaCha20; + msg : TBytes; + encr : TBytes; + encrTag : TBytes; + decr : TBytes; + decodeTag : TBytes; + cpuMode : TChaChaCpuMode; +begin + for cpuMode in [cmPas, cmSSE, cmAVX] do + begin + TCipher_ChaCha20.CpuMode := cpuMode; + + SetLength(msg, Length(cMsg)); + Move( cMsg[1], msg[0], Length(msg)); + + + chaCha := TCipher_ChaCha20.Create; + try + chaCha.Mode := cmPoly1305; + chaCha.DataToAuthenticate := cAAD; + chaCha.Init(cKey, cNonce); + encr := chaCha.EncodeBytes(msg); + chaCha.Done; + + encrTag := chaCha.CalculatedAuthenticationResult; + finally + chaCha.Free; + end; + + Check( Length(cCipherText) = Length(encr), 'Encryption length is wrong'); + Check( CompareMem( @cCipherText[0], @encr[0], Length(encr) ), 'Encryption failed'); + + + Check( Length(cTag) = Length(encrTag), 'Tag length is wrong'); + Check( CompareMem( @encrTag[0], @cTag[0], Length(cTag)), 'Calculated Tag is wrong'); + + // ########################################### + // #### Test decode + chaCha := TCipher_ChaCha20.Create; + try + chaCha.Mode := cmPoly1305; + chaCha.ExpectedAuthenticationResult := encrTag; + chaCha.DataToAuthenticate := cAAD; + + chaCha.Init(cKey, cNonce); + decr := chaCha.DecodeBytes(encr); + chaCha.Done; + + decodeTag := chaCha.CalculatedAuthenticationResult + finally + chaCha.Free; + end; + + Check( Length(cTag) = Length(decodeTag), 'Tag length is wrong'); + Check( CompareMem( @decodeTag[0], @cTag[0], Length(cTag)), 'Calculated Tag is wrong'); + end; +end; + + +{ TestChaCha20Poly1305.TTestEnumerator } + +constructor TestChaCha20Poly1305.TTestEnumerator.Create( + const aTestFile: string); +var groups : TJSONArray; + tests : TJsonValue; + aTest : TJsonValue; + testFile : TJSonObject; + testRec : TJsonTestCase; +begin + inherited Create; + + fTests := TList.Create; + with TSTringList.create do + try + Loadfromfile('..\..\Unit Tests\Data\chacha20_poly1305_test.json'); + testFile := TJSONObject.ParseJSONValue(Text) as TJSONObject; + finally + Free; + end; + + // ########################################### + // #### Build list of tests + try + groups := testFile.GetValue('testGroups') as TJsonArray; + + for tests in groups do + begin + for aTest in ((tests as TJsonObject).GetValue('tests') as TJsonArray) do + begin + testRec.aad := BytesOf(TFormat_HexL.Decode(RawByteString(aTest.GetValue('aad')))); + testRec.iv := BytesOf(TFormat_HexL.Decode(RawByteString(aTest.GetValue('iv')))); + testRec.key := BytesOf(TFormat_HexL.Decode(RawByteString(aTest.GetValue('key')))); + testRec.msg := BytesOf(TFormat_HexL.Decode(RawByteString(aTest.GetValue('msg')))); + testRec.tag := BytesOf(TFormat_HexL.Decode(RawByteString(aTest.GetValue('tag')))); + testRec.Enc := BytesOf(TFormat_HexL.Decode(RawByteString(aTest.GetValue('ct')))); + testRec.isValid := SameText( aTest.GetValue('result'), 'Valid'); + fTests.Add(testRec); + end; + end; + finally + testFile.Free; + end; +end; + +destructor TestChaCha20Poly1305.TTestEnumerator.Destroy; +begin + fTests.Free; + + inherited; +end; + +function TestChaCha20Poly1305.TTestEnumerator.DoGetEnumerator: TEnumerator; +begin + Result := fTests.GetEnumerator; +end; + +initialization + // Register all test cases to be run + {$IFDEF DUnitX} + TDUnitX.RegisterTestFixture(TPoly1305); + {$ELSE} + RegisterTest(TestChaCha20Poly1305.Suite); + {$ENDIF} + +end. diff --git a/Unit Tests/Tests/TestDECCipher.pas b/Unit Tests/Tests/TestDECCipher.pas index d72456f2..b8550f0a 100644 --- a/Unit Tests/Tests/TestDECCipher.pas +++ b/Unit Tests/Tests/TestDECCipher.pas @@ -4587,7 +4587,7 @@ procedure TestTCipher_AES.TestContext; CheckEquals( 32, ReturnValue.KeySize); CheckEquals( 16, ReturnValue.BlockSize); CheckEquals( 16, ReturnValue.BufferSize); - CheckEquals( 480, ReturnValue.AdditionalBufferSize); + CheckEquals( 512, ReturnValue.AdditionalBufferSize); CheckEquals( 1, ReturnValue.MinRounds); CheckEquals( 1, ReturnValue.MaxRounds); CheckEquals(false, ReturnValue.NeedsAdditionalBufferBackup); @@ -4675,7 +4675,7 @@ procedure TestTCipher_Rijndael.TestContext; CheckEquals( 32, ReturnValue.KeySize); CheckEquals( 16, ReturnValue.BlockSize); CheckEquals( 16, ReturnValue.BufferSize); - CheckEquals( 480, ReturnValue.AdditionalBufferSize); + CheckEquals( 512, ReturnValue.AdditionalBufferSize); CheckEquals( 1, ReturnValue.MinRounds); CheckEquals( 1, ReturnValue.MaxRounds); CheckEquals(false, ReturnValue.NeedsAdditionalBufferBackup); diff --git a/Unit Tests/Tests/TestDECCipherFormats.pas b/Unit Tests/Tests/TestDECCipherFormats.pas index adcd9a7e..978ba984 100644 --- a/Unit Tests/Tests/TestDECCipherFormats.pas +++ b/Unit Tests/Tests/TestDECCipherFormats.pas @@ -709,7 +709,7 @@ procedure TestTDECCipherFormats.TestEncodeWideStringToString; initialization // Register any test cases with the test runner {$IFNDEF DUnitX} - RegisterTest(TestTDECCipherFormats.Suite); + RegisterTest('DEC cipher formats', TestTDECCipherFormats.Suite); {$ELSE} TDUnitX.RegisterTestFixture(TestTDECCipherFormats); {$ENDIF} diff --git a/Unit Tests/Tests/TestDECCipherModes.pas b/Unit Tests/Tests/TestDECCipherModes.pas index 2437c44a..21d5d707 100644 --- a/Unit Tests/Tests/TestDECCipherModes.pas +++ b/Unit Tests/Tests/TestDECCipherModes.pas @@ -352,6 +352,12 @@ TestTDECCipherModes = class(TTestCase) /// /// Method needed because CheckException only allows procedure methods and /// not functions as parameter. + /// Simply sets FCipher.Mode to CCM. + /// + procedure TestFailureSetCCMMode; + /// + /// Method needed because CheckException only allows procedure methods and + /// not functions as parameter. /// Tries to encrypt data using ECB-mode but data is not a multiple of /// the block size (length data > 1 block) /// @@ -420,6 +426,7 @@ TestTDECCipherModes = class(TTestCase) procedure TestFailureSetExpectedAuthenticationTag; procedure TestFailureGetExpectedAuthenticationTag; procedure InitGCMBlocksizeNot128Failure; + procedure InitCCMBlocksizeNot128Failure; procedure InitGCMStreamCipherFailure; procedure TestEncodeECBDataDoesNotMatchBlockSizeFailureSmall; procedure TestEncodeECBDataDoesNotMatchBlockSizeFailure; @@ -777,6 +784,16 @@ procedure TestTDECCipherModes.InitGCMBlocksizeNot128Failure; end; end; +procedure TestTDECCipherModes.InitCCMBlocksizeNot128Failure; +begin + FCipher := TCipher_Blowfish.Create; + try + CheckException(TestFailureSetCCMMode, EDECCipherException); + finally + FCipher.Free; + end; +end; + procedure TestTDECCipherModes.InitGCMStreamCipherFailure; begin FCipher := TCipher_RC4.Create; @@ -814,6 +831,11 @@ procedure TestTDECCipherModes.TestFailureSetGCMMode; FCipher.Mode := TCipherMode.cmGCM; end; +procedure TestTDECCipherModes.TestFailureSetCCMMode; +begin + FCipher.Mode := TCipherMode.cmCCM; +end; + procedure TestTDECCipherModes.TestGetStandardAuthenticationTagBitLengths; var i, n : Integer; @@ -1009,6 +1031,6 @@ initialization {$IFDEF DUnitX} TDUnitX.RegisterTestFixture(TestTDECCipherModes); {$ELSE} - RegisterTest(TestTDECCipherModes.Suite); + RegisterTest('DEC cipher modes', TestTDECCipherModes.Suite); {$ENDIF} end. diff --git a/Unit Tests/Tests/TestDECCipherModesCCM.pas b/Unit Tests/Tests/TestDECCipherModesCCM.pas new file mode 100644 index 00000000..26fb507d --- /dev/null +++ b/Unit Tests/Tests/TestDECCipherModesCCM.pas @@ -0,0 +1,805 @@ +{***************************************************************************** + The DEC team (see file NOTICE.txt) licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. A copy of this licence is found in the root directory of + this project in the file LICENCE.txt or alternatively at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*****************************************************************************} + +{$M+} // DUnitX would add it anyway +unit TestDECCipherModesCCM; + +interface + +// Needs to be included before any other statements +{$INCLUDE TestDefines.inc} + +uses + {$IFDEF DUnitX} + DUnitX.TestFramework,DUnitX.DUnitCompatibility, + {$ELSE} + TestFramework, + {$ENDIF} + System.SysUtils, + Generics.Collections, + System.Math, + DECBaseClass, + DECCipherBase, + DECCipherModes, + DECCipherFormats, + DECCiphers, + AuthenticatedCiphersCommonTestData; + +type + // Testmethods for class TDECCipher + {$IFDEF DUnitX} [TestFixture] {$ENDIF} + TestTDECCCM = class(TTestCase) + strict private + FTestDataList : TAuthenticatedTestDataList; + FCipherAES : TCipher_AES; + FTestBitLength : Integer; // AuthenticationBitLength for test for wring lengths + private + function IsEqual(const a, b: TBytes): Boolean; + procedure DoTestEncodeStream_LoadAndTestCAVSData(const aMaxChunkSize: Int64); + procedure DoTestEncodeStream_TestSingleSet(const aSetIndex, aDataIndex: + Integer; const aMaxChunkSize: Int64 = -1); + procedure DoTestInitFailureIVTooLong; + procedure DoTestInitFailureIVTooShort; + procedure DoTestRFC3610(EncodeTest: Boolean); + procedure DoTestAuthenticationBitLengthWrong; + public + procedure SetUp; override; + procedure TearDown; override; + published + procedure TestEncode; + /// + /// Uses testvectors from RFC 3610 but in a generated way + /// as they are specified like this. + /// + procedure TestEncodeRFC3610; + /// + /// Uses testvectors from RFC 3610 but in a generated way + /// as they are specified like this. + /// + procedure TestDecodeRFC3610; + procedure TestDecode; + procedure TestDecodeStream; + procedure TestInitIV; + procedure TestInitFailureIVTooLong; + procedure TestInitFailureIVTooShort; + procedure TestEncodeStream; +// procedure TestEncodeLargeStream; +// procedure TestEncodeStreamChunked; + procedure TestGetDataToAuthenticate; + procedure TestSetDataToAuthenticate; + procedure TestSetAuthenticationBitLengths; + procedure TestSetWrongAuthenticationBitLengths; + procedure TestGetStandardAuthenticationTagBitLengths; + procedure TestGetExpectedAuthenticationResult; + procedure TestSetExpectedAuthenticationResult; + end; + + +implementation + +uses + System.Classes, + DECTypes, + DECFormat, + DECUtil, + DECAuthenticatedCipherModesBase; + +{ TestTDECCCM } + +procedure TestTDECCCM.SetUp; +var + TestDataSet : TAuthenticatedCipherTestSetEntry; +begin + inherited; + + FTestDataList := TAuthenticatedTestDataList.Create; + + FCipherAES := TCipher_AES.Create; + FCipherAES.Mode := TCipherMode.cmCCM; + + TestDataSet.Keylen := 256; + TestDataSet.IVlen := 92; + TestDataSet.PTlen := 23 * 8; + TestDataSet.AADlen := 64; // hdr1 length in initial source + TestDataSet.Taglen := 64; // authentication tag length in bit + SetLength(TestDataSet.TestData, 2); + TestDataSet.TestData[0].CryptKey := 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf'; + TestDataSet.TestData[0].InitVector := '00000003020100a0a1a2a3a4a5'; + TestDataSet.TestData[0].PT := '08090a0b0c0d0e0f101112131415161718191a1b1c1d1e'; + TestDataSet.TestData[0].AAD := '0001020304050607'; // hdr1 in initial source + TestDataSet.TestData[0].CT := '588c979a61c663d2f066d0c2c0f989806d5f6b61dac384'; + TestDataSet.TestData[0].TagResult := '17e8d12cfdf926e0'; + TestDataSet.TestData[0].ModifiedAAD := ''; + TestDataSet.TestData[0].ModifiedCT := ''; + + TestDataSet.TestData[1].CryptKey := 'c0c1c2c3c4c5c6c7c8c9cacbcccdcecf'; + TestDataSet.TestData[1].InitVector := '00000006050403a0a1a2a3a4a5'; + TestDataSet.TestData[1].PT := '0c0d0e0f101112131415161718191a1b1c1d1e'; + TestDataSet.TestData[1].AAD := '000102030405060708090a0b'; // hdr1 in initial source + TestDataSet.TestData[1].CT := 'a28c6865939a9a79faaa5c4c2a9d4a91cdac8c'; + TestDataSet.TestData[1].TagResult := '96c861b9c9e61ef1'; + TestDataSet.TestData[1].ModifiedAAD := ''; + TestDataSet.TestData[1].ModifiedCT := ''; + + FTestDataList.Add(TestDataSet); + + TestDataSet.Taglen := 32; // authentication tag length in bit + SetLength(TestDataSet.TestData, 1); + TestDataSet.TestData[0].CryptKey := '404142434445464748494a4b4c4d4e4f'; + TestDataSet.TestData[0].InitVector := '10111213141516'; + TestDataSet.TestData[0].PT := '20212223'; + TestDataSet.TestData[0].AAD := '0001020304050607'; // hdr1 in initial source + TestDataSet.TestData[0].CT := '7162015b'; + TestDataSet.TestData[0].TagResult := '4dac255d'; + TestDataSet.TestData[0].ModifiedAAD := ''; + TestDataSet.TestData[0].ModifiedCT := ''; + + FTestDataList.Add(TestDataSet); +end; + +procedure TestTDECCCM.TearDown; +begin + inherited; + + FCipherAES.Free; +// FTestDataLoader.Free; + FTestDataList.Free; +end; + +procedure TestTDECCCM.TestDecode; +var + TestDataSet : TAuthenticatedCipherTestSetEntry; + TestData : TSingleAuthenticatedTestData; + DecryptData : TBytes; +begin + for TestDataSet in FTestDataList do + begin + try + for TestData in TestDataSet.TestData do + begin + FCipherAES.Init(BytesOf(TFormat_HexL.Decode(TestData.CryptKey)), + BytesOf(TFormat_HexL.Decode(TestData.InitVector)), + $FF); + + FCipherAES.AuthenticationResultBitLength := TestDataSet.Taglen; + FCipherAES.DataToAuthenticate := TFormat_HexL.Decode( + BytesOf(TestData.AAD)); + + FCipherAES.ExpectedAuthenticationResult := + TFormat_HexL.Decode(BytesOf(TestData.TagResult)); + + DecryptData := FCipherAES.DecodeBytes( + TFormat_HexL.Decode( + BytesOf(TestData.CT))); + FCipherAES.Done; + + CheckEquals(string(TestData.PT), + StringOf(TFormat_HexL.Encode(DecryptData)), + 'Plaintext wrong for key ' + + string(TestData.CryptKey) + ' IV ' + + string(TestData.InitVector) + ' PT ' + + string(TestData.PT) + ' AAD ' + + string(TestData.AAD) + ' Exp. PT: ' + + string(TestData.CT) + ' Act. PT: ' + + StringOf(TFormat_HexL.Encode(DecryptData))); + + // Additional Authentication Data prüfen + CheckEquals(string(TestData.TagResult), + StringOf(TFormat_HexL.Encode(FCipherAES.CalculatedAuthenticationResult)), + 'Authentication tag wrong for key ' + + string(TestData.CryptKey) + ' IV ' + + string(TestData.InitVector) + ' PT ' + + string(TestData.PT) + ' AAD ' + + string(TestData.AAD) + ' Exp. AuthTag: ' + + string(TestData.TagResult) + ' Act. AuthTag: ' + + StringOf(TFormat_HexL.Encode(FCipherAES.DataToAuthenticate))); + end; + except + on E: Exception do + Status('CryptKey ' + string(TestData.CryptKey) + + ' ' + E.ClassName + ': ' + E.Message); + end; + end; +end; + +procedure TestTDECCCM.TestInitFailureIVTooLong; +begin + CheckException(DoTestInitFailureIVTooLong, + EDECNonceLengthException, + 'Init vector too long not detected'); +end; + +procedure TestTDECCCM.DoTestInitFailureIVTooLong; +var + CipherAES : TCipher_AES; +begin + CipherAES := TCipher_AES.Create; + + try + CipherAES.Mode := cmCCM; + CipherAES.Init(BytesOf(TFormat_HexL.Decode('000102030405060708')), + BytesOf(TFormat_HexL.Decode('0a0b0c0d0e0f0a0b0c0d0e0f0a0b0c0d')), + $FF); + finally + CipherAES.Free; + end; +end; + +procedure TestTDECCCM.TestInitFailureIVTooShort; +begin + CheckException(DoTestInitFailureIVTooShort, + EDECNonceLengthException, + 'Init vector too long not detected'); +end; + +procedure TestTDECCCM.TestInitIV; +var + Key : TBytes; + IV : TBytes; + i : Integer; +begin + Key := [1, 2, 3, 4, 5, 6, 7, 8]; + + for i := 7 to 13 do + begin + SetLength(IV, i); + FillChar(IV[0], length(IV), $FF); + + FCipherAES.Init(Key, IV, $FF, pmNone); + Check(true); + end; +end; + +procedure TestTDECCCM.DoTestInitFailureIVTooShort; +var + CipherAES : TCipher_AES; +begin + CipherAES := TCipher_AES.Create; + + try + CipherAES.Mode := cmCCM; + CipherAES.Init(BytesOf(TFormat_HexL.Decode('000102030405060708')), + BytesOf(TFormat_HexL.Decode('0a0b0c0d0e0f')), + $FF); + finally + CipherAES.Free; + end; +end; + +procedure TestTDECCCM.TestEncode; +var + TestDataSet : TAuthenticatedCipherTestSetEntry; + TestData : TSingleAuthenticatedTestData; + EncryptData : TBytes; + EncrDataStr : string; +begin + for TestDataSet in FTestDataList do + begin + for TestData in TestDataSet.TestData do + begin + FCipherAES.Init(BytesOf(TFormat_HexL.Decode(TestData.CryptKey)), + BytesOf(TFormat_HexL.Decode(TestData.InitVector)), + $FF); + + FCipherAES.AuthenticationResultBitLength := TestDataSet.Taglen; + FCipherAES.DataToAuthenticate := TFormat_HexL.Decode( + BytesOf(TestData.AAD)); + + EncryptData := FCipherAES.EncodeBytes( + TFormat_HexL.Decode( + BytesOf(TestData.PT))); + FCipherAES.Done; + + EncrDataStr := StringOf(TFormat_HexL.Encode(EncryptData)); + CheckEquals(string(TestData.CT), + EncrDataStr, + 'Cipher text wrong for Key ' + + string(TestData.CryptKey) + ' IV ' + + string(TestData.InitVector) + ' PT ' + + string(TestData.PT) + ' AAD ' + + string(TestData.AAD) + ' Exp.: ' + + string(TestData.CT) + ' Act.: ' + + EncrDataStr); + + // Additional Authentication Data prüfen + CheckEquals(string(TestData.TagResult), + StringOf(TFormat_HexL.Encode(FCipherAES.CalculatedAuthenticationResult)), + 'Authentication tag wrong for Key ' + + string(TestData.CryptKey) + ' IV ' + + string(TestData.InitVector) + ' PT ' + + string(TestData.PT) + ' AAD ' + + string(TestData.AAD) + ' Exp.: ' + + string(TestData.TagResult) + ' Act.: ' + + StringOf(TFormat_HexL.Encode(FCipherAES.DataToAuthenticate))); + end; + end; +end; + +procedure TestTDECCCM.TestGetExpectedAuthenticationResult; +var + Exp, Act: TBytes; +begin + SetLength(Exp, 4); + Exp := [1, 2, 3, 4]; + FCipherAES.ExpectedAuthenticationResult := Exp; + Act := FCipherAES.ExpectedAuthenticationResult; + + CheckEquals(true, IsEqual(Exp, Act), 'Data length = 4'); + + SetLength(Exp, 0); + FCipherAES.ExpectedAuthenticationResult := Exp; + Act := FCipherAES.ExpectedAuthenticationResult; + + CheckEquals(true, IsEqual(Exp, Act), 'Data length = 0'); +end; + +//procedure TestTDECCCM.DoTestDecodeFailure; +//begin +// FDecryptedData := FCipherAES.DecodeBytes(FCipherText); +// FCipherAES.Done; +//end; + +function TestTDECCCM.IsEqual(const a, b : TBytes):Boolean; +begin + if (length(a) <> length(b)) then + Result := false + else + if (Length(a) > 0) then + Result := CompareMem(@a[0], @b[0], length(a)) + else + Result := true; +end; + +procedure TestTDECCCM.TestDecodeStream; +var + ctbStream: TBytesStream; + ctBytes: TBytes; + TestDataSet : TAuthenticatedCipherTestSetEntry; + TestData : TSingleAuthenticatedTestData; + DecryptData : TBytes; + ptbStream: TBytesStream; +begin + for TestDataSet in FTestDataList do + begin + for TestData in TestDataSet.TestData do + begin + ctBytes := TFormat_HexL.Decode(BytesOf(TestData.CT)); + + try + FCipherAES.Init(BytesOf(TFormat_HexL.Decode(TestData.CryptKey)), + BytesOf(TFormat_HexL.Decode(TestData.InitVector)), + $FF); + + FCipherAES.AuthenticationResultBitLength := TestDataSet.Taglen; + FCipherAES.DataToAuthenticate := TFormat_HexL.Decode( + BytesOf(TestData.AAD)); + + FCipherAES.ExpectedAuthenticationResult := + TFormat_HexL.Decode(BytesOf(TestData.TagResult)); + + ctbStream := TBytesStream.Create(ctBytes); + ptbStream := TBytesStream.Create; + + FCipherAES.DecodeStream(ctbStream, ptbStream, ctbStream.Size); + + FCipherAES.Done; + + DecryptData := ptbStream.Bytes; + SetLength(DecryptData, ptbStream.Size); + + except + on E: Exception do + Status('CryptKey ' + string(TestData.CryptKey) + + ' ' + E.ClassName + ': ' + E.Message); + end; + FreeAndNil(ptbStream); + FreeAndNil(ctbStream); + + CheckEquals(string(TestData.PT), + StringOf(TFormat_HexL.Encode(DecryptData)), + 'Plaintext wrong for key ' + + string(TestData.CryptKey) + ' IV ' + + string(TestData.InitVector) + ' PT ' + + string(TestData.PT) + ' AAD ' + + string(TestData.AAD) + ' Exp.: ' + + string(TestData.CT) + ' Act.: ' + + StringOf(TFormat_HexL.Encode(DecryptData))); + + // Additional Authentication Data prüfen + CheckEquals(string(TestData.TagResult), + StringOf(TFormat_HexL.Encode(FCipherAES.CalculatedAuthenticationResult)), + 'Authentication tag wrong for key ' + + string(TestData.CryptKey) + ' IV ' + + string(TestData.InitVector) + ' PT ' + + string(TestData.PT) + ' AAD ' + + string(TestData.AAD) + ' Exp.: ' + + string(TestData.TagResult) + ' Act.: ' + + StringOf(TFormat_HexL.Encode(FCipherAES.DataToAuthenticate))); + end; + end; +end; + +procedure TestTDECCCM.TestEncodeStream; +begin + // -1 to disable chunking + DoTestEncodeStream_LoadAndTestCAVSData(-1); +end; + +procedure TestTDECCCM.DoTestAuthenticationBitLengthWrong; +begin + FCipherAES.AuthenticationResultBitLength := FTestBitLength; +end; + +//procedure TestTDECCCM.TestEncodeStreamChunked; +//begin +// // Use cipher block size as max chunk size +// DoTestEncodeStream_LoadAndTestCAVSData( +// Max(FCipherAES.Context.BlockSize, FCipherAES.Context.BufferSize)); +//end; +// +procedure TestTDECCCM.DoTestEncodeStream_LoadAndTestCAVSData(const + aMaxChunkSize: Int64); +var + TestDataSet : TAuthenticatedCipherTestSetEntry; + curSetIndex: Integer; +begin + for curSetIndex := 0 to FTestDataList.Count - 1 do + begin + TestDataSet := FTestDataList[curSetIndex]; + DoTestEncodeStream_TestSingleSet(curSetIndex, 0, aMaxChunkSize); + end; +end; +// +//procedure TestTDECCCM.TestEncodeLargeStream; +//begin +// // There is only one record in test data set atm, so need to allow +// // incomplete load +// FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV256_large.rsp', +// FTestDataList, True); +// Status('Encode large stream using chunking'); +// CheckEquals(8192, StreamBufferSize, 'Might need to update data set to have enough data!'); +//{ TODO : Auskommentierten Code entfernen } +//// Assert(StreamBufferSize = 8192, 'Might need to update data set to have enough data!'); +// DoTestEncodeStream_TestSingleSet(0, 0, StreamBufferSize); +// Status('Encode large stream without chunking'); +// DoTestEncodeStream_TestSingleSet(0, 0, -1); +//end; + +procedure TestTDECCCM.DoTestEncodeStream_TestSingleSet(const aSetIndex, + aDataIndex: Integer; const aMaxChunkSize: Int64 = -1); +var + ctbStream: TBytesStream; + curChunkSize: Int64; + dataLeftToEncode: Int64; + ptBytes: TBytes; + TestDataSet : TAuthenticatedCipherTestSetEntry; + TestData : TSingleAuthenticatedTestData; + EncryptData : TBytes; + ptbStream: TBytesStream; +begin + TestDataSet := FTestDataList[aSetIndex]; + + for TestData in TestDataSet.TestData do + begin + ptBytes := TFormat_HexL.Decode(BytesOf(TestData.PT)); + + FCipherAES.Init(BytesOf(TFormat_HexL.Decode(TestData.CryptKey)), + BytesOf(TFormat_HexL.Decode(TestData.InitVector)), + $FF); + + FCipherAES.AuthenticationResultBitLength := TestDataSet.Taglen; + FCipherAES.DataToAuthenticate := TFormat_HexL.Decode( + BytesOf(TestData.AAD)); + + ptbStream := TBytesStream.Create(ptBytes); + ctbStream := TBytesStream.Create; + try + dataLeftToEncode := ptbStream.Size; + curChunkSize := dataLeftToEncode; + repeat + // Apply chunking if needed + if aMaxChunkSize > 0 then + curChunkSize := Min(dataLeftToEncode, aMaxChunkSize); + FCipherAES.EncodeStream(ptbStream, ctbStream, curChunkSize); + Dec(dataLeftToEncode, curChunkSize); + until (dataLeftToEncode = 0); + + FCipherAES.Done; + + EncryptData := ctbStream.Bytes; + SetLength(EncryptData, ctbStream.Size); + except + on E: Exception do + Status('CryptKey ' + string(TestData.CryptKey) + + ' ' + E.ClassName + ': ' + E.Message); + end; + + FreeAndNil(ptbStream); + FreeAndNil(ctbStream); + + CheckEquals(string(TestData.CT), + StringOf(TFormat_HexL.Encode(EncryptData)), + 'Cipher text wrong for Set ' + aSetIndex.ToString + ' and Data ' + aDataIndex.ToString + + ' and Key ' + string(TestData.CryptKey) + ' IV ' + + string(TestData.InitVector) + ' PT ' + + string(TestData.PT) + ' AAD Exp.: ' + + string(TestData.AAD) + ' Act.: ' + + StringOf(TFormat_HexL.Encode(FCipherAES.DataToAuthenticate))); + + // Additional Authentication Data prüfen + CheckEquals(string(TestData.TagResult), + StringOf(TFormat_HexL.Encode(FCipherAES.CalculatedAuthenticationResult)), + 'Authentication tag wrong for Set ' + aSetIndex.ToString + ' and Data ' + aDataIndex.ToString + + ' and Key ' + string(TestData.CryptKey) + ' IV ' + + string(TestData.InitVector) + ' PT ' + + string(TestData.PT) + ' AAD Exp.: ' + + string(TestData.AAD) + ' Act.: ' + + StringOf(TFormat_HexL.Encode(FCipherAES.DataToAuthenticate))); + end; +end; + +procedure TestTDECCCM.TestGetStandardAuthenticationTagBitLengths; +var + BitLengths: TStandardBitLengths; +begin + BitLengths := FCipherAES.GetStandardAuthenticationTagBitLengths; + + CheckEquals( 32, BitLengths[0]); + CheckEquals( 48, BitLengths[1]); + CheckEquals( 64, BitLengths[2]); + CheckEquals( 80, BitLengths[3]); + CheckEquals( 96, BitLengths[4]); + CheckEquals(112, BitLengths[5]); + CheckEquals(128, BitLengths[6]); +end; + +procedure TestTDECCCM.TestSetExpectedAuthenticationResult; +var + Exp, Act: TBytes; +begin + SetLength(Exp, 4); + Exp := [1, 2, 3, 4]; + FCipherAES.ExpectedAuthenticationResult := Exp; + Act := FCipherAES.ExpectedAuthenticationResult; + + CheckEquals(true, IsEqual(Exp, Act), 'Data length = 4'); + + SetLength(Exp, 8); + Exp := [1, 2, 3, 4, 5, 6, 7, 8]; + FCipherAES.ExpectedAuthenticationResult := Exp; + Act := FCipherAES.ExpectedAuthenticationResult; + + CheckEquals(true, IsEqual(Exp, Act), 'Data length = 8'); + + SetLength(Exp, 12); + Exp := [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; + FCipherAES.ExpectedAuthenticationResult := Exp; + Act := FCipherAES.ExpectedAuthenticationResult; + + CheckEquals(true, IsEqual(Exp, Act), 'Data length = 12'); + + SetLength(Exp, 0); + FCipherAES.ExpectedAuthenticationResult := Exp; + Act := FCipherAES.ExpectedAuthenticationResult; + + CheckEquals(true, IsEqual(Exp, Act), 'Data length = 0'); +end; + +procedure TestTDECCCM.TestSetWrongAuthenticationBitLengths; +var + bl : Integer; +begin + bl := 31; + while (bl < 128) do + begin + FTestBitLength := bl; + CheckException(DoTestAuthenticationBitLengthWrong, EDECAuthLengthException); + inc(bl, 16); + end; + + bl := 33; + while (bl <= 129) do + begin + FTestBitLength := bl; + CheckException(DoTestAuthenticationBitLengthWrong, EDECAuthLengthException); + inc(bl, 16); + end; +end; + +procedure TestTDECCCM.TestSetAuthenticationBitLengths; +var + bl : Integer; +begin + bl := 32; + + while (bl <= 128) do + begin + FCipherAES.AuthenticationResultBitLength := bl; + CheckEquals(bl, FCipherAES.AuthenticationResultBitLength); + + inc(bl, 16); + end; +end; + +procedure TestTDECCCM.TestGetDataToAuthenticate; +var + inp, outp : TBytes; +begin + inp := BytesOf(RawByteString('Hello')); + FCipherAES.DataToAuthenticate := inp; + outp := FCipherAES.DataToAuthenticate; + + CheckEquals(true, CompareMem(@inp[0], @outp[0], length(inp)), + 'Data to authenticate not properly set. Expected: ' + + string(BytesToRawString(inp)) + ' Result: ' + + string(BytesToRawString(outp))); +end; + +procedure TestTDECCCM.TestSetDataToAuthenticate; +begin + FCipherAES.DataToAuthenticate := BytesOf(RawByteString('Hello')); + CheckEquals(RawByteString('Hello'), + RawByteString(StringOf(FCipherAES.DataToAuthenticate))); + + FCipherAES.DataToAuthenticate := BytesOf(RawByteString('The quick brown fox jumped over the lazy dog')); + CheckEquals(RawByteString('The quick brown fox jumped over the lazy dog'), + RawByteString(StringOf(FCipherAES.DataToAuthenticate))); +end; + +procedure TestTDECCCM.TestEncodeRFC3610; +begin + DoTestRFC3610(true); +end; + +procedure TestTDECCCM.TestDecodeRFC3610; +begin + DoTestRFC3610(false); +end; + +procedure TestTDECCCM.DoTestRFC3610(EncodeTest: Boolean); +type + ta25 = array[0..24] of UInt8; + ta10 = array[0..09] of UInt8; +const + ctest: array[1..12] of ta25 = ( + ($58,$8C,$97,$9A,$61,$C6,$63,$D2,$F0,$66,$D0,$C2,$C0,$F9,$89,$80,$6D,$5F,$6B,$61,$DA,$C3,$84,$00,$00), + ($72,$C9,$1A,$36,$E1,$35,$F8,$CF,$29,$1C,$A8,$94,$08,$5C,$87,$E3,$CC,$15,$C4,$39,$C9,$E4,$3A,$3B,$00), + ($51,$B1,$E5,$F4,$4A,$19,$7D,$1D,$A4,$6B,$0F,$8E,$2D,$28,$2A,$E8,$71,$E8,$38,$BB,$64,$DA,$85,$96,$57), + ($A2,$8C,$68,$65,$93,$9A,$9A,$79,$FA,$AA,$5C,$4C,$2A,$9D,$4A,$91,$CD,$AC,$8C,$00,$00,$00,$00,$00,$00), + ($DC,$F1,$FB,$7B,$5D,$9E,$23,$FB,$9D,$4E,$13,$12,$53,$65,$8A,$D8,$6E,$BD,$CA,$3E,$00,$00,$00,$00,$00), + ($6F,$C1,$B0,$11,$F0,$06,$56,$8B,$51,$71,$A4,$2D,$95,$3D,$46,$9B,$25,$70,$A4,$BD,$87,$00,$00,$00,$00), + ($01,$35,$D1,$B2,$C9,$5F,$41,$D5,$D1,$D4,$FE,$C1,$85,$D1,$66,$B8,$09,$4E,$99,$9D,$FE,$D9,$6C,$00,$00), + ($7B,$75,$39,$9A,$C0,$83,$1D,$D2,$F0,$BB,$D7,$58,$79,$A2,$FD,$8F,$6C,$AE,$6B,$6C,$D9,$B7,$DB,$24,$00), + ($82,$53,$1A,$60,$CC,$24,$94,$5A,$4B,$82,$79,$18,$1A,$B5,$C8,$4D,$F2,$1C,$E7,$F9,$B7,$3F,$42,$E1,$97), + ($07,$34,$25,$94,$15,$77,$85,$15,$2B,$07,$40,$98,$33,$0A,$BB,$14,$1B,$94,$7B,$00,$00,$00,$00,$00,$00), + ($67,$6B,$B2,$03,$80,$B0,$E3,$01,$E8,$AB,$79,$59,$0A,$39,$6D,$A7,$8B,$83,$49,$34,$00,$00,$00,$00,$00), + ($C0,$FF,$A0,$D6,$F0,$5B,$DB,$67,$F2,$4D,$43,$A4,$33,$8D,$2A,$A4,$BE,$D7,$B2,$0E,$43,$00,$00,$00,$00)); + ttest: array[1..12] of ta10 = ( + ($17,$E8,$D1,$2C,$FD,$F9,$26,$E0,$00,$00), + ($A0,$91,$D5,$6E,$10,$40,$09,$16,$00,$00), + ($4A,$DA,$A7,$6F,$BD,$9F,$B0,$C5,$00,$00), + ($96,$C8,$61,$B9,$C9,$E6,$1E,$F1,$00,$00), + ($51,$E8,$3F,$07,$7D,$9C,$2D,$93,$00,$00), + ($40,$5A,$04,$43,$AC,$91,$CB,$94,$00,$00), + ($04,$8C,$56,$60,$2C,$97,$AC,$BB,$74,$90), + ($C1,$7B,$44,$33,$F4,$34,$96,$3F,$34,$B4), + ($EA,$9C,$07,$E5,$6B,$5E,$B1,$7E,$5F,$4E), + ($56,$6A,$A9,$40,$6B,$4D,$99,$99,$88,$DD), + ($F5,$3A,$A2,$E9,$10,$7A,$8B,$6C,$02,$2C), + ($CD,$1A,$A3,$16,$62,$E7,$AD,$65,$D6,$DB)); +var + buf, DecodeBuf : array[0..63] of UInt8; + pn : Integer; + key, nonce : TBlock16Byte; + i, ih, it, k : Integer; + plen, tlen, hlen : UInt16; + x : UInt32; + b : UInt8; + CipherAES : TCipher_AES; + DataToAuth : TBytes; + TagResult : TBytes; +begin + nonce[00] := 0; // = init vector + nonce[01] := 0; + nonce[02] := 0; + nonce[07] := $A0; + nonce[08] := $A1; + nonce[09] := $A2; + nonce[10] := $A3; + nonce[11] := $A4; + nonce[12] := $A5; + + pn := 0; + + // key setup, all tests use the same one + for i:= 0 to 15 do + key[i] := $C0 + i; + + for it := 0 to 1 do + begin + tlen := 8 + 2*it; // authentication tag length + + for ih := 0 to 1 do + begin + hlen := 8 + 4*ih; // length of the data to authenticate + SetLength(DataToAuth, hlen); + + for k := 31 to 33 do + begin + pLen := k-hlen; // plain text length? + + x := pn * $01010101+$03020100; + inc(pn); + + // some positions of the nonce/init vector are different for each test + nonce[03] := (x shr 24) and $ff; + nonce[04] := (x shr 16) and $ff; + nonce[05] := (x shr 08) and $ff; + nonce[06] := x and $ff; + + b := 0; + for i := 0 to hlen - 1 do + begin + DataToAuth[i] := b; + inc(b); + end; + + for i := 0 to pLen - 1 do + begin + buf[i] := b; + inc(b); + end; + + CipherAES := TCipher_AES256.Create; + try + CipherAES.Mode := TCipherMode.cmCCM; + CipherAES.DataToAuthenticate := DataToAuth; + CipherAES.AuthenticationResultBitLength := tlen * 8; + + CipherAES.Init(Key[0], Length(Key), Nonce[0], 13, 0, pmNone); + + if EncodeTest then + begin + CipherAES.Encode(buf[0], buf[0], plen); + CheckEquals(true, CompareMem(@buf,@ctest[pn],plen), 'Ciphertext wrong'); + end + else + begin + CipherAES.Decode(ctest[pn], DecodeBuf[0], plen); + CheckEquals(true, CompareMem(@buf,@DecodeBuf,plen), 'Plaintext wrong'); + end; + + TagResult := CipherAES.CalculatedAuthenticationResult; + + // Test the generated tag + CheckEquals(true, CompareMem(@TagResult[0], @ttest[pn],tlen), 'Tag wrong'); + finally + CipherAES.Free; + end; + end; + end; + end; +end; + +initialization + // Register all test cases to be run + {$IFDEF DUnitX} + TDUnitX.RegisterTestFixture(TestTDECCCM); + {$ELSE} + RegisterTest('DEC authenticated cipher modes', TestTDECCCM.Suite); + {$ENDIF} +end. diff --git a/Unit Tests/Tests/TestDECCipherModesGCM.pas b/Unit Tests/Tests/TestDECCipherModesGCM.pas index aae0da91..0d6c0727 100644 --- a/Unit Tests/Tests/TestDECCipherModesGCM.pas +++ b/Unit Tests/Tests/TestDECCipherModesGCM.pas @@ -29,100 +29,17 @@ interface {$ELSE} TestFramework, {$ENDIF} - System.SysUtils, Generics.Collections, System.Math, + System.SysUtils, + Generics.Collections, + System.Math, DECBaseClass, - DECCipherBase, DECCipherModes, DECCipherFormats, DECCiphers; + DECCipherBase, + DECCipherModes, + DECCipherFormats, + DECCiphers, + AuthenticatedCiphersCommonTestData; type - /// - /// Test data for one single GCM test, all in HexL - /// - TGCMSingleTestData = record - /// - /// Encryption/decryption key - /// - CryptKey : RawByteString; - /// - /// Initialization vecotr - /// - InitVector : RawByteString; - /// - /// Plain Text: text to be encrypted, given in HexL - /// - PT : RawByteString; - /// - /// Additional Authenticated Data: the data which shall be authenticated - /// but not encrypted. - /// - AAD : RawByteString; - /// - /// Cipher Text: encrypted text, given in HexL - /// - CT : RawByteString; - /// - /// Calculated authenticated "tag" value - /// - TagResult : RawByteString; - /// - /// Used additional authenticated data for testing authentication failures. - /// Only filled when present in test data file. - /// - ModifiedAAD: RawByteString; - /// - /// Used ciphertext data for testing authentication failures. - /// Only filled when present in test data file. - /// - ModifiedCT: RawByteString; - - /// - /// Sets all fields and array entries to default values - /// - procedure Clear; - end; - - /// - /// Test data for one single GCM test - /// - TGCMTestSetEntry = record - /// - /// Length of the encryption/decryption key in bit, determines the - /// algorithm used in case of AES (AES128, AES192, AES256) - /// - Keylen : UInt16; - /// - /// Length of the initialization vector in bit - /// - IVlen : UInt16; - /// - /// Length of the ? in bit - /// - PTlen : UInt16; - /// - /// Length of the ? in bit - /// - AADlen : UInt16; - /// - /// Length of the "tag" resulting from the authentication part in bit - /// - Taglen : UInt16; - - /// - /// The test data files provided contain 14 tests for the meta data - /// specified above. This array holds the test data. - /// - TestData : array[0..14] of TGCMSingleTestData; - - /// - /// Sets all fields and array entries to default values - /// - procedure Clear; - end; - - /// - /// List of loaded GCM test vectors - /// - TGCMTestDataList = TList; - /// /// Class for loading a GCM style test data file /// @@ -164,7 +81,7 @@ TGCMTestDataLoader = class(TObject) /// the start of a new block has been detected in the method. /// procedure ReadBlockMetaDataLine(const Line : string; - var Entry : TGCMTestSetEntry; + var Entry : TAuthenticatedCipherTestSetEntry; var Index : Byte); /// @@ -187,8 +104,8 @@ TGCMTestDataLoader = class(TObject) /// line will be ignored. /// procedure ReadDataLine(const Line : string; - var Entry : TGCMTestSetEntry; - TestData : TGCMTestDataList; + var Entry : TAuthenticatedCipherTestSetEntry; + TestData : TAuthenticatedTestDataList; var Index : Byte); public /// @@ -204,7 +121,7 @@ TGCMTestDataLoader = class(TObject) /// /// Use when loading data set with incomplete entries. /// - procedure LoadFile(const FileName: string; TestData : TGCMTestDataList; + procedure LoadFile(const FileName: string; TestData : TAuthenticatedTestDataList; AllowIncompleteEntries: Boolean = False); end; @@ -213,7 +130,7 @@ TGCMTestDataLoader = class(TObject) TestTDECGCM = class(TTestCase) strict private FTestDataLoader : TGCMTestDataLoader; - FTestDataList : TGCMTestDataList; + FTestDataList : TAuthenticatedTestDataList; FCipherAES : TCipher_AES; // Needed for passing data to and from DoTestDecodeFailure @@ -241,6 +158,12 @@ TestTDECGCM = class(TTestCase) procedure TestGetStandardAuthenticationTagBitLengths; procedure TestGetExpectedAuthenticationResult; procedure TestSetExpectedAuthenticationResult; + + /// + /// Test for GitHub issue #86 + /// + procedure TestEncodeConstData_86; + procedure TestStreamGCM_87; end; @@ -251,36 +174,6 @@ implementation DECTypes, DECFormat; -{ TGCMTestSetEntry } - -procedure TGCMTestSetEntry.Clear; -var - i : Integer; -begin - Keylen := 0; - IVlen := 0; - PTlen := 0; - AADlen := 0; - Taglen := 0; - - for i := Low(TestData) to High(TestData) do - TestData[i].Clear; -end; - -{ TGCMSingleTestData } - -procedure TGCMSingleTestData.Clear; -begin - CryptKey := ''; - InitVector := ''; - PT := ''; - AAD := ''; - CT := ''; - TagResult := ''; - ModifiedAAD := ''; - ModifiedCT := ''; -end; - { TGCMTestDataLoader } function TGCMTestDataLoader.ExtractHexString(const Line: string): RawByteString; @@ -313,17 +206,19 @@ function TGCMTestDataLoader.ExtractNumber(const Line: string): UInt16; end; procedure TGCMTestDataLoader.LoadFile(const FileName: string; - TestData : TGCMTestDataList; AllowIncompleteEntries: Boolean = False); + TestData : TAuthenticatedTestDataList; AllowIncompleteEntries: Boolean = False); var Reader : TStreamReader; Line : string; - Entry : TGCMTestSetEntry; + Entry : TAuthenticatedCipherTestSetEntry; Index : Byte; begin System.Assert(FileName <> '', 'No file to load specified'); System.Assert(Assigned(TestData), 'Unassigned test data list given'); + SetLength(Entry.TestData, 15); Entry.Clear; + Index := 0; Reader := TStreamReader.Create(FileName, TEncoding.UTF8); @@ -367,13 +262,14 @@ procedure TGCMTestDataLoader.LoadFile(const FileName: string; end; procedure TGCMTestDataLoader.ReadBlockMetaDataLine(const Line : string; - var Entry : TGCMTestSetEntry; + var Entry : TAuthenticatedCipherTestSetEntry; var Index : Byte); begin // Loading of the block metadata // Does a new block start? if (Pos('[keylen', Line) > 0) then begin + SetLength(Entry.TestData, 15); Entry.Clear; Index := 0; @@ -390,8 +286,8 @@ procedure TGCMTestDataLoader.ReadBlockMetaDataLine(const Line : string; end; procedure TGCMTestDataLoader.ReadDataLine(const Line : string; - var Entry : TGCMTestSetEntry; - TestData : TGCMTestDataList; + var Entry : TAuthenticatedCipherTestSetEntry; + TestData : TAuthenticatedTestDataList; var Index : Byte); begin // Data entries do not contain [ @@ -441,7 +337,7 @@ procedure TestTDECGCM.SetUp; inherited; FTestDataLoader := TGCMTestDataLoader.Create; - FTestDataList := TGCMTestDataList.Create; + FTestDataList := TAuthenticatedTestDataList.Create; FCipherAES := TCipher_AES.Create; FCipherAES.Mode := TCipherMode.cmGCM; @@ -458,7 +354,7 @@ procedure TestTDECGCM.TearDown; procedure TestTDECGCM.TestDecode; var - TestDataSet : TGCMTestSetEntry; + TestDataSet : TAuthenticatedCipherTestSetEntry; i : Integer; DecryptData : TBytes; begin @@ -520,7 +416,7 @@ procedure TestTDECGCM.TestDecode; procedure TestTDECGCM.TestDecodeAuthenticationFailure; var - TestDataSet : TGCMTestSetEntry; + TestDataSet : TAuthenticatedCipherTestSetEntry; i : Integer; begin FTestDataLoader.LoadFile('..\..\Unit Tests\Data\GCM128AuthenticationFailures.rsp', FTestDataList); @@ -564,7 +460,7 @@ procedure TestTDECGCM.TestDecodeAuthenticationFailure; procedure TestTDECGCM.TestEncode; var - TestDataSet : TGCMTestSetEntry; + TestDataSet : TAuthenticatedCipherTestSetEntry; i : Integer; EncryptData : TBytes; EncrDataStr : string; @@ -616,6 +512,90 @@ procedure TestTDECGCM.TestEncode; end; end; +procedure TestTDECGCM.TestEncodeConstData_86; +var + cipher : TCipher_AES128; + tag : TBytes; + refPlainText : Array[0..3] of LongWord; + ciphText : Array[0..3] of LongWord; + key : Array[0..3] of LongWord; + iv : Array[0..2] of LongWord; + refCipherText : Array[0..3] of LongWord; + refTag : Array[0..3] of LongWord; + hea : TBytes; + +type + TUINT32Byte = Array[0..3] of Byte; + PUINT32Byte = ^TUINT32Byte; + +// test key/cipher text and IV from an ARM based platform +const cAESKey : Array[0..3] of Longword = ($C939CC13, $397C1D37, $DE6AE0E1, $CB7C423C ); + cAESIV : Array[0..2] of Longword = ($B3D8CC01, $7CBB89B3, $9E0F67E2); + + cPlainText : Array[0..3] of LongWord = ($c3b3c41f, $113a31b7, $3d9a5cd4, $32103069 ); + cCipherText : Array[0..3] of LongWord = ($93FE7D9E, $9BFD1034, $8A5606E5, $CAFA7354 ); + + cExpectedTag : Array[0..3] of LongWord = ($0032A1DC, $85F1C978, $6925A2E7, $1D8272DD); + cAESHea : Array[0..3] of LongWord = ( $24825602, $bd12a984, $e0092d3e, $448eda5f ); + + function InvUINT32( value : UINT32 ) : UINT32; + var + v1, v2 : PUINT32Byte; + begin + v1 := @value; + v2 := @Result; + + v2^[3] := v1^[0]; + v2^[2] := v1^[1]; + v2^[1] := v1^[2]; + v2^[0] := v1^[3]; + end; + + procedure InitKey; + var + i : Integer; + begin + for i := 0 to High(cAESKey) do + key[i] := InvUINT32(cAESKey[i]); + + for i := 0 to High(cAESIV) do + iv[i] := InvUINT32(cAESIV[i]); + + for i := 0 to High(refPlainText) do + refPlainText[i] := InvUINT32(cPlainText[i]); + + for i := 0 to High(refCipherText) do + refCipherText[i] := InvUINT32(cCipherText[i]); + + for i := 0 to High(cExpectedTag) do + refTag[i] := InvUINT32(cExpectedTag[i]); + + SetLength(hea, sizeof(cAESHea)); + for i := 0 to High(cExpectedTag) do + PLongWord(@hea[i*4])^ := InvUINT32(cAESHea[i]); + end; + +begin + InitKey; + cipher := TCipher_AES128.Create; + try + cipher.Mode := cmGCM; + cipher.Init( key, sizeof(key), iv, sizeof(iv), 0 ); + cipher.AuthenticationResultBitLength := 128; + cipher.DataToAuthenticate := hea; + + cipher.Encode(refPlainText, ciphText, sizeof(refPlainText)); + cipher.Done; + tag := cipher.CalculatedAuthenticationResult; + finally + cipher.Free; + end; + + Check( CompareMem(@refCipherText[0], @ciphText[0], sizeof(ciphText)), 'Cipher failed'); + Check( CompareMem(@refTag[0], @tag[0], sizeof(refTag)), 'Tag failed'); +end; + + procedure TestTDECGCM.TestGetExpectedAuthenticationResult; var Exp, Act: TBytes; @@ -655,7 +635,7 @@ procedure TestTDECGCM.TestDecodeStream; var ctbStream: TBytesStream; ctBytes: TBytes; - TestDataSet : TGCMTestSetEntry; + TestDataSet : TAuthenticatedCipherTestSetEntry; i : Integer; DecryptData : TBytes; ptbStream: TBytesStream; @@ -745,7 +725,7 @@ procedure TestTDECGCM.DoTestEncodeStream_LoadAndTestCAVSData(const aMaxChunkSize: Int64); var i : Integer; - TestDataSet : TGCMTestSetEntry; + TestDataSet : TAuthenticatedCipherTestSetEntry; curSetIndex: Integer; begin FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV128.rsp', FTestDataList); @@ -784,7 +764,7 @@ procedure TestTDECGCM.DoTestEncodeStream_TestSingleSet(const aSetIndex, curChunkSize: Int64; dataLeftToEncode: Int64; ptBytes: TBytes; - TestDataSet : TGCMTestSetEntry; + TestDataSet : TAuthenticatedCipherTestSetEntry; EncryptData : TBytes; ptbStream: TBytesStream; begin @@ -810,6 +790,13 @@ procedure TestTDECGCM.DoTestEncodeStream_TestSingleSet(const aSetIndex, // Apply chunking if needed if aMaxChunkSize > 0 then curChunkSize := Min(dataLeftToEncode, aMaxChunkSize); +// Darf vermutlich so nicht sein, es darf vermutlich nur einen EncodeStream Aufruf +// geben. Möglicherwiese ist das Padding wie es jetzt umgesetzt ist nicht ganz richtig, +// da man sonst keinen dynamischen Stream haben kann. Gehört vermutlich ins Done, +// aber das hat noch keinen Stream, braucht also eine überladene Variante mit +// Outputstream als Parameter... +// Zuerst test mal ohne Schleife testen. EncodeStream darf nicht anhand der Size +// das "globale" Ende des Streams ermitteln, sonst nichts nachschiebbar. FCipherAES.EncodeStream(ptbStream, ctbStream, curChunkSize); Dec(dataLeftToEncode, curChunkSize); until (dataLeftToEncode = 0); @@ -912,12 +899,115 @@ procedure TestTDECGCM.TestSetGetDataToAuthenticate; RawByteString(StringOf(FCipherAES.DataToAuthenticate))); end; +procedure TestTDECGCM.TestStreamGCM_87; +// testing of https://github.com/MHumm/DelphiEncryptionCompendium/issues/87 +const cKey : Array[0..3] of LongWord = ( $55A46905, $AA23072B, $1309087f, $A5020869 ); + cIV : Array[0..2] of LongWord = ($1, $2, $3 ); + +var inp : TBytes; + inpStream : TMemoryStream; + + cipher : TCipher_AES128; + outStream : TMemoryStream; + decodeStream : TMemoryStream; + out1, out2 : TBytes; + i : integer; + hea : TBytes; + tag2, tag1, tag3 : TBytes; +begin + // needs to be larger than the default block size of 8192 (in EncodeStream) + SetLength(inp, 32768); + + for i := 0 to Length(inp) - 1 do + inp[i] := i mod 255; + + inpStream := TMemoryStream.Create; + inpStream.WriteBuffer(inp, Length(inp)); + + // ########################################### + // #### First run -> direct encoding + cipher := TCipher_AES128.Create; + try + cipher.Mode := cmGCM; + cipher.Init( cKey, sizeof(cKey), civ, sizeof(civ) ); + + cipher.AuthenticationResultBitLength := 128; + // some authenticatino data + hea := [1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + cipher.DataToAuthenticate := hea; + + out1 := cipher.EncodeBytes(inp); + + cipher.Done; + tag1 := cipher.CalculatedAuthenticationResult; + finally + cipher.Free; + end; + + + // ########################################### + // #### Second run -> stream + outStream := TMemoryStream.Create; + inpStream.Position := 0; + cipher := TCipher_AES128.Create; + try + cipher.Mode := cmGCM; + cipher.Init( cKey, sizeof(cKey), civ, sizeof(civ) ); + + cipher.AuthenticationResultBitLength := 128; + hea := [1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + cipher.DataToAuthenticate := hea; + + cipher.EncodeStream(inpStream, outStream, inpStream.Size, nil); + cipher.Done; + tag2 := cipher.CalculatedAuthenticationResult; + finally + cipher.Free; + end; + + outStream.Position := 0; + SetLength(out2, outStream.Size); + outStream.ReadBuffer(out2, outStream.Size); + + Check( CompareMem(@out1[0], @out2[0], Length(out1) ), 'AES128 Encryption failed'); + Check( CompareMem(@tag1[0], @tag2[0], Length(tag1) ), 'Authentication Result do not match'); + + + // ########################################### + // #### Decode + decodeStream := TMemoryStream.Create; + inpStream.Position := 0; + outStream.Position := 0; + cipher := TCipher_AES128.Create; + try + cipher.Mode := cmGCM; + cipher.Init( cKey, sizeof(cKey), civ, sizeof(civ) ); + + cipher.AuthenticationResultBitLength := 128; + hea := [1, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + cipher.DataToAuthenticate := hea; + + cipher.DecodeStream(outStream, decodeStream, outStream.Size, nil); + cipher.Done; + tag3 := cipher.CalculatedAuthenticationResult; + finally + cipher.Free; + end; + + Check( CompareMem(@tag3[0], @tag2[0], Length(tag1) ), 'Authentication Result do not match'); + Check( CompareMem( inpStream.Memory, decodeStream.Memory, inpStream.Size ), 'Decoding failed'); + + decodeStream.Free; + outStream.Free; + inpStream.Free; +end; + initialization // Register all test cases to be run {$IFDEF DUnitX} TDUnitX.RegisterTestFixture(TestTDECGCM); {$ELSE} - RegisterTest(TestTDECGCM.Suite); + RegisterTest('DEC authenticated cipher modes', TestTDECGCM.Suite); {$ENDIF} end. diff --git a/Unit Tests/Tests/TestDECHashSHA3.pas b/Unit Tests/Tests/TestDECHashSHA3.pas index a427b9aa..e545fa12 100644 --- a/Unit Tests/Tests/TestDECHashSHA3.pas +++ b/Unit Tests/Tests/TestDECHashSHA3.pas @@ -1,4 +1,4 @@ -{***************************************************************************** +{***************************************************************************** The DEC team (see file NOTICE.txt) licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance @@ -1755,14 +1755,13 @@ procedure TestTHash_SHA3_Base.AddLastByteForCodeTest(var lDataRow : IHashTest SHA3InputVector : RawByteString; LastByteLength : UInt8); var - LastByteLen : UInt8; MsgWithFixup : RawByteString; begin - MsgWithFixup := AddLastByteForKeccakTest(SHA3InputVector, LastByteLen); + MsgWithFixup := AddLastByteForKeccakTest(SHA3InputVector, LastByteLength); //LastByteLen); lDataRow.AddInputVector(MsgWithFixup); - lDataRow.FinalBitLength := LastByteLen; + lDataRow.FinalBitLength := LastByteLength; - THash_SHA3Base(FHash).FinalByteLength := LastByteLen; + THash_SHA3Base(FHash).FinalByteLength := LastByteLength; lDataRow.ExpectedOutputUTFStrTest := CalcUnicodeHash(string(TFormat_HexL.Encode(MsgWithFixup)), FHash); diff --git a/readme.md b/readme.md index 3b91ddaa..7fe40e2c 100644 --- a/readme.md +++ b/readme.md @@ -12,7 +12,7 @@ It contains algorithms for these categories: * CRCs: non cryptographic checksums based on CRC algorithms ## Which Delphi versions are compatible? -The current version 6.4.1 is compatible with Delphi XE2 - Delphi 12.3 Athens. +The last release version 6.4.1 is compatible with Delphi XE2 - Delphi 12.3 Athens. When defining the NO_ASM define in DECOptions.inc it is compatible with all platforms supported by Delphi! It might be compatible with FPC, but this has not been focus and is not tested. The development branch contains a more @@ -146,6 +146,7 @@ Modes ending on x have been invented by the original developer of DEC * CFS8 * CFSx * GCM +* CCM ## Contained key derivation algorithms: * KDF1