Home > Net >  DEC AES output does not match other library output
DEC AES output does not match other library output

Time:08-24

I got the task to encrypt a firmware file that is decrypted on a small device using AES. The firmware library comes with an AES framework, so I need to get that one in sync with my Delphi code....

To get the task done I used the DEC cipher suite which we also use for different purposes in the software... now the thing is that I cannot sync the output of the firmware tool set with DEC...

Here is the code I use:

program Project1;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,
  DECBaseClass,
  DECCipherBase,
  DECHash,
  DECCiphers,
  DECTypes,
  DECFormatBase,
  DECFormat;

type
  Binary = RawByteString;

var
  ACipherClass: TDECCipherClass = TCipher_AES;
  ACipherMode: TCipherMode = cmCBCx;
  ATextFormat: TDECFormatClass = TFormat_Mime64;

  InvertUINT32 : boolean = False;
  InvertText : boolean = False;

type
  //TMK6AESTextSize = Array[0..15] of UInt32;
  TMK6AESTextSize = Array[0..3] of UInt32;
  TMK6Key = Array[0..3] of UINT32;

const mk6Key : TMK6Key = ($1, $0, $0, $0);
      //mk6Key : TMK6Key = ($09CF4F3C, $ABF71588, $28AED2A6, $2B7E1516 );  // rotated
      //mk6IV : TMK6Key = ($00010203 , $04050607 , $08090A0B , $0C0D0E0F);
      mk6IV : TMK6Key = ($0 , $0 , $0 , $0);
      //mk6IV : TMK6Key = ($0C0D0E0F, $08090A0B, $04050607, $00010203);

//      mk6Plaintext : TMK6AESTextSize =
//                   ( $E2BEC16B ,$969F402E ,$117E3DE9 ,$2A179373 ,
//                     $578A2DAE ,$9CAC031E ,$AC6FB79E ,$518EAF45 ,
//                     $461CC830 ,$11E45CA3 ,$19C1FBE5 ,$EF520A1A ,
//                     $45249FF6 ,$179B4FDF ,$7B412BAD ,$10376CE6 );

//      mk6Plaintext : TMK6AESTextSize =
//                   ( $E2BEC16B ,$969F402E ,$117E3DE9 ,$2A179373 );

      //mk6Plaintext : TMK6AESTextSize =
      //             ( $2A179373, $117E3DE9, $969F402E, $E2BEC16B );
      mk6Plaintext : TMK6AESTextSize = ( $0, $0, $0, $0 );

type
  TUINT32Byte = Array[0..3] of Byte;
  PUINT32Byte = ^TUINT32Byte;

function InvUINT32( value : UINT32 ) : UINT32;
var v1, v2 : PUINT32Byte;
begin
     v1 := @value;
     v2 := @Result;

     v2^[3] := v1^[0];
     v2^[2] := v1^[1];
     v2^[1] := v1^[2];
     v2^[0] := v1^[3];
end;

function GenMK6Text( const txt : TMK6AESTextSize ) : TMK6AESTextSize;
var i : integer;
begin
     if InvertText then
     begin
          for i := 0 to High(txt) do
              Result[i] := InvUINT32(txt[i]);
     end
     else
         Result := txt;
end;

function GenMK6Key( const aKey : TMK6Key ) : TMK6Key;
var i : integer;
begin
     Result := aKey;

     if InvertUINT32 then
     begin
          for i := 0 to High(aKey) do
              Result[i] := InvUINT32(aKey[i]);
     end;
end;


function EncryptBin(const buf : TMK6AESTextSize): Binary;
var AData: Binary;
    cipher : TCipher_AES128; //AES
    aKey : TMK6Key;
    aIV : TMK6Key;
    aBuf : TMK6AESTextSize;
begin
     cipher := TCipher_AES128.Create;
     try
        cipher.Mode := ACipherMode;
        aKey := GenMK6Key(mk6Key);
        aIV := GenMK6Key(mk6IV);
        aBuf := GenMK6Text(buf);
        cipher.Init( aKey, sizeof(mk6key), aIV, sizeof(mk6IV) );

        SetLength(AData, sizeof(buf));
        cipher.Encode(aBuf, AData[1], Length(AData));

        Result := AData;
     finally
            cipher.Free;
     end;
end;

function DecryptBin(buf : Binary): TMK6AESTextSize;
var AData: Binary;
    //ACheck: Binary;
    //APass: Binary;
    ALen: Integer;
    ARes : Binary;
    cipher : TCipher_AES128; 
    aKey : TMK6Key;
    aIV : TMK6Key;
begin
     cipher := TCipher_AES128.Create;
     try
        //AData := ValidFormat(ATextFormat).Decode(AText);
        AData := buf;
        ALen := Length(AData); // - cipher.Context.BufferSize;
        //ALen := Length(AData); // - cipher.Context.BufferSize;
        //ACheck := System.Copy(Adata, ALen   1, cipher.Context.BufferSize);
        cipher.Mode := ACipherMode;
        aKey := GenMK6Key(mk6Key);
        aIV := GenMK6Key(mk6IV);
        cipher.Init(aKey, sizeof(mk6key), aIV, sizeof(mk6IV));
        SetLength(ARes, ALen);
        cipher.Decode(AData[1], ARes[1], ALen);
        //if ACheck <> cipher.CalcMAC then
//           raise Exception.Create('Invalid data');

        Assert(Length(ARes) >= sizeof(Result), 'WTF');
        Move(ARes[1], Result, sizeof(Result));
        Result := GenMK6Text(Result);
     finally
            cipher.Free;
     end;
end;

var binBuf : Binary;
    decBuf : TMK6AESTextSize;
    i : integer;
begin
  try
    binBuf := EncryptBin(mk6Plaintext);

    for i := 1 to Length(binBuf) do
    begin
         Write( IntToHex( Ord(binBuf[i]), 2 )   ' ' );
    end;

    Writeln;

    decBuf := DecryptBin(binBuf);

    for i := 0 to Length(decBuf) - 1 do
        Writeln( IntToHex( decBuf[i], 4 ) );

    readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

The output of the firmware tool is D5 AA 45 05 7C A9 A2 6D 43 D1 63 36 84 1C 3D 2A (which actually also is the output if I use this input on http://aes.online-domain-tools.com/ ) so I guess I miss something here....

Please note that if all input data (Key, IV data) is set to zero, I get the output 66 E9 4B D4 EF 8A 2C 3B 88 4C FA 59 CA 34 2B 2E which is close to the one I get from the other tool: D4 4B E9 66 3B 2C 8A EF 59 FA 4C 88 2E 2B 34 CA ... so basically only the UINT32 byte order is different.

The thing is that I cannot get any close if just one bit is different from 0 in the key vector (hence the one value of 1.) ... I tried various things... change the position of the "1", changed the lowest to the highest bit - nothing worked... What am I missing here?

CodePudding user response:

You are using older DEC library that was written to be compatible with Delphi 2009.

Instead of this version you should be using newer DEC library that is fully compatible with with newer Delphi versions including Delphi 11 that you are using.

Switching to newer version of DEC library should solve all of your problems.

  • Related