From 760681ff6f90b645dec964797d1e744e0b12ab9a Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Mon, 16 Jun 2025 23:09:04 +0200 Subject: [PATCH 01/12] Progress: Removed class TCipher_ChaCha_Poly1305 -> now in Mode Still not working. --- Source/DECCipherBase.pas | 3 +- Source/DECCipherModes.pas | 71 +- Source/DECCipherModesPoly1305.pas | 2017 ++++++++++++++++++++ Source/DECCiphers.pas | 1085 ++++++++++- Source/DECOptions.inc | 2 +- Unit Tests/DECDUnitTestSuite.dpr | 31 +- Unit Tests/DECDUnitTestSuite.dproj | 28 + Unit Tests/Tests/TestDECChaChaPoly1305.pas | 353 ++++ 8 files changed, 3578 insertions(+), 12 deletions(-) create mode 100644 Source/DECCipherModesPoly1305.pas create mode 100644 Unit Tests/Tests/TestDECChaChaPoly1305.pas diff --git a/Source/DECCipherBase.pas b/Source/DECCipherBase.pas index f6cecfae..c2efe356 100644 --- a/Source/DECCipherBase.pas +++ b/Source/DECCipherBase.pas @@ -183,7 +183,8 @@ interface cmCFSx, // CFS on Blocksize bytes cmECBx, // Electronic Code Book cmGCM, // Galois Counter Mode - cmCCM // Counter with CBC-MAC 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) diff --git a/Source/DECCipherModes.pas b/Source/DECCipherModes.pas index e4673bda..7f3e4c0e 100644 --- a/Source/DECCipherModes.pas +++ b/Source/DECCipherModes.pas @@ -27,6 +27,7 @@ interface System.SysUtils, {$ENDIF} DECTypes, DECCipherBase, DECCipherModesGCM, DECCipherModesCCM, + DECCipherModesPoly1305, DECCipherInterface; type @@ -155,6 +156,14 @@ TDECCipherModes = class(TDECCipher, IDECAuthenticatedCipher) /// /// Exception raised unconditionally. /// + + + /// + /// Implementation of the Pol1305 polynom. Only created when gmPoly1305 is + /// set as mode. + /// + FPOLY1305 : TPoly1305; + procedure ReportInvalidMessageLength(Cipher: TDECCipher); /// /// Allows to run code after the initialization vector has been initialized @@ -245,7 +254,15 @@ TDECCipherModes = class(TDECCipher, IDECAuthenticatedCipher) /// source length is 0. /// procedure EncodeGCM(Source, Dest: PUInt8Array; Size: Integer); virtual; + /// + /// Poly1305: encryption with addtional optional authentication. + /// Implemented in its own unit and only usable with ChaCha20 (and maybe AES128) - + /// Currently only one class overrides this method. + /// + procedure EncodePoly1305(Source, Dest: PUInt8Array; Size: Integer); virtual; + + /// /// Counter with CBC-MAC Mode: encryption with addtional optional authentication. /// Implemented in its own unit, but needed here to be callable even if /// source length is 0. @@ -338,7 +355,14 @@ TDECCipherModes = class(TDECCipher, IDECAuthenticatedCipher) /// Galois Counter Mode, details are implemented in DECCipherModesGCM /// procedure DecodeGCM(Source, Dest: PUInt8Array; Size: Integer); virtual; + /// + /// Poly1305, details are implemented in DECCipherModesPoly1305. + /// This routine needs to be overridden by successor classes. + /// + procedure DecodePoly1305(Source, Dest: PUInt8Array; Size: Integer); virtual; + + /// /// Counter with CBC-MAC Mode, details are implemented in DECCipherModesCCM /// procedure DecodeCCM(Source, Dest: PUInt8Array; Size: Integer); virtual; @@ -494,6 +518,7 @@ procedure TDECCipherModes.SetDataToAuthenticate(const Value: TBytes); case FMode of cmGCM: FGCM.DataToAuthenticate := Value; cmCCM: FCCM.DataToAuthenticate := Value; + cmPoly1305: FPOLY1305.DataToAuthenticate := Value; else raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; @@ -504,6 +529,7 @@ procedure TDECCipherModes.SetExpectedAuthenticationResult(const Value: TBytes); case FMode of cmGCM: FGCM.ExpectedAuthenticationTag := Value; cmCCM: FCCM.ExpectedAuthenticationTag := Value; + cmPoly1305: FPOLY1305.ExpectedAuthenticationTag := Value; else raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; @@ -515,6 +541,7 @@ procedure TDECCipherModes.SetAuthenticationResultBitLength( case FMode of cmGCM: FGCM.AuthenticationTagBitLength := Value; cmCCM: FCCM.AuthenticationTagBitLength := Value; + cmPoly1305: FPOLY1305.AuthenticationTagBitLength := Value; else raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; @@ -538,6 +565,7 @@ procedure TDECCipherModes.Encode(const Source; var Dest; DataSize: Integer); cmCFS8: EncodeCFS8(@Source, @Dest, DataSize); cmCFSx: EncodeCFSx(@Source, @Dest, DataSize); cmGCM : EncodeGCM(@Source, @Dest, DataSize); + cmPoly1305: EncodePoly1305(@Source, @Dest, DataSize); cmCCM : EncodeCCM(@Source, @Dest, DataSize); end; end; @@ -713,6 +741,7 @@ function TDECCipherModes.GetDataToAuthenticate: TBytes; case FMode of cmGCM: Result := FGCM.DataToAuthenticate; cmCCM: Result := FCCM.DataToAuthenticate; + cmPoly1305: Result := FPOLY1305.DataToAuthenticate; else raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cCCM']); end; @@ -723,6 +752,7 @@ function TDECCipherModes.GetExpectedAuthenticationResult: TBytes; case FMode of cmGCM: Result := FGCM.ExpectedAuthenticationTag; cmCCM: Result := FCCM.ExpectedAuthenticationTag; + cmPoly1305: REsult := FPOLY1305.ExpectedAuthenticationTag; else raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; @@ -733,6 +763,7 @@ function TDECCipherModes.GetStandardAuthenticationTagBitLengths: TStandardBitLen case FMode of cmGCM: Result := FGCM.GetStandardAuthenticationTagBitLengths; cmCCM: Result := FCCM.GetStandardAuthenticationTagBitLengths; + cmPoly1305: Result := FPOLY1305.GetStandardAuthenticationTagBitLengths; else begin SetLength(Result, 1); @@ -746,6 +777,7 @@ function TDECCipherModes.GetAuthenticationResultBitLength: Integer; case FMode of cmGCM: Result := FGCM.AuthenticationTagBitLength; cmCCM: Result := FCCM.AuthenticationTagBitLength; + cmPoly1305: Result := FPOLY1305.AuthenticationTagBitLength; else raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; @@ -756,6 +788,7 @@ function TDECCipherModes.GetCalcAuthenticatonResult: TBytes; case FMode of cmGCM: Result := FGCM.CalculatedAuthenticationTag; cmCCM: Result := FCCM.CalculatedAuthenticationTag; + cmPoly1305: Result := FPOLY1305.CalculatedAuthenticationTag; else raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; @@ -763,15 +796,19 @@ function TDECCipherModes.GetCalcAuthenticatonResult: TBytes; procedure TDECCipherModes.InitMode; begin - if FMode in [TCipherMode.cmGCM, TCipherMode.cmCCM] then + if FMode in [TCipherMode.cmGCM, TCipherMode.cmCCM, TCipherMode.cmPoly1305] then begin if (Context.BlockSize = 16) then begin case FMode of cmGCM: FGCM := TGCM.Create; cmCCM: FCCM := TCCM.Create; + cmPoly1305: FPOLY1305 := TPoly1305.Create; end; end + else if Context.BlockSize < 16 + then + FPOLY1305 := TPoly1305.Create else // GCM and CCM require a cipher with 128 bit block size raise EDECCipherException.CreateResFmt(@sInvalidBlockSize, @@ -785,6 +822,9 @@ procedure TDECCipherModes.InitMode; if Assigned(FCCM) then FreeAndNil(FCCM); + + if Assigned(FPOLY1305) then + FreeAndNil(FPOLY1305); end; end; @@ -886,6 +926,14 @@ procedure TDECCipherModes.EncodeGCM(Source, Dest: PUInt8Array; Size: Integer); FGCM.Encode(Source, Dest, Size); end; +procedure TDECCipherModes.EncodePoly1305(Source, Dest: PUInt8Array; + Size: Integer); +begin + if size < 0 then + Size := 0; + FPOLY1305.Encode(Source, Dest, Size); +end; + procedure TDECCipherModes.EncodeCCM(Source, Dest: PUInt8Array; Size: Integer); begin if (Size < 0) then @@ -937,6 +985,7 @@ procedure TDECCipherModes.Decode(const Source; var Dest; DataSize: Integer); cmCFS8: DecodeCFS8(@Source, @Dest, DataSize); cmCFSx: DecodeCFSx(@Source, @Dest, DataSize); cmGCM : DecodeGCM(@Source, @Dest, DataSize); + cmPoly1305: DecodePoly1305(@Source, @Dest, DataSize); cmCCM : DecodeCCM(@Source, @Dest, DataSize); end; end; @@ -1135,10 +1184,20 @@ procedure TDECCipherModes.DecodeOFBx(Source, Dest: PUInt8Array; Size: Integer); end; end; +procedure TDECCipherModes.DecodePoly1305(Source, Dest: PUInt8Array; + Size: Integer); +begin + if (Size < 0) then + Size := 0; + + FPOLY1305.Decode(Source, Dest, Size); +end; + destructor TDECCipherModes.Destroy; begin FGCM.Free; FCCM.Free; + FPOLY1305.Free; inherited; end; @@ -1159,6 +1218,15 @@ procedure TDECCipherModes.Done; (not IsEqual(FCCM.ExpectedAuthenticationTag, FCCM.CalculatedAuthenticationTag)) then raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); end; + cmPoly1305: begin + // ########################################### + // #### Now the time is here to create the tag... + FPOLY1305.Finalize; + + if (length(FPOLY1305.ExpectedAuthenticationTag) > 0) and + (not IsEqual(FPOLY1305.ExpectedAuthenticationTag, FPOLY1305.CalculatedAuthenticationTag)) then + raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); + end; end; end; @@ -1169,6 +1237,7 @@ procedure TDECCipherModes.OnAfterInitVectorInitialization(const OriginalInitVect case FMode of cmGCM: FGCM.Init(self.DoEncode, OriginalInitVector); cmCCM: FCCM.Init(self.DoEncode, OriginalInitVector); + cmPoly1305: FPOLY1305.Init(self.DoEncode, OriginalInitVector); end; end; diff --git a/Source/DECCipherModesPoly1305.pas b/Source/DECCipherModesPoly1305.pas new file mode 100644 index 00000000..5495a6ff --- /dev/null +++ b/Source/DECCipherModesPoly1305.pas @@ -0,0 +1,2017 @@ +{***************************************************************************** + 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; + + POLY1305_SSE2_BLOCK_SIZE = 32; + type + TPoly1305Nonce = Array[0..3] of UInt32; + TPoly1305BlockMethod = procedure ( pData : PByteArray; size : integer ) of Object; + TPoly1305EmitMethod = procedure( var mac: TBlock16Byte ) of Object; + THArr = Array[0..4] of UInt32; + PHArr = ^THArr; + TRArr = Array[0..3] of UInt32; + PRArr = ^TRArr; + TYMM = Array[0..7] of UInt32; + TYMM64 = Array[0..3] of Int64; + TXMM = Array[0..3] of UInt32; + + TPoly1305StateFlag = (poly1305_started = 1, poly1305_final_shift8 = 4, + poly1305_final_shift16 = 8, + poly1305_final_r2_r = 16, // use [r^2,r] for the final block */ + poly1305_final_r_1 = 32 // use [r,1] for the final block */ + ); + + type + TH = packed record + case byte of + 0: (H : Array[0..2] of UInt64); + 1: (HH: Array[0..19] of Uint32); + 2: (H32 : THArr); + end; + + TPoly1305_state_internal_t = packed record + hmac : TH; + R : Array[0..4] of Uint32; + R2 : Array[0..4] of UInt32; + R3 : Array[0..4] of UInt32; + R4 : Array[0..4] of UInt32; + pad : Array[0..1] of UInt64; + flags : Uint64; + end; + PPoly1305_state_internal_t = ^TPoly1305_state_internal_t; + + TPoly1305State = Array[0..191] of Byte; + private + // avx structures + fPoly1305State : TPoly1305State; + fPPoly1305State : PPoly1305_state_internal_t; + + // pas structures + FH : PHArr; + FR : PRArr; + + // + + fIV : T32ByteArray; + FNonce : TPoly1305Nonce; + + FEncryptionMethod : TEncodeDecodeMethod; + + // reminder... + fNum : integer; + fData : Array[0..POLY1305_BLOCK_SIZE - 1] of Byte; + + FAuthDataLen : integer; + FCipherLen : integer; + fPolyInitComplete : boolean; + fPolyBlkFunc : TPoly1305BlockMethod; + fPolyEmitFunc : TPoly1305EmitMethod; + + function U8ToU32( pData : PByteArray ) : UInt32; + procedure U32ToU8(pData : PByteArray; value : UInt32); + + procedure Poly1305Blocks( pData : PByteArray; size : integer; padBit : UInt32 ); + procedure Poly1305Emit( var mac : TBlock16Byte; const nonce : TPoly1305Nonce ); + procedure Poly1305Finalize( var mac : TBlock16Byte ); + + procedure Poly1305Init_SSE( initVec : PByte ); + procedure Poly1305Blocks_SSE( pData : PByteArray; size : integer ); + procedure Poly1305Emit_SSE( var mac : TBlock16Byte ); + + procedure Burn; + protected + // ########################################### + // #### base functionality + + // ########################################### + // #### Authentication block functions + procedure BeginPoly1304Auth; + public + class var UseSSE : boolean; + + constructor Create; + + procedure UpdatePoly( pData : PByteArray; size : integer); + procedure InitInternal(const InitVector : T32ByteArray); + procedure PadAndFinalizeAEAD; + procedure Finalize; + + /// + /// 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. + /// The function can be called multiple times. Internally the + /// hash is updated on each call. + /// + procedure Encode(Source, Dest : PUInt8Array; + CiphertextSize : Integer); override; + + /// + /// Decodes a block of data using the supplied cipher. + /// The function can be called multiple times. Internally the + /// hash is updated on each call. + /// + procedure Decode(Source, + Dest : PUInt8Array; + Size : Integer + ); 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.BeginPoly1304Auth; +var aLen : integer; + vec : TBytes; +begin + InitInternal(fIV); + + // update the polynom with the unencrypted authentication data + FAuthDataLen := Length(FDataToAuthenticate); + if fAuthDataLen > 0 then + begin + // pad to blocksize if ncessary + aLen := Length(FDataToAuthenticate); + 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], FAuthDataLen); + //vec[FAuthDataLen] := 1; + end + else + vec := FDataToAuthenticate; + fPolyBlkFunc( @vec[0], POLY1305_BLOCK_SIZE); + end; + FCipherLen := 0; +end; + + +procedure TPoly1305.Burn; +begin + FillChar(FH, sizeof(FH), 0); + FillChar(FNonce, sizeof(FNonce), 0); + FillChar(FR, sizeof(FR), 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; + + fPPoly1305State := @fPoly1305State[0]; + FH := @fPoly1305State[0]; + FR := @fPoly1305State[sizeof(THarr)]; + + if useSSE then + begin + fPolyBlkFunc := Poly1305Blocks_SSE; // Poly1305Blocks_AVX + fPolyEmitFunc := Poly1305Emit_SSE; + end + else + begin + fPolyBlkFunc := UpdatePoly; + fPolyEmitFunc := Poly1305Finalize; + end; +end; + +procedure TPoly1305.Decode(Source, Dest: PUInt8Array; Size: Integer); +begin + if not fPolyInitComplete then + BeginPoly1304Auth; + + fPolyBlkFunc( PByteArray( Source ), Size ); + inc( FCipherLen, Size ); + + FEncryptionMethod( Source, Dest, Size ); +end; + +procedure TPoly1305.Encode(Source, Dest: PUInt8Array; + CiphertextSize: Integer); +begin + if not fPolyInitComplete then + BeginPoly1304Auth; + + FEncryptionMethod( Source, Dest, CipherTextSize ); + fPolyBlkFunc( PByteArray( dest ), CipherTextSize ); + inc( FCipherLen, CipherTextSize ); +end; + + +procedure TPoly1305.Finalize; +var mac : TBlock16Byte; +begin + if not fPolyInitComplete then + BeginPoly1304Auth; + + fPolyEmitFunc( mac ); + + SetLength(FCalcAuthenticationTag, sizeof(mac)); + Move(mac, FCalcAuthenticationTag[0], sizeof(mac)); + + FillChar(mac, sizeof(mac), 0); + Burn; +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)); + + FAuthDataLen := 0; + FCipherLen := 0; + FEncryptionMethod := EncryptionMethod; +end; + +procedure TPoly1305.InitInternal(const InitVector: T32ByteArray); +begin + fPolyInitComplete := True; + + if UseSSE then + begin + Poly1305Init_SSE(@initVector[0]); + end + else + begin + 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]); + end; + + fNum := 0; + +end; + +procedure TPoly1305.PadAndFinalizeAEAD; +var lens : Array[0..1] of UInt64; +begin + if not fPolyInitComplete then + BeginPoly1304Auth; + + // 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] := FAuthDataLen; + lens[1] := FCipherLen; + 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]); + 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; + +type + XMMWORD = Array[0..7] of Word; + +// dump from poly1305-donna-x86-sse2-incremental-source.c +procedure _poly1305_init_ext_sse2(st : TPoly1305.PPoly1305_state_internal_t; key : PByte; bytes : integer); cdecl; +asm + push ebp + pxor xmm0, xmm0 + mov ebp, esp + push edi + push esi + push ebx + and esp, -8 + sub esp, 56 + mov edx, DWORD PTR [ebp+12] + mov eax, DWORD PTR [ebp+8] + movups XMMWORD PTR [eax+32], xmm0 + movups XMMWORD PTR [eax], xmm0 + movups XMMWORD PTR [eax+16], xmm0 + mov ebx, DWORD PTR [edx] + mov eax, DWORD PTR [edx+4] + mov ecx, DWORD PTR [edx+8] + mov edi, DWORD PTR [edx+12] + mov esi, ebx + shr ebx, 26 + and esi, 67108863 + mov DWORD PTR [esp+40], esi + mov esi, eax + shr eax, 20 + sal esi, 6 + or esi, ebx + mov ebx, esi + mov esi, DWORD PTR [esp+40] + and ebx, 67108611 + mov DWORD PTR [esp+36], ebx + mov ebx, ecx + shr ecx, 14 + sal ebx, 12 + or ebx, eax + mov eax, edi + shr edi, 8 + sal eax, 18 + and ebx, 67092735 + and edi, 1048575 + or eax, ecx + mov ecx, eax + mov eax, DWORD PTR [ebp+8] + and ecx, 66076671 + mov DWORD PTR [eax+40], esi + mov esi, eax + mov eax, DWORD PTR [esp+36] + mov DWORD PTR [esi+48], ebx + mov DWORD PTR [esi+52], ecx + mov DWORD PTR [esi+56], edi + mov DWORD PTR [esi+44], eax + mov eax, DWORD PTR [edx+16] + mov DWORD PTR [esi+100], eax + mov eax, DWORD PTR [edx+20] + mov DWORD PTR [esi+104], eax + mov eax, DWORD PTR [edx+24] + mov DWORD PTR [esi+108], eax + mov eax, DWORD PTR [edx+28] + lea edx, [ecx+ecx*4] + mov DWORD PTR [esi+112], eax + mov esi, edx + lea edx, [edi+edi] + mov DWORD PTR [esp+28], edi + lea edi, [ebx+ebx] + mov eax, edi + mov DWORD PTR [esp+48], edx + mul esi + mov DWORD PTR [esp+12], esi + mov DWORD PTR [esp+32], ebx + lea ebx, [ebx+ebx*4] + mov esi, eax + mov eax, DWORD PTR [esp+36] + mov edi, edx + lea eax, [eax+eax*4] + mul DWORD PTR [esp+48] + add esi, eax + mov eax, DWORD PTR [esp+40] + adc edi, edx + mul eax + add esi, eax + adc edi, edx + mov eax, esi + mov edx, edi + mov edi, DWORD PTR [esp+36] + mov DWORD PTR [esp], eax + and eax, 67108863 + mov DWORD PTR [esp+4], edx + lea esi, [edi+edi] + mov DWORD PTR [esp+8], eax + mov eax, ebx + mov DWORD PTR [esp+20], esi + mul DWORD PTR [esp+48] + mov esi, DWORD PTR [esp+40] + lea edi, [esi+esi] + lea esi, [ecx+ecx] + mov DWORD PTR [esp+24], edi + mov edi, edx + mov DWORD PTR [esp+16], esi + mov esi, eax + mov eax, DWORD PTR [esp+20] + mul DWORD PTR [esp+40] + add esi, eax + mov eax, ecx + mov ecx, DWORD PTR [esp+36] + adc edi, edx + mul DWORD PTR [esp+12] + add eax, esi + mov esi, DWORD PTR [esp] + adc edx, edi + mov edi, DWORD PTR [esp+4] + shrd esi, edi, 26 + shr edi, 26 + add esi, eax + mov eax, esi + adc edi, edx + and eax, 67108863 + mov DWORD PTR [esp], eax + mov eax, ecx + mul ecx + mov ecx, eax + mov ebx, edx + mov eax, DWORD PTR [esp+32] + mul DWORD PTR [esp+24] + add ecx, eax + mov eax, DWORD PTR [esp+12] + adc ebx, edx + mul DWORD PTR [esp+48] + add eax, ecx + adc edx, ebx + shrd esi, edi, 26 + shr edi, 26 + add esi, eax + mov eax, esi + adc edi, edx + and eax, 67108863 + mov DWORD PTR [esp+48], eax + mov eax, DWORD PTR [esp+40] + mul DWORD PTR [esp+16] + mov ecx, eax + mov ebx, edx + mov eax, DWORD PTR [esp+20] + mul DWORD PTR [esp+32] + add ecx, eax + adc ebx, edx + mov edx, DWORD PTR [esp+28] + lea eax, [edx+edx*4] + mul edx + add eax, ecx + adc edx, ebx + shrd esi, edi, 26 + shr edi, 26 + add eax, esi + mov DWORD PTR [esp+40], eax + mov ebx, DWORD PTR [esp+32] + adc edx, edi + mov esi, eax + mov DWORD PTR [esp+44], edx + and esi, 67108863 + mov edi, DWORD PTR [esp+48] + mov eax, ebx + mul ebx + mov ecx, eax + mov ebx, edx + mov eax, DWORD PTR [esp+28] + mul DWORD PTR [esp+24] + add ecx, eax + mov eax, DWORD PTR [esp+36] + adc ebx, edx + mul DWORD PTR [esp+16] + add eax, ecx + mov ecx, DWORD PTR [esp+40] + adc edx, ebx + mov ebx, DWORD PTR [esp+44] + shrd ecx, ebx, 26 + shr ebx, 26 + add eax, ecx + adc edx, ebx + mov ecx, eax + mov ebx, DWORD PTR [esp+8] + shrd eax, edx, 26 + mov edx, DWORD PTR [esp] + and ecx, 67108863 + lea eax, [eax+eax*4] + mov DWORD PTR [esp+32], ecx + add eax, ebx + mov ebx, eax + shr eax, 26 + add edx, eax + mov eax, DWORD PTR [ebp+8] + and ebx, 67108863 + mov DWORD PTR [esp+40], ebx + mov DWORD PTR [eax+60], ebx + mov DWORD PTR [eax+64], edx + mov DWORD PTR [eax+68], edi + mov DWORD PTR [eax+72], esi + mov DWORD PTR [eax+76], ecx + lea eax, [esi+esi*4] + mov ebx, eax + lea eax, [ecx+ecx] + lea ecx, [edi+edi] + mov DWORD PTR [esp+36], edx + mov DWORD PTR [esp+28], eax + mov eax, ecx + lea edi, [edi+edi*4] + mul ebx + mov DWORD PTR [esp+12], ebx + mov ecx, eax + mov eax, DWORD PTR [esp+40] + mov ebx, edx + mul eax + add ecx, eax + adc ebx, edx + mov edx, DWORD PTR [esp+36] + lea eax, [edx+edx*4] + mul DWORD PTR [esp+28] + add ecx, eax + adc ebx, edx + mov edx, DWORD PTR [esp+36] + lea eax, [edx+edx] + lea edx, [esi+esi] + mov DWORD PTR [esp+16], eax + mov eax, DWORD PTR [esp+40] + mov DWORD PTR [esp+24], edx + add eax, eax + mov DWORD PTR [esp+20], eax + mov eax, ecx + and eax, 67108863 + mov DWORD PTR [esp+8], eax + mov eax, edi + mul DWORD PTR [esp+28] + mov DWORD PTR [esp], eax + mov eax, esi + mov DWORD PTR [esp+4], edx + mul DWORD PTR [esp+12] + mov esi, eax + mov edi, edx + add esi, DWORD PTR [esp] + mov eax, DWORD PTR [esp+16] + adc edi, DWORD PTR [esp+4] + mul DWORD PTR [esp+40] + add eax, esi + adc edx, edi + shrd ecx, ebx, 26 + shr ebx, 26 + add ecx, eax + mov eax, DWORD PTR [esp+48] + adc ebx, edx + mul DWORD PTR [esp+20] + mov esi, ecx + and esi, 67108863 + mov DWORD PTR [esp], esi + mov esi, eax + mov eax, DWORD PTR [esp+36] + mov edi, edx + mul eax + add esi, eax + mov eax, DWORD PTR [esp+28] + adc edi, edx + mul DWORD PTR [esp+12] + add eax, esi + adc edx, edi + shrd ecx, ebx, 26 + shr ebx, 26 + add eax, ecx + mov ecx, DWORD PTR [esp+32] + adc edx, ebx + mov esi, eax + lea ebx, [ecx+ecx*4] + mov edi, edx + mov eax, ebx + mov DWORD PTR [esp+44], edi + mul ecx + mov ecx, eax + mov ebx, edx + mov eax, DWORD PTR [esp+40] + mov DWORD PTR [esp+40], esi + mul DWORD PTR [esp+24] + add ecx, eax + mov eax, DWORD PTR [esp+16] + adc ebx, edx + mul DWORD PTR [esp+48] + add eax, ecx + adc edx, ebx + shrd esi, edi, 26 + shr edi, 26 + add esi, eax + mov eax, DWORD PTR [esp+24] + adc edi, edx + mul DWORD PTR [esp+36] + mov ecx, eax + mov ebx, edx + mov eax, DWORD PTR [esp+32] + mul DWORD PTR [esp+20] + add ecx, eax + mov eax, DWORD PTR [esp+48] + adc ebx, edx + mul eax + add eax, ecx + mov ecx, esi + adc edx, ebx + shrd ecx, edi, 26 + mov ebx, edi + shr ebx, 26 + add eax, ecx + adc edx, ebx + mov DWORD PTR [esp+48], eax + mov ebx, DWORD PTR [ebp+8] + shrd eax, edx, 26 + mov DWORD PTR [esp+52], edx + lea edx, [eax+eax*4] + mov eax, DWORD PTR [esp+8] + add edx, eax + mov eax, DWORD PTR [esp] + mov ecx, edx + shr edx, 26 + add edx, eax + and ecx, 67108863 + mov DWORD PTR [ebx+80], ecx + mov DWORD PTR [ebx+84], edx + mov edx, DWORD PTR [esp+40] + mov eax, DWORD PTR [esp+48] + mov DWORD PTR [ebx+116], 0 + and edx, 67108863 + mov DWORD PTR [ebx+88], edx + mov edx, esi + and eax, 67108863 + and edx, 67108863 + mov DWORD PTR [ebx+96], eax + mov DWORD PTR [ebx+92], edx + lea esp, [ebp-12] + pop ebx + pop esi + pop edi + pop ebp +end; + +procedure _Poly1305_Blocks_sse2( st : TPoly1305.PPoly1305_state_internal_t; m : PByte; bytes : integer ); cdecl; +label L6, L7, L8, L10, L12, L13, L14, L15, L16, L18, L19, L28, L29; +const LC3 : TPoly1305.TXMM = ( 1, 0, 0, 0 ); + LC4 : TPoly1305.TXMM = ( 16777216, 0, 16777216, 0); + LC5 : TPoly1305.TXMM = ( 67108863, 0, 67108863, 0); + LC6 : TPoly1305.TXMM = ( 5, 0, 5, 0); +asm + push ebp + mov ebp, esp + push edi + push esi + push ebx + and esp, -16 + sub esp, 1168 + mov esi, DWORD PTR [ebp+8] + mov eax, DWORD PTR [ebp+12] + movdqa xmm0, XMMWORD PTR LC4 + mov ecx, DWORD PTR [ebp+16] + mov edx, DWORD PTR [esi+116] + movaps XMMWORD PTR [esp+1136], xmm0 + test dl, 4 + je L6 + movdqa xmm7, xmm0 + psrldq xmm7, 8 + movaps XMMWORD PTR [esp+1136], xmm7 +L6: + test dl, 8 + je L7 + pxor xmm7, xmm7 + movaps XMMWORD PTR [esp+1136], xmm7 +L7: + test dl, 1 + jne L8 + movq xmm0, QWORD PTR [eax+16] + movq xmm1, QWORD PTR [eax] + or edx, 1 + add eax, 32 + movq xmm2, QWORD PTR [eax-8] + sub ecx, 32 + movdqa xmm7, XMMWORD PTR LC5 + movdqa xmm5, XMMWORD PTR LC5 + punpcklqdq xmm1, xmm0 + movq xmm0, QWORD PTR [eax-24] + mov DWORD PTR [esi+116], edx + pand xmm7, xmm1 + punpcklqdq xmm0, xmm2 + movdqa xmm2, xmm1 + psrlq xmm2, 26 + psrlq xmm1, 52 + pand xmm2, XMMWORD PTR LC5 + movaps XMMWORD PTR [esp+1120], xmm2 + movdqa xmm2, xmm0 + psrlq xmm0, 40 + por xmm0, XMMWORD PTR [esp+1136] + psllq xmm2, 12 + por xmm1, xmm2 + movdqa xmm2, xmm0 + pand xmm5, xmm1 + psrlq xmm1, 26 + pand xmm1, XMMWORD PTR LC5 + test dl, 48 + je L10 +L29: + movd xmm3, DWORD PTR [esi+56] + and edx, 16 + movdqu xmm4, XMMWORD PTR [esi+40] + movaps XMMWORD PTR [esp+320], xmm3 + jne L28 + movdqa xmm6, xmm4 + movdqa xmm0, xmm4 + punpckldq xmm6, XMMWORD PTR LC3 + punpckhdq xmm0, XMMWORD PTR LC3 +L12: + pshufd xmm4, xmm6, 80 + movaps XMMWORD PTR [esp+304], xmm4 + pshufd xmm4, xmm6, 250 + movaps XMMWORD PTR [esp+336], xmm4 + pshufd xmm4, xmm0, 80 + pshufd xmm0, xmm0, 250 + movaps XMMWORD PTR [esp+288], xmm4 + movaps XMMWORD PTR [esp+272], xmm0 + jmp L13 + // .p2align 4,,10 + // .p2align 3 +L8: + movdqu xmm1, XMMWORD PTR [esi] + movdqu xmm0, XMMWORD PTR [esi+16] + movdqu xmm7, XMMWORD PTR [esi] + pshufd xmm1, xmm1, 250 + pshufd xmm5, xmm0, 80 + movaps XMMWORD PTR [esp+1120], xmm1 + pshufd xmm1, xmm0, 250 + movdqu xmm0, XMMWORD PTR [esi+32] + pshufd xmm7, xmm7, 80 + pshufd xmm2, xmm0, 80 + test dl, 48 + jne L29 +L10: + movdqu xmm0, XMMWORD PTR [esi+60] + pshufd xmm0, xmm0, 0 + movaps XMMWORD PTR [esp+304], xmm0 + movdqu xmm0, XMMWORD PTR [esi+60] + pshufd xmm0, xmm0, 85 + movaps XMMWORD PTR [esp+336], xmm0 + movdqu xmm0, XMMWORD PTR [esi+60] + pshufd xmm0, xmm0, 170 + movaps XMMWORD PTR [esp+288], xmm0 + movdqu xmm0, XMMWORD PTR [esi+60] + pshufd xmm0, xmm0, 255 + movaps XMMWORD PTR [esp+272], xmm0 + movd xmm0, DWORD PTR [esi+76] + pshufd xmm0, xmm0, 0 + movaps XMMWORD PTR [esp+320], xmm0 +L13: + movdqa xmm0, XMMWORD PTR [esp+336] + movdqa xmm4, XMMWORD PTR [esp+288] + pmuludq xmm0, XMMWORD PTR LC6 + movaps XMMWORD PTR [esp+48], xmm0 + movdqa xmm6, XMMWORD PTR [esp+320] + movdqa xmm0, XMMWORD PTR [esp+272] + pmuludq xmm6, XMMWORD PTR LC6 + movaps XMMWORD PTR [esp+32], xmm6 + pmuludq xmm4, XMMWORD PTR LC6 + pmuludq xmm0, XMMWORD PTR LC6 + cmp ecx, 63 + jbe L14 + movdqu xmm6, XMMWORD PTR [esi+80] + lea edx, [ecx-64] + movaps XMMWORD PTR [esp], xmm0 + movaps XMMWORD PTR [esp+160], xmm0 + and edx, -64 + movdqa xmm0, XMMWORD PTR [esp+1120] + pshufd xmm6, xmm6, 0 + movaps XMMWORD PTR [esp+112], xmm4 + lea edx, [eax+64+edx] + movaps XMMWORD PTR [esp+208], xmm6 + movdqu xmm6, XMMWORD PTR [esi+80] + movaps XMMWORD PTR [esp+16], xmm4 + pshufd xmm3, xmm6, 85 + pshufd xmm6, xmm6, 170 + movaps XMMWORD PTR [esp+256], xmm6 + movdqu xmm6, XMMWORD PTR [esi+80] + movaps XMMWORD PTR [esp+192], xmm3 + pshufd xmm6, xmm6, 255 + movaps XMMWORD PTR [esp+240], xmm6 + movd xmm6, DWORD PTR [esi+96] + pshufd xmm6, xmm6, 0 + movaps XMMWORD PTR [esp+224], xmm6 + movdqa xmm6, XMMWORD PTR LC5 + movaps XMMWORD PTR [esp+1152], xmm6 + movdqa xmm6, XMMWORD PTR [esp+32] + movaps XMMWORD PTR [esp+176], xmm6 + movdqa xmm6, XMMWORD PTR [esp+240] + pmuludq xmm6, XMMWORD PTR LC6 + movaps XMMWORD PTR [esp+144], xmm6 + movdqa xmm6, XMMWORD PTR [esp+224] + pmuludq xmm6, XMMWORD PTR LC6 + movaps XMMWORD PTR [esp+128], xmm6 + movdqa xmm6, XMMWORD PTR [esp+48] + movaps XMMWORD PTR [esp+96], xmm6 + movdqa xmm6, xmm3 + pmuludq xmm6, XMMWORD PTR LC6 + movaps XMMWORD PTR [esp+80], xmm6 + movdqa xmm6, XMMWORD PTR [esp+256] + pmuludq xmm6, XMMWORD PTR LC6 + movaps XMMWORD PTR [esp+64], xmm6 + movdqa xmm6, xmm2 + movdqa xmm2, xmm1 + movdqa xmm1, xmm7 +// .p2align 4,,10 +// .p2align 3 +L15: + movdqa xmm7, XMMWORD PTR [esp+64] + movdqa xmm4, XMMWORD PTR [esp+80] + add eax, 64 + movdqa xmm3, xmm7 + pmuludq xmm4, xmm6 + pmuludq xmm3, xmm2 + movaps XMMWORD PTR [esp+1120], xmm4 + movaps XMMWORD PTR [esp+1104], xmm3 + movdqa xmm3, xmm7 + movdqa xmm7, XMMWORD PTR [esp+144] + pmuludq xmm3, xmm6 + movdqa xmm4, xmm7 + pmuludq xmm4, xmm2 + movaps XMMWORD PTR [esp+1088], xmm3 + movdqa xmm3, xmm7 + pmuludq xmm3, xmm6 + movaps XMMWORD PTR [esp+1072], xmm4 + movdqa xmm4, xmm7 + movdqa xmm7, XMMWORD PTR [esp+128] + pmuludq xmm4, xmm5 + movaps XMMWORD PTR [esp+1056], xmm3 + movdqa xmm3, xmm7 + pmuludq xmm3, xmm5 + movaps XMMWORD PTR [esp+1040], xmm4 + movdqa xmm4, xmm7 + pmuludq xmm4, xmm6 + movaps XMMWORD PTR [esp+992], xmm3 + movdqa xmm3, XMMWORD PTR [esp+208] + movaps XMMWORD PTR [esp+1024], xmm4 + movdqa xmm4, xmm7 + pmuludq xmm6, xmm3 + pmuludq xmm4, xmm0 + movaps XMMWORD PTR [esp+944], xmm6 + movdqa xmm6, xmm3 + movaps XMMWORD PTR [esp+1008], xmm4 + movdqa xmm4, xmm7 + pmuludq xmm6, xmm1 + pmuludq xmm4, xmm2 + movaps XMMWORD PTR [esp+928], xmm6 + movdqa xmm6, xmm3 + movaps XMMWORD PTR [esp+976], xmm4 + movdqa xmm4, xmm3 + pmuludq xmm6, xmm0 + pmuludq xmm4, xmm2 + movaps XMMWORD PTR [esp+912], xmm6 + movdqa xmm6, xmm3 + movaps XMMWORD PTR [esp+960], xmm4 + pmuludq xmm6, xmm5 + movdqa xmm4, XMMWORD PTR [esp+192] + pmuludq xmm2, xmm4 + movdqa xmm3, xmm4 + pmuludq xmm3, xmm5 + movaps XMMWORD PTR [esp+896], xmm6 + movdqa xmm6, XMMWORD PTR [esp+256] + movaps XMMWORD PTR [esp+864], xmm2 + movdqa xmm2, xmm4 + pmuludq xmm5, xmm6 + pmuludq xmm2, xmm1 + movaps XMMWORD PTR [esp+880], xmm3 + movaps XMMWORD PTR [esp+800], xmm5 + movdqa xmm5, xmm6 + movaps XMMWORD PTR [esp+848], xmm2 + movdqa xmm2, xmm4 + pmuludq xmm5, xmm1 + pmuludq xmm2, xmm0 + movaps XMMWORD PTR [esp+784], xmm5 + movaps XMMWORD PTR [esp+832], xmm2 + movdqa xmm2, xmm6 + pmuludq xmm2, xmm0 + movaps XMMWORD PTR [esp+816], xmm2 + movdqa xmm2, XMMWORD PTR [esp+240] + movdqa xmm5, xmm2 + pmuludq xmm0, xmm2 + pmuludq xmm5, xmm1 + movaps XMMWORD PTR [esp+752], xmm0 + movaps XMMWORD PTR [esp+768], xmm5 + pmuludq xmm1, XMMWORD PTR [esp+224] + movq xmm0, QWORD PTR [eax-64] + movq xmm4, QWORD PTR [eax-56] + movaps XMMWORD PTR [esp+736], xmm1 + movq xmm1, QWORD PTR [eax-48] + movdqa xmm6, XMMWORD PTR [esp+96] + movdqa xmm7, XMMWORD PTR [esp+112] + punpcklqdq xmm0, xmm1 + movq xmm1, QWORD PTR [eax-40] + punpcklqdq xmm4, xmm1 + movdqa xmm1, xmm0 + movdqa xmm2, xmm4 + psrlq xmm1, 26 + movdqa xmm3, xmm4 + psrlq xmm4, 40 + psrlq xmm3, 14 + por xmm4, XMMWORD PTR [esp+1136] + pand xmm3, XMMWORD PTR [esp+1152] + psllq xmm2, 12 + pmuludq xmm6, xmm4 + movdqa xmm5, xmm2 + movdqa xmm2, xmm0 + psrlq xmm2, 52 + por xmm2, xmm5 + pand xmm2, XMMWORD PTR [esp+1152] + movaps XMMWORD PTR [esp+720], xmm6 + movdqa xmm6, xmm7 + pmuludq xmm6, xmm3 + movaps XMMWORD PTR [esp+704], xmm6 + movdqa xmm6, xmm7 + movdqa xmm7, XMMWORD PTR [esp+160] + pmuludq xmm6, xmm4 + movdqa xmm5, xmm7 + pmuludq xmm5, xmm2 + movaps XMMWORD PTR [esp+688], xmm6 + movdqa xmm6, xmm7 + pmuludq xmm6, xmm3 + movaps XMMWORD PTR [esp+640], xmm5 + movaps XMMWORD PTR [esp+672], xmm6 + movdqa xmm6, xmm7 + movdqa xmm7, XMMWORD PTR [esp+1152] + pmuludq xmm6, xmm4 + pand xmm1, xmm7 + pand xmm0, xmm7 + movaps XMMWORD PTR [esp+656], xmm6 + movdqa xmm6, XMMWORD PTR [esp+176] + movdqa xmm5, xmm6 + pmuludq xmm5, xmm4 + movaps XMMWORD PTR [esp+624], xmm5 + movdqa xmm5, xmm6 + pmuludq xmm5, xmm1 + movaps XMMWORD PTR [esp+608], xmm5 + movdqa xmm5, xmm6 + pmuludq xmm5, xmm2 + movaps XMMWORD PTR [esp+592], xmm5 + movdqa xmm5, xmm6 + pmuludq xmm5, xmm3 + movaps XMMWORD PTR [esp+576], xmm5 + movdqa xmm5, XMMWORD PTR [esp+304] + movdqa xmm6, xmm5 + pmuludq xmm4, xmm5 + pmuludq xmm6, xmm3 + movaps XMMWORD PTR [esp+544], xmm4 + movdqa xmm4, xmm5 + movaps XMMWORD PTR [esp+560], xmm6 + movdqa xmm6, xmm5 + pmuludq xmm4, xmm0 + pmuludq xmm6, xmm1 + movaps XMMWORD PTR [esp+528], xmm6 + movdqa xmm6, xmm5 + pmuludq xmm6, xmm2 + movaps XMMWORD PTR [esp+512], xmm6 + movdqa xmm6, XMMWORD PTR [esp+336] + movdqa xmm5, xmm6 + pmuludq xmm3, xmm6 + pmuludq xmm5, xmm2 + movaps XMMWORD PTR [esp+480], xmm3 + movaps XMMWORD PTR [esp+496], xmm5 + movdqa xmm5, xmm6 + pmuludq xmm5, xmm0 + movaps XMMWORD PTR [esp+464], xmm5 + movdqa xmm5, xmm6 + movdqu xmm7, XMMWORD PTR [eax-16] + paddq xmm4, XMMWORD PTR [esp+608] + pmuludq xmm5, xmm1 + movaps XMMWORD PTR [esp+448], xmm5 + movdqa xmm5, XMMWORD PTR [esp+288] + pmuludq xmm2, xmm5 + movdqa xmm3, xmm5 + pmuludq xmm3, xmm1 + movaps XMMWORD PTR [esp+416], xmm2 + movdqa xmm2, xmm5 + pmuludq xmm2, xmm0 + movaps XMMWORD PTR [esp+432], xmm3 + movdqa xmm3, XMMWORD PTR [esp+272] + pmuludq xmm1, xmm3 + movaps XMMWORD PTR [esp+400], xmm2 + movdqa xmm2, xmm3 + pmuludq xmm2, xmm0 + pmuludq xmm0, XMMWORD PTR [esp+320] + movaps XMMWORD PTR [esp+368], xmm0 + movdqu xmm0, XMMWORD PTR [eax-32] + movaps XMMWORD PTR [esp+384], xmm1 + punpckldq xmm0, xmm7 + movdqa xmm1, xmm0 + movdqu xmm0, XMMWORD PTR [eax-32] + movdqa xmm3, xmm1 + punpckhdq xmm0, xmm7 + movdqa xmm5, xmm2 + pxor xmm2, xmm2 + movdqa xmm7, xmm0 + punpckldq xmm3, xmm2 + punpckhdq xmm1, xmm2 + punpckldq xmm7, xmm2 + psllq xmm1, 6 + movdqa xmm6, xmm3 + paddq xmm5, XMMWORD PTR [esp+432] + movdqa xmm3, xmm2 + movdqa xmm2, xmm7 + psllq xmm2, 12 + punpckhdq xmm0, xmm3 + movaps XMMWORD PTR [esp+352], xmm2 + psllq xmm0, 18 + movdqa xmm2, XMMWORD PTR [esp+1008] + paddq xmm2, XMMWORD PTR [esp+1040] + movdqa xmm3, xmm2 + movdqa xmm2, XMMWORD PTR [esp+1120] + paddq xmm2, XMMWORD PTR [esp+1104] + paddq xmm2, xmm3 + movdqa xmm3, XMMWORD PTR [esp+720] + paddq xmm3, XMMWORD PTR [esp+928] + paddq xmm3, xmm2 + movdqa xmm2, XMMWORD PTR [esp+640] + paddq xmm2, XMMWORD PTR [esp+704] + paddq xmm2, xmm3 + paddq xmm2, xmm4 + movdqa xmm4, XMMWORD PTR [esp+816] + paddq xmm4, XMMWORD PTR [esp+880] + paddq xmm2, xmm6 + movdqa xmm3, xmm4 + movdqa xmm7, xmm2 + movdqa xmm4, XMMWORD PTR [esp+1024] + paddq xmm4, XMMWORD PTR [esp+960] + psrlq xmm7, 26 + paddq xmm4, xmm3 + movdqa xmm3, XMMWORD PTR [esp+624] + paddq xmm3, XMMWORD PTR [esp+768] + paddq xmm4, xmm3 + movdqa xmm3, XMMWORD PTR [esp+496] + paddq xmm3, XMMWORD PTR [esp+560] + paddq xmm4, xmm3 + paddq xmm4, xmm5 + movdqa xmm5, xmm7 + paddq xmm4, xmm0 + paddq xmm1, xmm5 + movdqa xmm0, XMMWORD PTR [esp+912] + paddq xmm0, XMMWORD PTR [esp+992] + movdqa xmm7, xmm4 + movdqa xmm6, XMMWORD PTR [esp+1088] + paddq xmm6, XMMWORD PTR [esp+1072] + psrlq xmm7, 26 + movdqa xmm3, xmm7 + paddq xmm3, XMMWORD PTR [esp+1136] + paddq xmm6, xmm0 + movdqa xmm0, XMMWORD PTR [esp+688] + paddq xmm0, XMMWORD PTR [esp+848] + paddq xmm0, xmm6 + movdqa xmm6, XMMWORD PTR [esp+592] + paddq xmm6, XMMWORD PTR [esp+672] + paddq xmm0, xmm6 + movdqa xmm6, XMMWORD PTR [esp+464] + paddq xmm6, XMMWORD PTR [esp+528] + paddq xmm0, xmm6 + movdqa xmm6, XMMWORD PTR [esp+944] + paddq xmm6, XMMWORD PTR [esp+864] + paddq xmm0, xmm1 + movdqa xmm1, XMMWORD PTR [esp+752] + paddq xmm1, XMMWORD PTR [esp+800] + paddq xmm6, xmm1 + movdqa xmm1, XMMWORD PTR [esp+544] + paddq xmm1, XMMWORD PTR [esp+736] + paddq xmm1, xmm6 + movdqa xmm6, XMMWORD PTR [esp+416] + paddq xmm6, XMMWORD PTR [esp+480] + paddq xmm1, xmm6 + movdqa xmm6, XMMWORD PTR [esp+384] + paddq xmm6, XMMWORD PTR [esp+368] + movdqa xmm5, xmm6 + paddq xmm5, xmm1 + movdqa xmm7, xmm5 + movdqa xmm5, XMMWORD PTR [esp+832] + paddq xmm5, XMMWORD PTR [esp+896] + paddq xmm7, xmm3 + movdqa xmm3, XMMWORD PTR [esp+1056] + paddq xmm3, XMMWORD PTR [esp+976] + movdqa xmm6, xmm7 + movdqa xmm7, xmm0 + paddq xmm3, xmm5 + psrlq xmm7, 26 + movdqa xmm1, xmm6 + movdqa xmm5, XMMWORD PTR [esp+656] + paddq xmm5, XMMWORD PTR [esp+784] + psrlq xmm1, 26 + pmuludq xmm1, XMMWORD PTR LC6 + paddq xmm5, xmm3 + movdqa xmm3, XMMWORD PTR [esp+512] + paddq xmm3, XMMWORD PTR [esp+576] + paddq xmm3, xmm5 + movdqa xmm5, XMMWORD PTR [esp+448] + paddq xmm5, XMMWORD PTR [esp+400] + paddq xmm3, xmm5 + movdqa xmm5, XMMWORD PTR [esp+352] + paddq xmm5, xmm7 + movdqa xmm7, XMMWORD PTR [esp+1152] + paddq xmm5, xmm3 + pand xmm2, xmm7 + pand xmm4, xmm7 + pand xmm0, xmm7 + paddq xmm1, xmm2 + movdqa xmm2, xmm5 + pand xmm6, xmm7 + movdqa xmm3, xmm1 + psrlq xmm2, 26 + pand xmm5, xmm7 + psrlq xmm3, 26 + paddq xmm2, xmm4 + pand xmm1, xmm7 + paddq xmm0, xmm3 + movdqa xmm3, xmm2 + pand xmm2, xmm7 + psrlq xmm3, 26 + paddq xmm6, xmm3 + cmp eax, edx + jne L15 + movaps XMMWORD PTR [esp+1120], xmm0 + movdqa xmm4, XMMWORD PTR [esp+16] + movdqa xmm7, xmm1 + and ecx, 63 + movdqa xmm0, XMMWORD PTR [esp] + movdqa xmm1, xmm2 + movdqa xmm2, xmm6 +L14: + cmp ecx, 31 + jbe L16 + movdqa xmm6, XMMWORD PTR [esp+48] + movdqa xmm3, XMMWORD PTR [esp+32] + pmuludq xmm6, xmm2 + movaps XMMWORD PTR [esp+1152], xmm6 + movdqa xmm6, xmm1 + pmuludq xmm6, xmm4 + pmuludq xmm4, xmm2 + movaps XMMWORD PTR [esp+1104], xmm6 + movdqa xmm6, xmm1 + pmuludq xmm6, xmm0 + movaps XMMWORD PTR [esp+1088], xmm4 + movaps XMMWORD PTR [esp+1072], xmm6 + movdqa xmm6, xmm2 + pmuludq xmm6, xmm0 + pmuludq xmm0, xmm5 + movaps XMMWORD PTR [esp+1056], xmm6 + movdqa xmm6, xmm5 + movdqa xmm4, xmm0 + movdqa xmm0, xmm2 + pmuludq xmm6, xmm3 + pmuludq xmm0, xmm3 + movaps XMMWORD PTR [esp+1024], xmm6 + movdqa xmm6, xmm3 + pmuludq xmm6, xmm1 + movaps XMMWORD PTR [esp+1040], xmm0 + movdqa xmm0, XMMWORD PTR [esp+1120] + pmuludq xmm0, xmm3 + movaps XMMWORD PTR [esp+1008], xmm6 + movdqa xmm6, XMMWORD PTR [esp+304] + pmuludq xmm2, xmm6 + movdqa xmm3, xmm6 + paddq xmm0, xmm4 + movdqa xmm4, XMMWORD PTR [esp+1152] + paddq xmm4, XMMWORD PTR [esp+1104] + pmuludq xmm3, xmm1 + paddq xmm0, xmm4 + movdqa xmm4, XMMWORD PTR [esp+1120] + movaps XMMWORD PTR [esp+976], xmm2 + movdqa xmm2, xmm6 + pmuludq xmm2, xmm7 + movaps XMMWORD PTR [esp+992], xmm3 + movdqa xmm3, xmm6 + pmuludq xmm3, XMMWORD PTR [esp+1120] + movdqa xmm6, xmm3 + movdqa xmm3, XMMWORD PTR [esp+304] + paddq xmm6, XMMWORD PTR [esp+1024] + pmuludq xmm3, xmm5 + paddq xmm0, xmm2 + movdqa xmm2, XMMWORD PTR [esp+336] + movaps XMMWORD PTR [esp+1104], xmm0 + movdqa xmm0, xmm2 + pmuludq xmm1, xmm2 + pmuludq xmm0, xmm7 + movaps XMMWORD PTR [esp+960], xmm3 + movdqa xmm3, XMMWORD PTR [esp+336] + pmuludq xmm3, xmm5 + movaps XMMWORD PTR [esp+928], xmm1 + movdqa xmm1, xmm0 + movdqa xmm0, xmm2 + pmuludq xmm0, xmm4 + movdqa xmm4, XMMWORD PTR [esp+1088] + paddq xmm4, XMMWORD PTR [esp+1072] + movaps XMMWORD PTR [esp+944], xmm3 + movdqa xmm3, XMMWORD PTR [esp+288] + paddq xmm6, xmm4 + movdqa xmm4, xmm6 + pmuludq xmm5, xmm3 + movdqa xmm2, xmm3 + movdqa xmm6, XMMWORD PTR [esp+272] + pmuludq xmm2, XMMWORD PTR [esp+1120] + paddq xmm4, xmm1 + movaps XMMWORD PTR [esp+1152], xmm4 + movdqa xmm4, xmm3 + movdqa xmm1, xmm6 + movdqa xmm3, XMMWORD PTR [esp+1120] + pmuludq xmm4, xmm7 + pmuludq xmm1, xmm7 + paddq xmm0, XMMWORD PTR [esp+960] + paddq xmm2, XMMWORD PTR [esp+944] + pmuludq xmm3, xmm6 + movdqa xmm6, XMMWORD PTR [esp+320] + pmuludq xmm6, xmm7 + movdqa xmm7, XMMWORD PTR [esp+1056] + paddq xmm7, XMMWORD PTR [esp+1008] + paddq xmm0, xmm7 + paddq xmm0, xmm4 + paddq xmm3, xmm5 + movdqa xmm4, XMMWORD PTR [esp+1040] + paddq xmm4, XMMWORD PTR [esp+992] + paddq xmm2, xmm4 + paddq xmm2, xmm1 + movdqa xmm1, XMMWORD PTR [esp+976] + paddq xmm1, XMMWORD PTR [esp+928] + paddq xmm3, xmm1 + paddq xmm3, xmm6 + test eax, eax + je L18 + movdqu xmm5, XMMWORD PTR [eax+16] + movdqu xmm1, XMMWORD PTR [eax] + paddq xmm3, XMMWORD PTR [esp+1136] + punpckldq xmm1, xmm5 + movdqa xmm4, xmm1 + movdqu xmm1, XMMWORD PTR [eax] + movdqa xmm6, xmm4 + punpckhdq xmm1, xmm5 + pxor xmm5, xmm5 + punpckldq xmm6, xmm5 + punpckhdq xmm4, xmm5 + movdqa xmm7, xmm6 + psllq xmm4, 6 + movdqa xmm6, xmm1 + punpckldq xmm6, xmm5 + punpckhdq xmm1, xmm5 + movdqa xmm5, XMMWORD PTR [esp+1104] + psllq xmm6, 12 + psllq xmm1, 18 + paddq xmm5, xmm7 + paddq xmm0, xmm6 + movaps XMMWORD PTR [esp+1104], xmm5 + paddq xmm2, xmm1 + movdqa xmm5, XMMWORD PTR [esp+1152] + paddq xmm5, xmm4 + movaps XMMWORD PTR [esp+1152], xmm5 +L18: + movdqa xmm7, XMMWORD PTR [esp+1104] + movdqa xmm4, xmm2 + pand xmm2, XMMWORD PTR LC5 + psrlq xmm4, 26 + movdqa xmm1, xmm7 + paddq xmm4, xmm3 + pand xmm7, XMMWORD PTR LC5 + psrlq xmm1, 26 + movdqa xmm3, xmm4 + paddq xmm1, XMMWORD PTR [esp+1152] + pand xmm4, XMMWORD PTR LC5 + psrlq xmm3, 26 + pmuludq xmm3, XMMWORD PTR LC6 + paddq xmm7, xmm3 + movdqa xmm5, xmm1 + movdqa xmm3, xmm7 + pand xmm1, XMMWORD PTR LC5 + psrlq xmm5, 26 + psrlq xmm3, 26 + pand xmm7, XMMWORD PTR LC5 + paddq xmm0, xmm5 + paddq xmm3, xmm1 + movdqa xmm1, XMMWORD PTR LC5 + movdqa xmm6, xmm0 + movaps XMMWORD PTR [esp+1120], xmm3 + pand xmm0, XMMWORD PTR LC5 + psrlq xmm6, 26 + paddq xmm2, xmm6 + movdqa xmm5, xmm0 + movdqa xmm0, xmm2 + pand xmm1, xmm2 + psrlq xmm0, 26 + paddq xmm4, xmm0 + movdqa xmm2, xmm4 +L16: + test eax, eax + je L19 + pshufd xmm3, xmm5, 8 + pshufd xmm4, xmm7, 8 + pshufd xmm5, xmm1, 8 + pshufd xmm6, XMMWORD PTR [esp+1120], 8 + pshufd xmm0, xmm2, 8 + movdqa xmm1, xmm3 + movdqa xmm2, xmm4 + punpcklqdq xmm2, xmm6 + punpcklqdq xmm1, xmm5 + movq QWORD PTR [esi+32], xmm0 + movups XMMWORD PTR [esi], xmm2 + movups XMMWORD PTR [esi+16], xmm1 + lea esp, [ebp-12] + pop ebx + pop esi + pop edi + pop ebp + ret +// .p2align 4,,10 +// .p2align 3 +L28: + movdqu xmm6, XMMWORD PTR [esi+60] + movdqu xmm0, XMMWORD PTR [esi+60] + punpckldq xmm6, xmm4 + punpckhdq xmm0, xmm4 + movd xmm4, DWORD PTR [esi+76] + punpcklqdq xmm4, xmm3 + movaps XMMWORD PTR [esp+320], xmm4 + jmp L12 +// .p2align 4,,10 +// .p2align 3 +L19: + movdqa xmm3, xmm1 + movdqa xmm6, xmm7 + movdqa xmm0, xmm5 + movdqa xmm4, XMMWORD PTR [esp+1120] + psrldq xmm3, 8 + psrldq xmm6, 8 + psrldq xmm4, 8 + psrldq xmm0, 8 + paddq xmm7, xmm6 + movaps XMMWORD PTR [esp+1136], xmm3 + movdqa xmm3, XMMWORD PTR [esp+1120] + movd edx, xmm7 + movaps XMMWORD PTR [esp+1152], xmm0 + paddq xmm5, XMMWORD PTR [esp+1152] + paddq xmm1, XMMWORD PTR [esp+1136] + mov edi, edx + shr edx, 26 + movdqa xmm0, xmm2 + paddq xmm3, xmm4 + psrldq xmm0, 8 + and edi, 67108863 + movd eax, xmm3 + paddq xmm2, xmm0 + add eax, edx + movd edx, xmm5 + mov ebx, eax + shr eax, 26 + add eax, edx + movd edx, xmm1 + and ebx, 67108863 + mov ecx, eax + shr eax, 26 + add eax, edx + and ecx, 67108863 + movd edx, xmm2 + mov DWORD PTR [esp+1152], ecx + mov ecx, eax + shr eax, 26 + add eax, edx + and ecx, 67108863 + mov edx, eax + shr eax, 26 + lea eax, [eax+eax*4] + and edx, 67108863 + add eax, edi + mov edi, eax + shr eax, 26 + add eax, ebx + and edi, 67108863 + mov ebx, eax + shr eax, 26 + and ebx, 67108863 + mov DWORD PTR [esp+1120], ebx + mov ebx, DWORD PTR [esp+1152] + add eax, ebx + mov ebx, eax + shr eax, 26 + add eax, ecx + and ebx, 67108863 + mov ecx, eax + shr eax, 26 + mov DWORD PTR [esp+1152], ebx + mov ebx, DWORD PTR [esp+1120] + add eax, edx + and ecx, 67108863 + mov DWORD PTR [esp+1136], ecx + mov edx, eax + mov ecx, eax + and edx, 67108863 + shr ecx, 26 + mov DWORD PTR [esp+1104], edx + lea edx, [ecx+ecx*4] + add edx, edi + mov ecx, edx + shr edx, 26 + and ecx, 67108863 + add edx, ebx + or eax, -67108864 + lea ebx, [ecx+5] + mov DWORD PTR [esp+1088], ebx + shr ebx, 26 + lea edi, [ebx+edx] + mov DWORD PTR [esp+1072], edi + shr edi, 26 + mov ebx, edi + mov edi, DWORD PTR [esp+1152] + add ebx, edi + mov edi, DWORD PTR [esp+1136] + mov DWORD PTR [esp+1056], ebx + shr ebx, 26 + add ebx, edi + mov DWORD PTR [esp+1040], ebx + shr ebx, 26 + add eax, ebx + mov edi, eax + shr edi, 31 + mov ebx, edi + mov edi, eax + sar edi, 31 + sub ebx, 1 + and edx, edi + and ecx, edi + and eax, ebx + mov DWORD PTR [esp+1120], edx + mov edx, DWORD PTR [esp+1152] + and edx, edi + mov DWORD PTR [esp+1152], edx + mov edx, DWORD PTR [esp+1136] + and edx, edi + mov DWORD PTR [esp+1136], edx + mov edx, DWORD PTR [esp+1104] + and edx, edi + mov edi, DWORD PTR [esp+1088] + mov DWORD PTR [esp+1104], edx + and edi, ebx + and edi, 67108863 + or edi, ecx + mov ecx, DWORD PTR [esp+1072] + mov DWORD PTR [esi], edi + mov edi, DWORD PTR [esp+1120] + and ecx, ebx + and ecx, 67108863 + or ecx, edi + mov DWORD PTR [esi+4], ecx + mov ecx, DWORD PTR [esp+1056] + mov edi, DWORD PTR [esp+1152] + and ecx, ebx + mov edx, ecx + mov ecx, DWORD PTR [esp+1040] + and edx, 67108863 + or edx, edi + and ecx, ebx + mov edi, DWORD PTR [esp+1136] + mov DWORD PTR [esi+8], edx + mov edx, ecx + and edx, 67108863 + or edx, edi + mov DWORD PTR [esi+12], edx + mov edx, DWORD PTR [esp+1104] + or eax, edx + mov DWORD PTR [esi+16], eax + lea esp, [ebp-12] + pop ebx + pop esi + pop edi + pop ebp +end; + +procedure _Poly1305_finish_SSE2(st : TPoly1305.PPoly1305_state_internal_t; m : PByte; leftover : integer; var mac : TBlock16Byte) cdecl; +label L63, L33, L34, L35, L36, L37, L38, L42, L43, L64, L65, L99; +asm + push ebp + mov ebp, esp + push edi + push esi + push ebx + and esp, -16 + sub esp, 64 + mov ebx, DWORD PTR [ebp+8] + mov edx, DWORD PTR [ebp+16] + mov eax, DWORD PTR [ebx+116] + mov DWORD PTR [esp+28], eax + test edx, edx + je L63 + mov edi, DWORD PTR [ebp+12] + pxor xmm0, xmm0 + lea esi, [esp+32] + movaps XMMWORD PTR [esp+32], xmm0 + mov ecx, esi + movaps XMMWORD PTR [esp+48], xmm0 + sub edi, esi + test BYTE PTR [ebp+16], 16 + je L34 + mov eax, DWORD PTR [ebp+12] + lea ecx, [esp+48] + movdqu xmm4, XMMWORD PTR [eax] + movaps XMMWORD PTR [esp+32], xmm4 +L34: + test BYTE PTR [ebp+16], 8 + je L35 + mov eax, DWORD PTR [ecx+edi] + mov edx, DWORD PTR [ecx+4+edi] + add ecx, 8 + mov DWORD PTR [ecx-8], eax + mov DWORD PTR [ecx-4], edx +L35: + test BYTE PTR [ebp+16], 4 + je L36 + mov eax, DWORD PTR [ecx+edi] + add ecx, 4 + mov DWORD PTR [ecx-4], eax +L36: + test BYTE PTR [ebp+16], 2 + je L37 + movzx eax, WORD PTR [ecx+edi] + add ecx, 2 + mov WORD PTR [ecx-2], ax +L37: + test BYTE PTR [ebp+16], 1 + je L38 + movzx edx, BYTE PTR [ecx+edi] + mov BYTE PTR [ecx], dl +L38: + cmp DWORD PTR [ebp+16], 16 + je L65 + mov eax, DWORD PTR [ebp+16] + mov edx, DWORD PTR [esp+28] + mov BYTE PTR [esp+32+eax], 1 + cmp eax, 15 + jbe L42 + or edx, 4 + mov DWORD PTR [ebx+116], edx + mov DWORD PTR [esp+8], 32 + mov DWORD PTR [esp+4], esi + mov DWORD PTR [esp], ebx + call _Poly1305_Blocks_sse2 + mov eax, DWORD PTR [ebx+116] + mov DWORD PTR [esp+28], eax +L63: + test al, 1 + je L33 + mov edx, DWORD PTR [esp+28] + or edx, 16 +L43: + mov DWORD PTR [ebx+116], edx + mov DWORD PTR [esp+8], 32 + mov DWORD PTR [esp+4], 0 + mov DWORD PTR [esp], ebx + call _Poly1305_Blocks_sse2 +L33: + mov esi, DWORD PTR [ebx+4] + mov edx, DWORD PTR [ebx+8] + mov ecx, DWORD PTR [ebx+12] + mov eax, esi + mov edi, esi + mov esi, edx + shr edi, 6 + sal esi, 20 + or esi, edi + mov edi, edx + mov edx, ecx + shr ecx, 18 + shr edi, 12 + sal edx, 14 + or edx, edi + mov edi, ecx + mov ecx, DWORD PTR [ebx+16] + sal eax, 26 + or eax, DWORD PTR [ebx] + sal ecx, 8 + or ecx, edi + //APP + // # 526 "poly1305-donna-x86-sse2-incremental-source - Kopie.c" 1 + //addl DWORD PTR [ebx+100], eax; +// adcl DWORD PTR [ebx+104], esi; +// adcl DWORD PTR [ebx+108], edx; +// adcl DWORD PTR [ebx+112], ecx; + add DWORD PTR [ebx+100], eax; + adc DWORD PTR [ebx+104], esi; + adc DWORD PTR [ebx+108], edx; + adc DWORD PTR [ebx+112], ecx; + + //# 0 "" 2 + //NO_APP + pxor xmm0, xmm0 + movd xmm3, esi + movd xmm1, edx + movups XMMWORD PTR [ebx], xmm0 + movd xmm2, ecx + movups XMMWORD PTR [ebx+16], xmm0 + punpckldq xmm1, xmm2 + movups XMMWORD PTR [ebx+32], xmm0 + movups XMMWORD PTR [ebx+48], xmm0 + movups XMMWORD PTR [ebx+64], xmm0 + movups XMMWORD PTR [ebx+80], xmm0 + movups XMMWORD PTR [ebx+96], xmm0 + movups XMMWORD PTR [ebx+112], xmm0 + movd xmm0, eax + mov eax, DWORD PTR [ebp+20] + punpckldq xmm0, xmm3 + punpcklqdq xmm0, xmm1 + movups XMMWORD PTR [eax], xmm0 + lea esp, [ebp-12] + pop ebx + pop esi + pop edi + pop ebp + + jmp L99; + +// now that is some kind of epiolog +L65: + mov edx, DWORD PTR [esp+28] + or edx, 4 +L64: + mov DWORD PTR [ebx+116], edx + mov DWORD PTR [esp+8], 32 + mov DWORD PTR [esp+4], esi + mov DWORD PTR [esp], ebx + call _poly1305_blocks_sse2 + mov edx, DWORD PTR [ebx+116] + test dl, 1 + je L33 + or edx, 32 + jmp L43 +// .p2align 4,,10 +// .p2align 3 +L42: + or edx, 8 + jmp L64 + +// return: +L99: +end; + +procedure TPoly1305.Poly1305Emit_SSE(var mac: TBlock16Byte); +begin + FillChar(mac, sizeof(mac), 0); + //nonce is not used - it is already stored + _Poly1305_finish_SSE2( fPPoly1305State, nil, 0, mac) +end; + + +procedure TPoly1305.Poly1305Finalize(var mac: TBlock16Byte); +begin + if fNum > 0 then + begin + fData[fNum] := 1; + 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); +end; + +procedure TPoly1305.Poly1305Init_SSE(initVec: PByte); +begin + FillChar(fPoly1305State[0], Length(fPoly1305State), 0); + + _poly1305_init_ext_sse2( fPPoly1305State, initVec, 0); +end; + +procedure TPoly1305.Poly1305Blocks_SSE(pData: PByteArray; size: integer); +begin + _Poly1305_Blocks_sse2( fPPoly1305State, PByte(pData), size ); +end; + +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.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; + +initialization + TPoly1305.UseSSE := False; + +end. diff --git a/Source/DECCiphers.pas b/Source/DECCiphers.pas index d91593ad..6da6e74a 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,11 @@ TCipher_TEAN = class; /// TCipher_XTEA_DEC52 = class; + /// + /// ChaCha20 cipher. + /// + TCipher_ChaCha20 = class; + // Definitions needed for Skipjack algorithm PSkipjackTab = ^TSkipjackTab; TSkipjackTab = array[0..255] of Byte; @@ -477,6 +487,65 @@ 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} + + private + 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; + TCipher_Square = class(TDECFormattedCipher) protected /// @@ -1020,11 +1089,6 @@ implementation {$IFOPT R+}{$DEFINE RESTORE_RANGECHECKS}{$R-}{$ENDIF} uses - {$IFDEF FPC} - SysUtils, - {$ELSE} - System.SysUtils, - {$ENDIF} DECData, DECDataCipher; { TCipher_Null } @@ -6786,12 +6850,1019 @@ procedure TCipher_XTEA_DEC52.DoDecode(Source, Dest: Pointer; Size: Integer); PUInt32Array(Dest)[1] := Y; end; +{ TCipher_ChaCha20 } + +{$IFDEF FPC} {$ASMMODE intel} {$S-} {$ENDIF} + +{$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(MRMATH_NOASM)} +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 + {$IF defined(x64)} + mov eax, ecx; + mov cl, dl; + rol eax, cl; + {$ELSE} + xchg cl,dl + rol eax, cl + {$IFEND} +end; +{$IFDEF FPC} +end; +{$ENDIF} +{$IFEND} + +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 ); +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 + 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 Exception.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 + // 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'; + +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; + +begin + inherited; + + if size <> 32 then + raise Exception.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 x86} + +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 x64} +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 x86} + +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 x64} + +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 x64} + {$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} +{$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} + +procedure TCipher_ChaCha20.AfterConstruction; +begin + inherited; + + // default is poly1305!! + Mode := cmPoly1305; + SetChaChaMode( cmSecure ); + {$IFDEF PUREPASCAL} + fFullBlockFunc := FullBlockPas; + {$ELSE} + case CpuMode of + cmSSE: fFullBlockFunc := FullBlockSSE; + cmAVX: 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 Exception.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 x64} +var dXMM4, dXMM5 : Array[0..1] of Int64; +{$ENDIF} +asm + {$IFDEF x64} + // 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 x64} + 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; + initialization SetDefaultCipherClass(TCipher_Null); + TCipher_ChaCha20.CpuMode := cmPas; + {$IFNDEF ManualRegisterCipherClasses} TCipher_Null.RegisterClass(TDECCipher.ClassList); TCipher_Blowfish.RegisterClass(TDECCipher.ClassList); diff --git a/Source/DECOptions.inc b/Source/DECOptions.inc index eceec526..da05d4bd 100644 --- a/Source/DECOptions.inc +++ b/Source/DECOptions.inc @@ -119,7 +119,7 @@ /// {$IF DECLARED(FireMonkeyVersion)} {$DEFINE FMXTranslateableExceptions} -{$ENDIF} +{$IFEND} { TODO: convert to $ENDIF when raising minimum supported version to XE4+} //------------------------------------------------------------------------------ // Do NOT change anything below! //------------------------------------------------------------------------------ diff --git a/Unit Tests/DECDUnitTestSuite.dpr b/Unit Tests/DECDUnitTestSuite.dpr index 224f30ca..0c9b25d7 100644 --- a/Unit Tests/DECDUnitTestSuite.dpr +++ b/Unit Tests/DECDUnitTestSuite.dpr @@ -16,7 +16,6 @@ program DECDUnitTestSuite; {$ENDIF} uses -// FastMM4, Vcl.Forms, {$IFDEF TESTINSIGHT} TestInsight.Client, @@ -42,8 +41,36 @@ uses TestDECCipherModesGCM in 'Tests\TestDECCipherModesGCM.pas', TestDECZIPHelper in 'Tests\TestDECZIPHelper.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', - AuthenticatedCiphersCommonTestData in 'Tests\AuthenticatedCiphersCommonTestData.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'; {$R *.RES} diff --git a/Unit Tests/DECDUnitTestSuite.dproj b/Unit Tests/DECDUnitTestSuite.dproj index 1670f30e..36118404 100644 --- a/Unit Tests/DECDUnitTestSuite.dproj +++ b/Unit Tests/DECDUnitTestSuite.dproj @@ -163,8 +163,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + Base diff --git a/Unit Tests/Tests/TestDECChaChaPoly1305.pas b/Unit Tests/Tests/TestDECChaChaPoly1305.pas new file mode 100644 index 00000000..946f7a27 --- /dev/null +++ b/Unit Tests/Tests/TestDECChaChaPoly1305.pas @@ -0,0 +1,353 @@ +unit TestDECChaChaPoly1305; + +interface + +uses {$IFDEF DUnitX} + DUnitX.TestFramework,DUnitX.DUnitCompatibility, + {$ELSE} + TestFramework, + {$ENDIF} + System.SysUtils, Generics.Collections, System.Math, + DECBaseClass, + DECCipherBase, DECCipherModes, DECCipherFormats, DECCiphers; + + +type +// Testmethods for class TDECCipher + {$IFDEF DUnitX} [TestFixture] {$ENDIF} + TestChaCha20Poly1305 = class(TTestCase) + published + procedure TestPoly1305; + procedure TestChaCha20_Poly1305_KeySetup; + procedure TestChaCha20_Poly1305_AEAD; + procedure TestChaChaEncodeDecodeSpeed; + + end; +implementation + +uses DECCipherModesPoly1305, System.Diagnostics; + + +//// ########################################### +//// #### OpenSSL reference implementation +//// ########################################### +// +// +//const POLY1305_KEY_SIZE = 32; +// POLY1305_DIGEST_SIZE = 16; +// +//type +// PPoly1305Ctx = PByte; +// TPoly1305Key = Array[0..POLY1305_KEY_SIZE-1] of byte; +// TPoly1305Mac = Array[0..POLY1305_DIGEST_SIZE-1] of byte; +// size_t = Integer; +// +// +//function Poly1305_ctx_size : size_t; cdecl; external 'libcrypto-3.dll'; +//procedure Poly1305_Init(ctx : PPoly1305Ctx; const key : TPoly1305Key); cdecl; external 'libcrypto-3.dll'; +//procedure Poly1305_Update(ctx : PPoly1305Ctx; inp : PByte; len : size_t); cdecl; external 'libcrypto-3.dll'; +//procedure Poly1305_Final(ctx : PPoly1305Ctx; var mac : TPoly1305Mac); cdecl; external 'libcrypto-3.dll'; + + + +// ########################################### +// #### +// ########################################### + +{ 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 + 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.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 + poly.InitInternal(iv); + poly.UpdatePoly(@msg[0], Length(msg)); + 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 + poly.InitInternal(iv); + poly.UpdatePoly(@msg[0], Length(msg)); + 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; + +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.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.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; + + +initialization + // Register all test cases to be run + {$IFDEF DUnitX} + TDUnitX.RegisterTestFixture(TPoly1305); + {$ELSE} + RegisterTest(TestChaCha20Poly1305.Suite); + {$ENDIF} + +end. From 90987167dd72fc58a5fd2f0aa86d45a770555b2f Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Wed, 9 Jul 2025 23:17:15 +0200 Subject: [PATCH 02/12] * Poly1305 hash updated to new authentication Class * Fixed bugs to get stream functions working - not yet tested * shrinking base classes to get the extended aead functions working (ccm, gcm, poly1305) - not yet tested --- Source/DECAuthenticatedCipherModesBase.pas | 94 +- Source/DECCipherBase.pas | 2 +- Source/DECCipherFormats.pas | 15 +- Source/DECCipherModes.pas | 280 +--- Source/DECCipherModesCCM.pas | 40 + Source/DECCipherModesGCM.pas | 475 +++--- Source/DECCipherModesPoly1305.pas | 1686 ++------------------ Source/DECCiphers.pas | 3 + Unit Tests/DECDUnitTestSuite.dpr | 3 +- Unit Tests/DECDUnitTestSuite.dproj | 9 +- Unit Tests/Tests/TestDECChaChaPoly1305.pas | 21 +- 11 files changed, 666 insertions(+), 1962 deletions(-) diff --git a/Source/DECAuthenticatedCipherModesBase.pas b/Source/DECAuthenticatedCipherModesBase.pas index 6245f1af..b24c14dc 100644 --- a/Source/DECAuthenticatedCipherModesBase.pas +++ b/Source/DECAuthenticatedCipherModesBase.pas @@ -59,6 +59,16 @@ EDECAuthLengthException = class(EDECException); /// 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 @@ -99,6 +109,32 @@ TAuthenticatedCipherModesBase = class(TObject) /// 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 @@ -127,7 +163,7 @@ TAuthenticatedCipherModesBase = class(TObject) /// procedure Encode(Source, Dest : PUInt8Array; - Size : Integer); virtual; abstract; + Size : Integer); virtual; /// /// Decodes a block of data using the supplied cipher /// @@ -142,7 +178,13 @@ TAuthenticatedCipherModesBase = class(TObject) /// procedure Decode(Source, Dest : PUInt8Array; - Size : Integer); virtual; abstract; + 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 @@ -192,6 +234,48 @@ implementation { 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; @@ -221,6 +305,12 @@ procedure TAuthenticatedCipherModesBase.Init(EncryptionMethod : TEncodeDecodeMet 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; diff --git a/Source/DECCipherBase.pas b/Source/DECCipherBase.pas index c2efe356..99e0a4fc 100644 --- a/Source/DECCipherBase.pas +++ b/Source/DECCipherBase.pas @@ -1013,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 20e5c145..eb3d5aca 100644 --- a/Source/DECCipherFormats.pas +++ b/Source/DECCipherFormats.pas @@ -733,7 +733,7 @@ function TDECFormattedCipher.EncodeBytes(const Source: TBytes): TBytes; Encode(Source[0], Result[0], Length(Source)) else if (FMode = cmGCM) then - EncodeGCM(nil, nil, 0); + 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(nil, nil, 0); + end; + //else + //if (FMode = cmGCM) then + // DecodeGCM(nil, nil, 0); if not (FPaddingClass = nil) then Result := FPaddingClass.RemovePadding(Result, Context.BlockSize); diff --git a/Source/DECCipherModes.pas b/Source/DECCipherModes.pas index 7f3e4c0e..4840ce09 100644 --- a/Source/DECCipherModes.pas +++ b/Source/DECCipherModes.pas @@ -26,9 +26,8 @@ interface {$ELSE} System.SysUtils, {$ENDIF} - DECTypes, DECCipherBase, DECCipherModesGCM, DECCipherModesCCM, - DECCipherModesPoly1305, - DECCipherInterface; + DECTypes, DECCipherBase, + DECCipherInterface, DECAuthenticatedCipherModesBase; type /// @@ -140,29 +139,11 @@ 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; - /// - /// Implementation of the Counter with CBC-MAC mode. Only created when - /// gmCCM is set as mode. - /// - FCCM : TCCM; - /// - /// Raises an EDECCipherException exception and provides the correct value - /// for block size in that message - /// - /// - /// Exception raised unconditionally. - /// - + fAuthObj : TAuthenticatedCipherModesBase; - /// - /// Implementation of the Pol1305 polynom. Only created when gmPoly1305 is - /// set as mode. - /// - FPOLY1305 : TPoly1305; procedure ReportInvalidMessageLength(Cipher: TDECCipher); /// @@ -253,21 +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; - /// - /// Poly1305: encryption with addtional optional authentication. - /// Implemented in its own unit and only usable with ChaCha20 (and maybe AES128) - - /// Currently only one class overrides this method. - /// - procedure EncodePoly1305(Source, Dest: PUInt8Array; Size: Integer); virtual; - - /// - /// Counter with CBC-MAC Mode: encryption with addtional optional authentication. - /// Implemented in its own unit, but needed here to be callable even if - /// source length is 0. - /// - procedure EncodeCCM(Source, Dest: PUInt8Array; Size: Integer); virtual; {$IFDEF DEC3_CMCTS} /// /// double CBC, with @@ -351,21 +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 - /// - procedure DecodeGCM(Source, Dest: PUInt8Array; Size: Integer); virtual; - /// - /// Poly1305, details are implemented in DECCipherModesPoly1305. - /// This routine needs to be overridden by successor classes. - /// - procedure DecodePoly1305(Source, Dest: PUInt8Array; Size: Integer); virtual; - /// - /// Counter with CBC-MAC Mode, details are implemented in DECCipherModesCCM + /// Decoding for gcm, poly1305 and ccm, details are implemented in special units. /// - procedure DecodeCCM(Source, Dest: PUInt8Array; Size: Integer); virtual; + procedure DecodeWithAuthObj(Source, Dest: PUInt8Array; Size: Integer); virtual; {$IFDEF DEC3_CMCTS} /// /// double CBC @@ -491,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'; @@ -515,36 +476,30 @@ procedure TDECCipherModes.ReportInvalidMessageLength(Cipher: TDECCipher); procedure TDECCipherModes.SetDataToAuthenticate(const Value: TBytes); begin - case FMode of - cmGCM: FGCM.DataToAuthenticate := Value; - cmCCM: FCCM.DataToAuthenticate := Value; - cmPoly1305: FPOLY1305.DataToAuthenticate := Value; - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); - end; + if Assigned(fAuthObj) + then + fAuthObj.DataToAuthenticate := Value + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; procedure TDECCipherModes.SetExpectedAuthenticationResult(const Value: TBytes); begin - case FMode of - cmGCM: FGCM.ExpectedAuthenticationTag := Value; - cmCCM: FCCM.ExpectedAuthenticationTag := Value; - cmPoly1305: FPOLY1305.ExpectedAuthenticationTag := Value; - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); - end; + if Assigned(fAuthObj) + then + fAuthObj.ExpectedAuthenticationTag := Value + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); end; procedure TDECCipherModes.SetAuthenticationResultBitLength( const Value: Integer); begin - case FMode of - cmGCM: FGCM.AuthenticationTagBitLength := Value; - cmCCM: FCCM.AuthenticationTagBitLength := Value; - cmPoly1305: FPOLY1305.AuthenticationTagBitLength := Value; - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); - end; + 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); @@ -564,9 +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); - cmPoly1305: EncodePoly1305(@Source, @Dest, DataSize); - cmCCM : EncodeCCM(@Source, @Dest, DataSize); + cmGCM, + cmPoly1305, + cmCCM: EncodeWithAuthObj(@Source, @Dest, DataSize); end; end; @@ -738,60 +693,50 @@ procedure TDECCipherModes.EncodeOFBx(Source, Dest: PUInt8Array; Size: Integer); function TDECCipherModes.GetDataToAuthenticate: TBytes; begin - case FMode of - cmGCM: Result := FGCM.DataToAuthenticate; - cmCCM: Result := FCCM.DataToAuthenticate; - cmPoly1305: Result := FPOLY1305.DataToAuthenticate; - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cCCM']); - end; + if Assigned(fAuthObj) + then + Result := fAuthObj.DataToAuthenticate + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM, cmPoly1305 or cCCM']); end; function TDECCipherModes.GetExpectedAuthenticationResult: TBytes; begin - case FMode of - cmGCM: Result := FGCM.ExpectedAuthenticationTag; - cmCCM: Result := FCCM.ExpectedAuthenticationTag; - cmPoly1305: REsult := FPOLY1305.ExpectedAuthenticationTag; - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); - end; + 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; - cmCCM: Result := FCCM.GetStandardAuthenticationTagBitLengths; - cmPoly1305: Result := FPOLY1305.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 - case FMode of - cmGCM: Result := FGCM.AuthenticationTagBitLength; - cmCCM: Result := FCCM.AuthenticationTagBitLength; - cmPoly1305: Result := FPOLY1305.AuthenticationTagBitLength; - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); - end; + if Assigned(fAuthObj) + then + Result := fAuthObj.AuthenticationTagBitLength + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM, cmPoly1305 or cmCCM']); end; function TDECCipherModes.GetCalcAuthenticatonResult: TBytes; begin - case FMode of - cmGCM: Result := FGCM.CalculatedAuthenticationTag; - cmCCM: Result := FCCM.CalculatedAuthenticationTag; - cmPoly1305: Result := FPOLY1305.CalculatedAuthenticationTag; - else - raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM or cmCCM']); - end; + if Assigned(fAuthObj) + then + Result := fAuthObj.CalculatedAuthenticationTag + else + raise EDECCipherException.CreateResFmt(@sInvalidModeForMethod, ['cmGCM, cmPoly1305 or cmCCM']); end; procedure TDECCipherModes.InitMode; @@ -800,15 +745,15 @@ procedure TDECCipherModes.InitMode; begin if (Context.BlockSize = 16) then begin - case FMode of - cmGCM: FGCM := TGCM.Create; - cmCCM: FCCM := TCCM.Create; - cmPoly1305: FPOLY1305 := TPoly1305.Create; + case FMode of + cmGCM: fAuthObj := TGCM.Create; + cmCCM: fAuthObj := TCCM.Create; + cmPoly1305: fAuthObj := TPoly1305.Create; end; end else if Context.BlockSize < 16 then - FPOLY1305 := TPoly1305.Create + fAuthObj := TPoly1305.Create else // GCM and CCM require a cipher with 128 bit block size raise EDECCipherException.CreateResFmt(@sInvalidBlockSize, @@ -817,14 +762,8 @@ procedure TDECCipherModes.InitMode; end else begin - if Assigned(FGCM) then - FreeAndNil(FGCM); - - if Assigned(FCCM) then - FreeAndNil(FCCM); - - if Assigned(FPOLY1305) then - FreeAndNil(FPOLY1305); + if Assigned(fAuthObj) then + FreeAndNil(fAuthObj); end; end; @@ -918,28 +857,12 @@ procedure TDECCipherModes.EncodeCTSx(Source, Dest: PUInt8Array; Size: Integer); FState := csEncode; end; -procedure TDECCipherModes.EncodeGCM(Source, Dest: PUInt8Array; Size: Integer); -begin - if (Size < 0) then - Size := 0; - - FGCM.Encode(Source, Dest, Size); -end; - -procedure TDECCipherModes.EncodePoly1305(Source, Dest: PUInt8Array; - Size: Integer); -begin - if size < 0 then - Size := 0; - FPOLY1305.Encode(Source, Dest, Size); -end; - -procedure TDECCipherModes.EncodeCCM(Source, Dest: PUInt8Array; Size: Integer); +procedure TDECCipherModes.EncodeWithAuthObj(Source, Dest: PUInt8Array; Size: Integer); begin if (Size < 0) then Size := 0; - FCCM.Encode(Source, Dest, Size); + fAuthObj.Encode(Source, Dest, Size); end; {$IFDEF DEC3_CMCTS} @@ -984,9 +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); - cmPoly1305: DecodePoly1305(@Source, @Dest, DataSize); - cmCCM : DecodeCCM(@Source, @Dest, DataSize); + cmGCM, + cmPoly1305, + cmCCM : DecodeWithAuthObj(@Source, @Dest, DataSize); end; end; @@ -1025,20 +948,12 @@ procedure TDECCipherModes.DecodeECBx(Source, Dest: PUInt8Array; Size: Integer); end; end; -procedure TDECCipherModes.DecodeGCM(Source, Dest: PUInt8Array; Size: Integer); +procedure TDECCipherModes.DecodeWithAuthObj(Source, Dest: PUInt8Array; Size: Integer); begin if (Size < 0) then Size := 0; - FGCM.Decode(Source, Dest, Size); -end; - -procedure TDECCipherModes.DecodeCCM(Source, Dest: PUInt8Array; Size: Integer); -begin - if (Size < 0) then - Size := 0; - - FCCM.Decode(Source, Dest, Size); + fAuthObj.Decode(Source, Dest, Size); end; procedure TDECCipherModes.DecodeCFB8(Source, Dest: PUInt8Array; Size: Integer); @@ -1184,49 +1099,25 @@ procedure TDECCipherModes.DecodeOFBx(Source, Dest: PUInt8Array; Size: Integer); end; end; -procedure TDECCipherModes.DecodePoly1305(Source, Dest: PUInt8Array; - Size: Integer); -begin - if (Size < 0) then - Size := 0; - - FPOLY1305.Decode(Source, Dest, Size); -end; - destructor TDECCipherModes.Destroy; begin - FGCM.Free; - FCCM.Free; - FPOLY1305.Free; + fAuthObj.Free; - inherited; + inherited; end; procedure TDECCipherModes.Done; begin inherited; - case FMode of - cmGCM : begin - if (length(FGCM.ExpectedAuthenticationTag) > 0) and - (not IsEqual(FGCM.ExpectedAuthenticationTag, FGCM.CalculatedAuthenticationTag)) then - raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); - end; - - cmCCM : begin - if (length(FCCM.ExpectedAuthenticationTag) > 0) and - (not IsEqual(FCCM.ExpectedAuthenticationTag, FCCM.CalculatedAuthenticationTag)) then - raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); - end; - cmPoly1305: begin - // ########################################### - // #### Now the time is here to create the tag... - FPOLY1305.Finalize; - - if (length(FPOLY1305.ExpectedAuthenticationTag) > 0) and - (not IsEqual(FPOLY1305.ExpectedAuthenticationTag, FPOLY1305.CalculatedAuthenticationTag)) then - raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); - end; + if Assigned(fAuthObj) then + begin + fAuthObj.FinalizeAEAD; + + if (length(fAuthObj.ExpectedAuthenticationTag) > 0) and + (not IsEqual(fAuthObj.ExpectedAuthenticationTag, fAuthObj.CalculatedAuthenticationTag)) + then + raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); end; end; @@ -1234,11 +1125,8 @@ procedure TDECCipherModes.OnAfterInitVectorInitialization(const OriginalInitVect begin inherited; - case FMode of - cmGCM: FGCM.Init(self.DoEncode, OriginalInitVector); - cmCCM: FCCM.Init(self.DoEncode, OriginalInitVector); - cmPoly1305: FPOLY1305.Init(self.DoEncode, OriginalInitVector); - end; + 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 index 3f835f67..966ce7a4 100644 --- a/Source/DECCipherModesCCM.pas +++ b/Source/DECCipherModesCCM.pas @@ -78,6 +78,15 @@ TCCM = class(TAuthenticatedCipherModesBase) /// 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 @@ -396,4 +405,35 @@ procedure TCCM.Init(EncryptionMethod : TEncodeDecodeMethod; 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 ed2cde55..1eb24739 100644 --- a/Source/DECCipherModesGCM.pas +++ b/Source/DECCipherModesGCM.pas @@ -52,16 +52,37 @@ interface /// Galois Counter Mode specific methods /// TGCM = class(TAuthenticatedCipherModesBase) + strict private + const cGCMBlkSize = 16; strict private /// /// Empty value? /// nullbytes : T128; + + /// + /// if flag is set no more encoding is allowed + /// + fIsLastBlock : boolean; + + /// + /// One reserve buffer for the GCM intermediate blocks + /// + FData : Array[0..cGCMBlkSize-1] of Byte; + + /// + /// Current index of non encoded fdata bytes + /// + FDataIdx : integer; + /// /// Table with precalculated values /// FM : array[0..15,0..255] of T128; + /// + FGHash : T128; + /// /// Required for creating the table and encryption at least /// @@ -174,6 +195,11 @@ TGCM = class(TAuthenticatedCipherModesBase) /// procedure INCR(var Y : T128); + /// + // ########################################### + // #### blocked version of GaloisHash functions + // ########################################### + /// /// Calculates the hash value /// @@ -193,10 +219,18 @@ TGCM = class(TAuthenticatedCipherModesBase) /// /// Calculated raw hash value which will later get returned as AuthenticatedTag /// - function CalcGaloisHash(AuthenticatedData : PUInt8Array; - AuthLen : Integer; - Ciphertext : PUInt8Array; - 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 @@ -207,7 +241,7 @@ TGCM = class(TAuthenticatedCipherModesBase) /// /// Encrypted value /// - function EncodeT128(Value: T128): T128; + function EncodeT128(Value: T128): T128; inline; strict protected /// /// Defines the length of the resulting authentication value in bit. @@ -219,50 +253,65 @@ TGCM = class(TAuthenticatedCipherModesBase) /// constrains the length of the input data and the lifetime of the key. /// procedure SetAuthenticationTagLength(const Value: UInt32); override; - public + + /// - /// Should be called when starting encryption/decryption in order to - /// initialize internal tables etc. + /// 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. /// - /// - /// Encryption method of the cypher used + 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. /// - /// - /// Initialization vector + /// + /// Length of the buffer /// - procedure Init(EncryptionMethod : TEncodeDecodeMethod; - InitVector : TBytes); override; + procedure UpdateWithEncDecBuf(buf : PUInt8Array; Size : Integer); override; + /// - /// Encodes 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) /// /// - /// Plain text to encrypt + /// Pointer the data that updates the hash. /// /// - /// Ciphertext after encryption + /// Pointer the data that updates the hash. /// - /// - /// Number of bytes to encrypt + /// + /// Length of the buffer /// - procedure Encode(Source, - Dest : PUInt8Array; - Size : Integer); override; + procedure LocEncodeDecode(Source, Dest: Pointer; Size: Integer); override; + + + procedure Burn; override; + public /// - /// Decodes a block of data using the supplied cipher + /// Should be called when starting encryption/decryption in order to + /// initialize internal tables etc. /// - /// - /// Encrypted ciphertext to decrypt - /// - /// - /// Plaintext after decryption + /// + /// Encryption method of the cypher used /// - /// - /// Number of bytes to decrypt + /// + /// Initialization vector /// - procedure Decode(Source, - Dest : PUInt8Array; - Size : Integer); override; - + procedure Init(EncryptionMethod : TEncodeDecodeMethod; + InitVector : TBytes); override; /// /// Returns a list of authentication tag lengths explicitely specified by /// the official specification of the standard. @@ -275,6 +324,14 @@ TGCM = class(TAuthenticatedCipherModesBase) 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]; @@ -436,11 +493,13 @@ procedure TGCM.Init(EncryptionMethod : TEncodeDecodeMethod; begin inherited; + FEncryptionMethod := EncryptionMethod; + Nullbytes[0] := 0; 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 @@ -460,205 +519,259 @@ procedure TGCM.Init(EncryptionMethod : TEncodeDecodeMethod; FEncryptionMethod(@FY[0], @FE_K_Y0[0], 16); end; -function TGCM.CalcGaloisHash(AuthenticatedData : PUInt8Array; AuthLen : integer; Ciphertext : PUInt8Array; - CiphertextSize: Integer): T128; -var - AuthCipherLength : T128; - x : T128; - n : Uint64; +procedure TGCM.InitAuth; +begin + FillChar(fData, sizeof(fData), 0); + FDataIdx := 0; - 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; + FGHash := nullbytes; + if Length(FDataToAuthenticate) > 0 then + UpdateWithEncDecBuf(@FDataToAuthenticate[0], Length(FDataToAuthenticate)); +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; +procedure TGCM.LocEncodeDecode(Source, Dest: Pointer; Size: Integer); +var i, j : integer; + div_len_plain : integer; + +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; - if AuthLen > 0 then - encode(@AuthenticatedData[0], AuthLen); - //Assert(length(Ciphertext) >= CiphertextSize); - encode(Ciphertext, CiphertextSize); - SetAuthenticationCipherLength(AuthCipherLength, AuthLen 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 > 0) then + begin + div_d := len_d div cGCMBlkSize; + if div_d > 0 then + begin + for i := 0 to div_d - 1 do + begin + FGHash := poly_mult_H(XOR_PointerWithT128(@buf^[n], FGHash )); + inc(n, cGCMBlkSize); + end; + end; + end; + + if n < size then + begin + Move(buf^[n], fData[fDataIdx], size - n); + inc(FDataIdx, size - n); + end; end; -procedure TGCM.Decode(Source, Dest: PUInt8Array; 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; - pSrc : 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); + + inc(i,16); end; if i < Size then begin INCR(FY); - XOR_ArrayWithT128(@Source^[0], i, UInt64(Size)-i, EncodeT128(FY), @Dest^[0]); + XOR_ArrayWithT128(Source, i, UInt64(Size)-i, EncodeT128(FY), Dest); end; pDataToAuth := nil; if Length(DataToAuthenticate) > 0 then pDataToAuth := @DataToAuthenticate[0]; - pSrc := nil; - if Size > 0 then - pSrc := @source[0]; - - a_tag := XOR_T128(CalcGaloisHash(pDataToAuth, Length(DataToAuthenticate), - pSrc, Size), FE_K_Y0); - + 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.Encode(Source, Dest: PUInt8Array; 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; - pDataToAuth : PUInt8Array; 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; - 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(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.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; -// +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 index 5495a6ff..c09ae043 100644 --- a/Source/DECCipherModesPoly1305.pas +++ b/Source/DECCipherModesPoly1305.pas @@ -41,101 +41,88 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) const POLY1305_BLOCK_SIZE = 16; POLY1305_DIGEST_SIZE = 16; POLY1305_KEY_SIZE = 32; - - POLY1305_SSE2_BLOCK_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; - TYMM = Array[0..7] of UInt32; - TYMM64 = Array[0..3] of Int64; - TXMM = Array[0..3] of UInt32; - - TPoly1305StateFlag = (poly1305_started = 1, poly1305_final_shift8 = 4, - poly1305_final_shift16 = 8, - poly1305_final_r2_r = 16, // use [r^2,r] for the final block */ - poly1305_final_r_1 = 32 // use [r,1] for the final block */ - ); - - type - TH = packed record - case byte of - 0: (H : Array[0..2] of UInt64); - 1: (HH: Array[0..19] of Uint32); - 2: (H32 : THArr); - end; - - TPoly1305_state_internal_t = packed record - hmac : TH; - R : Array[0..4] of Uint32; - R2 : Array[0..4] of UInt32; - R3 : Array[0..4] of UInt32; - R4 : Array[0..4] of UInt32; - pad : Array[0..1] of UInt64; - flags : Uint64; - end; - PPoly1305_state_internal_t = ^TPoly1305_state_internal_t; - - TPoly1305State = Array[0..191] of Byte; + TPoly1305State = Array[0..160] of Byte; private - // avx structures + /// + /// avx buffer for h and R (may be extended in future fo for SSE, AVX) + /// fPoly1305State : TPoly1305State; - fPPoly1305State : PPoly1305_state_internal_t; - // pas structures + /// + /// 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; - FEncryptionMethod : TEncodeDecodeMethod; - - // reminder... + /// + /// Internal state variables - number of remaining bytes, block size and intermediate buffer + /// fNum : integer; - fData : Array[0..POLY1305_BLOCK_SIZE - 1] of Byte; + fPolyBlockSize : integer; + fData : Array[0..2*POLY1305_BLOCK_SIZE - 1] of Byte; // for both the sse and pas version - FAuthDataLen : integer; - FCipherLen : integer; + /// + /// #bytes of encrypted data + /// fPolyInitComplete : boolean; + + /// + /// Reference to the actual poly block function. For future SSE, AVX use + /// fPolyBlkFunc : TPoly1305BlockMethod; - fPolyEmitFunc : TPoly1305EmitMethod; + fPadAndFinalizeFunc : TPoly1305PadAndFinalize; - function U8ToU32( pData : PByteArray ) : UInt32; - procedure U32ToU8(pData : PByteArray; value : UInt32); + function U8ToU32( pData : PByteArray ) : UInt32; inline; + procedure U32ToU8(pData : PByteArray; value : UInt32); inline; + /// + /// Poly1305 blocks function + /// procedure Poly1305Blocks( pData : PByteArray; size : integer; padBit : UInt32 ); - procedure Poly1305Emit( var mac : TBlock16Byte; const nonce : TPoly1305Nonce ); - procedure Poly1305Finalize( var mac : TBlock16Byte ); - - procedure Poly1305Init_SSE( initVec : PByte ); - procedure Poly1305Blocks_SSE( pData : PByteArray; size : integer ); - procedure Poly1305Emit_SSE( var mac : TBlock16Byte ); - procedure Burn; + /// + /// Finaly MAC creating function + /// + procedure Poly1305Emit( var mac : TBlock16Byte; const nonce : TPoly1305Nonce ); + procedure PadAndFinalizePAS( authLen, encDecBufLen : int64); protected - // ########################################### - // #### base functionality - // ########################################### // #### Authentication block functions - procedure BeginPoly1304Auth; - public - class var UseSSE : boolean; - - constructor Create; - procedure UpdatePoly( pData : PByteArray; size : integer); procedure InitInternal(const InitVector : T32ByteArray); - procedure PadAndFinalizeAEAD; 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. @@ -148,24 +135,6 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) /// procedure Init(EncryptionMethod : TEncodeDecodeMethod; InitVector : TBytes); override; - - /// - /// Encodes a block of data using the supplied cipher. - /// The function can be called multiple times. Internally the - /// hash is updated on each call. - /// - procedure Encode(Source, Dest : PUInt8Array; - CiphertextSize : Integer); override; - - /// - /// Decodes a block of data using the supplied cipher. - /// The function can be called multiple times. Internally the - /// hash is updated on each call. - /// - procedure Decode(Source, - Dest : PUInt8Array; - Size : Integer - ); override; end; implementation @@ -180,40 +149,56 @@ function ConstTimeCarray32(a, b : UInt32 ) : UInt32; inline; Result := (a xor ( (a xor b) or (a - b) xor b )) shr 31; end; + { TPoly1305 } -procedure TPoly1305.BeginPoly1304Auth; +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 - FAuthDataLen := Length(FDataToAuthenticate); - if fAuthDataLen > 0 then + if aLen > 0 then begin // pad to blocksize if ncessary - aLen := Length(FDataToAuthenticate); 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], FAuthDataLen); - //vec[FAuthDataLen] := 1; + 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], POLY1305_BLOCK_SIZE); + fPolyBlkFunc( @vec[0], Length(vec)); end; - FCipherLen := 0; end; procedure TPoly1305.Burn; begin - FillChar(FH, sizeof(FH), 0); + inherited; + + FillChar(fPoly1305State, sizeof(fPoly1305State), 0); FillChar(FNonce, sizeof(FNonce), 0); - FillChar(FR, sizeof(FR), 0); FillChar(fIV, sizeof(fIV), 0); FillChar(fData, sizeof(fData), 0); fNum := 0; @@ -231,58 +216,38 @@ constructor TPoly1305.Create; begin inherited Create; - fPPoly1305State := @fPoly1305State[0]; FH := @fPoly1305State[0]; FR := @fPoly1305State[sizeof(THarr)]; - if useSSE then - begin - fPolyBlkFunc := Poly1305Blocks_SSE; // Poly1305Blocks_AVX - fPolyEmitFunc := Poly1305Emit_SSE; - end - else - begin - fPolyBlkFunc := UpdatePoly; - fPolyEmitFunc := Poly1305Finalize; - end; + // for future use -> here is a good place to add sse AVX functions + fPadAndFinalizeFunc := PadAndFinalizePAS; + fPolyBlkFunc := UpdatePoly; + fPolyBlockSize := POLY1305_BLOCK_SIZE; end; -procedure TPoly1305.Decode(Source, Dest: PUInt8Array; Size: Integer); -begin - if not fPolyInitComplete then - BeginPoly1304Auth; - - fPolyBlkFunc( PByteArray( Source ), Size ); - inc( FCipherLen, Size ); - - FEncryptionMethod( Source, Dest, Size ); -end; - -procedure TPoly1305.Encode(Source, Dest: PUInt8Array; - CiphertextSize: Integer); -begin - if not fPolyInitComplete then - BeginPoly1304Auth; - - FEncryptionMethod( Source, Dest, CipherTextSize ); - fPolyBlkFunc( PByteArray( dest ), CipherTextSize ); - inc( FCipherLen, CipherTextSize ); -end; - - procedure TPoly1305.Finalize; var mac : TBlock16Byte; begin - if not fPolyInitComplete then - BeginPoly1304Auth; + if fNum > 0 then + begin + fData[fNum] := 1; + inc(fNum); + while fNum < Length(fData) do + begin + fData[fNum] := 0; + inc(fNum); + end; + + Poly1305Blocks(@fData[0], POLY1305_BLOCK_SIZE, 0); + fNum := 0; + end; - fPolyEmitFunc( mac ); + Poly1305Emit(mac, FNonce); SetLength(FCalcAuthenticationTag, sizeof(mac)); Move(mac, FCalcAuthenticationTag[0], sizeof(mac)); FillChar(mac, sizeof(mac), 0); - Burn; end; procedure TPoly1305.Init(EncryptionMethod: TEncodeDecodeMethod; @@ -302,51 +267,43 @@ procedure TPoly1305.Init(EncryptionMethod: TEncodeDecodeMethod; // build the poly1305 iv from the first 256 bits FillChar( fIV, sizeof(fIV), 0); Move( initVector[0], fIV, Length(initVector)); - - FAuthDataLen := 0; - FCipherLen := 0; - FEncryptionMethod := EncryptionMethod; end; procedure TPoly1305.InitInternal(const InitVector: T32ByteArray); begin fPolyInitComplete := True; - if UseSSE then - begin - Poly1305Init_SSE(@initVector[0]); - end - else - begin - 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; + 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]); - end; - fNum := 0; + 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.PadAndFinalizeAEAD; -var lens : Array[0..1] of UInt64; +procedure TPoly1305.FinalizeMAC( authLen, encDecBufLen : int64); begin - if not fPolyInitComplete then - BeginPoly1304Auth; + 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 @@ -364,8 +321,8 @@ procedure TPoly1305.PadAndFinalizeAEAD; // finalize with the tag with the lengths! - lens[0] := FAuthDataLen; - lens[1] := FCipherLen; + lens[0] := authLen; + lens[1] := encDecBufLen; Poly1305Blocks(@lens[0], POLY1305_BLOCK_SIZE, 1); Finalize; @@ -576,1401 +533,6 @@ procedure TPoly1305.Poly1305Emit(var mac: TBlock16Byte; U32ToU8(@mac[12], h3); end; -type - XMMWORD = Array[0..7] of Word; - -// dump from poly1305-donna-x86-sse2-incremental-source.c -procedure _poly1305_init_ext_sse2(st : TPoly1305.PPoly1305_state_internal_t; key : PByte; bytes : integer); cdecl; -asm - push ebp - pxor xmm0, xmm0 - mov ebp, esp - push edi - push esi - push ebx - and esp, -8 - sub esp, 56 - mov edx, DWORD PTR [ebp+12] - mov eax, DWORD PTR [ebp+8] - movups XMMWORD PTR [eax+32], xmm0 - movups XMMWORD PTR [eax], xmm0 - movups XMMWORD PTR [eax+16], xmm0 - mov ebx, DWORD PTR [edx] - mov eax, DWORD PTR [edx+4] - mov ecx, DWORD PTR [edx+8] - mov edi, DWORD PTR [edx+12] - mov esi, ebx - shr ebx, 26 - and esi, 67108863 - mov DWORD PTR [esp+40], esi - mov esi, eax - shr eax, 20 - sal esi, 6 - or esi, ebx - mov ebx, esi - mov esi, DWORD PTR [esp+40] - and ebx, 67108611 - mov DWORD PTR [esp+36], ebx - mov ebx, ecx - shr ecx, 14 - sal ebx, 12 - or ebx, eax - mov eax, edi - shr edi, 8 - sal eax, 18 - and ebx, 67092735 - and edi, 1048575 - or eax, ecx - mov ecx, eax - mov eax, DWORD PTR [ebp+8] - and ecx, 66076671 - mov DWORD PTR [eax+40], esi - mov esi, eax - mov eax, DWORD PTR [esp+36] - mov DWORD PTR [esi+48], ebx - mov DWORD PTR [esi+52], ecx - mov DWORD PTR [esi+56], edi - mov DWORD PTR [esi+44], eax - mov eax, DWORD PTR [edx+16] - mov DWORD PTR [esi+100], eax - mov eax, DWORD PTR [edx+20] - mov DWORD PTR [esi+104], eax - mov eax, DWORD PTR [edx+24] - mov DWORD PTR [esi+108], eax - mov eax, DWORD PTR [edx+28] - lea edx, [ecx+ecx*4] - mov DWORD PTR [esi+112], eax - mov esi, edx - lea edx, [edi+edi] - mov DWORD PTR [esp+28], edi - lea edi, [ebx+ebx] - mov eax, edi - mov DWORD PTR [esp+48], edx - mul esi - mov DWORD PTR [esp+12], esi - mov DWORD PTR [esp+32], ebx - lea ebx, [ebx+ebx*4] - mov esi, eax - mov eax, DWORD PTR [esp+36] - mov edi, edx - lea eax, [eax+eax*4] - mul DWORD PTR [esp+48] - add esi, eax - mov eax, DWORD PTR [esp+40] - adc edi, edx - mul eax - add esi, eax - adc edi, edx - mov eax, esi - mov edx, edi - mov edi, DWORD PTR [esp+36] - mov DWORD PTR [esp], eax - and eax, 67108863 - mov DWORD PTR [esp+4], edx - lea esi, [edi+edi] - mov DWORD PTR [esp+8], eax - mov eax, ebx - mov DWORD PTR [esp+20], esi - mul DWORD PTR [esp+48] - mov esi, DWORD PTR [esp+40] - lea edi, [esi+esi] - lea esi, [ecx+ecx] - mov DWORD PTR [esp+24], edi - mov edi, edx - mov DWORD PTR [esp+16], esi - mov esi, eax - mov eax, DWORD PTR [esp+20] - mul DWORD PTR [esp+40] - add esi, eax - mov eax, ecx - mov ecx, DWORD PTR [esp+36] - adc edi, edx - mul DWORD PTR [esp+12] - add eax, esi - mov esi, DWORD PTR [esp] - adc edx, edi - mov edi, DWORD PTR [esp+4] - shrd esi, edi, 26 - shr edi, 26 - add esi, eax - mov eax, esi - adc edi, edx - and eax, 67108863 - mov DWORD PTR [esp], eax - mov eax, ecx - mul ecx - mov ecx, eax - mov ebx, edx - mov eax, DWORD PTR [esp+32] - mul DWORD PTR [esp+24] - add ecx, eax - mov eax, DWORD PTR [esp+12] - adc ebx, edx - mul DWORD PTR [esp+48] - add eax, ecx - adc edx, ebx - shrd esi, edi, 26 - shr edi, 26 - add esi, eax - mov eax, esi - adc edi, edx - and eax, 67108863 - mov DWORD PTR [esp+48], eax - mov eax, DWORD PTR [esp+40] - mul DWORD PTR [esp+16] - mov ecx, eax - mov ebx, edx - mov eax, DWORD PTR [esp+20] - mul DWORD PTR [esp+32] - add ecx, eax - adc ebx, edx - mov edx, DWORD PTR [esp+28] - lea eax, [edx+edx*4] - mul edx - add eax, ecx - adc edx, ebx - shrd esi, edi, 26 - shr edi, 26 - add eax, esi - mov DWORD PTR [esp+40], eax - mov ebx, DWORD PTR [esp+32] - adc edx, edi - mov esi, eax - mov DWORD PTR [esp+44], edx - and esi, 67108863 - mov edi, DWORD PTR [esp+48] - mov eax, ebx - mul ebx - mov ecx, eax - mov ebx, edx - mov eax, DWORD PTR [esp+28] - mul DWORD PTR [esp+24] - add ecx, eax - mov eax, DWORD PTR [esp+36] - adc ebx, edx - mul DWORD PTR [esp+16] - add eax, ecx - mov ecx, DWORD PTR [esp+40] - adc edx, ebx - mov ebx, DWORD PTR [esp+44] - shrd ecx, ebx, 26 - shr ebx, 26 - add eax, ecx - adc edx, ebx - mov ecx, eax - mov ebx, DWORD PTR [esp+8] - shrd eax, edx, 26 - mov edx, DWORD PTR [esp] - and ecx, 67108863 - lea eax, [eax+eax*4] - mov DWORD PTR [esp+32], ecx - add eax, ebx - mov ebx, eax - shr eax, 26 - add edx, eax - mov eax, DWORD PTR [ebp+8] - and ebx, 67108863 - mov DWORD PTR [esp+40], ebx - mov DWORD PTR [eax+60], ebx - mov DWORD PTR [eax+64], edx - mov DWORD PTR [eax+68], edi - mov DWORD PTR [eax+72], esi - mov DWORD PTR [eax+76], ecx - lea eax, [esi+esi*4] - mov ebx, eax - lea eax, [ecx+ecx] - lea ecx, [edi+edi] - mov DWORD PTR [esp+36], edx - mov DWORD PTR [esp+28], eax - mov eax, ecx - lea edi, [edi+edi*4] - mul ebx - mov DWORD PTR [esp+12], ebx - mov ecx, eax - mov eax, DWORD PTR [esp+40] - mov ebx, edx - mul eax - add ecx, eax - adc ebx, edx - mov edx, DWORD PTR [esp+36] - lea eax, [edx+edx*4] - mul DWORD PTR [esp+28] - add ecx, eax - adc ebx, edx - mov edx, DWORD PTR [esp+36] - lea eax, [edx+edx] - lea edx, [esi+esi] - mov DWORD PTR [esp+16], eax - mov eax, DWORD PTR [esp+40] - mov DWORD PTR [esp+24], edx - add eax, eax - mov DWORD PTR [esp+20], eax - mov eax, ecx - and eax, 67108863 - mov DWORD PTR [esp+8], eax - mov eax, edi - mul DWORD PTR [esp+28] - mov DWORD PTR [esp], eax - mov eax, esi - mov DWORD PTR [esp+4], edx - mul DWORD PTR [esp+12] - mov esi, eax - mov edi, edx - add esi, DWORD PTR [esp] - mov eax, DWORD PTR [esp+16] - adc edi, DWORD PTR [esp+4] - mul DWORD PTR [esp+40] - add eax, esi - adc edx, edi - shrd ecx, ebx, 26 - shr ebx, 26 - add ecx, eax - mov eax, DWORD PTR [esp+48] - adc ebx, edx - mul DWORD PTR [esp+20] - mov esi, ecx - and esi, 67108863 - mov DWORD PTR [esp], esi - mov esi, eax - mov eax, DWORD PTR [esp+36] - mov edi, edx - mul eax - add esi, eax - mov eax, DWORD PTR [esp+28] - adc edi, edx - mul DWORD PTR [esp+12] - add eax, esi - adc edx, edi - shrd ecx, ebx, 26 - shr ebx, 26 - add eax, ecx - mov ecx, DWORD PTR [esp+32] - adc edx, ebx - mov esi, eax - lea ebx, [ecx+ecx*4] - mov edi, edx - mov eax, ebx - mov DWORD PTR [esp+44], edi - mul ecx - mov ecx, eax - mov ebx, edx - mov eax, DWORD PTR [esp+40] - mov DWORD PTR [esp+40], esi - mul DWORD PTR [esp+24] - add ecx, eax - mov eax, DWORD PTR [esp+16] - adc ebx, edx - mul DWORD PTR [esp+48] - add eax, ecx - adc edx, ebx - shrd esi, edi, 26 - shr edi, 26 - add esi, eax - mov eax, DWORD PTR [esp+24] - adc edi, edx - mul DWORD PTR [esp+36] - mov ecx, eax - mov ebx, edx - mov eax, DWORD PTR [esp+32] - mul DWORD PTR [esp+20] - add ecx, eax - mov eax, DWORD PTR [esp+48] - adc ebx, edx - mul eax - add eax, ecx - mov ecx, esi - adc edx, ebx - shrd ecx, edi, 26 - mov ebx, edi - shr ebx, 26 - add eax, ecx - adc edx, ebx - mov DWORD PTR [esp+48], eax - mov ebx, DWORD PTR [ebp+8] - shrd eax, edx, 26 - mov DWORD PTR [esp+52], edx - lea edx, [eax+eax*4] - mov eax, DWORD PTR [esp+8] - add edx, eax - mov eax, DWORD PTR [esp] - mov ecx, edx - shr edx, 26 - add edx, eax - and ecx, 67108863 - mov DWORD PTR [ebx+80], ecx - mov DWORD PTR [ebx+84], edx - mov edx, DWORD PTR [esp+40] - mov eax, DWORD PTR [esp+48] - mov DWORD PTR [ebx+116], 0 - and edx, 67108863 - mov DWORD PTR [ebx+88], edx - mov edx, esi - and eax, 67108863 - and edx, 67108863 - mov DWORD PTR [ebx+96], eax - mov DWORD PTR [ebx+92], edx - lea esp, [ebp-12] - pop ebx - pop esi - pop edi - pop ebp -end; - -procedure _Poly1305_Blocks_sse2( st : TPoly1305.PPoly1305_state_internal_t; m : PByte; bytes : integer ); cdecl; -label L6, L7, L8, L10, L12, L13, L14, L15, L16, L18, L19, L28, L29; -const LC3 : TPoly1305.TXMM = ( 1, 0, 0, 0 ); - LC4 : TPoly1305.TXMM = ( 16777216, 0, 16777216, 0); - LC5 : TPoly1305.TXMM = ( 67108863, 0, 67108863, 0); - LC6 : TPoly1305.TXMM = ( 5, 0, 5, 0); -asm - push ebp - mov ebp, esp - push edi - push esi - push ebx - and esp, -16 - sub esp, 1168 - mov esi, DWORD PTR [ebp+8] - mov eax, DWORD PTR [ebp+12] - movdqa xmm0, XMMWORD PTR LC4 - mov ecx, DWORD PTR [ebp+16] - mov edx, DWORD PTR [esi+116] - movaps XMMWORD PTR [esp+1136], xmm0 - test dl, 4 - je L6 - movdqa xmm7, xmm0 - psrldq xmm7, 8 - movaps XMMWORD PTR [esp+1136], xmm7 -L6: - test dl, 8 - je L7 - pxor xmm7, xmm7 - movaps XMMWORD PTR [esp+1136], xmm7 -L7: - test dl, 1 - jne L8 - movq xmm0, QWORD PTR [eax+16] - movq xmm1, QWORD PTR [eax] - or edx, 1 - add eax, 32 - movq xmm2, QWORD PTR [eax-8] - sub ecx, 32 - movdqa xmm7, XMMWORD PTR LC5 - movdqa xmm5, XMMWORD PTR LC5 - punpcklqdq xmm1, xmm0 - movq xmm0, QWORD PTR [eax-24] - mov DWORD PTR [esi+116], edx - pand xmm7, xmm1 - punpcklqdq xmm0, xmm2 - movdqa xmm2, xmm1 - psrlq xmm2, 26 - psrlq xmm1, 52 - pand xmm2, XMMWORD PTR LC5 - movaps XMMWORD PTR [esp+1120], xmm2 - movdqa xmm2, xmm0 - psrlq xmm0, 40 - por xmm0, XMMWORD PTR [esp+1136] - psllq xmm2, 12 - por xmm1, xmm2 - movdqa xmm2, xmm0 - pand xmm5, xmm1 - psrlq xmm1, 26 - pand xmm1, XMMWORD PTR LC5 - test dl, 48 - je L10 -L29: - movd xmm3, DWORD PTR [esi+56] - and edx, 16 - movdqu xmm4, XMMWORD PTR [esi+40] - movaps XMMWORD PTR [esp+320], xmm3 - jne L28 - movdqa xmm6, xmm4 - movdqa xmm0, xmm4 - punpckldq xmm6, XMMWORD PTR LC3 - punpckhdq xmm0, XMMWORD PTR LC3 -L12: - pshufd xmm4, xmm6, 80 - movaps XMMWORD PTR [esp+304], xmm4 - pshufd xmm4, xmm6, 250 - movaps XMMWORD PTR [esp+336], xmm4 - pshufd xmm4, xmm0, 80 - pshufd xmm0, xmm0, 250 - movaps XMMWORD PTR [esp+288], xmm4 - movaps XMMWORD PTR [esp+272], xmm0 - jmp L13 - // .p2align 4,,10 - // .p2align 3 -L8: - movdqu xmm1, XMMWORD PTR [esi] - movdqu xmm0, XMMWORD PTR [esi+16] - movdqu xmm7, XMMWORD PTR [esi] - pshufd xmm1, xmm1, 250 - pshufd xmm5, xmm0, 80 - movaps XMMWORD PTR [esp+1120], xmm1 - pshufd xmm1, xmm0, 250 - movdqu xmm0, XMMWORD PTR [esi+32] - pshufd xmm7, xmm7, 80 - pshufd xmm2, xmm0, 80 - test dl, 48 - jne L29 -L10: - movdqu xmm0, XMMWORD PTR [esi+60] - pshufd xmm0, xmm0, 0 - movaps XMMWORD PTR [esp+304], xmm0 - movdqu xmm0, XMMWORD PTR [esi+60] - pshufd xmm0, xmm0, 85 - movaps XMMWORD PTR [esp+336], xmm0 - movdqu xmm0, XMMWORD PTR [esi+60] - pshufd xmm0, xmm0, 170 - movaps XMMWORD PTR [esp+288], xmm0 - movdqu xmm0, XMMWORD PTR [esi+60] - pshufd xmm0, xmm0, 255 - movaps XMMWORD PTR [esp+272], xmm0 - movd xmm0, DWORD PTR [esi+76] - pshufd xmm0, xmm0, 0 - movaps XMMWORD PTR [esp+320], xmm0 -L13: - movdqa xmm0, XMMWORD PTR [esp+336] - movdqa xmm4, XMMWORD PTR [esp+288] - pmuludq xmm0, XMMWORD PTR LC6 - movaps XMMWORD PTR [esp+48], xmm0 - movdqa xmm6, XMMWORD PTR [esp+320] - movdqa xmm0, XMMWORD PTR [esp+272] - pmuludq xmm6, XMMWORD PTR LC6 - movaps XMMWORD PTR [esp+32], xmm6 - pmuludq xmm4, XMMWORD PTR LC6 - pmuludq xmm0, XMMWORD PTR LC6 - cmp ecx, 63 - jbe L14 - movdqu xmm6, XMMWORD PTR [esi+80] - lea edx, [ecx-64] - movaps XMMWORD PTR [esp], xmm0 - movaps XMMWORD PTR [esp+160], xmm0 - and edx, -64 - movdqa xmm0, XMMWORD PTR [esp+1120] - pshufd xmm6, xmm6, 0 - movaps XMMWORD PTR [esp+112], xmm4 - lea edx, [eax+64+edx] - movaps XMMWORD PTR [esp+208], xmm6 - movdqu xmm6, XMMWORD PTR [esi+80] - movaps XMMWORD PTR [esp+16], xmm4 - pshufd xmm3, xmm6, 85 - pshufd xmm6, xmm6, 170 - movaps XMMWORD PTR [esp+256], xmm6 - movdqu xmm6, XMMWORD PTR [esi+80] - movaps XMMWORD PTR [esp+192], xmm3 - pshufd xmm6, xmm6, 255 - movaps XMMWORD PTR [esp+240], xmm6 - movd xmm6, DWORD PTR [esi+96] - pshufd xmm6, xmm6, 0 - movaps XMMWORD PTR [esp+224], xmm6 - movdqa xmm6, XMMWORD PTR LC5 - movaps XMMWORD PTR [esp+1152], xmm6 - movdqa xmm6, XMMWORD PTR [esp+32] - movaps XMMWORD PTR [esp+176], xmm6 - movdqa xmm6, XMMWORD PTR [esp+240] - pmuludq xmm6, XMMWORD PTR LC6 - movaps XMMWORD PTR [esp+144], xmm6 - movdqa xmm6, XMMWORD PTR [esp+224] - pmuludq xmm6, XMMWORD PTR LC6 - movaps XMMWORD PTR [esp+128], xmm6 - movdqa xmm6, XMMWORD PTR [esp+48] - movaps XMMWORD PTR [esp+96], xmm6 - movdqa xmm6, xmm3 - pmuludq xmm6, XMMWORD PTR LC6 - movaps XMMWORD PTR [esp+80], xmm6 - movdqa xmm6, XMMWORD PTR [esp+256] - pmuludq xmm6, XMMWORD PTR LC6 - movaps XMMWORD PTR [esp+64], xmm6 - movdqa xmm6, xmm2 - movdqa xmm2, xmm1 - movdqa xmm1, xmm7 -// .p2align 4,,10 -// .p2align 3 -L15: - movdqa xmm7, XMMWORD PTR [esp+64] - movdqa xmm4, XMMWORD PTR [esp+80] - add eax, 64 - movdqa xmm3, xmm7 - pmuludq xmm4, xmm6 - pmuludq xmm3, xmm2 - movaps XMMWORD PTR [esp+1120], xmm4 - movaps XMMWORD PTR [esp+1104], xmm3 - movdqa xmm3, xmm7 - movdqa xmm7, XMMWORD PTR [esp+144] - pmuludq xmm3, xmm6 - movdqa xmm4, xmm7 - pmuludq xmm4, xmm2 - movaps XMMWORD PTR [esp+1088], xmm3 - movdqa xmm3, xmm7 - pmuludq xmm3, xmm6 - movaps XMMWORD PTR [esp+1072], xmm4 - movdqa xmm4, xmm7 - movdqa xmm7, XMMWORD PTR [esp+128] - pmuludq xmm4, xmm5 - movaps XMMWORD PTR [esp+1056], xmm3 - movdqa xmm3, xmm7 - pmuludq xmm3, xmm5 - movaps XMMWORD PTR [esp+1040], xmm4 - movdqa xmm4, xmm7 - pmuludq xmm4, xmm6 - movaps XMMWORD PTR [esp+992], xmm3 - movdqa xmm3, XMMWORD PTR [esp+208] - movaps XMMWORD PTR [esp+1024], xmm4 - movdqa xmm4, xmm7 - pmuludq xmm6, xmm3 - pmuludq xmm4, xmm0 - movaps XMMWORD PTR [esp+944], xmm6 - movdqa xmm6, xmm3 - movaps XMMWORD PTR [esp+1008], xmm4 - movdqa xmm4, xmm7 - pmuludq xmm6, xmm1 - pmuludq xmm4, xmm2 - movaps XMMWORD PTR [esp+928], xmm6 - movdqa xmm6, xmm3 - movaps XMMWORD PTR [esp+976], xmm4 - movdqa xmm4, xmm3 - pmuludq xmm6, xmm0 - pmuludq xmm4, xmm2 - movaps XMMWORD PTR [esp+912], xmm6 - movdqa xmm6, xmm3 - movaps XMMWORD PTR [esp+960], xmm4 - pmuludq xmm6, xmm5 - movdqa xmm4, XMMWORD PTR [esp+192] - pmuludq xmm2, xmm4 - movdqa xmm3, xmm4 - pmuludq xmm3, xmm5 - movaps XMMWORD PTR [esp+896], xmm6 - movdqa xmm6, XMMWORD PTR [esp+256] - movaps XMMWORD PTR [esp+864], xmm2 - movdqa xmm2, xmm4 - pmuludq xmm5, xmm6 - pmuludq xmm2, xmm1 - movaps XMMWORD PTR [esp+880], xmm3 - movaps XMMWORD PTR [esp+800], xmm5 - movdqa xmm5, xmm6 - movaps XMMWORD PTR [esp+848], xmm2 - movdqa xmm2, xmm4 - pmuludq xmm5, xmm1 - pmuludq xmm2, xmm0 - movaps XMMWORD PTR [esp+784], xmm5 - movaps XMMWORD PTR [esp+832], xmm2 - movdqa xmm2, xmm6 - pmuludq xmm2, xmm0 - movaps XMMWORD PTR [esp+816], xmm2 - movdqa xmm2, XMMWORD PTR [esp+240] - movdqa xmm5, xmm2 - pmuludq xmm0, xmm2 - pmuludq xmm5, xmm1 - movaps XMMWORD PTR [esp+752], xmm0 - movaps XMMWORD PTR [esp+768], xmm5 - pmuludq xmm1, XMMWORD PTR [esp+224] - movq xmm0, QWORD PTR [eax-64] - movq xmm4, QWORD PTR [eax-56] - movaps XMMWORD PTR [esp+736], xmm1 - movq xmm1, QWORD PTR [eax-48] - movdqa xmm6, XMMWORD PTR [esp+96] - movdqa xmm7, XMMWORD PTR [esp+112] - punpcklqdq xmm0, xmm1 - movq xmm1, QWORD PTR [eax-40] - punpcklqdq xmm4, xmm1 - movdqa xmm1, xmm0 - movdqa xmm2, xmm4 - psrlq xmm1, 26 - movdqa xmm3, xmm4 - psrlq xmm4, 40 - psrlq xmm3, 14 - por xmm4, XMMWORD PTR [esp+1136] - pand xmm3, XMMWORD PTR [esp+1152] - psllq xmm2, 12 - pmuludq xmm6, xmm4 - movdqa xmm5, xmm2 - movdqa xmm2, xmm0 - psrlq xmm2, 52 - por xmm2, xmm5 - pand xmm2, XMMWORD PTR [esp+1152] - movaps XMMWORD PTR [esp+720], xmm6 - movdqa xmm6, xmm7 - pmuludq xmm6, xmm3 - movaps XMMWORD PTR [esp+704], xmm6 - movdqa xmm6, xmm7 - movdqa xmm7, XMMWORD PTR [esp+160] - pmuludq xmm6, xmm4 - movdqa xmm5, xmm7 - pmuludq xmm5, xmm2 - movaps XMMWORD PTR [esp+688], xmm6 - movdqa xmm6, xmm7 - pmuludq xmm6, xmm3 - movaps XMMWORD PTR [esp+640], xmm5 - movaps XMMWORD PTR [esp+672], xmm6 - movdqa xmm6, xmm7 - movdqa xmm7, XMMWORD PTR [esp+1152] - pmuludq xmm6, xmm4 - pand xmm1, xmm7 - pand xmm0, xmm7 - movaps XMMWORD PTR [esp+656], xmm6 - movdqa xmm6, XMMWORD PTR [esp+176] - movdqa xmm5, xmm6 - pmuludq xmm5, xmm4 - movaps XMMWORD PTR [esp+624], xmm5 - movdqa xmm5, xmm6 - pmuludq xmm5, xmm1 - movaps XMMWORD PTR [esp+608], xmm5 - movdqa xmm5, xmm6 - pmuludq xmm5, xmm2 - movaps XMMWORD PTR [esp+592], xmm5 - movdqa xmm5, xmm6 - pmuludq xmm5, xmm3 - movaps XMMWORD PTR [esp+576], xmm5 - movdqa xmm5, XMMWORD PTR [esp+304] - movdqa xmm6, xmm5 - pmuludq xmm4, xmm5 - pmuludq xmm6, xmm3 - movaps XMMWORD PTR [esp+544], xmm4 - movdqa xmm4, xmm5 - movaps XMMWORD PTR [esp+560], xmm6 - movdqa xmm6, xmm5 - pmuludq xmm4, xmm0 - pmuludq xmm6, xmm1 - movaps XMMWORD PTR [esp+528], xmm6 - movdqa xmm6, xmm5 - pmuludq xmm6, xmm2 - movaps XMMWORD PTR [esp+512], xmm6 - movdqa xmm6, XMMWORD PTR [esp+336] - movdqa xmm5, xmm6 - pmuludq xmm3, xmm6 - pmuludq xmm5, xmm2 - movaps XMMWORD PTR [esp+480], xmm3 - movaps XMMWORD PTR [esp+496], xmm5 - movdqa xmm5, xmm6 - pmuludq xmm5, xmm0 - movaps XMMWORD PTR [esp+464], xmm5 - movdqa xmm5, xmm6 - movdqu xmm7, XMMWORD PTR [eax-16] - paddq xmm4, XMMWORD PTR [esp+608] - pmuludq xmm5, xmm1 - movaps XMMWORD PTR [esp+448], xmm5 - movdqa xmm5, XMMWORD PTR [esp+288] - pmuludq xmm2, xmm5 - movdqa xmm3, xmm5 - pmuludq xmm3, xmm1 - movaps XMMWORD PTR [esp+416], xmm2 - movdqa xmm2, xmm5 - pmuludq xmm2, xmm0 - movaps XMMWORD PTR [esp+432], xmm3 - movdqa xmm3, XMMWORD PTR [esp+272] - pmuludq xmm1, xmm3 - movaps XMMWORD PTR [esp+400], xmm2 - movdqa xmm2, xmm3 - pmuludq xmm2, xmm0 - pmuludq xmm0, XMMWORD PTR [esp+320] - movaps XMMWORD PTR [esp+368], xmm0 - movdqu xmm0, XMMWORD PTR [eax-32] - movaps XMMWORD PTR [esp+384], xmm1 - punpckldq xmm0, xmm7 - movdqa xmm1, xmm0 - movdqu xmm0, XMMWORD PTR [eax-32] - movdqa xmm3, xmm1 - punpckhdq xmm0, xmm7 - movdqa xmm5, xmm2 - pxor xmm2, xmm2 - movdqa xmm7, xmm0 - punpckldq xmm3, xmm2 - punpckhdq xmm1, xmm2 - punpckldq xmm7, xmm2 - psllq xmm1, 6 - movdqa xmm6, xmm3 - paddq xmm5, XMMWORD PTR [esp+432] - movdqa xmm3, xmm2 - movdqa xmm2, xmm7 - psllq xmm2, 12 - punpckhdq xmm0, xmm3 - movaps XMMWORD PTR [esp+352], xmm2 - psllq xmm0, 18 - movdqa xmm2, XMMWORD PTR [esp+1008] - paddq xmm2, XMMWORD PTR [esp+1040] - movdqa xmm3, xmm2 - movdqa xmm2, XMMWORD PTR [esp+1120] - paddq xmm2, XMMWORD PTR [esp+1104] - paddq xmm2, xmm3 - movdqa xmm3, XMMWORD PTR [esp+720] - paddq xmm3, XMMWORD PTR [esp+928] - paddq xmm3, xmm2 - movdqa xmm2, XMMWORD PTR [esp+640] - paddq xmm2, XMMWORD PTR [esp+704] - paddq xmm2, xmm3 - paddq xmm2, xmm4 - movdqa xmm4, XMMWORD PTR [esp+816] - paddq xmm4, XMMWORD PTR [esp+880] - paddq xmm2, xmm6 - movdqa xmm3, xmm4 - movdqa xmm7, xmm2 - movdqa xmm4, XMMWORD PTR [esp+1024] - paddq xmm4, XMMWORD PTR [esp+960] - psrlq xmm7, 26 - paddq xmm4, xmm3 - movdqa xmm3, XMMWORD PTR [esp+624] - paddq xmm3, XMMWORD PTR [esp+768] - paddq xmm4, xmm3 - movdqa xmm3, XMMWORD PTR [esp+496] - paddq xmm3, XMMWORD PTR [esp+560] - paddq xmm4, xmm3 - paddq xmm4, xmm5 - movdqa xmm5, xmm7 - paddq xmm4, xmm0 - paddq xmm1, xmm5 - movdqa xmm0, XMMWORD PTR [esp+912] - paddq xmm0, XMMWORD PTR [esp+992] - movdqa xmm7, xmm4 - movdqa xmm6, XMMWORD PTR [esp+1088] - paddq xmm6, XMMWORD PTR [esp+1072] - psrlq xmm7, 26 - movdqa xmm3, xmm7 - paddq xmm3, XMMWORD PTR [esp+1136] - paddq xmm6, xmm0 - movdqa xmm0, XMMWORD PTR [esp+688] - paddq xmm0, XMMWORD PTR [esp+848] - paddq xmm0, xmm6 - movdqa xmm6, XMMWORD PTR [esp+592] - paddq xmm6, XMMWORD PTR [esp+672] - paddq xmm0, xmm6 - movdqa xmm6, XMMWORD PTR [esp+464] - paddq xmm6, XMMWORD PTR [esp+528] - paddq xmm0, xmm6 - movdqa xmm6, XMMWORD PTR [esp+944] - paddq xmm6, XMMWORD PTR [esp+864] - paddq xmm0, xmm1 - movdqa xmm1, XMMWORD PTR [esp+752] - paddq xmm1, XMMWORD PTR [esp+800] - paddq xmm6, xmm1 - movdqa xmm1, XMMWORD PTR [esp+544] - paddq xmm1, XMMWORD PTR [esp+736] - paddq xmm1, xmm6 - movdqa xmm6, XMMWORD PTR [esp+416] - paddq xmm6, XMMWORD PTR [esp+480] - paddq xmm1, xmm6 - movdqa xmm6, XMMWORD PTR [esp+384] - paddq xmm6, XMMWORD PTR [esp+368] - movdqa xmm5, xmm6 - paddq xmm5, xmm1 - movdqa xmm7, xmm5 - movdqa xmm5, XMMWORD PTR [esp+832] - paddq xmm5, XMMWORD PTR [esp+896] - paddq xmm7, xmm3 - movdqa xmm3, XMMWORD PTR [esp+1056] - paddq xmm3, XMMWORD PTR [esp+976] - movdqa xmm6, xmm7 - movdqa xmm7, xmm0 - paddq xmm3, xmm5 - psrlq xmm7, 26 - movdqa xmm1, xmm6 - movdqa xmm5, XMMWORD PTR [esp+656] - paddq xmm5, XMMWORD PTR [esp+784] - psrlq xmm1, 26 - pmuludq xmm1, XMMWORD PTR LC6 - paddq xmm5, xmm3 - movdqa xmm3, XMMWORD PTR [esp+512] - paddq xmm3, XMMWORD PTR [esp+576] - paddq xmm3, xmm5 - movdqa xmm5, XMMWORD PTR [esp+448] - paddq xmm5, XMMWORD PTR [esp+400] - paddq xmm3, xmm5 - movdqa xmm5, XMMWORD PTR [esp+352] - paddq xmm5, xmm7 - movdqa xmm7, XMMWORD PTR [esp+1152] - paddq xmm5, xmm3 - pand xmm2, xmm7 - pand xmm4, xmm7 - pand xmm0, xmm7 - paddq xmm1, xmm2 - movdqa xmm2, xmm5 - pand xmm6, xmm7 - movdqa xmm3, xmm1 - psrlq xmm2, 26 - pand xmm5, xmm7 - psrlq xmm3, 26 - paddq xmm2, xmm4 - pand xmm1, xmm7 - paddq xmm0, xmm3 - movdqa xmm3, xmm2 - pand xmm2, xmm7 - psrlq xmm3, 26 - paddq xmm6, xmm3 - cmp eax, edx - jne L15 - movaps XMMWORD PTR [esp+1120], xmm0 - movdqa xmm4, XMMWORD PTR [esp+16] - movdqa xmm7, xmm1 - and ecx, 63 - movdqa xmm0, XMMWORD PTR [esp] - movdqa xmm1, xmm2 - movdqa xmm2, xmm6 -L14: - cmp ecx, 31 - jbe L16 - movdqa xmm6, XMMWORD PTR [esp+48] - movdqa xmm3, XMMWORD PTR [esp+32] - pmuludq xmm6, xmm2 - movaps XMMWORD PTR [esp+1152], xmm6 - movdqa xmm6, xmm1 - pmuludq xmm6, xmm4 - pmuludq xmm4, xmm2 - movaps XMMWORD PTR [esp+1104], xmm6 - movdqa xmm6, xmm1 - pmuludq xmm6, xmm0 - movaps XMMWORD PTR [esp+1088], xmm4 - movaps XMMWORD PTR [esp+1072], xmm6 - movdqa xmm6, xmm2 - pmuludq xmm6, xmm0 - pmuludq xmm0, xmm5 - movaps XMMWORD PTR [esp+1056], xmm6 - movdqa xmm6, xmm5 - movdqa xmm4, xmm0 - movdqa xmm0, xmm2 - pmuludq xmm6, xmm3 - pmuludq xmm0, xmm3 - movaps XMMWORD PTR [esp+1024], xmm6 - movdqa xmm6, xmm3 - pmuludq xmm6, xmm1 - movaps XMMWORD PTR [esp+1040], xmm0 - movdqa xmm0, XMMWORD PTR [esp+1120] - pmuludq xmm0, xmm3 - movaps XMMWORD PTR [esp+1008], xmm6 - movdqa xmm6, XMMWORD PTR [esp+304] - pmuludq xmm2, xmm6 - movdqa xmm3, xmm6 - paddq xmm0, xmm4 - movdqa xmm4, XMMWORD PTR [esp+1152] - paddq xmm4, XMMWORD PTR [esp+1104] - pmuludq xmm3, xmm1 - paddq xmm0, xmm4 - movdqa xmm4, XMMWORD PTR [esp+1120] - movaps XMMWORD PTR [esp+976], xmm2 - movdqa xmm2, xmm6 - pmuludq xmm2, xmm7 - movaps XMMWORD PTR [esp+992], xmm3 - movdqa xmm3, xmm6 - pmuludq xmm3, XMMWORD PTR [esp+1120] - movdqa xmm6, xmm3 - movdqa xmm3, XMMWORD PTR [esp+304] - paddq xmm6, XMMWORD PTR [esp+1024] - pmuludq xmm3, xmm5 - paddq xmm0, xmm2 - movdqa xmm2, XMMWORD PTR [esp+336] - movaps XMMWORD PTR [esp+1104], xmm0 - movdqa xmm0, xmm2 - pmuludq xmm1, xmm2 - pmuludq xmm0, xmm7 - movaps XMMWORD PTR [esp+960], xmm3 - movdqa xmm3, XMMWORD PTR [esp+336] - pmuludq xmm3, xmm5 - movaps XMMWORD PTR [esp+928], xmm1 - movdqa xmm1, xmm0 - movdqa xmm0, xmm2 - pmuludq xmm0, xmm4 - movdqa xmm4, XMMWORD PTR [esp+1088] - paddq xmm4, XMMWORD PTR [esp+1072] - movaps XMMWORD PTR [esp+944], xmm3 - movdqa xmm3, XMMWORD PTR [esp+288] - paddq xmm6, xmm4 - movdqa xmm4, xmm6 - pmuludq xmm5, xmm3 - movdqa xmm2, xmm3 - movdqa xmm6, XMMWORD PTR [esp+272] - pmuludq xmm2, XMMWORD PTR [esp+1120] - paddq xmm4, xmm1 - movaps XMMWORD PTR [esp+1152], xmm4 - movdqa xmm4, xmm3 - movdqa xmm1, xmm6 - movdqa xmm3, XMMWORD PTR [esp+1120] - pmuludq xmm4, xmm7 - pmuludq xmm1, xmm7 - paddq xmm0, XMMWORD PTR [esp+960] - paddq xmm2, XMMWORD PTR [esp+944] - pmuludq xmm3, xmm6 - movdqa xmm6, XMMWORD PTR [esp+320] - pmuludq xmm6, xmm7 - movdqa xmm7, XMMWORD PTR [esp+1056] - paddq xmm7, XMMWORD PTR [esp+1008] - paddq xmm0, xmm7 - paddq xmm0, xmm4 - paddq xmm3, xmm5 - movdqa xmm4, XMMWORD PTR [esp+1040] - paddq xmm4, XMMWORD PTR [esp+992] - paddq xmm2, xmm4 - paddq xmm2, xmm1 - movdqa xmm1, XMMWORD PTR [esp+976] - paddq xmm1, XMMWORD PTR [esp+928] - paddq xmm3, xmm1 - paddq xmm3, xmm6 - test eax, eax - je L18 - movdqu xmm5, XMMWORD PTR [eax+16] - movdqu xmm1, XMMWORD PTR [eax] - paddq xmm3, XMMWORD PTR [esp+1136] - punpckldq xmm1, xmm5 - movdqa xmm4, xmm1 - movdqu xmm1, XMMWORD PTR [eax] - movdqa xmm6, xmm4 - punpckhdq xmm1, xmm5 - pxor xmm5, xmm5 - punpckldq xmm6, xmm5 - punpckhdq xmm4, xmm5 - movdqa xmm7, xmm6 - psllq xmm4, 6 - movdqa xmm6, xmm1 - punpckldq xmm6, xmm5 - punpckhdq xmm1, xmm5 - movdqa xmm5, XMMWORD PTR [esp+1104] - psllq xmm6, 12 - psllq xmm1, 18 - paddq xmm5, xmm7 - paddq xmm0, xmm6 - movaps XMMWORD PTR [esp+1104], xmm5 - paddq xmm2, xmm1 - movdqa xmm5, XMMWORD PTR [esp+1152] - paddq xmm5, xmm4 - movaps XMMWORD PTR [esp+1152], xmm5 -L18: - movdqa xmm7, XMMWORD PTR [esp+1104] - movdqa xmm4, xmm2 - pand xmm2, XMMWORD PTR LC5 - psrlq xmm4, 26 - movdqa xmm1, xmm7 - paddq xmm4, xmm3 - pand xmm7, XMMWORD PTR LC5 - psrlq xmm1, 26 - movdqa xmm3, xmm4 - paddq xmm1, XMMWORD PTR [esp+1152] - pand xmm4, XMMWORD PTR LC5 - psrlq xmm3, 26 - pmuludq xmm3, XMMWORD PTR LC6 - paddq xmm7, xmm3 - movdqa xmm5, xmm1 - movdqa xmm3, xmm7 - pand xmm1, XMMWORD PTR LC5 - psrlq xmm5, 26 - psrlq xmm3, 26 - pand xmm7, XMMWORD PTR LC5 - paddq xmm0, xmm5 - paddq xmm3, xmm1 - movdqa xmm1, XMMWORD PTR LC5 - movdqa xmm6, xmm0 - movaps XMMWORD PTR [esp+1120], xmm3 - pand xmm0, XMMWORD PTR LC5 - psrlq xmm6, 26 - paddq xmm2, xmm6 - movdqa xmm5, xmm0 - movdqa xmm0, xmm2 - pand xmm1, xmm2 - psrlq xmm0, 26 - paddq xmm4, xmm0 - movdqa xmm2, xmm4 -L16: - test eax, eax - je L19 - pshufd xmm3, xmm5, 8 - pshufd xmm4, xmm7, 8 - pshufd xmm5, xmm1, 8 - pshufd xmm6, XMMWORD PTR [esp+1120], 8 - pshufd xmm0, xmm2, 8 - movdqa xmm1, xmm3 - movdqa xmm2, xmm4 - punpcklqdq xmm2, xmm6 - punpcklqdq xmm1, xmm5 - movq QWORD PTR [esi+32], xmm0 - movups XMMWORD PTR [esi], xmm2 - movups XMMWORD PTR [esi+16], xmm1 - lea esp, [ebp-12] - pop ebx - pop esi - pop edi - pop ebp - ret -// .p2align 4,,10 -// .p2align 3 -L28: - movdqu xmm6, XMMWORD PTR [esi+60] - movdqu xmm0, XMMWORD PTR [esi+60] - punpckldq xmm6, xmm4 - punpckhdq xmm0, xmm4 - movd xmm4, DWORD PTR [esi+76] - punpcklqdq xmm4, xmm3 - movaps XMMWORD PTR [esp+320], xmm4 - jmp L12 -// .p2align 4,,10 -// .p2align 3 -L19: - movdqa xmm3, xmm1 - movdqa xmm6, xmm7 - movdqa xmm0, xmm5 - movdqa xmm4, XMMWORD PTR [esp+1120] - psrldq xmm3, 8 - psrldq xmm6, 8 - psrldq xmm4, 8 - psrldq xmm0, 8 - paddq xmm7, xmm6 - movaps XMMWORD PTR [esp+1136], xmm3 - movdqa xmm3, XMMWORD PTR [esp+1120] - movd edx, xmm7 - movaps XMMWORD PTR [esp+1152], xmm0 - paddq xmm5, XMMWORD PTR [esp+1152] - paddq xmm1, XMMWORD PTR [esp+1136] - mov edi, edx - shr edx, 26 - movdqa xmm0, xmm2 - paddq xmm3, xmm4 - psrldq xmm0, 8 - and edi, 67108863 - movd eax, xmm3 - paddq xmm2, xmm0 - add eax, edx - movd edx, xmm5 - mov ebx, eax - shr eax, 26 - add eax, edx - movd edx, xmm1 - and ebx, 67108863 - mov ecx, eax - shr eax, 26 - add eax, edx - and ecx, 67108863 - movd edx, xmm2 - mov DWORD PTR [esp+1152], ecx - mov ecx, eax - shr eax, 26 - add eax, edx - and ecx, 67108863 - mov edx, eax - shr eax, 26 - lea eax, [eax+eax*4] - and edx, 67108863 - add eax, edi - mov edi, eax - shr eax, 26 - add eax, ebx - and edi, 67108863 - mov ebx, eax - shr eax, 26 - and ebx, 67108863 - mov DWORD PTR [esp+1120], ebx - mov ebx, DWORD PTR [esp+1152] - add eax, ebx - mov ebx, eax - shr eax, 26 - add eax, ecx - and ebx, 67108863 - mov ecx, eax - shr eax, 26 - mov DWORD PTR [esp+1152], ebx - mov ebx, DWORD PTR [esp+1120] - add eax, edx - and ecx, 67108863 - mov DWORD PTR [esp+1136], ecx - mov edx, eax - mov ecx, eax - and edx, 67108863 - shr ecx, 26 - mov DWORD PTR [esp+1104], edx - lea edx, [ecx+ecx*4] - add edx, edi - mov ecx, edx - shr edx, 26 - and ecx, 67108863 - add edx, ebx - or eax, -67108864 - lea ebx, [ecx+5] - mov DWORD PTR [esp+1088], ebx - shr ebx, 26 - lea edi, [ebx+edx] - mov DWORD PTR [esp+1072], edi - shr edi, 26 - mov ebx, edi - mov edi, DWORD PTR [esp+1152] - add ebx, edi - mov edi, DWORD PTR [esp+1136] - mov DWORD PTR [esp+1056], ebx - shr ebx, 26 - add ebx, edi - mov DWORD PTR [esp+1040], ebx - shr ebx, 26 - add eax, ebx - mov edi, eax - shr edi, 31 - mov ebx, edi - mov edi, eax - sar edi, 31 - sub ebx, 1 - and edx, edi - and ecx, edi - and eax, ebx - mov DWORD PTR [esp+1120], edx - mov edx, DWORD PTR [esp+1152] - and edx, edi - mov DWORD PTR [esp+1152], edx - mov edx, DWORD PTR [esp+1136] - and edx, edi - mov DWORD PTR [esp+1136], edx - mov edx, DWORD PTR [esp+1104] - and edx, edi - mov edi, DWORD PTR [esp+1088] - mov DWORD PTR [esp+1104], edx - and edi, ebx - and edi, 67108863 - or edi, ecx - mov ecx, DWORD PTR [esp+1072] - mov DWORD PTR [esi], edi - mov edi, DWORD PTR [esp+1120] - and ecx, ebx - and ecx, 67108863 - or ecx, edi - mov DWORD PTR [esi+4], ecx - mov ecx, DWORD PTR [esp+1056] - mov edi, DWORD PTR [esp+1152] - and ecx, ebx - mov edx, ecx - mov ecx, DWORD PTR [esp+1040] - and edx, 67108863 - or edx, edi - and ecx, ebx - mov edi, DWORD PTR [esp+1136] - mov DWORD PTR [esi+8], edx - mov edx, ecx - and edx, 67108863 - or edx, edi - mov DWORD PTR [esi+12], edx - mov edx, DWORD PTR [esp+1104] - or eax, edx - mov DWORD PTR [esi+16], eax - lea esp, [ebp-12] - pop ebx - pop esi - pop edi - pop ebp -end; - -procedure _Poly1305_finish_SSE2(st : TPoly1305.PPoly1305_state_internal_t; m : PByte; leftover : integer; var mac : TBlock16Byte) cdecl; -label L63, L33, L34, L35, L36, L37, L38, L42, L43, L64, L65, L99; -asm - push ebp - mov ebp, esp - push edi - push esi - push ebx - and esp, -16 - sub esp, 64 - mov ebx, DWORD PTR [ebp+8] - mov edx, DWORD PTR [ebp+16] - mov eax, DWORD PTR [ebx+116] - mov DWORD PTR [esp+28], eax - test edx, edx - je L63 - mov edi, DWORD PTR [ebp+12] - pxor xmm0, xmm0 - lea esi, [esp+32] - movaps XMMWORD PTR [esp+32], xmm0 - mov ecx, esi - movaps XMMWORD PTR [esp+48], xmm0 - sub edi, esi - test BYTE PTR [ebp+16], 16 - je L34 - mov eax, DWORD PTR [ebp+12] - lea ecx, [esp+48] - movdqu xmm4, XMMWORD PTR [eax] - movaps XMMWORD PTR [esp+32], xmm4 -L34: - test BYTE PTR [ebp+16], 8 - je L35 - mov eax, DWORD PTR [ecx+edi] - mov edx, DWORD PTR [ecx+4+edi] - add ecx, 8 - mov DWORD PTR [ecx-8], eax - mov DWORD PTR [ecx-4], edx -L35: - test BYTE PTR [ebp+16], 4 - je L36 - mov eax, DWORD PTR [ecx+edi] - add ecx, 4 - mov DWORD PTR [ecx-4], eax -L36: - test BYTE PTR [ebp+16], 2 - je L37 - movzx eax, WORD PTR [ecx+edi] - add ecx, 2 - mov WORD PTR [ecx-2], ax -L37: - test BYTE PTR [ebp+16], 1 - je L38 - movzx edx, BYTE PTR [ecx+edi] - mov BYTE PTR [ecx], dl -L38: - cmp DWORD PTR [ebp+16], 16 - je L65 - mov eax, DWORD PTR [ebp+16] - mov edx, DWORD PTR [esp+28] - mov BYTE PTR [esp+32+eax], 1 - cmp eax, 15 - jbe L42 - or edx, 4 - mov DWORD PTR [ebx+116], edx - mov DWORD PTR [esp+8], 32 - mov DWORD PTR [esp+4], esi - mov DWORD PTR [esp], ebx - call _Poly1305_Blocks_sse2 - mov eax, DWORD PTR [ebx+116] - mov DWORD PTR [esp+28], eax -L63: - test al, 1 - je L33 - mov edx, DWORD PTR [esp+28] - or edx, 16 -L43: - mov DWORD PTR [ebx+116], edx - mov DWORD PTR [esp+8], 32 - mov DWORD PTR [esp+4], 0 - mov DWORD PTR [esp], ebx - call _Poly1305_Blocks_sse2 -L33: - mov esi, DWORD PTR [ebx+4] - mov edx, DWORD PTR [ebx+8] - mov ecx, DWORD PTR [ebx+12] - mov eax, esi - mov edi, esi - mov esi, edx - shr edi, 6 - sal esi, 20 - or esi, edi - mov edi, edx - mov edx, ecx - shr ecx, 18 - shr edi, 12 - sal edx, 14 - or edx, edi - mov edi, ecx - mov ecx, DWORD PTR [ebx+16] - sal eax, 26 - or eax, DWORD PTR [ebx] - sal ecx, 8 - or ecx, edi - //APP - // # 526 "poly1305-donna-x86-sse2-incremental-source - Kopie.c" 1 - //addl DWORD PTR [ebx+100], eax; -// adcl DWORD PTR [ebx+104], esi; -// adcl DWORD PTR [ebx+108], edx; -// adcl DWORD PTR [ebx+112], ecx; - add DWORD PTR [ebx+100], eax; - adc DWORD PTR [ebx+104], esi; - adc DWORD PTR [ebx+108], edx; - adc DWORD PTR [ebx+112], ecx; - - //# 0 "" 2 - //NO_APP - pxor xmm0, xmm0 - movd xmm3, esi - movd xmm1, edx - movups XMMWORD PTR [ebx], xmm0 - movd xmm2, ecx - movups XMMWORD PTR [ebx+16], xmm0 - punpckldq xmm1, xmm2 - movups XMMWORD PTR [ebx+32], xmm0 - movups XMMWORD PTR [ebx+48], xmm0 - movups XMMWORD PTR [ebx+64], xmm0 - movups XMMWORD PTR [ebx+80], xmm0 - movups XMMWORD PTR [ebx+96], xmm0 - movups XMMWORD PTR [ebx+112], xmm0 - movd xmm0, eax - mov eax, DWORD PTR [ebp+20] - punpckldq xmm0, xmm3 - punpcklqdq xmm0, xmm1 - movups XMMWORD PTR [eax], xmm0 - lea esp, [ebp-12] - pop ebx - pop esi - pop edi - pop ebp - - jmp L99; - -// now that is some kind of epiolog -L65: - mov edx, DWORD PTR [esp+28] - or edx, 4 -L64: - mov DWORD PTR [ebx+116], edx - mov DWORD PTR [esp+8], 32 - mov DWORD PTR [esp+4], esi - mov DWORD PTR [esp], ebx - call _poly1305_blocks_sse2 - mov edx, DWORD PTR [ebx+116] - test dl, 1 - je L33 - or edx, 32 - jmp L43 -// .p2align 4,,10 -// .p2align 3 -L42: - or edx, 8 - jmp L64 - -// return: -L99: -end; - -procedure TPoly1305.Poly1305Emit_SSE(var mac: TBlock16Byte); -begin - FillChar(mac, sizeof(mac), 0); - //nonce is not used - it is already stored - _Poly1305_finish_SSE2( fPPoly1305State, nil, 0, mac) -end; - - -procedure TPoly1305.Poly1305Finalize(var mac: TBlock16Byte); -begin - if fNum > 0 then - begin - fData[fNum] := 1; - 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); -end; - -procedure TPoly1305.Poly1305Init_SSE(initVec: PByte); -begin - FillChar(fPoly1305State[0], Length(fPoly1305State), 0); - - _poly1305_init_ext_sse2( fPPoly1305State, initVec, 0); -end; - -procedure TPoly1305.Poly1305Blocks_SSE(pData: PByteArray; size: integer); -begin - _Poly1305_Blocks_sse2( fPPoly1305State, PByte(pData), size ); -end; - -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.UpdatePoly(pData: PByteArray; size: integer); var num : integer; rem : integer; @@ -2011,7 +573,9 @@ procedure TPoly1305.UpdatePoly(pData: PByteArray; size: integer); fNum := rem; end; -initialization - TPoly1305.UseSSE := False; +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 6da6e74a..cd0172d7 100644 --- a/Source/DECCiphers.pas +++ b/Source/DECCiphers.pas @@ -6941,6 +6941,7 @@ 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); @@ -6965,6 +6966,7 @@ procedure TCipher_ChaCha20.DoEncode(Source, Dest: Pointer; Size: Integer); end; end; begin + FState := csEncode; pChaCha := PByte(fOutChaChaMtx); inc(pChaCha, fChaChaIdx); @@ -7011,6 +7013,7 @@ procedure TCipher_ChaCha20.OnAfterInitVectorInitialization( // 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 diff --git a/Unit Tests/DECDUnitTestSuite.dpr b/Unit Tests/DECDUnitTestSuite.dpr index 0c9b25d7..201e9f34 100644 --- a/Unit Tests/DECDUnitTestSuite.dpr +++ b/Unit Tests/DECDUnitTestSuite.dpr @@ -70,7 +70,8 @@ uses DECUtilRawByteStringHelper in '..\Source\DECUtilRawByteStringHelper.pas', DECZIPHelper in '..\Source\DECZIPHelper.pas', DECCipherModesGCM in '..\Source\DECCipherModesGCM.pas', - TESTDECChaChaPoly1305 in 'Tests\TESTDECChaChaPoly1305.pas'; + TESTDECChaChaPoly1305 in 'Tests\TESTDECChaChaPoly1305.pas', + poly1305dll in '..\Source\poly1305dll.pas'; {$R *.RES} diff --git a/Unit Tests/DECDUnitTestSuite.dproj b/Unit Tests/DECDUnitTestSuite.dproj index 36118404..35201323 100644 --- a/Unit Tests/DECDUnitTestSuite.dproj +++ b/Unit Tests/DECDUnitTestSuite.dproj @@ -112,6 +112,8 @@ .\..\Compiled\DCU_IDE$(ProductVersion)_$(Platform)_$(Config) 3 /L /LL65535 + ASSEMBLER;$(DCC_Define) + none true @@ -193,6 +195,7 @@ + Base @@ -246,10 +249,8 @@ 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 diff --git a/Unit Tests/Tests/TestDECChaChaPoly1305.pas b/Unit Tests/Tests/TestDECChaChaPoly1305.pas index 946f7a27..f0cd3888 100644 --- a/Unit Tests/Tests/TestDECChaChaPoly1305.pas +++ b/Unit Tests/Tests/TestDECChaChaPoly1305.pas @@ -25,7 +25,7 @@ TestChaCha20Poly1305 = class(TTestCase) end; implementation -uses DECCipherModesPoly1305, System.Diagnostics; +uses DECCipherModesPoly1305, System.Diagnostics, poly1305dll; //// ########################################### @@ -163,6 +163,7 @@ procedure EncodeBuf( var dest : TBytes ); // test decode for cpuMode in [cmPas, cmSSE, cmAVX] do begin + TCipher_ChaCha20.CpuMode := cpuMode; chaCha := TCipher_ChaCha20.Create; try chaCha.Mode := cmECBx; @@ -177,6 +178,9 @@ procedure EncodeBuf( var dest : TBytes ); 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 ]; @@ -229,9 +233,9 @@ procedure InvData( data : PByte; len : integer ); poly := TPoly1305.Create; try - poly.InitInternal(iv); - poly.UpdatePoly(@msg[0], Length(msg)); - poly.Finalize; + THackPly1305(poly).InitInternal(iv); + THackPly1305(poly).UpdatePoly(@msg[0], Length(msg)); + THackPly1305(poly).Finalize; calcTag := poly.CalculatedAuthenticationTag; finally @@ -252,9 +256,9 @@ procedure InvData( data : PByte; len : integer ); poly := TPoly1305.Create; try - poly.InitInternal(iv); - poly.UpdatePoly(@msg[0], Length(msg)); - poly.Finalize; + THackPly1305(poly).InitInternal(iv); + THackPly1305(poly).UpdatePoly(@msg[0], Length(msg)); + THackPly1305(poly).Finalize; calcTag := poly.CalculatedAuthenticationTag; finally @@ -265,6 +269,7 @@ procedure InvData( data : PByte; len : integer ); Check( CompareMem(@cTag[0], @calcTag[0], Length(calcTag)), 'Polynom calculated tag does not match'); 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]; @@ -303,6 +308,7 @@ procedure TestChaCha20Poly1305.TestChaCha20_Poly1305_AEAD; chaCha := TCipher_ChaCha20.Create; try + chaCha.Mode := cmPoly1305; chaCha.DataToAuthenticate := cAAD; chaCha.Init(cKey, cNonce); encr := chaCha.EncodeBytes(msg); @@ -324,6 +330,7 @@ procedure TestChaCha20Poly1305.TestChaCha20_Poly1305_AEAD; // #### Test decode chaCha := TCipher_ChaCha20.Create; try + chaCha.Mode := cmPoly1305; chaCha.ExpectedAuthenticationResult := encrTag; chaCha.DataToAuthenticate := cAAD; From 7375a5436d422e8b06b52a2bc008df95e109c76a Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Sat, 12 Jul 2025 07:18:39 +0200 Subject: [PATCH 03/12] Working GCM and Poly1305 --- Source/DECAuthenticatedCipherModesBase.pas | 2 + Source/DECCipherFormats.pas | 8 +- Source/DECCipherModes.pas | 4 +- Source/DECCipherModesGCM.pas | 25 +++-- Unit Tests/Tests/TestDECCipherModesGCM.pas | 107 +++++++++++++++++++++ 5 files changed, 132 insertions(+), 14 deletions(-) diff --git a/Source/DECAuthenticatedCipherModesBase.pas b/Source/DECAuthenticatedCipherModesBase.pas index b24c14dc..1b392833 100644 --- a/Source/DECAuthenticatedCipherModesBase.pas +++ b/Source/DECAuthenticatedCipherModesBase.pas @@ -294,6 +294,7 @@ procedure TAuthenticatedCipherModesBase.Init(EncryptionMethod : TEncodeDecodeMet Assert(Assigned(EncryptionMethod), 'No encryption method specified'); // Clear calculated authentication value + fAuthMethodInit := False; CalcAuthLength := Length(FCalcAuthenticationTag); if (CalcAuthLength > 0) then begin @@ -302,6 +303,7 @@ procedure TAuthenticatedCipherModesBase.Init(EncryptionMethod : TEncodeDecodeMet FillChar(FCalcAuthenticationTag[0], CalcAuthLength, #0); end; + fEncDecLen := 0; FEncryptionMethod := EncryptionMethod; end; diff --git a/Source/DECCipherFormats.pas b/Source/DECCipherFormats.pas index eb3d5aca..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 - EncodeWithAuthObj(nil, nil, 0); + Encode(Source[0], Result[0], Length(Source)); + //else +// if (FMode = cmGCM) then +// EncodeWithAuthObj(nil, nil, 0); end; begin diff --git a/Source/DECCipherModes.pas b/Source/DECCipherModes.pas index 4840ce09..5770152c 100644 --- a/Source/DECCipherModes.pas +++ b/Source/DECCipherModes.pas @@ -1108,8 +1108,6 @@ destructor TDECCipherModes.Destroy; procedure TDECCipherModes.Done; begin - inherited; - if Assigned(fAuthObj) then begin fAuthObj.FinalizeAEAD; @@ -1119,6 +1117,8 @@ procedure TDECCipherModes.Done; then raise EDECCipherAuthenticationException.CreateRes(@sInvalidAuthenticationValue); end; + + inherited; end; procedure TDECCipherModes.OnAfterInitVectorInitialization(const OriginalInitVector: TBytes); diff --git a/Source/DECCipherModesGCM.pas b/Source/DECCipherModesGCM.pas index 1eb24739..c87009b8 100644 --- a/Source/DECCipherModesGCM.pas +++ b/Source/DECCipherModesGCM.pas @@ -520,13 +520,25 @@ procedure TGCM.Init(EncryptionMethod : TEncodeDecodeMethod; end; procedure TGCM.InitAuth; +var authLen : integer; begin + inherited; + FillChar(fData, sizeof(fData), 0); FDataIdx := 0; FGHash := nullbytes; if Length(FDataToAuthenticate) > 0 then - UpdateWithEncDecBuf(@FDataToAuthenticate[0], Length(FDataToAuthenticate)); + 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 TGCM.LocEncodeDecode(Source, Dest: Pointer; Size: Integer); @@ -607,16 +619,13 @@ procedure TGCM.UpdateWithEncDecBuf(buf: PUInt8Array; Size: Integer); end; len_d := size - n; - if (len_d > 0) then + if (len_d >= cGCMBlkSize) then begin div_d := len_d div cGCMBlkSize; - if div_d > 0 then + for i := 0 to div_d - 1 do begin - for i := 0 to div_d - 1 do - begin - FGHash := poly_mult_H(XOR_PointerWithT128(@buf^[n], FGHash )); - inc(n, cGCMBlkSize); - end; + FGHash := poly_mult_H(XOR_PointerWithT128(@buf^[n], FGHash )); + inc(n, cGCMBlkSize); end; end; diff --git a/Unit Tests/Tests/TestDECCipherModesGCM.pas b/Unit Tests/Tests/TestDECCipherModesGCM.pas index b7f5f6cc..6e233c48 100644 --- a/Unit Tests/Tests/TestDECCipherModesGCM.pas +++ b/Unit Tests/Tests/TestDECCipherModesGCM.pas @@ -163,6 +163,7 @@ TestTDECGCM = class(TTestCase) /// Test for GitHub issue #86 /// procedure TestEncodeConstData_86; + procedure TestStreamGCM_87; end; @@ -463,11 +464,13 @@ procedure TestTDECGCM.TestEncode; i : Integer; EncryptData : TBytes; EncrDataStr : string; + idx : integer; begin FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV128.rsp', FTestDataList); FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV192.rsp', FTestDataList); FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV256.rsp', FTestDataList); + idx := 0; for TestDataSet in FTestDataList do begin for i := Low(TestDataSet.TestData) to High(TestDataSet.TestData) do @@ -584,6 +587,7 @@ procedure TestTDECGCM.TestEncodeConstData_86; cipher.DataToAuthenticate := hea; cipher.Encode(refPlainText, ciphText, sizeof(refPlainText)); + cipher.Done; tag := cipher.CalculatedAuthenticationResult; finally cipher.Free; @@ -897,6 +901,109 @@ 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} From dd312e60c8ffb6237a621c0c29864db7af1aeca3 Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Sun, 13 Jul 2025 20:59:25 +0200 Subject: [PATCH 04/12] Minor: unchecked assembler in inc file. Minor: removed debug idx variable. --- Source/DECOptions.inc | 4 +++- Unit Tests/Tests/TestDECCipherModesGCM.pas | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/DECOptions.inc b/Source/DECOptions.inc index da05d4bd..8ed98108 100644 --- a/Source/DECOptions.inc +++ b/Source/DECOptions.inc @@ -73,10 +73,12 @@ // 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} diff --git a/Unit Tests/Tests/TestDECCipherModesGCM.pas b/Unit Tests/Tests/TestDECCipherModesGCM.pas index 6e233c48..0d6c0727 100644 --- a/Unit Tests/Tests/TestDECCipherModesGCM.pas +++ b/Unit Tests/Tests/TestDECCipherModesGCM.pas @@ -464,13 +464,11 @@ procedure TestTDECGCM.TestEncode; i : Integer; EncryptData : TBytes; EncrDataStr : string; - idx : integer; begin FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV128.rsp', FTestDataList); FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV192.rsp', FTestDataList); FTestDataLoader.LoadFile('..\..\Unit Tests\Data\gcmEncryptExtIV256.rsp', FTestDataList); - idx := 0; for TestDataSet in FTestDataList do begin for i := Low(TestDataSet.TestData) to High(TestDataSet.TestData) do From 07775f50a9b737cbc58c7d8345ca11cd41b3a36f Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Wed, 16 Jul 2025 21:46:47 +0200 Subject: [PATCH 05/12] Implemented XChacha20 according to https://datatracker.ietf.org/doc/html/draft-arciszewski-xchacha-03 --- Source/DECCiphers.pas | 95 ++++++++++++++++++++-- Unit Tests/Tests/TestDECChaChaPoly1305.pas | 80 ++++++++++++++++++ 2 files changed, 170 insertions(+), 5 deletions(-) diff --git a/Source/DECCiphers.pas b/Source/DECCiphers.pas index cd0172d7..a437d105 100644 --- a/Source/DECCiphers.pas +++ b/Source/DECCiphers.pas @@ -211,6 +211,11 @@ TCipher_XTEA_DEC52 = class; /// TCipher_ChaCha20 = class; + /// + /// XChaCha20 cipher + /// + TCipher_XChaCha20 = class; + // Definitions needed for Skipjack algorithm PSkipjackTab = ^TSkipjackTab; TSkipjackTab = array[0..255] of Byte; @@ -504,7 +509,7 @@ TCipher_ChaCha20 = class(TDECFormattedCipher) // double the size -> two blocks at once TChaChaEncodeBlkFunc = procedure(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); register; {$IFDEF FPC} assembler; {$ENDIF} - private + protected fInpChaChaMTX : PChaChaMtx; fOutChaChaMtx : PChaChaAVXMtx; @@ -546,6 +551,18 @@ TCipher_ChaCha20 = class(TDECFormattedCipher) 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 /// @@ -7040,10 +7057,6 @@ procedure TCipher_ChaCha20.OnAfterInitVectorInitialization( 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'; - function AlignPtr32( A : Pointer ) : Pointer; begin Result := A; @@ -7051,6 +7064,10 @@ function AlignPtr32( A : Pointer ) : Pointer; Result := Pointer( NativeUint(Result) + $20 - NativeUint(Result) and $1F ); 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; @@ -7861,6 +7878,71 @@ function TCipher_ChaCha20.TestChaChaMtx( 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 Exception.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); @@ -7894,6 +7976,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); diff --git a/Unit Tests/Tests/TestDECChaChaPoly1305.pas b/Unit Tests/Tests/TestDECChaChaPoly1305.pas index f0cd3888..ca1e8514 100644 --- a/Unit Tests/Tests/TestDECChaChaPoly1305.pas +++ b/Unit Tests/Tests/TestDECChaChaPoly1305.pas @@ -22,6 +22,7 @@ TestChaCha20Poly1305 = class(TTestCase) procedure TestChaCha20_Poly1305_AEAD; procedure TestChaChaEncodeDecodeSpeed; + procedure TestXChaCha_Poly1305_AEAD; end; implementation @@ -270,6 +271,85 @@ procedure InvData( data : PByte; len : integer ); 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; + + 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]; From a4f52c7d145b30cf4f75f634272aa49cb89ed013 Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Sun, 20 Jul 2025 22:33:24 +0200 Subject: [PATCH 06/12] Removed poly1305 dll reference - (was a test to implement a sse/avx version) --- Unit Tests/Tests/TestDECChaChaPoly1305.pas | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Unit Tests/Tests/TestDECChaChaPoly1305.pas b/Unit Tests/Tests/TestDECChaChaPoly1305.pas index ca1e8514..dd4e5c91 100644 --- a/Unit Tests/Tests/TestDECChaChaPoly1305.pas +++ b/Unit Tests/Tests/TestDECChaChaPoly1305.pas @@ -26,7 +26,7 @@ TestChaCha20Poly1305 = class(TTestCase) end; implementation -uses DECCipherModesPoly1305, System.Diagnostics, poly1305dll; +uses DECCipherModesPoly1305, System.Diagnostics; //// ########################################### From 2cb78328acb4bdcb8a10d5dc378c66c2d9f3af25 Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Tue, 29 Jul 2025 17:38:43 +0200 Subject: [PATCH 07/12] Added a json based test suite. Removed dll reference Fixed a crucial bug in the poly1305 generation - the ConstTimeCarray32 had wrong brackets applied. --- Source/DECCipherModesPoly1305.pas | 6 +- Source/DECCiphers.pas | 8 +- Unit Tests/DECDUnitTestSuite.dpr | 3 +- Unit Tests/DECDUnitTestSuite.dproj | 3 +- Unit Tests/Data/chacha20_poly1305_test.json | 3710 +++++++++++++++++++ Unit Tests/Tests/TestDECChaChaPoly1305.pas | 210 +- 6 files changed, 3905 insertions(+), 35 deletions(-) create mode 100644 Unit Tests/Data/chacha20_poly1305_test.json diff --git a/Source/DECCipherModesPoly1305.pas b/Source/DECCipherModesPoly1305.pas index c09ae043..ce2f8094 100644 --- a/Source/DECCipherModesPoly1305.pas +++ b/Source/DECCipherModesPoly1305.pas @@ -146,7 +146,7 @@ implementation // ) function ConstTimeCarray32(a, b : UInt32 ) : UInt32; inline; begin - Result := (a xor ( (a xor b) or (a - b) xor b )) shr 31; + Result := (a xor ( (a xor b) or ((a - b) xor b))) shr 31; end; @@ -230,7 +230,7 @@ procedure TPoly1305.Finalize; begin if fNum > 0 then begin - fData[fNum] := 1; + fData[fNum] := 1; // padbit.. inc(fNum); while fNum < Length(fData) do begin @@ -372,7 +372,7 @@ procedure TPoly1305.Poly1305Blocks(pData: PByteArray; size: integer; // h4 += (u32)(d3 >> 32) + padbit; d0 := UInt64(h0) + U8ToU32(pData); h0 := UInt32(d0); - d1 := UInt64(h1) + d0 shr 32 + U8ToU32(@pData^[4]); + 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); diff --git a/Source/DECCiphers.pas b/Source/DECCiphers.pas index a437d105..3cdff231 100644 --- a/Source/DECCiphers.pas +++ b/Source/DECCiphers.pas @@ -7022,7 +7022,7 @@ procedure TCipher_ChaCha20.OnAfterInitVectorInitialization( var iv : TBytes; begin if FInitVectorSize <> 12 then - raise Exception.Create('Nonce is not 96 bit.'); + raise EDECException.Create('Nonce is not 96 bit.'); fInpChaChaMTX^[12] := 0; // counter Move( FInitializationVector^, fInpChaChaMTX^[13], 3*sizeof(longword)); @@ -7072,7 +7072,7 @@ procedure TCipher_ChaCha20.DoInit(const Key; Size: Integer); inherited; if size <> 32 then - raise Exception.Create('Given ChaCha key size is not 256 bit'); + 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); @@ -7695,7 +7695,7 @@ procedure TCipher_ChaCha20.InitChaChaBlk; // is this here for xchacha? if fInpChaChaMTX^[12] <= 1 then - raise Exception.Create('Counter overflow!'); + raise EDECException.Create('Counter overflow!'); // inc(fInpChaChaMTX^[13]); end; end; @@ -7913,7 +7913,7 @@ procedure TCipher_XChaCha20.OnAfterInitVectorInitialization( // RFC point 2.3 and 2.3.1: if length(OriginalInitVector) <> 24 then //192 div 8 - raise Exception.Create('IV vector needs to be 192 bits long'); + raise EDECException.Create('IV vector needs to be 192 bits long'); // update iv -> use the first 16 bytes! HChaCha(OriginalInitVector); diff --git a/Unit Tests/DECDUnitTestSuite.dpr b/Unit Tests/DECDUnitTestSuite.dpr index 201e9f34..2a1a612f 100644 --- a/Unit Tests/DECDUnitTestSuite.dpr +++ b/Unit Tests/DECDUnitTestSuite.dpr @@ -70,8 +70,7 @@ uses DECUtilRawByteStringHelper in '..\Source\DECUtilRawByteStringHelper.pas', DECZIPHelper in '..\Source\DECZIPHelper.pas', DECCipherModesGCM in '..\Source\DECCipherModesGCM.pas', - TESTDECChaChaPoly1305 in 'Tests\TESTDECChaChaPoly1305.pas', - poly1305dll in '..\Source\poly1305dll.pas'; + TestDECChaChaPoly1305 in 'Tests\TestDECChaChaPoly1305.pas'; {$R *.RES} diff --git a/Unit Tests/DECDUnitTestSuite.dproj b/Unit Tests/DECDUnitTestSuite.dproj index 35201323..f8ffab9f 100644 --- a/Unit Tests/DECDUnitTestSuite.dproj +++ b/Unit Tests/DECDUnitTestSuite.dproj @@ -194,8 +194,7 @@ - - + Base 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/TestDECChaChaPoly1305.pas b/Unit Tests/Tests/TestDECChaChaPoly1305.pas index dd4e5c91..f70aecb2 100644 --- a/Unit Tests/Tests/TestDECChaChaPoly1305.pas +++ b/Unit Tests/Tests/TestDECChaChaPoly1305.pas @@ -8,7 +8,7 @@ interface TestFramework, {$ENDIF} System.SysUtils, Generics.Collections, System.Math, - DECBaseClass, + DECBaseClass, System.JSON, DECCipherBase, DECCipherModes, DECCipherFormats, DECCiphers; @@ -16,6 +16,30 @@ interface // 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; published procedure TestPoly1305; procedure TestChaCha20_Poly1305_KeySetup; @@ -23,32 +47,16 @@ TestChaCha20Poly1305 = class(TTestCase) procedure TestChaChaEncodeDecodeSpeed; procedure TestXChaCha_Poly1305_AEAD; + // test suite code + procedure TestEncode; + procedure TestDecode; + + destructor Destroy; override; end; implementation -uses DECCipherModesPoly1305, System.Diagnostics; - - -//// ########################################### -//// #### OpenSSL reference implementation -//// ########################################### -// -// -//const POLY1305_KEY_SIZE = 32; -// POLY1305_DIGEST_SIZE = 16; -// -//type -// PPoly1305Ctx = PByte; -// TPoly1305Key = Array[0..POLY1305_KEY_SIZE-1] of byte; -// TPoly1305Mac = Array[0..POLY1305_DIGEST_SIZE-1] of byte; -// size_t = Integer; -// -// -//function Poly1305_ctx_size : size_t; cdecl; external 'libcrypto-3.dll'; -//procedure Poly1305_Init(ctx : PPoly1305Ctx; const key : TPoly1305Key); cdecl; external 'libcrypto-3.dll'; -//procedure Poly1305_Update(ctx : PPoly1305Ctx; inp : PByte; len : size_t); cdecl; external 'libcrypto-3.dll'; -//procedure Poly1305_Final(ctx : PPoly1305Ctx; var mac : TPoly1305Mac); cdecl; external 'libcrypto-3.dll'; - +uses DECCipherModesPoly1305, System.Diagnostics, classes, DECFormat, DECTypes, + System.JSON.Readers; // ########################################### @@ -179,6 +187,88 @@ procedure EncodeBuf( var dest : TBytes ); 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); @@ -271,6 +361,14 @@ procedure InvData( data : PByte; len : integer ); 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.'; @@ -350,6 +448,13 @@ procedure TestChaCha20Poly1305.TestXChaCha_Poly1305_AEAD; 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]; @@ -429,6 +534,63 @@ procedure TestChaCha20Poly1305.TestChaCha20_Poly1305_AEAD; 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} From e8ffbb5264853596bb6e7f9d325f8719ca691a6c Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Tue, 29 Jul 2025 23:03:36 +0200 Subject: [PATCH 08/12] Fix: the destructor was actually a test - moved to public section --- Unit Tests/Tests/TestDECChaChaPoly1305.pas | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Unit Tests/Tests/TestDECChaChaPoly1305.pas b/Unit Tests/Tests/TestDECChaChaPoly1305.pas index f70aecb2..f3e7c1dc 100644 --- a/Unit Tests/Tests/TestDECChaChaPoly1305.pas +++ b/Unit Tests/Tests/TestDECChaChaPoly1305.pas @@ -40,6 +40,8 @@ TTestEnumerator = class(TEnumerable) fTests : TTestEnumerator; function IterTests : TTestEnumerator; + public + destructor Destroy; override; published procedure TestPoly1305; procedure TestChaCha20_Poly1305_KeySetup; @@ -50,8 +52,6 @@ TTestEnumerator = class(TEnumerable) // test suite code procedure TestEncode; procedure TestDecode; - - destructor Destroy; override; end; implementation From a025e6c2b4871f1db435c7ef66fb2d620ba570f8 Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Sat, 2 Aug 2025 22:38:50 +0200 Subject: [PATCH 09/12] Extended intel CPU support (added unit to detect features AVX, SSE and also AES HW support). --- Source/DEC60.dpr | 4 +- Source/DECCPUSupport.pas | 117 +++++++++++++++++++++++++++++ Source/DECCipherModesPoly1305.pas | 1 + Source/DECCiphers.pas | 21 +++++- Unit Tests/DECDUnitTestSuite.dpr | 3 +- Unit Tests/DECDUnitTestSuite.dproj | 19 +++++ 6 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 Source/DECCPUSupport.pas diff --git a/Source/DEC60.dpr b/Source/DEC60.dpr index 10cdafa5..bca0efc0 100644 --- a/Source/DEC60.dpr +++ b/Source/DEC60.dpr @@ -49,7 +49,9 @@ uses DECZIPHelper in 'DECZIPHelper.pas', DECCipherPaddings in 'DECCipherPaddings.pas', DECCipherModesCCM in 'DECCipherModesCCM.pas', - DECAuthenticatedCipherModesBase in 'DECAuthenticatedCipherModesBase.pas'; + DECAuthenticatedCipherModesBase in 'DECAuthenticatedCipherModesBase.pas', + DECCipherModesPoly1305 in 'DECCipherModesPoly1305.pas', + DECCPUSupport in 'DECCPUSupport.pas'; begin try 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/DECCipherModesPoly1305.pas b/Source/DECCipherModesPoly1305.pas index ce2f8094..90307f39 100644 --- a/Source/DECCipherModesPoly1305.pas +++ b/Source/DECCipherModesPoly1305.pas @@ -216,6 +216,7 @@ constructor TPoly1305.Create; begin inherited Create; + FCalcAuthenticationTagLength := sizeof(TBlock16Byte); FH := @fPoly1305State[0]; FR := @fPoly1305State[sizeof(THarr)]; diff --git a/Source/DECCiphers.pas b/Source/DECCiphers.pas index 3cdff231..9d707193 100644 --- a/Source/DECCiphers.pas +++ b/Source/DECCiphers.pas @@ -1106,7 +1106,7 @@ implementation {$IFOPT R+}{$DEFINE RESTORE_RANGECHECKS}{$R-}{$ENDIF} uses - DECData, DECDataCipher; + DECData, DECDataCipher, DECCPUSupport; { TCipher_Null } @@ -7609,9 +7609,13 @@ procedure TCipher_ChaCha20.AfterConstruction; {$IFDEF PUREPASCAL} fFullBlockFunc := FullBlockPas; {$ELSE} + fFullBlockFunc := FullBlockPas; + case CpuMode of - cmSSE: fFullBlockFunc := FullBlockSSE; - cmAVX: fFullBlockFunc := FullBlockAVX; + cmSSE: if TDEC_CPUSupport.SSE3 then + fFullBlockFunc := FullBlockSSE; + cmAVX: if TDEC_CPUSupport.AVX2 then + fFullBlockFunc := FullBlockAVX; else fFullBlockFunc := FullBlockPas; end; @@ -8002,6 +8006,17 @@ initialization {$ENDIF} {$ENDIF} + {$IFDEF CPUx86} + if TDEC_CPUSupport.AVX2 + then + TCipher_ChaCha20.CpuMode := cmAVX + else if TDEC_CPUSupport.SSE3 + then + TCipher_ChaCha20.CpuMode := cmSSE + else + TCipher_ChaCha20.CpuMode := cmPas; + {$ENDIF} + finalization end. diff --git a/Unit Tests/DECDUnitTestSuite.dpr b/Unit Tests/DECDUnitTestSuite.dpr index 2a1a612f..fdf107d2 100644 --- a/Unit Tests/DECDUnitTestSuite.dpr +++ b/Unit Tests/DECDUnitTestSuite.dpr @@ -70,7 +70,8 @@ uses DECUtilRawByteStringHelper in '..\Source\DECUtilRawByteStringHelper.pas', DECZIPHelper in '..\Source\DECZIPHelper.pas', DECCipherModesGCM in '..\Source\DECCipherModesGCM.pas', - TestDECChaChaPoly1305 in 'Tests\TestDECChaChaPoly1305.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 f8ffab9f..b08d731b 100644 --- a/Unit Tests/DECDUnitTestSuite.dproj +++ b/Unit Tests/DECDUnitTestSuite.dproj @@ -195,6 +195,7 @@ + Base @@ -260,6 +261,18 @@ true + + + DECDUnitTestSuite.exe + true + + + + + DECDUnitTestSuite.rsm + true + + @@ -267,6 +280,12 @@ true + + + .\ + true + + 1 From 7e1b4431557af090205d1d3bb41d774c6191294f Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Wed, 20 Aug 2025 11:50:10 +0200 Subject: [PATCH 10/12] * New AES assembler routines based on the Intel Whitepaper * extended additional buffer size in AES to allow alignment * Moved align code to DECUtil.pas * Fixed an old assembler routine for 64 bit byte swapping * Fixed include file - it only worked for 32bits environments but not for 64 bits * Updated chacha defines so they work with the DEC internal defines (removed my original ifdefs) * Fixed bug appearing in the gcm testcases -> wrong blocksize should throw an exception --- Source/DECCipherModes.pas | 2 +- Source/DECCiphers.pas | 687 ++++++++++++++++++++++++++--- Source/DECOptions.inc | 48 +- Source/DECUtil.pas | 19 + Source/x86_64/DECUtil.inc | 5 +- Unit Tests/Tests/TestDECCipher.pas | 4 +- 6 files changed, 683 insertions(+), 82 deletions(-) diff --git a/Source/DECCipherModes.pas b/Source/DECCipherModes.pas index 5770152c..e687f63b 100644 --- a/Source/DECCipherModes.pas +++ b/Source/DECCipherModes.pas @@ -751,7 +751,7 @@ procedure TDECCipherModes.InitMode; cmPoly1305: fAuthObj := TPoly1305.Create; end; end - else if Context.BlockSize < 16 + else if (Context.BlockSize < 16) and (TCipherMode.cmPoly1305 = FMode) then fAuthObj := TPoly1305.Create else diff --git a/Source/DECCiphers.pas b/Source/DECCiphers.pas index 9d707193..6237f0d0 100644 --- a/Source/DECCiphers.pas +++ b/Source/DECCiphers.pas @@ -380,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". @@ -409,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 @@ -2829,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} { @@ -2934,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 @@ -2942,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; @@ -3046,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]; @@ -3111,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]; @@ -6869,28 +7477,7 @@ procedure TCipher_XTEA_DEC52.DoDecode(Source, Dest: Pointer; Size: Integer); { TCipher_ChaCha20 } -{$IFDEF FPC} {$ASMMODE intel} {$S-} {$ENDIF} - -{$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(MRMATH_NOASM)} +{$IFDEF PUREPASCAL} function rol(value: LongWord; Bits: Byte): LongWord; begin Result := (value shl Bits) or (value shr (32 - bits)); @@ -6901,19 +7488,19 @@ function rol(value: LongWord; Bits: Byte): LongWord; assembler; begin {$ENDIF} asm - {$IF defined(x64)} + {$IFdef X64ASM} mov eax, ecx; mov cl, dl; rol eax, cl; {$ELSE} xchg cl,dl rol eax, cl - {$IFEND} + {$ENDIF} end; {$IFDEF FPC} end; {$ENDIF} -{$IFEND} +{$ENDIF} procedure TCipher_ChaCha20.ChaChaQuarterRound(var a, b, c, d: LongWord); begin @@ -7057,14 +7644,6 @@ procedure TCipher_ChaCha20.OnAfterInitVectorInitialization( inherited; 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; - - procedure TCipher_ChaCha20.DoInit(const Key; Size: Integer); // from chacha-prng.h const cChaChaConst : Array[0..15] of AnsiChar = 'expand 32-byte k'; @@ -7118,7 +7697,7 @@ procedure TCipher_ChaCha20.SetChaChaMode(const Value: TChaChaMode); {$IFNDEF PUREPASCAL} -{$IFDEF x86} +{$IFDEF X86ASM} procedure FullBlockSSE(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); register; {$IFDEF FPC}assembler;{$ENDIF} // eax = ChaChaMtx, edx = source, ecx = dest @@ -7192,7 +7771,7 @@ procedure FullBlockAVX(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); regist {$ENDIF} -{$IFDEF x64} +{$IFDEF X64ASM} procedure FullBlockSSE(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); // rcx = ChaChaMtx, rdx = source, r8 = dest asm @@ -7293,7 +7872,7 @@ procedure FullBlockAVX(ChaChaMtx : PChaChaAVXMtx; Source, Dest: Pointer); 11, 8, 9, 10, 15, 12, 13, 14); -{$IFDEF x86} +{$IFDEF X86ASM} procedure AVXChaChaDoubleQuarterRound( chachaMtx : PChaChaAVXMtx ); {$IFDEF FPC} assembler; {$ELSE} register; {$ENDIF} asm @@ -7421,7 +8000,7 @@ procedure AVXRealingAndAddMtx( chaChaMtx : PChaChaAVXMtx; inpChaCha : PChaChaMtx end; {$ENDIF} -{$IFDEF x64} +{$IFDEF X64ASM} procedure AVXChaChaDoubleQuarterRound( chachaMtx : PChaChaAVXMtx ); var dYMM4, dYMM5 : Array[0..4] of int64; @@ -7436,7 +8015,6 @@ procedure AVXChaChaDoubleQuarterRound( chachaMtx : PChaChaAVXMtx ); // in our case only rdi to rcx mov rcx, rdi; {$ENDIF} - {$IFDEF x64} {$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} @@ -7530,7 +8108,6 @@ procedure AVXChaChaDoubleQuarterRound( chachaMtx : PChaChaAVXMtx ); {$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} -{$ENDIF} end; {$IFDEF FPC} end; @@ -7597,7 +8174,7 @@ procedure AVXRealingAndAddMtx( chaChaMtx : PChaChaAVXMtx; inpChaCha : PChaChaMtx {$ENDIF} -{$ENDIF} +{$ENDIF} // PUREPASCAL procedure TCipher_ChaCha20.AfterConstruction; begin @@ -7609,8 +8186,6 @@ procedure TCipher_ChaCha20.AfterConstruction; {$IFDEF PUREPASCAL} fFullBlockFunc := FullBlockPas; {$ELSE} - fFullBlockFunc := FullBlockPas; - case CpuMode of cmSSE: if TDEC_CPUSupport.SSE3 then fFullBlockFunc := FullBlockSSE; @@ -7743,11 +8318,11 @@ procedure TCipher_ChaCha20.PasChaChaDoubleQuarterRound(mtx : PChaChaMtx); procedure TCipher_ChaCha20.SSEChaChaDoubleQuarterRound(mtx : PChaChaMtx); // 32Bit: ecx = self, edx = mtx // 64bit: rcx = self, rdx = mtx -{$IFDEF x64} +{$IFDEF CPUX64} var dXMM4, dXMM5 : Array[0..1] of Int64; {$ENDIF} asm - {$IFDEF x64} + {$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 @@ -7854,7 +8429,7 @@ procedure TCipher_ChaCha20.SSEChaChaDoubleQuarterRound(mtx : PChaChaMtx); palignr xmm3, xmm4, 4; // move back - {$IFDEF x64} + {$IFDEF CPUX64} movdqa [rdx], xmm0; movdqa [rdx + 16], xmm1; movdqa [rdx + 32], xmm2; @@ -8006,7 +8581,6 @@ initialization {$ENDIF} {$ENDIF} - {$IFDEF CPUx86} if TDEC_CPUSupport.AVX2 then TCipher_ChaCha20.CpuMode := cmAVX @@ -8015,7 +8589,8 @@ initialization TCipher_ChaCha20.CpuMode := cmSSE else TCipher_ChaCha20.CpuMode := cmPas; - {$ENDIF} + + TCipher_Rijndael.UseAESAsm := TDEC_CPUSupport.AES; finalization diff --git a/Source/DECOptions.inc b/Source/DECOptions.inc index 8ed98108..a76838bc 100644 --- a/Source/DECOptions.inc +++ b/Source/DECOptions.inc @@ -73,7 +73,7 @@ // Automatically register all hash classes {.$DEFINE ManualRegisterHashClasses} (* default off *) -{.$DEFINE ASSEMBLER} +{$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 @@ -83,21 +83,29 @@ {$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} @@ -195,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/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/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/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); From dbe08c109a48f046a05379b3e20668d6cb43e531 Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Tue, 27 Jan 2026 16:51:23 +0100 Subject: [PATCH 11/12] * AVX implementations for the Poly1305 mode * Added tests --- Source/DECCipherModesPoly1305.pas | 682 ++++++++++++++++++++- Source/DECCiphers.pas | 2 +- Unit Tests/Tests/TestDECChaChaPoly1305.pas | 154 ++++- 3 files changed, 824 insertions(+), 14 deletions(-) diff --git a/Source/DECCipherModesPoly1305.pas b/Source/DECCipherModesPoly1305.pas index 90307f39..ba94deab 100644 --- a/Source/DECCipherModesPoly1305.pas +++ b/Source/DECCipherModesPoly1305.pas @@ -35,6 +35,7 @@ interface // 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 + TPoly1305CpuMode = (pmPas, pmAVX); type TPoly1305 = class(TAuthenticatedCipherModesBase) private @@ -43,6 +44,7 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) POLY1305_KEY_SIZE = 32; type TPoly1305Nonce = Array[0..3] of UInt32; + PPoly1305Nonce = ^TPoly1305Nonce; TPoly1305BlockMethod = procedure ( pData : PByteArray; size : integer ) of Object; TPoly1305EmitMethod = procedure( var mac: TBlock16Byte ) of Object; TPoly1305PadAndFinalize = procedure( authLen, encDecBufLen : int64) of Object; @@ -50,10 +52,31 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) PHArr = ^THArr; TRArr = Array[0..3] of UInt32; PRArr = ^TRArr; - TPoly1305State = Array[0..160] of Byte; + + TStateAVXArr = Array[0..4] of UInt64; + T4UInt64 = Array[0..3] of UInt64; + P4UInt64 = ^T4UInt64; + T2UInt64 = Array[0..1] of UInt64; + P2UInt64 = ^T2UInt64; + + PStateAVXArr = ^TStateAVXArr; + + TPoly1305CTX = packed record + r : TStateAVXArr; + rr : TStateAVXArr; + k0, k1, k2, k3, k4 : T4UInt64; // 4-lane kernels for H0..H3 + k0_5, k1_5, k2_5, k3_5, k4_5 : UInt64; // scalar 5th term multiplier + h : TStateAVXArr; + s0, s1 : UInt64; // nonce + end; + PPoly1305CTX = ^TPoly1305CTX; + + TPoly1305State = Array[0..431] of Byte; // sizeof(TPoly1305Ctx) + 2*xmm register size + 64 alignment bytes + private /// - /// avx buffer for h and R (may be extended in future fo for SSE, AVX) + /// buffer for h and R and other precomputed values. The buffer is shared between + /// the pure pascal and the AVX implementation /// fPoly1305State : TPoly1305State; @@ -63,6 +86,12 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) FH : PHArr; FR : PRArr; + /// + /// AVX2 optimized buffers. These point ot the fPoly1305State buffer + /// + fAVXCtx : PPoly1305CTX; + fXMMMem : PUint64; + /// /// Initialization vector and nonce - initialized from the 32Byte init vector /// @@ -74,7 +103,7 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) /// fNum : integer; fPolyBlockSize : integer; - fData : Array[0..2*POLY1305_BLOCK_SIZE - 1] of Byte; // for both the sse and pas version + fData : Array[0..2*POLY1305_BLOCK_SIZE - 1] of Byte; // for both the avx and pas version /// /// #bytes of encrypted data @@ -100,13 +129,19 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) /// procedure Poly1305Emit( var mac : TBlock16Byte; const nonce : TPoly1305Nonce ); procedure PadAndFinalizePAS( authLen, encDecBufLen : int64); + procedure PadAndFinalizeAVX(authLen, encDecBufLen: int64); protected // ########################################### // #### Authentication block functions + {$IFNDEF PUREPASCAL} + procedure UpdatePolyAVX( pData : PByteArray; size : integer); + procedure FinalizeAVX; + {$ENDIF} 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 @@ -119,8 +154,13 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) procedure UpdateWithEncDecBuf(buf : PUInt8Array; Size : Integer); override; procedure Burn; override; - public + /// + /// Defines either pure pascal code is used or specialized assembler routines utilizing AVX instructions + /// + class var CpuMode : TPoly1305CpuMode; + + constructor Create; /// @@ -141,6 +181,9 @@ implementation {$R-}{$Q-} +const cMask26 : uint64 = $3ffffff; + cShl24 : uint64 = $1000000; + //CONSTANT_TIME_CARRY(a,b) ( \ // (a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1) \ // ) @@ -149,6 +192,460 @@ function ConstTimeCarray32(a, b : UInt32 ) : UInt32; inline; Result := (a xor ( (a xor b) or ((a - b) xor b))) shr 31; end; +// ########################################### +// #### AVX Assembler - and associated procedures +// ########################################### + +{$IFNDEF PUREPASCAL} + +{$IFDEF FPC} {$ASMMode Intel} {$ENDIF} + +procedure Split26( const lo, hi : UInt64; outVal : TPoly1305.PStateAVXArr ); inline; +var t0, t1, t2, t3, t4 : UInt64; +begin + t0 := lo; + t1 := (lo shr 26) or (hi shl 38); + t2 := (lo shr 52) or (hi shl 12); + t3 := (hi shr 14); + t4 := hi shr 40; + outval^[0] := t0 and cMask26; + outval^[1] := t1 and cMask26; + outval^[2] := t2 and cMask26; + outval^[3] := t3 and cMask26; + outval^[4] := t4 and cMask26; +end; + +procedure clamp_r( r : TPoly1305.PStateAVXArr); inline; +begin + r^[1] := r^[1] and $3ffff03; + r^[2] := r^[2] and $3ffc0ff; + r^[3] := r^[3] and $3f03fff; + r^[4] := r^[4] and $00fffff; +end; + + +procedure InitPoly1305( ctx : TPoly1305.PPoly1305CTX; key : PByte ); +var i : integer; +begin + FillChar(ctx^, sizeof(ctx^), 0); + + Split26(TPoly1305.P4UInt64(key)^[0], TPoly1305.P4UInt64(key)^[1], @ctx.r[0]); + clamp_r(@ctx^.r[0]); + + for i := 0 to High(ctx^.rr) do + ctx^.rr[i] := 5*ctx^.r[i]; + + // Precompute k0..k4 once (no per-block _mm256_set_epi64x needed) + // Note: _mm256_set_epi64x order is [lane3,lane2,lane1,lane0] + ctx^.k0[3] := ctx^.rr[2]; + ctx^.k0[2] := ctx^.rr[3]; + ctx^.k0[1] := ctx^.rr[4]; + ctx^.k0[0] := ctx^.r[0]; + ctx^.k0_5 := ctx^.rr[1]; + + ctx^.k1[3] := ctx^.rr[3]; + ctx^.k1[2] := ctx^.rr[4]; + ctx^.k1[1] := ctx^.r[0]; + ctx^.k1[0] := ctx^.r[1]; + ctx^.k1_5 := ctx^.rr[2]; + + ctx^.k2[3] := ctx^.rr[4]; + ctx^.k2[2] := ctx^.r[0]; + ctx^.k2[1] := ctx^.r[1]; + ctx^.k2[0] := ctx^.r[2]; + ctx^.k2_5 := ctx^.rr[3]; + + ctx^.k3[3] := ctx^.r[0]; + ctx^.k3[2] := ctx^.r[1]; + ctx^.k3[1] := ctx^.r[2]; + ctx^.k3[0] := ctx^.r[3]; + ctx^.k3_5 := ctx^.rr[4]; + + ctx^.k4[3] := ctx^.r[1]; + ctx^.k4[2] := ctx^.r[2]; + ctx^.k4[1] := ctx^.r[3]; + ctx^.k4[0] := ctx^.r[4]; + ctx^.k4_5 := ctx^.r[0]; + + // first 16 byte went to R -> the rest is used for the "nonce" + ctx^.s0 := TPoly1305.P4UInt64(key)^[2]; + ctx^.s1 := TPoly1305.P4UInt64(key)^[3]; +end; + +procedure FinalizePoly1305( ctx : TPoly1305.PPoly1305CTX; mac : PByte ); +var h : TPoly1305.PStateAVXArr; + c : UInt64; + g : TPoly1305.TStateAVXArr; + mask : UInt64; + nmask : UInt64; + f0, f1 : UInt64; +begin + h := @(ctx^.h[0]); + c := h^[1] shr 26; h^[1] := h^[1] and cMask26; inc(h^[2], c); + c := h^[2] shr 26; h^[2] := h^[2] and cMask26; inc(h^[3], c); + c := h^[3] shr 26; h^[3] := h^[3] and cMask26; inc(h^[4], c); + c := h^[4] shr 26; h^[4] := h^[4] and cMask26; inc(h^[0], 5*c); + c := h^[0] shr 26; h^[0] := h^[0] and cMask26; inc(h^[1], c); + + g[0] := h[0] + 5; + g[1] := h[1] + (g[0] shr 26); g[0] := g[0] and cMask26; + g[2] := h[2] + (g[1] shr 26); g[0] := g[1] and cMask26; + g[3] := h[3] + (g[2] shr 26); g[0] := g[2] and cMask26; + g[4] := h[4] + (g[3] shr 26); g[0] := g[3] and cMask26; + + dec(g[4], 1 shl 26); + + // mask is either 0 or all ones depending on the last bit + // works only for disabled range checking and overflow checking! + mask := (g[4] shr 63) - 1; + g[4] := g[4] and cMask26; + nmask := not mask; + h^[0] := (h^[0] and nmask) or (g[0] and mask); + h^[1] := (h^[1] and nmask) or (g[1] and mask); + h^[2] := (h^[2] and nmask) or (g[2] and mask); + h^[3] := (h^[3] and nmask) or (g[3] and mask); + h^[4] := (h^[4] and nmask) or (g[4] and mask); + + // pack into 128-bit LE + f0 := h^[0] or (h^[1] shl 26) or (h^[2] shl 52); + f1 := (h^[2] shr 12) or (h^[3] shl 14) or (h^[4] shl 40); + + // add s + TPoly1305.P2UInt64(mac)^[0] := f0 + ctx^.s0; + TPoly1305.P2UInt64(mac)^[1] := f1 + ctx^.s1 + UInt64(TPoly1305.P2UInt64(@mac[0])^[0] < f0); +end; + +// central xmm register save and restor (we don't need that in a tight loop) + +{$IFDEF X86ASM} + +procedure poly1305_block_avx2_ctx(ctx : TPoly1305.PPoly1305CTX; t : TPoly1305.PStateAVXArr); {$IFDEF FPC} assembler; {$ENDIF} +asm + push ebp; + mov ecx, edx + mov ebp, esp + push edi + push esi + mov esi, eax + push ebx + + // reserver mem on the local stack -> aligned 32bytes + and esp, -32 + sub esp, 64 + + + mov eax, DWORD PTR [edx+32] + add eax, DWORD PTR [esi+312] + {$IFDEF AVXSUP}vmovdqu ymm0, [ecx] {$ELSE}db $C5,$FE,$6F,$01;{$ENDIF} + mov edi, DWORD PTR [esi+240] + mov ecx, eax + mov DWORD PTR [esp+52], 0 + mov eax, DWORD PTR [esi+244] + mov edx, DWORD PTR [edx+36] + mov DWORD PTR [esp+56], ecx + adc edx, DWORD PTR [esi+316] + {$IFDEF AVXSUP}vpaddq ymm0, ymm0, [esi+280] {$ELSE}db $C5,$FD,$D4,$86,$18,$01,$00,$00;{$ENDIF} + {$IFDEF AVXSUP}vpmuludq ymm1, ymm0, [esi+80] {$ELSE}db $C5,$FD,$F4,$4E,$50;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm2, xmm1 {$ELSE}db $C5,$F9,$6F,$D1;{$ENDIF} + imul eax, ecx + {$IFDEF AVXSUP}vextracti128 xmm1, ymm1, $1 {$ELSE}db $C4,$E3,$7D,$39,$C9,$01;{$ENDIF} + mov DWORD PTR [esp+60], edx + {$IFDEF AVXSUP}vpmuludq ymm3, ymm0, [esi+112] {$ELSE}db $C5,$FD,$F4,$5E,$70;{$ENDIF} + imul edi, edx + {$IFDEF AVXSUP}vpaddq xmm1, xmm1, xmm2 {$ELSE}db $C5,$F1,$D4,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpsrldq xmm2, xmm1, 8 {$ELSE}db $C5,$E9,$73,$D9,$08;{$ENDIF} + {$IFDEF AVXSUP}vpaddq xmm1, xmm1, xmm2 {$ELSE}db $C5,$F1,$D4,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpmuludq ymm2, ymm0, [esi+144] {$ELSE}db $C5,$FD,$F4,$96,$90,$00,$00,$00;{$ENDIF} + add edi, eax + mov eax, ecx + mul DWORD PTR [esi+240] + mov ecx, eax + mov ebx, edx + {$IFDEF AVXSUP}vmovd eax, xmm1 {$ELSE}db $C5,$F9,$7E,$C8;{$ENDIF} + add ebx, edi + {$IFDEF AVXSUP}vpextrd edx, xmm1, 1 {$ELSE}db $C4,$E3,$79,$16,$CA,$01;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm1, xmm3 {$ELSE}db $C5,$F9,$6F,$CB;{$ENDIF} + add ecx, eax + adc ebx, edx + mov eax, DWORD PTR [esp+56] + mov edx, DWORD PTR [esi+252] + mov edi, ecx + and edi, 67108863 + {$IFDEF AVXSUP}vextracti128 xmm3, ymm3, $1 {$ELSE}db $C4,$E3,$7D,$39,$DB,$01;{$ENDIF} + imul edx, eax + mov DWORD PTR [esp+48], edi + mov edi, DWORD PTR [esp+60] + {$IFDEF AVXSUP}vpaddq xmm3, xmm3, xmm1 {$ELSE}db $C5,$E1,$D4,$D9;{$ENDIF} + imul edi, DWORD PTR [esi+248] + mov eax, DWORD PTR [esp+56] + {$IFDEF AVXSUP}vpsrldq xmm6, xmm3, 8 {$ELSE}db $C5,$C9,$73,$DB,$08;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm1, xmm2 {$ELSE}db $C5,$F9,$6F,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpaddq xmm3, xmm3, xmm6 {$ELSE}db $C5,$E1,$D4,$DE;{$ENDIF} + {$IFDEF AVXSUP}vextracti128 xmm2, ymm2, $1 {$ELSE}db $C4,$E3,$7D,$39,$D2,$01;{$ENDIF} + {$IFDEF AVXSUP}vpaddq xmm2, xmm2, xmm1 {$ELSE}db $C5,$E9,$D4,$D1;{$ENDIF} + {$IFDEF AVXSUP}vmovq QWORD PTR [esp+32], xmm3 {$ELSE}db $C5,$F9,$D6,$5C,$24,$20;{$ENDIF} + {$IFDEF AVXSUP}vpmuludq ymm1, ymm0, [esi+176] {$ELSE}db $C5,$FD,$F4,$8E,$B0,$00,$00,$00;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm4, xmm1 {$ELSE}db $C5,$F9,$6F,$E1;{$ENDIF} + add edi, edx + mul DWORD PTR [esi+248] + {$IFDEF AVXSUP}vpmuludq ymm0, ymm0, [esi+208] {$ELSE}db $C5,$FD,$F4,$86,$D0,$00,$00,$00;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm7, xmm0 {$ELSE}db $C5,$F9,$6F,$F8;{$ENDIF} + {$IFDEF AVXSUP}vpsrldq xmm5, xmm2, 8 {$ELSE}db $C5,$D1,$73,$DA,$08;{$ENDIF} + {$IFDEF AVXSUP}vextracti128 xmm1, ymm1, $1 {$ELSE}db $C4,$E3,$7D,$39,$C9,$01;{$ENDIF} + {$IFDEF AVXSUP}vextracti128 xmm0, ymm0, $1 {$ELSE}db $C4,$E3,$7D,$39,$C0,$01;{$ENDIF} + {$IFDEF AVXSUP}vpaddq xmm2, xmm2, xmm5 {$ELSE}db $C5,$E9,$D4,$D5;{$ENDIF} + {$IFDEF AVXSUP}vpaddq xmm1, xmm1, xmm4 {$ELSE}db $C5,$F1,$D4,$CC;{$ENDIF} + add edx, edi + {$IFDEF AVXSUP}vpsrldq xmm4, xmm1, 8 {$ELSE}db $C5,$D9,$73,$D9,$08;{$ENDIF} + {$IFDEF AVXSUP}vpaddq xmm0, xmm0, xmm7 {$ELSE}db $C5,$F9,$D4,$C7;{$ENDIF} + add eax, DWORD PTR [esp+32] + adc edx, DWORD PTR [esp+36] + shrd ecx, ebx, 26 + {$IFDEF AVXSUP}vmovq QWORD PTR [esp+32], xmm2 {$ELSE}db $C5,$F9,$D6,$54,$24,$20;{$ENDIF} + {$IFDEF AVXSUP}vpaddq xmm1, xmm1, xmm4 {$ELSE}db $C5,$F1,$D4,$CC;{$ENDIF} + shr ebx, 26 + add ecx, eax + mov eax, DWORD PTR [esp+56] + mov DWORD PTR [esp+44], 0 + mov edi, ecx + {$IFDEF AVXSUP}vpsrldq xmm7, xmm0, 8 {$ELSE}db $C5,$C1,$73,$D8,$08;{$ENDIF} + adc ebx, edx + and edi, 67108863 + imul eax, DWORD PTR [esi+260] + {$IFDEF AVXSUP}vpaddq xmm0, xmm0, xmm7 {$ELSE}db $C5,$F9,$D4,$C7;{$ENDIF} + mov DWORD PTR [esp+40], edi + mov edi, DWORD PTR [esp+60] + imul edi, DWORD PTR [esi+256] + add edi, eax + mov eax, DWORD PTR [esp+56] + mul DWORD PTR [esi+256] + add edx, edi + add eax, DWORD PTR [esp+32] + adc edx, DWORD PTR [esp+36] + shrd ecx, ebx, 26 + shr ebx, 26 + add eax, ecx + mov ecx, DWORD PTR [esp+56] + mov edi, DWORD PTR [esp+60] + mov DWORD PTR [esp+32], eax + mov eax, DWORD PTR [esi+268] + adc edx, ebx + imul edi, DWORD PTR [esi+264] + mov DWORD PTR [esp+36], edx + imul eax, ecx + add edi, eax + mov eax, ecx + mul DWORD PTR [esi+264] + mov ecx, eax + mov ebx, edx + {$IFDEF AVXSUP}vmovd eax, xmm1 {$ELSE}db $C5,$F9,$7E,$C8;{$ENDIF} + add ebx, edi + {$IFDEF AVXSUP}vpextrd edx, xmm1, 1 {$ELSE}db $C4,$E3,$79,$16,$CA,$01;{$ENDIF} + add eax, ecx + mov ecx, DWORD PTR [esp+32] + adc edx, ebx + mov ebx, DWORD PTR [esp+36] + mov edi, DWORD PTR [esp+60] + shrd ecx, ebx, 26 + shr ebx, 26 + add eax, ecx + mov ecx, DWORD PTR [esp+56] + adc edx, ebx + imul edi, DWORD PTR [esi+272] + mov DWORD PTR [esp+24], eax + mov DWORD PTR [esp+28], edx + mov edx, DWORD PTR [esi+276] + mov eax, ecx + imul edx, ecx + add edi, edx + mul DWORD PTR [esi+272] + mov ecx, eax + mov ebx, edx + {$IFDEF AVXSUP}vmovd eax, xmm0 {$ELSE}db $C5,$F9,$7E,$C0;{$ENDIF} + add ebx, edi + {$IFDEF AVXSUP}vpextrd edx, xmm0, 1 {$ELSE}db $C4,$E3,$79,$16,$C2,$01;{$ENDIF} + add eax, ecx + mov ecx, DWORD PTR [esp+24] + adc edx, ebx + mov ebx, DWORD PTR [esp+28] + mov edi, 5 + shrd ecx, ebx, 26 + shr ebx, 26 + add ecx, eax + adc ebx, edx + mov eax, ecx + mov DWORD PTR [esp+56], ecx + mov edx, ebx + shrd eax, ebx, 26 + mov DWORD PTR [esp+60], ebx + mov DWORD PTR [esi+284], 0 + shr edx, 26 + mov DWORD PTR [esi+300], 0 + lea ebx, [edx+edx*4] + mov DWORD PTR [esi+308], 0 + mul edi + mov DWORD PTR [esi+316], 0 + add edx, ebx + add eax, DWORD PTR [esp+48] + adc edx, DWORD PTR [esp+52] + mov ebx, eax + shrd eax, edx, 26 + and ebx, 67108863 + shr edx, 26 + add eax, DWORD PTR [esp+40] + adc edx, DWORD PTR [esp+44] + mov DWORD PTR [esi+288], eax + mov eax, DWORD PTR [esp+32] + mov DWORD PTR [esi+280], ebx + and eax, 67108863 + mov DWORD PTR [esi+292], edx + mov DWORD PTR [esi+296], eax + mov eax, DWORD PTR [esp+24] + and eax, 67108863 + mov DWORD PTR [esi+304], eax + mov eax, DWORD PTR [esp+56] + and eax, 67108863 + mov DWORD PTR [esi+312], eax + {$IFDEF AVXSUP}vzeroupper {$ELSE}db $C5,$F8,$77;{$ENDIF} + lea esp, [ebp-12] + pop ebx + pop esi + pop edi + pop ebp +end; + + +{$ENDIF} + +{$IFDEF X64ASM} + +procedure StoreXMM( pXMM : PUInt64 ); register; {$IFDEF FPC} assembler; {$ENDIF} +asm + {$IFDEF AVXSUP}vmovaps [rcx], xmm6; {$ELSE}db $C5,$F8,$29,$31;{$ENDIF} + {$IFDEF AVXSUP}vmovaps [rcx + 16], xmm7; {$ELSE}db $C5,$F8,$29,$79,$10;{$ENDIF} +end; + +procedure RestoreXMM( pXMM : PUint64 ); register; {$IFDEF FPC} assembler; {$ENDIF} +asm + {$IFDEF AVXSUP}vmovntdqa xmm6, [rcx]; {$ELSE}db $C4,$E2,$79,$2A,$31;{$ENDIF} + {$IFDEF AVXSUP}vmovntdqa xmm7, [rcx + 16]; {$ELSE}db $C4,$E2,$79,$2A,$79,$10;{$ENDIF} +end; + +procedure poly1305_block_avx2_ctx(ctx : TPoly1305.PPoly1305CTX; t : TPoly1305.PStateAVXArr); {$IFDEF FPC} assembler; {$ENDIF} +asm + {$IFDEF UNIX} + // Linux uses a diffrent ABI -> copy over the registers so they meet with winABI + // (note that the 5th and 6th parameter are are on the stack) + // The parameters are passed in the following order: + // RDI, RSI, RDX, RCX -> mov to RCX, RDX, R8, R9 + mov rcx, rdi; + mov rdx, rsi; + {$ENDIF} + + // H = h + t + {$IFDEF AVXSUP}vmovdqu ymm0, [rdx] {$ELSE}db $C5,$FE,$6F,$02;{$ENDIF} // load t[0..3] + mov rax, rcx + mov rcx, [rdx + 32] // load t[4] + {$IFDEF AVXSUP}vpaddq ymm0, ymm0, [rax + 280] {$ELSE}db $C5,$FD,$D4,$80,$18,$01,$00,$00;{$ENDIF} // load h[0..3] + mov r8, [rax + 240] + + // calc c0 to c4 + {$IFDEF AVXSUP}vpmuludq ymm1, ymm0, [rax + 80] {$ELSE}db $C5,$FD,$F4,$48,$50;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm2, xmm1 {$ELSE}db $C5,$F9,$6F,$D1;{$ENDIF} + {$IFDEF AVXSUP}vextracti128 xmm1, ymm1, $1 {$ELSE}db $C4,$E3,$7D,$39,$C9,$01;{$ENDIF} + add rcx, [rax + 312] + {$IFDEF AVXSUP}vpmuludq ymm3, ymm0, [rax + 112] {$ELSE}db $C5,$FD,$F4,$58,$70;{$ENDIF} + mov r11, [rax + 256] + imul r8, rcx + {$IFDEF AVXSUP}vpaddq xmm1, xmm1, xmm2 {$ELSE}db $C5,$F1,$D4,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpsrldq xmm2, xmm1, 8 {$ELSE}db $C5,$E9,$73,$D9,$08;{$ENDIF} + imul r11, rcx + {$IFDEF AVXSUP}vpaddq xmm1, xmm1, xmm2 {$ELSE}db $C5,$F1,$D4,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpmuludq ymm2, ymm0, [rax + 144] {$ELSE}db $C5,$FD,$F4,$90,$90,$00,$00,$00;{$ENDIF} + {$IFDEF AVXSUP}vmovq rdx, xmm1 {$ELSE}db $C4,$E1,$F9,$7E,$CA;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm1, xmm3 {$ELSE}db $C5,$F9,$6F,$CB;{$ENDIF} + {$IFDEF AVXSUP}vextracti128 xmm3, ymm3, $1 {$ELSE}db $C4,$E3,$7D,$39,$DB,$01;{$ENDIF} + add rdx, r8 + mov r8, [rax + 248] + {$IFDEF AVXSUP}vpaddq xmm3, xmm3, xmm1 {$ELSE}db $C5,$E1,$D4,$D9;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm1, xmm2 {$ELSE}db $C5,$F9,$6F,$CA;{$ENDIF} + {$IFDEF AVXSUP}vpsrldq xmm7, xmm3, 8 {$ELSE}db $C5,$C1,$73,$DB,$08;{$ENDIF} + {$IFDEF AVXSUP}vextracti128 xmm2, ymm2, $1 {$ELSE}db $C4,$E3,$7D,$39,$D2,$01;{$ENDIF} + mov r9, rdx + shr rdx, 26 + imul r8, rcx + {$IFDEF AVXSUP}vpaddq xmm3, xmm3, xmm7 {$ELSE}db $C5,$E1,$D4,$DF;{$ENDIF} + and r9d, 67108863 + {$IFDEF AVXSUP}vpaddq xmm2, xmm2, xmm1 {$ELSE}db $C5,$E9,$D4,$D1;{$ENDIF} + {$IFDEF AVXSUP}vmovq r10, xmm3 {$ELSE}db $C4,$C1,$F9,$7E,$DA;{$ENDIF} + {$IFDEF AVXSUP}vpmuludq ymm1, ymm0, [rax + 176] {$ELSE}db $C5,$FD,$F4,$88,$B0,$00,$00,$00;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm4, xmm1 {$ELSE}db $C5,$F9,$6F,$E1;{$ENDIF} + {$IFDEF AVXSUP}vpsrldq xmm6, xmm2, 8 {$ELSE}db $C5,$C9,$73,$DA,$08;{$ENDIF} + {$IFDEF AVXSUP}vextracti128 xmm1, ymm1, $1 {$ELSE}db $C4,$E3,$7D,$39,$C9,$01;{$ENDIF} + {$IFDEF AVXSUP}vpmuludq ymm0, ymm0, [rax + 208] {$ELSE}db $C5,$FD,$F4,$80,$D0,$00,$00,$00;{$ENDIF} + add r8, r10 + {$IFDEF AVXSUP}vpaddq xmm2, xmm2, xmm6 {$ELSE}db $C5,$E9,$D4,$D6;{$ENDIF} + {$IFDEF AVXSUP}vpaddq xmm1, xmm1, xmm4 {$ELSE}db $C5,$F1,$D4,$CC;{$ENDIF} + add r8, rdx + {$IFDEF AVXSUP}vmovq rdx, xmm2 {$ELSE}db $C4,$E1,$F9,$7E,$D2;{$ENDIF} + {$IFDEF AVXSUP}vmovdqa xmm4, xmm0 {$ELSE}db $C5,$F9,$6F,$E0;{$ENDIF} + add rdx, r11 + mov r11, [rax + 264] + mov r10, r8 + + // carry chain 26-bit, reduction mod 2^130-5 + // + write back to h + {$IFDEF AVXSUP}vextracti128 xmm0, ymm0, $1 {$ELSE}db $C4,$E3,$7D,$39,$C0,$01;{$ENDIF} + {$IFDEF AVXSUP}vpsrldq xmm5, xmm1, 8 {$ELSE}db $C5,$D1,$73,$D9,$08;{$ENDIF} + shr r8, 26 + {$IFDEF AVXSUP}vpaddq xmm0, xmm0, xmm4 {$ELSE}db $C5,$F9,$D4,$C4;{$ENDIF} + and r10d, 67108863 + imul r11, rcx + {$IFDEF AVXSUP}vpaddq xmm1, xmm1, xmm5 {$ELSE}db $C5,$F1,$D4,$CD;{$ENDIF} + {$IFDEF AVXSUP}vpsrldq xmm4, xmm0, 8 {$ELSE}db $C5,$D9,$73,$D8,$08;{$ENDIF} + add r8, rdx + {$IFDEF AVXSUP}vmovq rdx, xmm1 {$ELSE}db $C4,$E1,$F9,$7E,$CA;{$ENDIF} + imul rcx, [rax + 272] + {$IFDEF AVXSUP}vpaddq xmm0, xmm0, xmm4 {$ELSE}db $C5,$F9,$D4,$C4;{$ENDIF} + add rdx, r11 + mov r11, r8 + and r8d, 67108863 + shr r11, 26 + mov [rax + 296], r8 + add r11, rdx + {$IFDEF AVXSUP}vmovq rdx, xmm0 {$ELSE}db $C4,$E1,$F9,$7E,$C2;{$ENDIF} + add rcx, rdx + mov rdx, r11 + shr rdx, 26 + add rcx, rdx + mov rdx, rcx + and ecx, 67108863 + shr rdx, 26 + mov [rax + 312], rcx + lea rdx, [rdx + rdx*4] + add rdx, r9 + mov r9, rdx + shr rdx, 26 + add rdx, r10 + and r9d, 67108863 + mov [rax + 288], rdx + mov rdx, r11 + and edx, 67108863 + mov [rax + 280], r9 + mov [rax + 304], rdx + + {$IFDEF AVXSUP}vzeroupper {$ELSE}db $C5,$F8,$77;{$ENDIF} +end; + +{$ENDIF} + + +{$ENDIF} + +// ########################################### +// #### Poly1305 +// ########################################### + { TPoly1305 } @@ -217,12 +714,29 @@ constructor TPoly1305.Create; 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; + fAVXCtx := AlignPtr64(@fPoly1305State[0]); + FH := @fAVXCtx^.h[0]; + FR := @fAVXCtx^.r[0]; + + inc(fAVXCtx); + fXMMMem := PUInt64(fAVXCtx); + dec(fAVXCtx); + + case CpuMode of + pmPas: begin + fPadAndFinalizeFunc := PadAndFinalizePAS; + fPolyBlkFunc := UpdatePoly; + end; + pmAVX: begin + {$IFNDEF PUREPASCAL} + fPadAndFinalizeFunc := PadAndFinalizeAVX; + fPolyBlkFunc := UpdatePolyAVX; + {$ELSE} + fPadAndFinalizeFunc := PadAndFinalizePAS; + fPolyBlkFunc := UpdatePoly; + {$ENDIF} + end; + end; fPolyBlockSize := POLY1305_BLOCK_SIZE; end; @@ -251,6 +765,43 @@ procedure TPoly1305.Finalize; FillChar(mac, sizeof(mac), 0); end; +{$IFNDEF PUREPASCAL} + +procedure TPoly1305.FinalizeAVX; +var mac : TBlock16Byte; + t : TStateAVXArr; +begin + if fNum > 0 then + begin + fData[fNum] := 1; // padbit.. + inc(fNum); + while fNum < Length(fData) do + begin + fData[fNum] := 0; + inc(fNum); + end; + + Split26(PUint64(@fData[0])^, PUint64(@fData[8])^, @t[0]); + {$IFDEF x64} + StoreXMM(fXMMMem) + {$ENDIF} + poly1305_block_avx2_ctx(fAVXCtx, @t[0]); + {$IFDEF x64} + RestoreXMM(fXMMMem); + {$ENDIF} + fNum := 0; + end; + + FinalizePoly1305(fAVXCtx, @mac[0]); + + SetLength(FCalcAuthenticationTag, sizeof(mac)); + Move(mac, FCalcAuthenticationTag[0], sizeof(mac)); + + FillChar(mac, sizeof(mac), 0); +end; +{$ENDIF} + + procedure TPoly1305.Init(EncryptionMethod: TEncodeDecodeMethod; InitVector: TBytes); begin @@ -274,7 +825,7 @@ procedure TPoly1305.InitInternal(const InitVector: T32ByteArray); begin fPolyInitComplete := True; - FillChar(FH^, sizeof(FH^), 0); + FillChar(fAVXCtx^, sizeof(fAVXCtx^), 0); ///* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ // st->r[0] = U8TOU32(&key[0]) & 0x0fffffff; @@ -292,6 +843,11 @@ procedure TPoly1305.InitInternal(const InitVector: T32ByteArray); FNonce[2] := U8ToU32(@initVector[24]); FNonce[3] := U8ToU32(@initVector[28]); + // initialize avx members + {$IFNDEF PUREPASCAL} + if CpuMode = pmAVX then + InitPoly1305(fAVXCtx, @InitVector[0]); + {$ENDIF} fNum := 0; end; @@ -329,6 +885,48 @@ procedure TPoly1305.PadAndFinalizePAS( authLen, encDecBufLen : int64); Finalize; end; +{$IFNDEF PUREPASCAL} +procedure TPoly1305.PadAndFinalizeAVX( authLen, encDecBufLen : int64); +var lens : Array[0..1] of UInt64; + t : TStateAVXArr; +begin + // pad the last block with 0 + {$IFDEF x64} + StoreXMM(fXMMMem); + {$ENDIF} + if fNum > 0 then + begin + fData[fNum] := 0; + inc(fNum); + while fNum < Length(fData) do + begin + fData[fNum] := 0; + inc(fNum); + end; + + Split26(PUint64(@fData[0])^, PUint64(@fData[8])^, @t[0]); + t[4] := t[4] + cShl24; + + poly1305_block_avx2_ctx(fAVXCtx, @t[0]); + fNum := 0; + end; + + + // the last block contains the lenghts + lens[0] := authLen; + lens[1] := encDecBufLen; + Split26(lens[0], lens[1], @t[0]); + t[4] := t[4] + cShl24; + poly1305_block_avx2_ctx(fAVXCtx, @t[0]); + {$IFDEF x64} + RestoreXMM(fXMMMem); + {$ENDIF} + + FinalizeAVX; +end; +{$ENDIF} + + procedure TPoly1305.Poly1305Blocks(pData: PByteArray; size: integer; padBit: UInt32); var r0, r1, r2, r3 : UInt32; @@ -574,9 +1172,69 @@ procedure TPoly1305.UpdatePoly(pData: PByteArray; size: integer); fNum := rem; end; +{$IFNDEF PUREPASCAL} +procedure TPoly1305.UpdatePolyAVX(pData: PByteArray; size: integer); +var num : integer; + rem : integer; + t : TStateAVXArr; +begin + num := fNum; + + {$IFDEF x64} + StoreXMM(fXMMMem); + {$ENDIF} + + if num <> 0 then + begin + rem := POLY1305_BLOCK_SIZE - num; + if size >= rem then + begin + Move( pData^, fData[num], rem); + Split26(PUInt64(@fData[0])^, PUInt64(@fData[8])^, @t[0]); + t[4] := t[4] + cShl24; + poly1305_block_avx2_ctx(fAVXCtx, @t[0]); + + 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); + {$IFDEF x64} + RestoreXMM(fXMMMem); + {$endif} + + exit; + end; + end; + + while size >= POLY1305_BLOCK_SIZE do + begin + Split26(PUInt64(@pData^[0])^, PUInt64(@pData^[8])^, @t[0]); + t[4] := t[4] + cShl24; + + poly1305_block_avx2_ctx(fAVXCtx, @t[0]); + inc(PByte(pData), POLY1305_BLOCK_SIZE); + dec(size, POLY1305_BLOCK_SIZE); + end; + + {$IFDEF x64} + RestoreXMM(fXMMMem); + {$ENDIF} + + if size > 0 then + Move( pData^, fData[0], size ); + + fNum := size; +end; +{$ENDIF} + + procedure TPoly1305.UpdateWithEncDecBuf(buf: PUInt8Array; Size: Integer); begin - UpdatePoly(PByteArray(buf), size); + fPolyBlkFunc(PByteArray(buf), size); end; end. diff --git a/Source/DECCiphers.pas b/Source/DECCiphers.pas index 6237f0d0..481624d6 100644 --- a/Source/DECCiphers.pas +++ b/Source/DECCiphers.pas @@ -558,7 +558,7 @@ TCipher_ChaCha20 = class(TDECFormattedCipher) class function Context: TCipherContext; override; /// - /// Set to true if the routine shall use SSE instructinos to build the chacha matrix + /// Defines either pure pascal code is used or specialized assembler routines for SSE, AVX /// class var CpuMode : TChaChaCpuMode; end; diff --git a/Unit Tests/Tests/TestDECChaChaPoly1305.pas b/Unit Tests/Tests/TestDECChaChaPoly1305.pas index f3e7c1dc..27d6c985 100644 --- a/Unit Tests/Tests/TestDECChaChaPoly1305.pas +++ b/Unit Tests/Tests/TestDECChaChaPoly1305.pas @@ -47,8 +47,10 @@ TTestEnumerator = class(TEnumerable) procedure TestChaCha20_Poly1305_KeySetup; procedure TestChaCha20_Poly1305_AEAD; procedure TestChaChaEncodeDecodeSpeed; + procedure TestChaChaPoly1305EncodeDecodeSpeed; procedure TestXChaCha_Poly1305_AEAD; + // test suite code procedure TestEncode; procedure TestDecode; @@ -56,7 +58,7 @@ TTestEnumerator = class(TEnumerable) implementation uses DECCipherModesPoly1305, System.Diagnostics, classes, DECFormat, DECTypes, - System.JSON.Readers; + System.JSON.Readers; // ########################################### @@ -187,6 +189,117 @@ procedure EncodeBuf( var dest : TBytes ); end; end; +procedure TestChaCha20Poly1305.TestChaChaPoly1305EncodeDecodeSpeed; +var startStop : TStopWatch; + encBuf : TBytes; + decBuf_pas, decBuf_SSe, decBuf_AVX, testDecode : TBytes; + i : Integer; + chaCha : TCipher_ChaCha20; + cpuMode : TChaChaCpuMode; + polyCPUMode : TPoly1305CpuMode; + tags : Array[pmPas..pmAVX] of TBytes; + +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]; + +function EncodeBuf( var dest : TBytes ) : TBytes; +var i : integer; +begin + for i := 0 to 3 do + begin + chaCha := TCipher_ChaCha20.Create; + try + chaCha.Mode := cmPoly1305; + chaCha.Init(cKey, cNonce); + + dest := chaCha.EncodeBytes(encBuf); + chaCha.Done; + + Result := chaCha.CalculatedAuthenticationResult; + finally + chaCha.Free; + end; + end; + +end; + +var tag : TBytes; + +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 + for polyCPUMode in [pmPas, pmAVX] do + begin + TPoly1305.CpuMode := polyCPUMode; + + case polyCPUMode of + pmPas: Status('POLY1305 Pascal mode'); + pmAVX: Status('POLY1305 AVX mode'); + end; + + // + TCipher_ChaCha20.CpuMode := cmPas; + startStop.Reset; + startStop.Start; + tags[polyCPUMode] := EncodeBuf( decbuf_pas ); + startStop.Stop; + Status( Format( 'Pas Encoding took %dms', [startStop.ElapsedMilliseconds])); + + TCipher_ChaCha20.CpuMode := cmSSE; + startStop.Reset; + startStop.Start; + tag := EncodeBuf( decbuf_sse ); + startStop.Stop; + Status( Format( 'SSE Encoding took %dms', [startStop.ElapsedMilliseconds])); + + Check(CompareMem( @tag[0], @tags[polyCPUMode][0], Length(tag)), 'Tag calculation failed'); + + TCipher_ChaCha20.CpuMode := cmAVX; + startStop.Reset; + startStop.Start; + tag := EncodeBuf( decbuf_avx ); + startStop.Stop; + Status( Format( 'AVX Encoding took %dms', [startStop.ElapsedMilliseconds])); + Check(CompareMem( @tag[0], @tags[polyCPUMode][0], Length(tag)), 'Tag calculation failed'); + + 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'); + end; + + Check(CompareMem( @tags[pmAVX][0], @tags[pmPas][0], Length(tags[pmPas])), 'AVX, PAS Tag calculation failed'); + + // test decode + for cpuMode in [cmPas, cmSSE, cmAVX] do + begin + TCipher_ChaCha20.CpuMode := cpuMode; + chaCha := TCipher_ChaCha20.Create; + try + chaCha.Mode := cmPoly1305; + chaCha.Init(cKey, cNonce); + + testDecode := chaCha.DecodeBytes(decbuf_sse); + chaCha.Done; + finally + chaCha.Free; + end; + + Check( CompareMem( @encBuf[0], @testDecode[0], Length(testDecode)), 'Decoding failed'); + end; +end; + procedure TestChaCha20Poly1305.TestDecode; var aTest : TJsonTestCase; chacha : TCipher_ChaCha20; @@ -322,6 +435,7 @@ procedure InvData( data : PByte; len : integer ); Move(cMsg1[0], msg[0], Length(msg)); //InvData( @msg[0], Length(msg)); + TPOly1305.CpuMode := pmPas; poly := TPoly1305.Create; try THackPly1305(poly).InitInternal(iv); @@ -358,6 +472,31 @@ procedure InvData( data : PByte; len : integer ); Check(Length(cTag) = Length(calcTag), 'MAC length is wrong'); Check( CompareMem(@cTag[0], @calcTag[0], Length(calcTag)), 'Polynom calculated tag does not match'); + + // ########################################### + // #### third 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)); + + TPoly1305.CpuMode := pmAVX; + poly := TPoly1305.Create; + try + THackPly1305(poly).InitInternal(iv); + THackPly1305(poly).UpdatePolyAVX(@msg[0], Length(msg)); + THackPly1305(poly).FinalizeAVX; + + calcTag := poly.CalculatedAuthenticationTag; + finally + poly.Free; + TPoly1305.CpuMode := pmPas; + 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; @@ -401,6 +540,12 @@ procedure TestChaCha20Poly1305.TestXChaCha_Poly1305_AEAD; begin TCipher_XChaCha20.CpuMode := cpuMode; + if cpuMode = cmPas + then + TPoly1305.CpuMode := pmPas + else + TPoly1305.CpuMode := pmAVX; + SetLength(msg, Length(cMsg)); Move( cMsg[1], msg[0], Length(msg)); @@ -445,6 +590,8 @@ procedure TestChaCha20Poly1305.TestXChaCha_Poly1305_AEAD; Check( Length(cTag) = Length(decodeTag), 'Tag length is wrong'); Check( CompareMem( @decodeTag[0], @cTag[0], Length(cTag)), 'Calculated Tag is wrong'); end; + + TPoly1305.CpuMode := pmPas end; @@ -486,6 +633,11 @@ procedure TestChaCha20Poly1305.TestChaCha20_Poly1305_AEAD; for cpuMode in [cmPas, cmSSE, cmAVX] do begin TCipher_ChaCha20.CpuMode := cpuMode; + if cpuMode = cmPas + then + TPoly1305.CpuMode := pmPas + else + TPoly1305.CpuMode := pmAVX; SetLength(msg, Length(cMsg)); Move( cMsg[1], msg[0], Length(msg)); From d6eb393cfa23b201c51d1a20588dcffb2ffe4844 Mon Sep 17 00:00:00 2001 From: Michael Rabatscher Date: Tue, 27 Jan 2026 22:28:58 +0100 Subject: [PATCH 12/12] Preinitialization of the supported assembler instruction set for Poly1305 - the current available CPU is queried and the best mode is selected --- Source/DECCipherModesPoly1305.pas | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Source/DECCipherModesPoly1305.pas b/Source/DECCipherModesPoly1305.pas index ba94deab..13a8086d 100644 --- a/Source/DECCipherModesPoly1305.pas +++ b/Source/DECCipherModesPoly1305.pas @@ -179,7 +179,9 @@ TPoly1305 = class(TAuthenticatedCipherModesBase) implementation -{$R-}{$Q-} +{$R-} + +uses DECCPUSupport;{$Q-} const cMask26 : uint64 = $3ffffff; cShl24 : uint64 = $1000000; @@ -1237,4 +1239,11 @@ procedure TPoly1305.UpdateWithEncDecBuf(buf: PUInt8Array; Size: Integer); fPolyBlkFunc(PByteArray(buf), size); end; +initialization + if TDEC_CPUSupport.AVX2 + then + TPoly1305.CpuMode := pmAVX + else + TPoly1305.CpuMode := pmPas; + end.