[openssl.org #1801] [BUGFIX] Segment fault when invoking AES_cbc_encrypt() on x86_64 with short input
Fix two bugs in .Lcbc_slow_enc_in_place. - At end of .Lcbc_slow_enc_in_place, %r10 instead of $_len should be set to 16. - In .Lcbc_slow_enc_in_place, %rdi should be initialized before stosb. Signed-off-by: Huang Ying --- crypto/aes/asm/aes-x86_64.pl |4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) --- a/crypto/aes/asm/aes-x86_64.pl +++ b/crypto/aes/asm/aes-x86_64.pl @@ -1994,10 +1994,12 @@ AES_cbc_encrypt: .Lcbc_slow_enc_in_place: mov \$16,%rcx # zero tail sub %r10,%rcx + mov $out,%rdi + add %r10,%rdi xor %rax,%rax .long 0x9066AAF3 # rep stosb mov $out,$inp # this is not a mistake! - movq\$16,$_len # len=16 + movq\$16,%r10 # len=16 jmp .Lcbc_slow_enc_loop # one more spin... #--- SLOW DECRYPT ---# .align 16 signature.asc Description: PGP signature
Re: [openssl.org #1801] [BUGFIX] Segment fault when invoking AES_cbc_encrypt() on x86_64 with short input
On Wed, 2008-12-17 at 22:30 +0800, Andy Polyakov via RT wrote: > > Fix two bugs in .Lcbc_slow_enc_in_place. > > > > - At end of .Lcbc_slow_enc_in_place, %r10 instead of $_len should be > > set to 16. > > - In .Lcbc_slow_enc_in_place, %rdi should be initialized before stosb. > > Thanks. The problem is addressed but in different way, see > http://cvs.openssl.org/chngview?cn=17698. > > > Signed-off-by: Huang Ying > > > > --- > > crypto/aes/asm/aes-x86_64.pl |4 +++- > > 1 file changed, 3 insertions(+), 1 deletion(-) > > > > --- a/crypto/aes/asm/aes-x86_64.pl > > +++ b/crypto/aes/asm/aes-x86_64.pl > > @@ -1994,10 +1994,12 @@ AES_cbc_encrypt: > > ??? What is it for version you have? In CVS .Lcbc_slow_enc_in_place > resided at line #1974! A. I use CVS. It's an issue of patch sequence, I put another personal patch before this one. And, I find with the simple test program attached with the mail. The output of CVS is different from that of openssl-0.9.8g if the specified input length is less than 16. Best Regards, Huang Ying #include #include #include #include #include void print_arr(unsigned char buf[], int sz, char *prefix) { int i; if (prefix) printf("%s", prefix); for (i = 0; i < sz; i++) printf("%02x", buf[i]); printf("\n"); } void test_cbc1(int in_len) { int ret; AES_KEY key; unsigned char user_key[16] = "123456"; unsigned char iv1[16] = "9876543210987654"; unsigned char iv2[16]; unsigned char in[16] = "1234567890"; unsigned char out[16]; memcpy(iv2, iv1, sizeof(iv1)); ret = AES_set_encrypt_key(user_key, 128, &key); assert(!ret); AES_cbc_encrypt(in, out, in_len, &key, iv1, 1); print_arr(out, sizeof(out), " out: "); //AES_cbc_encrypt(in, in, in_len, &key, iv2, 1); //print_arr(in, sizeof(in), "ip_out: "); ret = AES_set_decrypt_key(user_key, 128, &key); assert(!ret); AES_cbc_encrypt(out, in, in_len, &key, iv2, 0); print_arr(in, sizeof(in), " out: "); } void test_cbc2(int in_len) { int ret; AES_KEY key; unsigned char user_key[16] = "123456"; unsigned char iv1[16] = "9876543210987654"; unsigned char iv2[16]; unsigned char in[32] = "12345678901234567890123456789012"; unsigned char out[32]; in_len += 16; memcpy(iv2, iv1, sizeof(iv1)); ret = AES_set_encrypt_key(user_key, 128, &key); assert(!ret); AES_cbc_encrypt(in, out, in_len, &key, iv1, 1); print_arr(out, sizeof(out), "out: "); ret = AES_set_decrypt_key(user_key, 128, &key); assert(!ret); AES_cbc_encrypt(out, in, in_len, &key, iv2, 0); print_arr(in, sizeof(in), " in: "); } void test_cbc3(int in_len) { int ret; AES_KEY key; unsigned char user_key[16] = "123456"; unsigned char iv1[16] = "9876543210987654"; unsigned char iv2[16]; unsigned char in[80] = "1234567890123456789012345678901234567890" "1234567890123456789012345678901234567890"; unsigned char out[80]; in_len += 64; memcpy(iv2, iv1, sizeof(iv1)); ret = AES_set_encrypt_key(user_key, 128, &key); assert(!ret); AES_cbc_encrypt(in, out, in_len, &key, iv1, 1); print_arr(out, sizeof(out), "out: "); ret = AES_set_decrypt_key(user_key, 128, &key); assert(!ret); AES_cbc_encrypt(out, in, in_len, &key, iv2, 0); print_arr(in, sizeof(in), " in: "); } int main(int argc, char *argv[]) { int in_len; in_len = argc > 1 ? atoi(argv[1]) : 16; test_cbc1(in_len); test_cbc2(in_len); test_cbc3(in_len); return 0; } signature.asc Description: PGP signature
[openssl.org #1690] BN_GF2m_mod_arr() infinite loop
The following code will make BN_GF2m_mod_arr() into infinite loop. int main(int argc, char *argv[]) { BIGNUM *bn = NULL, *res = NULL, *p = NULL; BN_hex2bn(&bn3, "448692853686179295b477565726f6e5d"); BN_hex2bn(&p, "10087"); res = BN_new(); BN_GF2m_mod(res, bn3, p); } Because in final round of reduction d0 == 0 and z[dN] != 0, which makes z[dN] can not be changed for ever. This is fixed by set z[dn] = 0 if d0 == 0. This patch is based on openssl SNAPSHOT 20080519, and has been tested on x86_64 with openssl/test/bntest.c and above program. Signed-off-by: Huang Ying <[EMAIL PROTECTED]> --- crypto/bn/bn_gf2m.c |6 +- 1 file changed, 5 insertions(+), 1 deletion(-) --- a/crypto/bn/bn_gf2m.c +++ b/crypto/bn/bn_gf2m.c @@ -322,7 +322,11 @@ int BN_GF2m_mod_arr(BIGNUM *r, const BIG if (zz == 0) break; d1 = BN_BITS2 - d0; - if (d0) z[dN] = (z[dN] << d1) >> d1; /* clear up the top d1 bits */ + /* clear up the top d1 bits */ + if (d0) + z[dN] = (z[dN] << d1) >> d1; + else + z[dN] = 0; z[0] ^= zz; /* reduction t^0 component */ for (k = 1; p[k] != 0; k++) The following code will make BN_GF2m_mod_arr() into infinite loop. int main(int argc, char *argv[]) { BIGNUM *bn = NULL, *res = NULL, *p = NULL; BN_hex2bn(&bn3, "448692853686179295b477565726f6e5d"); BN_hex2bn(&p, "10087"); res = BN_new(); BN_GF2m_mod(res, bn3, p); } Because in final round of reduction d0 == 0 and z[dN] != 0, which makes z[dN] can not be changed for ever. This is fixed by set z[dn] = 0 if d0 == 0. This patch is based on openssl SNAPSHOT 20080519, and has been tested on x86_64 with openssl/test/bntest.c and above program. Signed-off-by: Huang Ying <[EMAIL PROTECTED]> --- crypto/bn/bn_gf2m.c |6 +- 1 file changed, 5 insertions(+), 1 deletion(-) --- a/crypto/bn/bn_gf2m.c +++ b/crypto/bn/bn_gf2m.c @@ -322,7 +322,11 @@ int BN_GF2m_mod_arr(BIGNUM *r, const BIG if (zz == 0) break; d1 = BN_BITS2 - d0; - if (d0) z[dN] = (z[dN] << d1) >> d1; /* clear up the top d1 bits */ + /* clear up the top d1 bits */ + if (d0) + z[dN] = (z[dN] << d1) >> d1; + else + z[dN] = 0; z[0] ^= zz; /* reduction t^0 component */ for (k = 1; p[k] != 0; k++) OpenSSL self-test report: OpenSSL version: 0.9.9-dev Last change: To support arbitrarily-typed thread IDs, deprecate the ... Options: no-gmp no-krb5 no-mdc2 no-rc5 no-rfc3779 no-shared no-zlib no-zlib-dynamic static-engine OS (uname): Linux caritas-dev 2.6.24-1-amd64 #1 SMP Fri Apr 18 23:08:22 UTC 2008 x86_64 GNU/Linux OS (config): x86_64-whatever-linux2 Target (default): linux-x86_64 Target: linux-x86_64 Compiler: Using built-in specs. Target: x86_64-linux-gnu Configured with: ../src/configure -v --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.2 --program-suffix=-4.2 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --disable-libmudflap --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.2.4 (Debian 4.2.4-1) Test passed.