0,0 → 1,274 |
; Implementation of AES crypto algorithm. |
; Buffer size is 0x10 bytes (128 bits), key size is not fixed. |
; Written by diamond in 2007. |
uglobal |
aes.pow_table rb 256 ; pow[a] = 3^a |
aes.log_table rb 256 ; log[3^a] = a |
aes.sbox rb 256 ; ShiftBytes(a) |
aes.sbox_rev rb 256 ; ShiftBytes^{-1}(a) |
aes.mctable rd 256 ; MixColumns(ShiftBytes(a,0,0,0)) |
aes.mcrtable rd 256 ; MixColumns^{-1}(a,0,0,0) |
endg |
|
init_aes: |
; Byte values in SubBytes transform are interpreted as items of |
; GF(2^8) \cong F_2[x]/(x^8+x^4+x^3+x+1)F_2[x]. |
; x+1 is primitive item in this field. |
xor ebx, ebx |
push 1 |
pop eax |
.1: |
mov [aes.pow_table+ebx], al |
mov [aes.log_table+eax], bl |
; Multiplication by x+1... |
mov cl, al ; save value |
; ...multiply by x with mod (x^8+x^4+x^3+x+1) = 0x11B... |
add al, al |
jnc @f |
xor al, 0x1B |
@@: |
; ...and add operand |
xor al, cl |
inc bl |
jnz .1 |
; generate table for SubBytes transform |
mov [aes.sbox+0], 0x63 |
mov [aes.sbox_rev+0x63], bl |
inc ebx |
.2: |
; calculate inverse in GF(2^8) |
mov al, [aes.log_table+ebx] |
xor al, 0xFF ; equivalent to "al = 0xFF - al" |
mov cl, [aes.pow_table+eax] |
; linear transform of byte as vector over F_2 |
mov al, cl |
rol cl, 1 |
xor al, cl |
rol cl, 1 |
xor al, cl |
rol cl, 1 |
xor al, cl |
rol cl, 1 |
xor al, cl |
xor al, 0x63 |
mov [aes.sbox+ebx], al |
mov [aes.sbox_rev+eax], bl |
inc bl |
jnz .2 |
; generate table for SubBytes + MixColumn transforms |
.3: |
mov al, [aes.sbox+ebx] ; SubBytes transform |
mov cl, al |
add cl, cl |
jnc @f |
xor cl, 0x1B |
@@: |
mov byte [aes.mctable+ebx*4], cl ; low byte of MixColumn(a,0,0,0) |
mov byte [aes.mctable+ebx*4+1], al |
mov byte [aes.mctable+ebx*4+2], al |
xor cl, al |
mov byte [aes.mctable+ebx*4+3], cl ; high byte of MixColumn(a,0,0,0) |
inc bl |
jnz .3 |
; generate table for reverse MixColumn transform |
mov dword [aes.mcrtable+0], ebx |
inc ebx |
.4: |
; log_table[9]=0xC7, log_table[0xB]=0x68, log_table[0xD]=0xEE, log_table[0xE]=0xDF |
mov cl, [aes.log_table+ebx] |
mov al, cl |
add al, 0xDF |
adc al, 0 |
mov al, [aes.pow_table+eax] |
mov byte [aes.mcrtable+ebx*4], al |
mov al, cl |
add al, 0xC7 |
adc al, 0 |
mov al, [aes.pow_table+eax] |
mov byte [aes.mcrtable+ebx*4+1], al |
mov al, cl |
add al, 0xEE |
adc al, 0 |
mov al, [aes.pow_table+eax] |
mov byte [aes.mcrtable+ebx*4+2], al |
mov al, cl |
add al, 0x68 |
adc al, 0 |
mov al, [aes.pow_table+eax] |
mov byte [aes.mcrtable+ebx*4+3], al |
inc bl |
jnz .4 |
ret |
|
aes_setkey: |
; in: esi->key, edx=key size in dwords, edi->AES data struc |
lea eax, [edx+6] ; calc number of rounds (buffer size=4) |
stosd |
shl eax, 4 |
lea ebx, [edi+eax+16] |
mov ecx, edx |
rep movsd |
push ebx |
mov bl, 1 |
.0: |
push 4 |
pop ecx |
@@: |
movzx esi, byte [edi-5+ecx] |
mov al, [aes.sbox+esi] |
rol eax, 8 |
loop @b |
ror eax, 16 |
mov esi, edx |
neg esi |
xor eax, [edi+esi*4] |
xor al, bl |
add bl, bl |
jnc @f |
xor bl, 0x1B |
@@: |
stosd |
lea ecx, [edx-1] |
.1: |
cmp edi, [esp] |
jz .ret |
cmp edx, 8 |
jnz @f |
cmp ecx, 4 |
jnz @f |
push eax |
movzx eax, al |
mov al, [aes.sbox+eax] |
mov [esp], al |
mov al, byte [esp+1] |
mov al, [aes.sbox+eax] |
mov [esp+1], al |
mov al, byte [esp+2] |
mov al, [aes.sbox+eax] |
mov [esp+2], al |
mov al, byte [esp+3] |
mov al, [aes.sbox+eax] |
mov [esp+3], al |
pop eax |
@@: |
xor eax, [edi+esi*4] |
stosd |
loop .1 |
cmp edi, [esp] |
jnz .0 |
.ret: |
pop eax |
ret |
|
aes_decode: |
; in: esi->in, ebx->out, edi->AES state |
push ebx ebp |
push dword [esi+12] |
push dword [esi+8] |
push dword [esi+4] |
push dword [esi] |
mov esi, esp |
; reverse final round |
mov ebp, [edi] ; number of rounds |
mov ecx, ebp |
shl ecx, 4 |
lea edi, [edi+ecx+4] ; edi->last round key |
; load buffer into registers |
mov eax, [esi] |
mov ebx, [esi+4] |
mov ecx, [esi+8] |
mov edx, [esi+12] |
; (AddRoundKey) |
xor eax, [edi] |
xor ebx, [edi+4] |
xor ecx, [edi+8] |
xor edx, [edi+12] |
; (ShiftRows) |
.loop0: |
xchg ch, dh |
xchg bh, ch |
xchg ah, bh |
rol eax, 16 |
rol ebx, 16 |
rol ecx, 16 |
rol edx, 16 |
xchg al, cl |
xchg bl, dl |
xchg ah, bh |
xchg bh, ch |
xchg ch, dh |
rol eax, 16 |
rol ebx, 16 |
rol ecx, 16 |
rol edx, 16 |
; (SubBytes) |
mov [esi], eax |
mov [esi+4], ebx |
mov [esi+8], ecx |
mov [esi+12], edx |
mov ecx, 16 |
@@: |
movzx eax, byte [esi] |
mov al, [aes.sbox_rev+eax] |
mov byte [esi], al |
add esi, 1 |
sub ecx, 1 |
jnz @b |
sub esi, 16 |
sub edi, 16 |
; reverse normal rounds |
sub ebp, 1 |
jz .done |
mov eax, [esi] |
mov ebx, [esi+4] |
mov ecx, [esi+8] |
mov edx, [esi+12] |
push esi edi |
; (AddRoundKey) |
xor eax, [edi] |
xor ebx, [edi+4] |
xor ecx, [edi+8] |
xor edx, [edi+12] |
; (MixColumns) |
macro mix_reg reg { |
movzx esi, reg#l |
mov edi, [aes.mcrtable+esi*4] |
movzx esi, reg#h |
rol e#reg#x, 16 |
mov esi, [aes.mcrtable+esi*4] |
rol esi, 8 |
xor edi, esi |
movzx esi, reg#l |
mov esi, [aes.mcrtable+esi*4] |
rol esi, 16 |
xor edi, esi |
movzx esi, reg#h |
mov esi, [aes.mcrtable+esi*4] |
ror esi, 8 |
xor edi, esi |
mov e#reg#x, edi |
} |
mix_reg a |
mix_reg b |
mix_reg c |
mix_reg d |
purge mix_reg |
pop edi esi |
jmp .loop0 |
.done: |
; (AddRoundKey) |
mov esi, [esp+20] |
pop eax |
xor eax, [edi] |
mov [esi], eax |
pop eax |
xor eax, [edi+4] |
mov [esi+4], eax |
pop eax |
xor eax, [edi+8] |
mov [esi+8], eax |
pop eax |
xor eax, [edi+12] |
mov [esi+12], eax |
pop ebp ebx |
ret |