138 lines
4.9 KiB
Plaintext
138 lines
4.9 KiB
Plaintext
unit aes_cprf;
|
|
|
|
{Variable-length key AES CMAC Pseudo-Random Function-128}
|
|
|
|
{$i STD.INC}
|
|
|
|
interface
|
|
|
|
uses
|
|
AES_Type, AES_OMAC;
|
|
|
|
|
|
(*************************************************************************
|
|
|
|
DESCRIPTION : Variable-length key AES CMAC Pseudo-Random Function-128
|
|
|
|
REQUIREMENTS : TP5-7, D1-D7/D9-D10, FPC, VP
|
|
|
|
EXTERNAL DATA : ---
|
|
|
|
MEMORY USAGE : ---
|
|
|
|
DISPLAY MODE : ---
|
|
|
|
REFERENCES : [1] RFC 4615: The Advanced Encryption Standard-Cipher-based
|
|
Message Authentication Code-Pseudo-Random Function-128
|
|
(AES-CMAC-PRF-128) Algorithm for the Internet Key
|
|
Exchange Protocol (IKE)
|
|
|
|
|
|
Version Date Author Modification
|
|
------- -------- ------- ------------------------------------------
|
|
0.10 28.05.07 W.Ehrhardt Initial version
|
|
0.11 28.05.07 we function returns OMAC results
|
|
0.12 16.06.07 we AES_CPRF128_selftest stdcall
|
|
**************************************************************************)
|
|
|
|
|
|
(*-------------------------------------------------------------------------
|
|
(C) Copyright 2007 Wolfgang Ehrhardt
|
|
|
|
This software is provided 'as-is', without any express or implied warranty.
|
|
In no event will the authors be held liable for any damages arising from
|
|
the use of this software.
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
including commercial applications, and to alter it and redistribute it
|
|
freely, subject to the following restrictions:
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
claim that you wrote the original software. If you use this software in
|
|
a product, an acknowledgment in the product documentation would be
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
----------------------------------------------------------------------------*)
|
|
|
|
|
|
function AES_CPRF128({$ifdef CONST} const Key {$else} var Key {$endif}; KeyBytes: word;
|
|
msg: pointer; msglen: longint; var PRV: TAESBlock): integer;
|
|
{Calculate variable-length key AES CMAC Pseudo-Random Function-128 for msg}
|
|
{returns AES_OMAC error and 128-bit pseudo-random value PRV}
|
|
{$ifdef DLL} stdcall; {$endif}
|
|
|
|
function AES_CPRF128_selftest: boolean;
|
|
{-Selftest with RFC 4615 test vectors}
|
|
{$ifdef DLL} stdcall; {$endif}
|
|
|
|
|
|
implementation
|
|
|
|
|
|
{---------------------------------------------------------------------------}
|
|
function AES_CPRF128({$ifdef CONST} const Key {$else} var Key {$endif}; KeyBytes: word;
|
|
msg: pointer; msglen: longint; var PRV: TAESBlock): integer;
|
|
{Calculate variable-length key AES CMAC Pseudo-Random Function-128 for msg}
|
|
{returns AES_OMAC error and 128-bit pseudo-random value PRV}
|
|
var
|
|
LK: TAESBlock; {local 128 bit key}
|
|
ctx: TAESContext;
|
|
err: integer;
|
|
const
|
|
ZB: TAESBlock = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
|
|
begin
|
|
if KeyBytes=16 then begin
|
|
{If the key, is exactly 128 bits, then we use it as-is (copy to local)}
|
|
move(Key, LK, 16);
|
|
err := 0;
|
|
end
|
|
else begin
|
|
{If key length is not 128 bits, then we derive the local key LK by
|
|
applying the AES-CMAC algorithm using a 128-bit zero as the CMAC key
|
|
and Key as the input message: LK := AES-CMAC(0, Key, KeyBytes)}
|
|
err := AES_OMAC_Init(ZB, 128, ctx);
|
|
if err=0 then err := AES_OMAC_Update(@Key, KeyBytes, ctx);
|
|
if err=0 then AES_OMAC_Final(LK, ctx);
|
|
end;
|
|
{PRV := AES-CMAC(LK, msg, msglen)}
|
|
if err=0 then err := AES_OMAC_Init(LK, 128, ctx);
|
|
if err=0 then err := AES_OMAC_Update(msg, msglen, ctx);
|
|
if err=0 then AES_OMAC_Final(PRV, ctx);
|
|
AES_CPRF128 := err;
|
|
end;
|
|
|
|
|
|
{---------------------------------------------------------------------------}
|
|
function AES_CPRF128_selftest: boolean;
|
|
{-Selftest with RFC 4615 test vectors}
|
|
var
|
|
PRV: TAESBlock;
|
|
i,j: integer;
|
|
const
|
|
{Test vectors from RFC section 4, Message is fix}
|
|
msg: array[0..19] of byte = ($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,
|
|
$0a,$0b,$0c,$0d,$0e,$0f,$10,$11,$12,$13);
|
|
{Base key is fix, but test three diffenrent length >16, =16, <16}
|
|
key: array[0..17] of byte = ($00,$01,$02,$03,$04,$05,$06,$07,$08,$09,
|
|
$0a,$0b,$0c,$0d,$0e,$0f,$ed,$cb);
|
|
KL: array[1..3] of word =(18,16,10);
|
|
{PRF outputs}
|
|
PRA: array[1..3] of TAESBlock = (($84,$a3,$48,$a4,$a4,$5d,$23,$5b,$ab,$ff,$fc,$0d,$2b,$4d,$a0,$9a),
|
|
($98,$0a,$e8,$7b,$5f,$4c,$9c,$52,$14,$f5,$b6,$a8,$45,$5e,$4c,$2d),
|
|
($29,$0d,$9e,$11,$2e,$db,$09,$ee,$14,$1f,$cf,$64,$c0,$b7,$2f,$3d));
|
|
begin
|
|
AES_CPRF128_selftest := false;
|
|
for i:=1 to 3 do begin
|
|
if AES_CPRF128(Key, KL[i], @msg, sizeof(msg), PRV)<>0 then exit;
|
|
for j:=0 to 15 do if PRV[j]<>PRA[i][j] then exit;
|
|
end;
|
|
AES_CPRF128_selftest := true;
|
|
end;
|
|
|
|
|
|
end.
|