diff options
Diffstat (limited to 'crypto/rc4')
-rw-r--r-- | crypto/rc4/asm/rc4-586.pl | 59 | ||||
-rwxr-xr-x | crypto/rc4/asm/rc4-amd64.pl | 29 | ||||
-rw-r--r-- | crypto/rc4/rc4_locl.h | 1 | ||||
-rw-r--r-- | crypto/rc4/rc4_skey.c | 47 |
4 files changed, 117 insertions, 19 deletions
diff --git a/crypto/rc4/asm/rc4-586.pl b/crypto/rc4/asm/rc4-586.pl index 7ef889e5a1..dbe3803f55 100644 --- a/crypto/rc4/asm/rc4-586.pl +++ b/crypto/rc4/asm/rc4-586.pl @@ -7,10 +7,10 @@ require "x86asm.pl"; &asm_init($ARGV[0],"rc4-586.pl"); -$tx="eax"; -$ty="ebx"; -$x="ecx"; -$y="edx"; +$x="eax"; +$y="ebx"; +$tx="ecx"; +$ty="edx"; $in="esi"; $out="edi"; $d="ebp"; @@ -31,7 +31,7 @@ sub RC4_loop { &mov($ty, &swtmp(2)); &cmp($ty, $in); - &jle(&label("finished")); + &jbe(&label("finished")); &inc($in); } else @@ -39,7 +39,7 @@ sub RC4_loop &add($ty, 8); &inc($in); &cmp($ty, $in); - &jl(&label("finished")); + &jb(&label("finished")); &mov(&swtmp(2), $ty); } } @@ -88,35 +88,44 @@ sub RC4 &function_begin_B($name,""); + &mov($ty,&wparam(1)); # len + &cmp($ty,0); + &jne(&label("proceed")); + &ret(); + &set_label("proceed"); + &comment(""); &push("ebp"); &push("ebx"); - &mov( $d, &wparam(0)); # key - &mov( $ty, &wparam(1)); # num &push("esi"); &push("edi"); + &mov( $d, &wparam(0)); # key + &mov( $in, &wparam(2)); &mov( $x, &DWP(0,$d,"",1)); &mov( $y, &DWP(4,$d,"",1)); - &mov( $in, &wparam(2)); + &mov( $out, &wparam(3)); &inc( $x); &stack_push(3); # 3 temp variables &add( $d, 8); &and( $x, 0xff); + # detect compressed schedule, see commentary section in rc4_skey.c... + &cmp(&DWP(256,$d),-1); + &je(&label("RC4_CHAR")); + &lea( $ty, &DWP(-8,$ty,$in)); # check for 0 length input - &mov( $out, &wparam(3)); &mov( &swtmp(2), $ty); # this is now address to exit at &mov( $tx, &DWP(0,$d,$x,4)); &cmp( $ty, $in); - &jl( &label("end")); # less than 8 bytes + &jb( &label("end")); # less than 8 bytes &set_label("start"); @@ -148,7 +157,7 @@ sub RC4 &mov( &DWP(-4,$out,"",0), $tx); &mov( $tx, &DWP(0,$d,$x,4)); &cmp($in, $ty); - &jle(&label("start")); + &jbe(&label("start")); &set_label("end"); @@ -162,6 +171,32 @@ sub RC4 &RC4_loop(5,0,1); &RC4_loop(6,1,1); + &jmp(&label("finished")); + + &align(16); + # this is essentially Intel P4 specific codepath, see rc4_skey.c... + &set_label("RC4_CHAR"); + + &lea ($ty,&DWP(0,$in,$ty)); + &mov (&swtmp(2),$ty); + + # strangely enough unrolled loop performs over 20% slower... + &set_label("RC4_CHAR_loop"); + &movz ($tx,&BP(0,$d,$x)); + &add (&LB($y),&LB($tx)); + &movz ($ty,&BP(0,$d,$y)); + &movb (&BP(0,$d,$y),&LB($tx)); + &movb (&BP(0,$d,$x),&LB($ty)); + &add (&LB($ty),&LB($tx)); + &movz ($ty,&BP(0,$d,$ty)); + &xorb (&LB($ty),&BP(0,$in)); + &movb (&BP(0,$out),&LB($ty)); + &inc (&LB($x)); + &inc ($in); + &inc ($out); + &cmp ($in,&swtmp(2)); + &jb (&label("RC4_CHAR_loop")); + &set_label("finished"); &dec( $x); &stack_pop(3); diff --git a/crypto/rc4/asm/rc4-amd64.pl b/crypto/rc4/asm/rc4-amd64.pl index cc3f0c0231..35e426d561 100755 --- a/crypto/rc4/asm/rc4-amd64.pl +++ b/crypto/rc4/asm/rc4-amd64.pl @@ -25,6 +25,13 @@ # Latter means that if you want to *estimate* what to expect from # *your* CPU, then multiply 54 by 3.3 and clock frequency in GHz. +# Intel P4 EM64T core was found to run the AMD64 code really slow... +# The only way to achieve comparable performance on P4 is to keep +# RC4_CHAR. Kind of ironic, huh? As it's apparently impossible to +# compose blended code, which would perform even within 30% marginal +# on either AMD and Intel platforms, I implement both cases. See +# rc4_skey.c for further details... + $output=shift; $win64a=1 if ($output =~ /win64a.[s|asm]/); @@ -90,6 +97,8 @@ $code.=<<___; add \$8,$dat movl `&PTR("DWORD:-8[$dat]")`,$XX#d movl `&PTR("DWORD:-4[$dat]")`,$YY#d + cmpl \$-1,`&PTR("DWORD:256[$dat]")` + je .LRC4_CHAR test \$-8,$len jz .Lloop1 .align 16 @@ -167,6 +176,24 @@ $code.=<<___; dec $len jnz .Lloop1 jmp .Lexit + +.align 16 +.LRC4_CHAR: + inc $XX#b + movzb `&PTR("BYTE:[$dat+$XX]")`,$TX#d + add $TX#b,$YY#b + movzb `&PTR("BYTE:[$dat+$YY]")`,$TY#d + movb $TX#b,`&PTR("BYTE:[$dat+$YY]")` + movb $TY#b,`&PTR("BYTE:[$dat+$XX]")` + add $TX#b,$TY#b + movzb `&PTR("BYTE:[$dat+$TY]")`,$TY#d + xorb `&PTR("BYTE:[$inp]")`,$TY#b + movb $TY#b,`&PTR("BYTE:[$out]")` + inc $inp + inc $out + dec $len + jnz .LRC4_CHAR + jmp .Lexit ___ $code.=<<___ if (defined($win64a)); RC4 ENDP @@ -189,6 +216,8 @@ if (defined($win64a)) { $code =~ s/mov[bwlq]/mov/gm; $code =~ s/movzb/movzx/gm; $code =~ s/repret/DB\t0F3h,0C3h/gm; + $code =~ s/cmpl/cmp/gm; + $code =~ s/xorb/xor/gm; } else { $code =~ s/([QD]*WORD|BYTE)://gm; $code =~ s/repret/.byte\t0xF3,0xC3/gm; diff --git a/crypto/rc4/rc4_locl.h b/crypto/rc4/rc4_locl.h index 3bb80b6ce9..c712e1632e 100644 --- a/crypto/rc4/rc4_locl.h +++ b/crypto/rc4/rc4_locl.h @@ -1,4 +1,5 @@ #ifndef HEADER_RC4_LOCL_H #define HEADER_RC4_LOCL_H #include <openssl/opensslconf.h> +#include <cryptlib.h> #endif diff --git a/crypto/rc4/rc4_skey.c b/crypto/rc4/rc4_skey.c index bb10c1ebe2..781ff2d8b9 100644 --- a/crypto/rc4/rc4_skey.c +++ b/crypto/rc4/rc4_skey.c @@ -93,25 +93,58 @@ void RC4_set_key(RC4_KEY *key, int len, const unsigned char *data) unsigned int i; d= &(key->data[0]); - for (i=0; i<256; i++) - d[i]=i; key->x = 0; key->y = 0; id1=id2=0; -#define SK_LOOP(n) { \ +#define SK_LOOP(d,n) { \ tmp=d[(n)]; \ id2 = (data[id1] + tmp + id2) & 0xff; \ if (++id1 == len) id1=0; \ d[(n)]=d[id2]; \ d[id2]=tmp; } +#if defined(OPENSSL_CPUID_OBJ) && !defined(OPENSSL_NO_ASM) +# if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__INTEL__) || \ + defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) + if (sizeof(RC4_INT) > 1) { + /* + * Unlike all other x86 [and x86_64] implementations, + * Intel P4 core [including EM64T] was found to perform + * poorly with wider RC4_INT. Performance improvement + * for IA-32 hand-coded assembler turned out to be 2.8x + * if re-coded for RC4_CHAR! It's however inappropriate + * to just switch to RC4_CHAR for x86[_64], as non-P4 + * implementations suffer from significant performance + * losses then, e.g. PIII exhibits >2x deterioration, + * and so does Opteron. In order to assure optimal + * all-round performance, let us [try to] detect P4 at + * run-time by checking upon HTT bit in CPU capability + * vector and set up compressed key schedule, which is + * recognized by correspondingly updated assembler + * module... + * <appro@fy.chalmers.se> + */ + if (OPENSSL_ia32cap_P & (1<<28)) { + unsigned char *cp=(unsigned char *)d; + + for (i=0;i<256;i++) cp[i]=i; + for (i=0;i<256;i++) SK_LOOP(cp,i); + /* mark schedule as compressed! */ + d[256/sizeof(RC4_INT)]=-1; + return; + } + } +# endif +#endif + for (i=0; i < 256; i++) d[i]=i; for (i=0; i < 256; i+=4) { - SK_LOOP(i+0); - SK_LOOP(i+1); - SK_LOOP(i+2); - SK_LOOP(i+3); + SK_LOOP(d,i+0); + SK_LOOP(d,i+1); + SK_LOOP(d,i+2); + SK_LOOP(d,i+3); } } |