; 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