gutmann
98524d117798423f424537c2b1ebc560e2c7401ebf01c0fa1df76831c0c10687
From: pgut01@cs.auckland.ac.nz (Peter Gutmann)
Newsgroups: sci.crypt
Subject: Correction to RC4 asm code
Date: 18 Oct 1995 11:23:13 GMT
Organization: University of Auckland
Lines: 150
Sender: pgut01@cs.auckland.ac.nz (Peter Gutmann)
Message-ID: <462o31$4ui@net.auckland.ac.nz>
NNTP-Posting-Host: cs26.cs.auckland.ac.nz
X-Newsreader: NN version 6.5.0 #3 (NOV)
It has been pointed out to me that there's a problem in the 80x86 RC4 code I
posted a week or so back in that I forgot to store the in-register values of x
and y back to their in-memory locations (since I was using it as a one-shot
RNG I never noticed this). The following code contains two extra instructions
which update the in-memory values at the end of the encryption, I've reposted
the whole thing since it's fairly small.
Peter.
; Simple RC4 implementation, Peter Gutmann, 21 September 1995.
; This code was written in about 30 minutes as a testbed for an asm.RC4. It
; uses a static data area as the key so it's not terribly practical as it
; stands. In addition, the RC4 algorithm leads to an almost solid block of
; pipeline stalls on anything >= '486, so I wouldn't recommend using it on
; anything except perhaps 8-bit microcontrollers and smart cards.
INCLUDE MISC.INC
MODULE RC4
PUBLIC _rc4expandKey, _rc4crypt
DATA
; The RC4 keying information
rc4key DB 256 DUP (?)
rc4x DB 0
rc4y DB 0
CODE
; void rc4ExpandKey( unsigned char const *key, int keylen )
_rc4expandKey PROCEDURE
push bp
mov bp, sp
push si
push di ; Save register vars
les si, [bp+4] ; ES:SI = key
mov dx, [bp+8] ; DX = keylen
mov dh, dl ; keylenTmp = keylen
; rc4word y = 0;
xor ax, ax ; y = 0
sub di, di ; DI = AX as an index register
; for( x = 0; x < 256; x++ )
; rc4key[ x ] = x;
xor bx, bx ; x = 0
@@initLoop:
mov rc4key[bx], bl ; rc4key[ x ] = x
inc bl ; x++
jnz SHORT @@initLoop
; for( x = 0; x < 256; x++ )
; {
; sx = rc4key[ x ];
; y += sx + key[ keypos ];
; rc4key[ x ] = rc4key[ y ];
; rc4key[ y ] = sx;
;
; if( ++keypos == keylen )
; keypos = 0;
; }
@@keyLoop:
mov cl, rc4key[bx] ; sx = rc4key[ x ]
add al, es:[si] ; y += key[ keypos ]
add al, cl ; y += sx
mov di, ax
mov ch, rc4key[di] ; temp = rc4key[ y ]
mov rc4key[bx], ch ; rc4key[ x ] = temp
mov rc4key[di], cl ; rc4key[ y ] = sx
inc si ; ++keypos
dec dh ; keylenTmp--
jnz SHORT @@noResetKeypos ; if( !keylenTmp )
sub si, dx ; keypos = 0
mov dh, dl ; keylenTmp = keylen
@@noResetKeypos:
inc bl ; x++
jnz SHORT @@keyLoop
; rc4->x = rc4->y = 0;
mov rc4x, bl ; rc4->x = 0
mov rc4y, bl ; rc4->y = 0
pop di
pop si ; Restore register vars
pop bp
ret
_rc4expandKey ENDP
; void rc4Crypt( unsigned char *data, int len )
_rc4crypt PROCEDURE
push bp
mov bp, sp
push si
push di ; Save register vars
les si, [bp+4] ; ES:SI = data
mov dx, [bp+8] ; DX = len
test dx, dx ; Check that len != 0
jz SHORT @@exit ; Yes, exit now
xor bx, bx
mov bl, rc4x ; BX = rc4x
xor ax, ax
mov al, rc4y ; AX = rc4y
xor di, di ; DI = AX as an index register
; while( len-- )
; {
; x++;
; sx = rc4key[ x ];
; y += sx;
; sy = rc4key[ y ];
; rc4key[ y ] = sx;
; rc4key[ x ] = sy;
; *data++ ^= rc4key[ ( sx + sy ) & 0xFF ];
; }
@@rc4loop:
inc bl ; x++
mov cl, rc4key[bx] ; sx = rc4key[ x ]
add al, cl ; y += sx
mov di, ax
mov ch, rc4key[di] ; sy = rc4key[ y ]
mov rc4key[di], cl ; rc4key[ y ] = sx
mov rc4key[bx], ch ; rc4key[ x ] = sy
add cl, ch
xor ch, ch
mov di, cx ; temp = ( sx + sy ) & 0xFF
mov cl, rc4key[di]
xor es:[si], cl ; *data ^= rc4key[ temp ]
inc si ; data++
dec dx ; len--
jnz SHORT @@rc4loop
mov rc4x, bl
mov rc4y, al ; Remember x and y values
@@exit:
pop di
pop si ; Restore register vars
pop bp
ret
_rc4crypt ENDP
ENDMODULE