Loading CHANGES +57 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,63 @@ [Matthew D Wood (Intel Corp)] *) Squeeze another 10% out of IGE mode when in != out. [Ben Laurie] *) AES IGE mode speedup. [Dean Gaudet (Google)] *) Add the Korean symmetric 128-bit cipher SEED (see http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp) and add SEED ciphersuites from RFC 4162: TLS_RSA_WITH_SEED_CBC_SHA = "SEED-SHA" TLS_DHE_DSS_WITH_SEED_CBC_SHA = "DHE-DSS-SEED-SHA" TLS_DHE_RSA_WITH_SEED_CBC_SHA = "DHE-RSA-SEED-SHA" TLS_DH_anon_WITH_SEED_CBC_SHA = "ADH-SEED-SHA" To minimize changes between patchlevels in the OpenSSL 0.9.8 series, SEED remains excluded from compilation unless OpenSSL is configured with 'enable-seed'. [KISA, Bodo Moeller] *) Mitigate branch prediction attacks, which can be practical if a single processor is shared, allowing a spy process to extract information. For detailed background information, see http://eprint.iacr.org/2007/039 (O. Aciicmez, S. Gueron, J.-P. Seifert, "New Branch Prediction Vulnerabilities in OpenSSL and Necessary Software Countermeasures"). The core of the change are new versions BN_div_no_branch() and BN_mod_inverse_no_branch() of BN_div() and BN_mod_inverse(), respectively, which are slower, but avoid the security-relevant conditional branches. These are automatically called by BN_div() and BN_mod_inverse() if the flag BN_FLG_CONSTTIME is set for one of the input BIGNUMs. Also, BN_is_bit_set() has been changed to remove a conditional branch. BN_FLG_CONSTTIME is the new name for the previous BN_FLG_EXP_CONSTTIME flag, since it now affects more than just modular exponentiation. (Since OpenSSL 0.9.7h, setting this flag in the exponent causes BN_mod_exp_mont() to use the alternative implementation in BN_mod_exp_mont_consttime().) The old name remains as a deprecated alias. Similary, RSA_FLAG_NO_EXP_CONSTTIME is replaced by a more general RSA_FLAG_NO_CONSTTIME flag since the RSA implementation now uses constant-time implementations for more than just exponentiation. Here too the old name is kept as a deprecated alias. BN_BLINDING_new() will now use BN_dup() for the modulus so that the BN_BLINDING structure gets an independent copy of the modulus. This means that the previous "BIGNUM *m" argument to BN_BLINDING_new() and to BN_BLINDING_create_param() now essentially becomes "const BIGNUM *m", although we can't actually change this in the header file before 0.9.9. It allows RSA_setup_blinding() to use BN_with_flags() on the modulus to enable BN_FLG_CONSTTIME. [Matthew D Wood (Intel Corp)] *) In the SSL/TLS server implementation, be strict about session ID context matching (which matters if an application uses a single external cache for different purposes). Previously, Loading apps/speed.c +59 −3 Original line number Diff line number Diff line Loading @@ -275,7 +275,7 @@ static void print_result(int alg,int run_no,int count,double time_used); static int do_multi(int multi); #endif #define ALGOR_NUM 25 #define ALGOR_NUM 28 #define SIZE_NUM 5 #define RSA_NUM 4 #define DSA_NUM 3 Loading @@ -289,7 +289,8 @@ static const char *names[ALGOR_NUM]={ "rc2 cbc","rc5-32/12 cbc","blowfish cbc","cast cbc", "aes-128 cbc","aes-192 cbc","aes-256 cbc", "camellia-128 cbc","camellia-192 cbc","camellia-256 cbc", "evp","sha256","sha512"}; "evp","sha256","sha512", "aes-128 ige","aes-192 ige","aes-256 ige"}; static double results[ALGOR_NUM][SIZE_NUM]; static int lengths[SIZE_NUM]={16,64,256,1024,8*1024}; static double rsa_results[RSA_NUM][2]; Loading Loading @@ -617,6 +618,9 @@ int MAIN(int argc, char **argv) #define D_EVP 22 #define D_SHA256 23 #define D_SHA512 24 #define D_IGE_128_AES 25 #define D_IGE_192_AES 26 #define D_IGE_256_AES 27 double d=0.0; long c[ALGOR_NUM][SIZE_NUM]; #define R_DSA_512 0 Loading Loading @@ -957,6 +961,9 @@ int MAIN(int argc, char **argv) if (strcmp(*argv,"aes-128-cbc") == 0) doit[D_CBC_128_AES]=1; else if (strcmp(*argv,"aes-192-cbc") == 0) doit[D_CBC_192_AES]=1; else if (strcmp(*argv,"aes-256-cbc") == 0) doit[D_CBC_256_AES]=1; else if (strcmp(*argv,"aes-128-ige") == 0) doit[D_IGE_128_AES]=1; else if (strcmp(*argv,"aes-192-ige") == 0) doit[D_IGE_192_AES]=1; else if (strcmp(*argv,"aes-256-ige") == 0) doit[D_IGE_256_AES]=1; else #endif #ifndef OPENSSL_NO_CAMELLIA Loading Loading @@ -1177,6 +1184,7 @@ int MAIN(int argc, char **argv) #endif #ifndef OPENSSL_NO_AES BIO_printf(bio_err,"aes-128-cbc aes-192-cbc aes-256-cbc "); BIO_printf(bio_err,"aes-128-ige aes-192-ige aes-256-ige "); #endif #ifndef OPENSSL_NO_CAMELLIA BIO_printf(bio_err,"\n"); Loading Loading @@ -1395,6 +1403,9 @@ int MAIN(int argc, char **argv) c[D_CBC_256_CML][0]=count; c[D_SHA256][0]=count; c[D_SHA512][0]=count; c[D_IGE_128_AES][0]=count; c[D_IGE_192_AES][0]=count; c[D_IGE_256_AES][0]=count; for (i=1; i<SIZE_NUM; i++) { Loading Loading @@ -1429,6 +1440,9 @@ int MAIN(int argc, char **argv) c[D_CBC_128_CML][i]=c[D_CBC_128_CML][i-1]*l0/l1; c[D_CBC_192_CML][i]=c[D_CBC_192_CML][i-1]*l0/l1; c[D_CBC_256_CML][i]=c[D_CBC_256_CML][i-1]*l0/l1; c[D_IGE_128_AES][i]=c[D_IGE_128_AES][i-1]*l0/l1; c[D_IGE_192_AES][i]=c[D_IGE_192_AES][i-1]*l0/l1; c[D_IGE_256_AES][i]=c[D_IGE_256_AES][i-1]*l0/l1; } #ifndef OPENSSL_NO_RSA rsa_c[R_RSA_512][0]=count/2000; Loading Loading @@ -1822,6 +1836,48 @@ int MAIN(int argc, char **argv) } } if (doit[D_IGE_128_AES]) { for (j=0; j<SIZE_NUM; j++) { print_message(names[D_IGE_128_AES],c[D_IGE_128_AES][j],lengths[j]); Time_F(START); for (count=0,run=1; COND(c[D_IGE_128_AES][j]); count++) AES_ige_encrypt(buf,buf2, (unsigned long)lengths[j],&aes_ks1, iv,AES_ENCRYPT); d=Time_F(STOP); print_result(D_IGE_128_AES,j,count,d); } } if (doit[D_IGE_192_AES]) { for (j=0; j<SIZE_NUM; j++) { print_message(names[D_IGE_192_AES],c[D_IGE_192_AES][j],lengths[j]); Time_F(START); for (count=0,run=1; COND(c[D_IGE_192_AES][j]); count++) AES_ige_encrypt(buf,buf2, (unsigned long)lengths[j],&aes_ks2, iv,AES_ENCRYPT); d=Time_F(STOP); print_result(D_IGE_192_AES,j,count,d); } } if (doit[D_IGE_256_AES]) { for (j=0; j<SIZE_NUM; j++) { print_message(names[D_IGE_256_AES],c[D_IGE_256_AES][j],lengths[j]); Time_F(START); for (count=0,run=1; COND(c[D_IGE_256_AES][j]); count++) AES_ige_encrypt(buf,buf2, (unsigned long)lengths[j],&aes_ks3, iv,AES_ENCRYPT); d=Time_F(STOP); print_result(D_IGE_256_AES,j,count,d); } } #endif #ifndef OPENSSL_NO_CAMELLIA if (doit[D_CBC_128_CML]) Loading crypto/aes/aes_ige.c +119 −83 Original line number Diff line number Diff line Loading @@ -54,21 +54,23 @@ #include <openssl/aes.h> #include "aes_locl.h" /* static void hexdump(FILE *f,const char *title,const unsigned char *s,int l) { int n=0; #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long)) typedef struct { unsigned long data[N_WORDS]; } aes_block_t; fprintf(f,"%s",title); for( ; n < l ; ++n) { if((n%16) == 0) fprintf(f,"\n%04x",n); fprintf(f," %02x",s[n]); } fprintf(f,"\n"); } */ // XXX: probably some better way to do this #if defined(__i386__) || defined(__x86_64__) #define UNALIGNED_MEMOPS_ARE_FAST 1 #endif #ifdef UNALIGNED_MEMOPS_ARE_FAST #define load_block(d, s) (d) = *(const aes_block_t *)(s) #define store_block(d, s) *(aes_block_t *)(d) = (s) #else #define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) #define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) #endif /* N.B. The IV for this mode is _twice_ the block size */ Loading @@ -77,68 +79,123 @@ void AES_ige_encrypt(const unsigned char *in, unsigned char *out, unsigned char *ivec, const int enc) { unsigned long n; unsigned long len = length; unsigned char tmp[AES_BLOCK_SIZE]; unsigned char tmp2[AES_BLOCK_SIZE]; unsigned char prev[AES_BLOCK_SIZE]; const unsigned char *iv = ivec; const unsigned char *iv2 = ivec + AES_BLOCK_SIZE; unsigned long len; OPENSSL_assert(in && out && key && ivec); OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); len = length / AES_BLOCK_SIZE; if (AES_ENCRYPT == enc) { /* XXX: Do a separate case for when in != out (strictly should check for overlap, too) */ while (len >= AES_BLOCK_SIZE) if (in != out) { /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] = in[n] ^ iv[n]; /* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ AES_encrypt(out, out, key); /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv2[n]; /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ iv = out; memcpy(prev, in, AES_BLOCK_SIZE); iv2 = prev; len -= AES_BLOCK_SIZE; aes_block_t *ivp = (aes_block_t *)ivec; aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); while (len) { aes_block_t *inp = (aes_block_t *)in; aes_block_t *outp = (aes_block_t *)out; for(n=0 ; n < N_WORDS; ++n) outp->data[n] = inp->data[n] ^ ivp->data[n]; AES_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key); for(n=0 ; n < N_WORDS; ++n) outp->data[n] ^= iv2p->data[n]; ivp = outp; iv2p = inp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy(ivec, iv, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); memcpy(ivec, ivp->data, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); } else { while (len >= AES_BLOCK_SIZE) aes_block_t tmp, tmp2; aes_block_t iv; aes_block_t iv2; load_block(iv, ivec); load_block(iv2, ivec + AES_BLOCK_SIZE); while (len) { memcpy(tmp, in, AES_BLOCK_SIZE); memcpy(tmp2, in, AES_BLOCK_SIZE); /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) tmp[n] ^= iv2[n]; /* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ AES_decrypt(tmp, out, key); /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= ivec[n]; /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ memcpy(ivec, tmp2, AES_BLOCK_SIZE); iv2 = out; len -= AES_BLOCK_SIZE; load_block(tmp, in); for(n=0 ; n < N_WORDS; ++n) tmp2.data[n] = tmp.data[n] ^ iv.data[n]; AES_encrypt((unsigned char *)tmp2.data, (unsigned char *)tmp2.data, key); for(n=0 ; n < N_WORDS; ++n) tmp2.data[n] ^= iv2.data[n]; store_block(out, tmp2); iv = tmp2; iv2 = tmp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy(ivec, iv.data, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } } else { if(in != out) { aes_block_t *ivp = (aes_block_t *)ivec; aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); while (len) { aes_block_t tmp; aes_block_t *inp = (aes_block_t *)in; aes_block_t *outp = (aes_block_t *)out; for(n=0 ; n < N_WORDS; ++n) tmp.data[n] = inp->data[n] ^ iv2p->data[n]; AES_decrypt((unsigned char *)tmp.data, (unsigned char *)outp->data, key); for(n=0 ; n < N_WORDS; ++n) outp->data[n] ^= ivp->data[n]; ivp = inp; iv2p = outp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); memcpy(ivec, ivp->data, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); } else { aes_block_t tmp, tmp2; aes_block_t iv; aes_block_t iv2; load_block(iv, ivec); load_block(iv2, ivec + AES_BLOCK_SIZE); while (len) { load_block(tmp, in); tmp2 = tmp; for(n=0 ; n < N_WORDS; ++n) tmp.data[n] ^= iv2.data[n]; AES_decrypt((unsigned char *)tmp.data, (unsigned char *)tmp.data, key); for(n=0 ; n < N_WORDS; ++n) tmp.data[n] ^= iv.data[n]; store_block(out, tmp); iv = tmp2; iv2 = tmp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy(ivec, iv.data, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } } } Loading Loading @@ -177,17 +234,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, iv2 = ivec + AES_BLOCK_SIZE; while (len >= AES_BLOCK_SIZE) { /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] = in[n] ^ iv[n]; /* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ AES_encrypt(out, out, key); /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv2[n]; /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ iv = out; memcpy(prev, in, AES_BLOCK_SIZE); iv2 = prev; Loading @@ -203,8 +254,6 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, while(len >= AES_BLOCK_SIZE) { out -= AES_BLOCK_SIZE; /* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ /* XXX: reduce copies by alternating between buffers */ memcpy(tmp, out, AES_BLOCK_SIZE); for(n=0 ; n < AES_BLOCK_SIZE ; ++n) Loading Loading @@ -235,17 +284,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, out -= AES_BLOCK_SIZE; memcpy(tmp, in, AES_BLOCK_SIZE); memcpy(tmp2, in, AES_BLOCK_SIZE); /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) tmp[n] ^= iv2[n]; /* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ AES_decrypt(tmp, out, key); /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv[n]; /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ memcpy(tmp3, tmp2, AES_BLOCK_SIZE); iv = tmp3; iv2 = out; Loading @@ -260,17 +303,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, { memcpy(tmp, out, AES_BLOCK_SIZE); memcpy(tmp2, out, AES_BLOCK_SIZE); /* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) tmp[n] ^= iv2[n]; /* hexdump(stdout, "out ^ iv2", tmp, AES_BLOCK_SIZE); */ AES_decrypt(tmp, out, key); /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv[n]; /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ memcpy(tmp3, tmp2, AES_BLOCK_SIZE); iv = tmp3; iv2 = out; Loading @@ -278,6 +315,5 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } } } test/igetest.c +17 −0 Original line number Diff line number Diff line Loading @@ -218,6 +218,23 @@ static int run_test_vectors(void) hexdump(stdout, "expected", v->out, v->length); hexdump(stdout, "got", buf, v->length); ++errs; } // try with in == out memcpy(iv, v->iv, sizeof iv); memcpy(buf, v->in, v->length); AES_ige_encrypt(buf, buf, v->length, &key, iv, v->encrypt); if(memcmp(v->out, buf, v->length)) { printf("IGE test vector %d failed (with in == out)\n", n); hexdump(stdout, "key", v->key, sizeof v->key); hexdump(stdout, "iv", v->iv, sizeof v->iv); hexdump(stdout, "in", v->in, v->length); hexdump(stdout, "expected", v->out, v->length); hexdump(stdout, "got", buf, v->length); ++errs; } } Loading Loading
CHANGES +57 −0 Original line number Diff line number Diff line Loading @@ -262,6 +262,63 @@ [Matthew D Wood (Intel Corp)] *) Squeeze another 10% out of IGE mode when in != out. [Ben Laurie] *) AES IGE mode speedup. [Dean Gaudet (Google)] *) Add the Korean symmetric 128-bit cipher SEED (see http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp) and add SEED ciphersuites from RFC 4162: TLS_RSA_WITH_SEED_CBC_SHA = "SEED-SHA" TLS_DHE_DSS_WITH_SEED_CBC_SHA = "DHE-DSS-SEED-SHA" TLS_DHE_RSA_WITH_SEED_CBC_SHA = "DHE-RSA-SEED-SHA" TLS_DH_anon_WITH_SEED_CBC_SHA = "ADH-SEED-SHA" To minimize changes between patchlevels in the OpenSSL 0.9.8 series, SEED remains excluded from compilation unless OpenSSL is configured with 'enable-seed'. [KISA, Bodo Moeller] *) Mitigate branch prediction attacks, which can be practical if a single processor is shared, allowing a spy process to extract information. For detailed background information, see http://eprint.iacr.org/2007/039 (O. Aciicmez, S. Gueron, J.-P. Seifert, "New Branch Prediction Vulnerabilities in OpenSSL and Necessary Software Countermeasures"). The core of the change are new versions BN_div_no_branch() and BN_mod_inverse_no_branch() of BN_div() and BN_mod_inverse(), respectively, which are slower, but avoid the security-relevant conditional branches. These are automatically called by BN_div() and BN_mod_inverse() if the flag BN_FLG_CONSTTIME is set for one of the input BIGNUMs. Also, BN_is_bit_set() has been changed to remove a conditional branch. BN_FLG_CONSTTIME is the new name for the previous BN_FLG_EXP_CONSTTIME flag, since it now affects more than just modular exponentiation. (Since OpenSSL 0.9.7h, setting this flag in the exponent causes BN_mod_exp_mont() to use the alternative implementation in BN_mod_exp_mont_consttime().) The old name remains as a deprecated alias. Similary, RSA_FLAG_NO_EXP_CONSTTIME is replaced by a more general RSA_FLAG_NO_CONSTTIME flag since the RSA implementation now uses constant-time implementations for more than just exponentiation. Here too the old name is kept as a deprecated alias. BN_BLINDING_new() will now use BN_dup() for the modulus so that the BN_BLINDING structure gets an independent copy of the modulus. This means that the previous "BIGNUM *m" argument to BN_BLINDING_new() and to BN_BLINDING_create_param() now essentially becomes "const BIGNUM *m", although we can't actually change this in the header file before 0.9.9. It allows RSA_setup_blinding() to use BN_with_flags() on the modulus to enable BN_FLG_CONSTTIME. [Matthew D Wood (Intel Corp)] *) In the SSL/TLS server implementation, be strict about session ID context matching (which matters if an application uses a single external cache for different purposes). Previously, Loading
apps/speed.c +59 −3 Original line number Diff line number Diff line Loading @@ -275,7 +275,7 @@ static void print_result(int alg,int run_no,int count,double time_used); static int do_multi(int multi); #endif #define ALGOR_NUM 25 #define ALGOR_NUM 28 #define SIZE_NUM 5 #define RSA_NUM 4 #define DSA_NUM 3 Loading @@ -289,7 +289,8 @@ static const char *names[ALGOR_NUM]={ "rc2 cbc","rc5-32/12 cbc","blowfish cbc","cast cbc", "aes-128 cbc","aes-192 cbc","aes-256 cbc", "camellia-128 cbc","camellia-192 cbc","camellia-256 cbc", "evp","sha256","sha512"}; "evp","sha256","sha512", "aes-128 ige","aes-192 ige","aes-256 ige"}; static double results[ALGOR_NUM][SIZE_NUM]; static int lengths[SIZE_NUM]={16,64,256,1024,8*1024}; static double rsa_results[RSA_NUM][2]; Loading Loading @@ -617,6 +618,9 @@ int MAIN(int argc, char **argv) #define D_EVP 22 #define D_SHA256 23 #define D_SHA512 24 #define D_IGE_128_AES 25 #define D_IGE_192_AES 26 #define D_IGE_256_AES 27 double d=0.0; long c[ALGOR_NUM][SIZE_NUM]; #define R_DSA_512 0 Loading Loading @@ -957,6 +961,9 @@ int MAIN(int argc, char **argv) if (strcmp(*argv,"aes-128-cbc") == 0) doit[D_CBC_128_AES]=1; else if (strcmp(*argv,"aes-192-cbc") == 0) doit[D_CBC_192_AES]=1; else if (strcmp(*argv,"aes-256-cbc") == 0) doit[D_CBC_256_AES]=1; else if (strcmp(*argv,"aes-128-ige") == 0) doit[D_IGE_128_AES]=1; else if (strcmp(*argv,"aes-192-ige") == 0) doit[D_IGE_192_AES]=1; else if (strcmp(*argv,"aes-256-ige") == 0) doit[D_IGE_256_AES]=1; else #endif #ifndef OPENSSL_NO_CAMELLIA Loading Loading @@ -1177,6 +1184,7 @@ int MAIN(int argc, char **argv) #endif #ifndef OPENSSL_NO_AES BIO_printf(bio_err,"aes-128-cbc aes-192-cbc aes-256-cbc "); BIO_printf(bio_err,"aes-128-ige aes-192-ige aes-256-ige "); #endif #ifndef OPENSSL_NO_CAMELLIA BIO_printf(bio_err,"\n"); Loading Loading @@ -1395,6 +1403,9 @@ int MAIN(int argc, char **argv) c[D_CBC_256_CML][0]=count; c[D_SHA256][0]=count; c[D_SHA512][0]=count; c[D_IGE_128_AES][0]=count; c[D_IGE_192_AES][0]=count; c[D_IGE_256_AES][0]=count; for (i=1; i<SIZE_NUM; i++) { Loading Loading @@ -1429,6 +1440,9 @@ int MAIN(int argc, char **argv) c[D_CBC_128_CML][i]=c[D_CBC_128_CML][i-1]*l0/l1; c[D_CBC_192_CML][i]=c[D_CBC_192_CML][i-1]*l0/l1; c[D_CBC_256_CML][i]=c[D_CBC_256_CML][i-1]*l0/l1; c[D_IGE_128_AES][i]=c[D_IGE_128_AES][i-1]*l0/l1; c[D_IGE_192_AES][i]=c[D_IGE_192_AES][i-1]*l0/l1; c[D_IGE_256_AES][i]=c[D_IGE_256_AES][i-1]*l0/l1; } #ifndef OPENSSL_NO_RSA rsa_c[R_RSA_512][0]=count/2000; Loading Loading @@ -1822,6 +1836,48 @@ int MAIN(int argc, char **argv) } } if (doit[D_IGE_128_AES]) { for (j=0; j<SIZE_NUM; j++) { print_message(names[D_IGE_128_AES],c[D_IGE_128_AES][j],lengths[j]); Time_F(START); for (count=0,run=1; COND(c[D_IGE_128_AES][j]); count++) AES_ige_encrypt(buf,buf2, (unsigned long)lengths[j],&aes_ks1, iv,AES_ENCRYPT); d=Time_F(STOP); print_result(D_IGE_128_AES,j,count,d); } } if (doit[D_IGE_192_AES]) { for (j=0; j<SIZE_NUM; j++) { print_message(names[D_IGE_192_AES],c[D_IGE_192_AES][j],lengths[j]); Time_F(START); for (count=0,run=1; COND(c[D_IGE_192_AES][j]); count++) AES_ige_encrypt(buf,buf2, (unsigned long)lengths[j],&aes_ks2, iv,AES_ENCRYPT); d=Time_F(STOP); print_result(D_IGE_192_AES,j,count,d); } } if (doit[D_IGE_256_AES]) { for (j=0; j<SIZE_NUM; j++) { print_message(names[D_IGE_256_AES],c[D_IGE_256_AES][j],lengths[j]); Time_F(START); for (count=0,run=1; COND(c[D_IGE_256_AES][j]); count++) AES_ige_encrypt(buf,buf2, (unsigned long)lengths[j],&aes_ks3, iv,AES_ENCRYPT); d=Time_F(STOP); print_result(D_IGE_256_AES,j,count,d); } } #endif #ifndef OPENSSL_NO_CAMELLIA if (doit[D_CBC_128_CML]) Loading
crypto/aes/aes_ige.c +119 −83 Original line number Diff line number Diff line Loading @@ -54,21 +54,23 @@ #include <openssl/aes.h> #include "aes_locl.h" /* static void hexdump(FILE *f,const char *title,const unsigned char *s,int l) { int n=0; #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long)) typedef struct { unsigned long data[N_WORDS]; } aes_block_t; fprintf(f,"%s",title); for( ; n < l ; ++n) { if((n%16) == 0) fprintf(f,"\n%04x",n); fprintf(f," %02x",s[n]); } fprintf(f,"\n"); } */ // XXX: probably some better way to do this #if defined(__i386__) || defined(__x86_64__) #define UNALIGNED_MEMOPS_ARE_FAST 1 #endif #ifdef UNALIGNED_MEMOPS_ARE_FAST #define load_block(d, s) (d) = *(const aes_block_t *)(s) #define store_block(d, s) *(aes_block_t *)(d) = (s) #else #define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) #define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) #endif /* N.B. The IV for this mode is _twice_ the block size */ Loading @@ -77,68 +79,123 @@ void AES_ige_encrypt(const unsigned char *in, unsigned char *out, unsigned char *ivec, const int enc) { unsigned long n; unsigned long len = length; unsigned char tmp[AES_BLOCK_SIZE]; unsigned char tmp2[AES_BLOCK_SIZE]; unsigned char prev[AES_BLOCK_SIZE]; const unsigned char *iv = ivec; const unsigned char *iv2 = ivec + AES_BLOCK_SIZE; unsigned long len; OPENSSL_assert(in && out && key && ivec); OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); len = length / AES_BLOCK_SIZE; if (AES_ENCRYPT == enc) { /* XXX: Do a separate case for when in != out (strictly should check for overlap, too) */ while (len >= AES_BLOCK_SIZE) if (in != out) { /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] = in[n] ^ iv[n]; /* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ AES_encrypt(out, out, key); /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv2[n]; /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ iv = out; memcpy(prev, in, AES_BLOCK_SIZE); iv2 = prev; len -= AES_BLOCK_SIZE; aes_block_t *ivp = (aes_block_t *)ivec; aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); while (len) { aes_block_t *inp = (aes_block_t *)in; aes_block_t *outp = (aes_block_t *)out; for(n=0 ; n < N_WORDS; ++n) outp->data[n] = inp->data[n] ^ ivp->data[n]; AES_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key); for(n=0 ; n < N_WORDS; ++n) outp->data[n] ^= iv2p->data[n]; ivp = outp; iv2p = inp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy(ivec, iv, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); memcpy(ivec, ivp->data, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); } else { while (len >= AES_BLOCK_SIZE) aes_block_t tmp, tmp2; aes_block_t iv; aes_block_t iv2; load_block(iv, ivec); load_block(iv2, ivec + AES_BLOCK_SIZE); while (len) { memcpy(tmp, in, AES_BLOCK_SIZE); memcpy(tmp2, in, AES_BLOCK_SIZE); /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) tmp[n] ^= iv2[n]; /* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ AES_decrypt(tmp, out, key); /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= ivec[n]; /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ memcpy(ivec, tmp2, AES_BLOCK_SIZE); iv2 = out; len -= AES_BLOCK_SIZE; load_block(tmp, in); for(n=0 ; n < N_WORDS; ++n) tmp2.data[n] = tmp.data[n] ^ iv.data[n]; AES_encrypt((unsigned char *)tmp2.data, (unsigned char *)tmp2.data, key); for(n=0 ; n < N_WORDS; ++n) tmp2.data[n] ^= iv2.data[n]; store_block(out, tmp2); iv = tmp2; iv2 = tmp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy(ivec, iv.data, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } } else { if(in != out) { aes_block_t *ivp = (aes_block_t *)ivec; aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); while (len) { aes_block_t tmp; aes_block_t *inp = (aes_block_t *)in; aes_block_t *outp = (aes_block_t *)out; for(n=0 ; n < N_WORDS; ++n) tmp.data[n] = inp->data[n] ^ iv2p->data[n]; AES_decrypt((unsigned char *)tmp.data, (unsigned char *)outp->data, key); for(n=0 ; n < N_WORDS; ++n) outp->data[n] ^= ivp->data[n]; ivp = inp; iv2p = outp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); memcpy(ivec, ivp->data, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); } else { aes_block_t tmp, tmp2; aes_block_t iv; aes_block_t iv2; load_block(iv, ivec); load_block(iv2, ivec + AES_BLOCK_SIZE); while (len) { load_block(tmp, in); tmp2 = tmp; for(n=0 ; n < N_WORDS; ++n) tmp.data[n] ^= iv2.data[n]; AES_decrypt((unsigned char *)tmp.data, (unsigned char *)tmp.data, key); for(n=0 ; n < N_WORDS; ++n) tmp.data[n] ^= iv.data[n]; store_block(out, tmp); iv = tmp2; iv2 = tmp; --len; in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } memcpy(ivec, iv.data, AES_BLOCK_SIZE); memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } } } Loading Loading @@ -177,17 +234,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, iv2 = ivec + AES_BLOCK_SIZE; while (len >= AES_BLOCK_SIZE) { /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] = in[n] ^ iv[n]; /* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ AES_encrypt(out, out, key); /* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv2[n]; /* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ iv = out; memcpy(prev, in, AES_BLOCK_SIZE); iv2 = prev; Loading @@ -203,8 +254,6 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, while(len >= AES_BLOCK_SIZE) { out -= AES_BLOCK_SIZE; /* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ /* XXX: reduce copies by alternating between buffers */ memcpy(tmp, out, AES_BLOCK_SIZE); for(n=0 ; n < AES_BLOCK_SIZE ; ++n) Loading Loading @@ -235,17 +284,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, out -= AES_BLOCK_SIZE; memcpy(tmp, in, AES_BLOCK_SIZE); memcpy(tmp2, in, AES_BLOCK_SIZE); /* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) tmp[n] ^= iv2[n]; /* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ AES_decrypt(tmp, out, key); /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv[n]; /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ memcpy(tmp3, tmp2, AES_BLOCK_SIZE); iv = tmp3; iv2 = out; Loading @@ -260,17 +303,11 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, { memcpy(tmp, out, AES_BLOCK_SIZE); memcpy(tmp2, out, AES_BLOCK_SIZE); /* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) tmp[n] ^= iv2[n]; /* hexdump(stdout, "out ^ iv2", tmp, AES_BLOCK_SIZE); */ AES_decrypt(tmp, out, key); /* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ /* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ for(n=0 ; n < AES_BLOCK_SIZE ; ++n) out[n] ^= iv[n]; /* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ memcpy(tmp3, tmp2, AES_BLOCK_SIZE); iv = tmp3; iv2 = out; Loading @@ -278,6 +315,5 @@ void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, in += AES_BLOCK_SIZE; out += AES_BLOCK_SIZE; } } }
test/igetest.c +17 −0 Original line number Diff line number Diff line Loading @@ -218,6 +218,23 @@ static int run_test_vectors(void) hexdump(stdout, "expected", v->out, v->length); hexdump(stdout, "got", buf, v->length); ++errs; } // try with in == out memcpy(iv, v->iv, sizeof iv); memcpy(buf, v->in, v->length); AES_ige_encrypt(buf, buf, v->length, &key, iv, v->encrypt); if(memcmp(v->out, buf, v->length)) { printf("IGE test vector %d failed (with in == out)\n", n); hexdump(stdout, "key", v->key, sizeof v->key); hexdump(stdout, "iv", v->iv, sizeof v->iv); hexdump(stdout, "in", v->in, v->length); hexdump(stdout, "expected", v->out, v->length); hexdump(stdout, "got", buf, v->length); ++errs; } } Loading