BSOne.SFC/Tocsg.Lib/VCL/EncLib/AES/aes_cprf.pas

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.