📄 phelix86.asm
字号:
;
;----------------------------------------------------------------
; Phelix encryption/authentication algorithm
; Author: Doug Whiting, Hifn. 2005.
;
; This source code is released to the public domain
;----------------------------------------------------------------
;
.386
.model flat,c ;C naming convention (underscore prefix)
.code
include strucmac.inc ;structured programming macros (_if/_else/_endif, etc)
page ,128 ;format things nicely in listing
;
PHELIX_INCREMENTAL_API equ 1 ;undef this to exclude incremental calls
;
;
; define a global label. Handle linking with and without underscore
C_global macro phelixName,ecryptName
ifdef MIX_ASM
public phelixName&_ASM
public _&phelixName&_ASM
phelixName&_ASM:
_&phelixName&_ASM:
else
public phelixName
public _&phelixName
ifdef ECRYPT_API
ifnb <ecryptName>
public ecryptName
public _&ecryptName
ecryptName:
_&ecryptName:
endif
endif
endif
phelixName:
_&phelixName:
endm
;
;
C_global _debugPhelix_ ;ignored here, but must be defined for testPhelix.c
dd 0
ifdef ??version ;Borland TASM32 pre-defined constant
%tabsize 4 ;format things pretty
AsmName db "TASM32 v"
db '0'+(??version/256),'.'
db '0'+(??version AND 0ffh)/16,'0'+(??version AND 0fh),0
else
AsmName db "MASM v"
db '0'+((@version/100) mod 10),'.'
db '0'+((@version/10 ) mod 10),'0'+(@version mod 10),0
endif
;
align 4
C_global PhelixCompiler_Name ;show who assembled us
lea eax,AsmName
ret
;
C_global PhelixInit,ECRYPT_init
ret
;
;----------------------------------------------------------------
; Macros and definitions
;----------------------------------------------------------------
;
; Phelix rotation constants
ROT_0a equ 9
ROT_1a equ 10
ROT_2a equ 17
ROT_3a equ 30
ROT_4a equ 13
;
ROT_0b equ 20
ROT_1b equ 11
ROT_2b equ 5
ROT_3b equ 15
ROT_4b equ 25
;
Z0 equ eax ;register assignments
Z1 equ ebx
Z2 equ ecx
Z3 equ edx
Z4 equ esi
t0 equ ebp ;"temp" scratch registers
t1 equ edi
oldZreg equ Z4
;
UNROLL_CNT equ 8 ;how many blocks to unroll in inner loop
ZERO_INIT_CNT equ 8 ;number of words of init
MAGIC_MAC_XOR equ 912d94f1h ;special constants
MAGIC_AAD_XOR equ 0aadaadaah
;
;
;----------------------------------------------------------------
; pseudo-instruction (assemble-time)
;----------------------------------------------------------------
;
_ASM_Assert macro cnd,msg
if (cnd)
;; all is well -- no error
else
ifb <msg>
.err "ASSERTION FAILURE: cnd"
else
.err "ASSERTION FAILURE: msg"
endif
endif
endm
;
_ASM_Assert <UNROLL_CNT eq (UNROLL_CNT and not (UNROLL_CNT-1))>,<Unroll count must be a power of 2>
;
;----------------------------------------------------------------
;
; Allocate and define local variables on the stack
; [Note: We use esp for locals, not ebp, since we need ebp as a variable.
; Thus, we can't use the assembler stack frame primitives.]
;
_maxPhelixStack_ = 0 ;max locals usage in bytes
_stack_offs = 0 ;current stack offset due to calls
_Phelix_LocalSize= 0 ;starting value: no locals allocated yet
;
_newLocal macro wCnt,lName ;macro to define a local variable
irp _offs_,<%_Phelix_LocalSize>
lName equ <dword ptr [esp + _offs_ + _stack_offs]>
lName&_Z4 equ <dword ptr [Z4 + _offs_ - _cpOfs_ ]>
endm
_Phelix_LocalSize = _Phelix_LocalSize + 4*(wCnt)
; keep running tabs on stack usage for locals
if _maxPhelixStack_ lt _Phelix_LocalSize
_maxPhelixStack_ = _Phelix_LocalSize
endif
endm
; now define local variables for the Encrypt/Decrypt functions
_newLocal 1,srcPtr ;pointer to input data buffer
_newLocal 1,dstPtr ;pointer to output data buffer
_newLocal 1,loopByteCnt ;inner loop byte counter
_newLocal 1,jmpTabPtr ;pointer to encrypt/decrypt jump table
_newLocal 8,X_i_0 ;local copy of the key values
_newLocal 8,X_i_1
_newLocal 4,oldZ ;"old" Z values
_newLocal 1,_i_ ;block number (+8)
_newLocal UNROLL_CNT ,exitTab;local jump table for exiting unrolled loop
_newLocal UNROLL_CNT+4,tmpBuf ;local buffer encryption/decryption blocks
_newLocal 1,aadLeft ;# bytes of aad remaining
_newLocal 1,msgLen0 ;initial value of src_ByteCnt
_newLocal 1,dstPtr0 ;initial dst pointer
_newLocal 1,retAddr ;local "return" address
;
;----------------------------------------------------------------
; Define caller's parameters on the stack, relative to esp
;
_cpOfs_ = 4+8*4+_Phelix_LocalSize ;caller parms offset from esp
_pOfs_ = _cpOfs_
;
_newParm macro _pp_
irp _offs_,<%_pOfs_>
_pp_ equ <dword ptr [esp + _offs_ + _stack_offs]>
_pp_&_Z4 equ <dword ptr [Z4 + _offs_ - _cpOfs_]> ;allow "short ofset" access via Z4
endm
_pOfs_ = _pOfs_+4
endm
;
irp _pp_,<ctxt_Ptr,nonce_Ptr,aad_Ptr,aad_Len,src_Ptr,dst_Ptr,src_ByteCnt,mac_Ptr>
_newParm _pp_
endm
;
callerParms equ <ctxt_Ptr>
;----------------------------------------------------------------
; Phelix context structure definition
pCtxt STRUCT
keySize dd ? ;size of raw key in bits
macSize dd ? ;size of mac tag in bits
X_1_Bump dd ? ;4*(keySize/8) + 256*(macSize mod 128)
X_0 dd 8 dup (?) ;subkeys
X_1 dd 8 dup (?) ;subkeys
; internal cipher state
old_Z dd 4 dup (?) ;previous Z[4] values for output
_Z_ dd 5 dup (?) ;5 internal state words
blkNum dd ? ;block number (i)
aadLen dd 2 dup (?) ;64-bit aadLen counter (LSW first)
msgLen dd ? ;32-bit msgLen counter (mod 2**32)
aadXor dd ? ;aad Xor constant
pCtxt ENDS
;
;----------------------------------------------------------------
;
_o_ macro op1,op2,op3,cond3 ;shorthand: instantiate 1-3 opcodes
op1
op2
ifb <cond3>
op3
elseif cond3
op3
endif
endm
;----------------------------------------------------------------
; adjust _stack_offs with push/pop operations
_push macro r0,r1,r2,r3,r4,r5,r6
irp _reg_,<r0,r1,r2,r3,r4,r5,r6>
ifnb <_reg_>
push _reg_
_stack_offs = _stack_offs + 4
endif
endm
endm
;
_pop macro r0,r1,r2,r3,r4,r5,r6
irp _reg_,<r0,r1,r2,r3,r4,r5,r6>
ifnb <_reg_>
pop _reg_
_stack_offs = _stack_offs - 4
endif
endm
endm
;
;----------------------------------------------------------------
; concatenate text together (useful in building names inside macros)
Concat macro aa,bb,cc,dd,ee,ff,gg,hh
aa&bb&cc&dd&ee&ff&gg&hh
endm
;
;----------------------------------------------------------------
; Init code, jump tables (for lblName = Encrypt/Decrypt)
;----------------------------------------------------------------
;
PhelixAlgo macro lblName
; first, set up the stack frame
pushad ;save all regs on stack
lea t0,lblName&_jmpTab ;handle the encrypt/decrypt difference
jmp Phelix_Main ;go run the algorithm
;
; the jump table for this operation
;
align 4
lblName&_jmpTab label dword
;first, a list of "block boundary" targets within unrolled processing loop
_blkNum_ = 0
rept UNROLL_CNT
Concat <dd offset &lblName&Blk_>,%_blkNum_
_blkNum_ = _blkNum_ + 1
endm
; next, successive "control" targets within Phelix_Main
irp _targetName_,<OddBytes>
Concat &_targetName_,<_OFFS = >,<($-lblName&_jmpTab)>
Concat <dd offset &lblName>,<_>,&_targetName_
endm
endm ;PhelixAlso
;
;----------------------------------------------------------------
; Common unrolled loop end code for encrypt/decrypt
;----------------------------------------------------------------
;
PhelixEndLoop macro CNT
add srcPtr ,(CNT)*4 ;bump the pointers
add dstPtr ,(CNT)*4
add _i_ ,(CNT) ;bump the count
sub loopByteCnt,(CNT)*4 ;are we done yet?
endm ;leave here with flags set for loop jmp
;
;----------------------------------------------------------------
; Common "early exit" code for encrypt/decrypt inner loop
;----------------------------------------------------------------
; This functionality is required for splicing AAD/text/padding
;
PhelixEarlyExit macro jTabReg,_bn_
if _bn_ lt (UNROLL_CNT-1) ;don't need early exit at bottom of loop
test jTabReg,jTabReg ;time to exit?
_if nz
mov oldZ[4*(_bn_ and 3)],oldZreg
jmp jTabReg ;go to "exit" address
;align 4 ;aligning -- doesn't seem to help!
_endif
endif
mov oldZ[4*(_bn_ and 3)],oldZreg
endm
;
;****************************************************************
; start of actual code (i.e., end of macro definitions)
;****************************************************************
;
align 4
INIT_ZEROES dd ZERO_INIT_CNT dup (0)
MASK_TAB dd 0,0ffh,0ffffh,0ffffffh
_PhelixCodeStart_:
;
;----------------------------------------------------------------
; Common control path for Encrypt/Decrypt
;----------------------------------------------------------------
; In: t0 --> (const) jump table (Encrypt_jmpTab or Decrypt_jmpTab)
; Out: everything done
;
Phelix_Main:
_stack_offs = -_Phelix_LocalSize ;stack frame not built yet
lea Z4,callerParms ;point to callers first parameter (save code size below)
sub esp,_Phelix_LocalSize ;make room for locals on stack
_stack_offs = 0 ;now at the "base" esp value
mov jmpTabPtr,t0 ;save jump table pointer
call InitNonce
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Finally ready to start running Phelix on some data
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; First, process the initialization zeroes (loopByteCnt == 0 from PhelixInit)
;
_ASM_Assert <UNROLL_CNT ge ZERO_INIT_CNT>
mov exitTab[4*(ZERO_INIT_CNT-1)],offset _ret_InitZeroDone
jmp EncryptBlk_0
;
; "local" function
_stack_offs = 4
InitNonce:
; first, init the local keys on the stack
mov t0,ctxt_Ptr_Z4 ;point to context structure
mov t1,[t0].pCtxt.X_1_Bump ;t1=4*(keySize/8)+256*(macSize mod 128)
mov Z3,nonce_Ptr_Z4 ;(const) pointer to nonce words
_push Z4 ;save Z4 (push/pop = smaller than lea Z4,callerParms)
xor Z4,Z4 ;use Z4 as the variable i in SetTwoKeys
inc Z4 ;start with i = 1, since t1 = X'_1 = 4*L(U) already
call SetTwoKeys ;set X_1_n, X_5_n, for n=0,1 [return w/t1 == 0]
call SetTwoKeys ;set X_2_n, X_6_n, for n=0,1
call SetTwoKeys ;set X_3_n, X_7_n, for n=0,1
xor Z4,Z4 ;wrap to i = 0
call SetTwoKeys ;set X_0_n, X_4_n, for n=0,1
_pop Z4 ;restore pointer to callerParms
;set up for initialization phase
xor Z2,Z2
lea t0,INIT_ZEROES ;use all zero input words, for i= -8 .. -1
lea t1,tmpBuf ;discard output
mov loopByteCnt,Z2 ;initialize loop byte count counter = 0
mov _i_,Z2 ;initialize i = 0 (block number + 8)
mov srcPtr,t0
mov dstPtr,t1
; now initialize the Zn register values
mov t0,ctxt_Ptr_Z4
mov t1,nonce_Ptr_Z4
irp zNum,<0,1,2,3,4>
mov Z&zNum,[t0+4*(3+zNum)].pCtxt.X_0
endm
irp zNum,<0,1,2,3>
xor Z&zNum,[t1+4*zNum]
endm
ret
_stack_offs = 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; done with the initial zeroes.
_ret_InitZeroDone:
if UNROLL_CNT gt ZERO_INIT_CNT ;do we need to clear out the return point?
xor t0,t0 ;(only if it's not already at the end)
mov exitTab[4*(ZERO_INIT_CNT-1)],t0
endif
;;;;;;;;;;;;;;;;;
; handle AAD here, looping if needed
xor Z1,MAGIC_AAD_XOR
mov t0,aad_Len
test t0,t0
_if nz,far ;if nothing there, skip all aad processing
mov t1,aad_Ptr
mov aadLeft,t0
mov srcPtr,t1 ;src will come from aad_Ptr
_aad_Loop: ;here with t0 == aad_Len
lea t1,tmpBuf ;always use tmpBuf for aad dst (discard)
mov dstPtr,t1
mov t0,aadLeft
sub t0,4*UNROLL_CNT ;only do one unrolled loop each time
_if ae ;(since we use tmpBuf to discard ciphertext)
mov aadLeft,t0
xor t1,t1
mov loopByteCnt,t1
mov exitTab[4*(UNROLL_CNT-1)],offset _aad_Loop
jmp EncryptBlk_0
_endif
; here to handle final partial loop
_aad_PartialLoop:
and t0,4*(UNROLL_CNT-1)
mov loopByteCnt,t0
cmp t0,4
_if ae
mov exitTab[t0-4],offset _ret_aad_1
jmp EncryptBlk_0
_ret_aad_1:
mov t0,loopByteCnt
xor t1,t1
mov exitTab[t0-4],t1 ;clear the entry
_endif
; here to handle final partial word of AAD
mov t0,aadLeft
mov t1,t0
and t1,3 ;any odd bytes?
_ifbrk z ;if not, we're done with AAD
add t0,4
and t0,4*(UNROLL_CNT-1)
mov loopByteCnt,t0
_push Z4
sub t0,4
and t0,4*(UNROLL_CNT-1)
mov Z4,srcPtr
mov Z4,[Z4+t0] ;get the last AAD word
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -