From fb8f5b39211fc1a77964a6955923d7e5f76d7e2f Mon Sep 17 00:00:00 2001 From: miod Date: Mon, 12 May 2014 19:19:55 +0000 Subject: [PATCH] Remove AES_bi_ige_encrypt() from libcrypto. This routine is supposed to use two keys and four IVs to do much magic, is specified as such with test vectors, but the implementation actually always uses the first key, and the test vectors were computed with it, so they are wrong. Fixing the code to match the intended specification would break interoperability with existing code (assuming such code would exist), so it is better to remove this interface, which is obviously too complex for mere mortals if even its author can not implement it correctly. Riding on the libcrypto major bump. --- lib/libcrypto/aes/aes.h | 4 - lib/libcrypto/aes/aes_ige.c | 112 ----------------------- lib/libssl/src/crypto/aes/aes.h | 4 - lib/libssl/src/crypto/aes/aes_ige.c | 112 ----------------------- regress/lib/libcrypto/ige/igetest.c | 134 ---------------------------- 5 files changed, 366 deletions(-) diff --git a/lib/libcrypto/aes/aes.h b/lib/libcrypto/aes/aes.h index d05f803494b..0b3db6420ba 100644 --- a/lib/libcrypto/aes/aes.h +++ b/lib/libcrypto/aes/aes.h @@ -117,10 +117,6 @@ void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, /* NB: the IV is _two_ blocks long */ void AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc); -/* NB: the IV is _four_ blocks long */ -void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, - size_t length, const AES_KEY *key, const AES_KEY *key2, - const unsigned char *ivec, const int enc); int AES_wrap_key(AES_KEY *key, const unsigned char *iv, unsigned char *out, const unsigned char *in, unsigned int inlen); diff --git a/lib/libcrypto/aes/aes_ige.c b/lib/libcrypto/aes/aes_ige.c index 0882a3d853a..883dff7d295 100644 --- a/lib/libcrypto/aes/aes_ige.c +++ b/lib/libcrypto/aes/aes_ige.c @@ -194,115 +194,3 @@ AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, } } } - -/* - * Note that its effectively impossible to do biIGE in anything other - * than a single pass, so no provision is made for chaining. - */ - -/* N.B. The IV for this mode is _four times_ the block size */ - -void -AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, - const AES_KEY *key, const AES_KEY *key2, const unsigned char *ivec, - const int enc) -{ - size_t n; - size_t len = length; - unsigned char tmp[AES_BLOCK_SIZE]; - unsigned char tmp2[AES_BLOCK_SIZE]; - unsigned char tmp3[AES_BLOCK_SIZE]; - unsigned char prev[AES_BLOCK_SIZE]; - const unsigned char *iv; - const unsigned char *iv2; - - OPENSSL_assert(in && out && key && ivec); - OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); - OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); - - if (AES_ENCRYPT == enc) { - /* XXX: Do a separate case for when in != out (strictly should - check for overlap, too) */ - - /* First the forward pass */ - iv = ivec; - iv2 = ivec + AES_BLOCK_SIZE; - while (len >= AES_BLOCK_SIZE) { - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] = in[n] ^ iv[n]; - AES_encrypt(out, out, key); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= iv2[n]; - iv = out; - memcpy(prev, in, AES_BLOCK_SIZE); - iv2 = prev; - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - - /* And now backwards */ - iv = ivec + AES_BLOCK_SIZE*2; - iv2 = ivec + AES_BLOCK_SIZE*3; - len = length; - while (len >= AES_BLOCK_SIZE) { - out -= AES_BLOCK_SIZE; - /* XXX: reduce copies by alternating between buffers */ - memcpy(tmp, out, AES_BLOCK_SIZE); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= iv[n]; - /* hexdump(stdout, "out ^ 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, tmp, AES_BLOCK_SIZE); - iv2 = prev; - len -= AES_BLOCK_SIZE; - } - } else { - /* First backwards */ - iv = ivec + AES_BLOCK_SIZE*2; - iv2 = ivec + AES_BLOCK_SIZE*3; - in += length; - out += length; - while (len >= AES_BLOCK_SIZE) { - in -= AES_BLOCK_SIZE; - out -= AES_BLOCK_SIZE; - memcpy(tmp, in, AES_BLOCK_SIZE); - memcpy(tmp2, in, AES_BLOCK_SIZE); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - tmp[n] ^= iv2[n]; - AES_decrypt(tmp, out, key); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= iv[n]; - memcpy(tmp3, tmp2, AES_BLOCK_SIZE); - iv = tmp3; - iv2 = out; - len -= AES_BLOCK_SIZE; - } - - /* And now forwards */ - iv = ivec; - iv2 = ivec + AES_BLOCK_SIZE; - len = length; - while (len >= AES_BLOCK_SIZE) { - memcpy(tmp, out, AES_BLOCK_SIZE); - memcpy(tmp2, out, AES_BLOCK_SIZE); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - tmp[n] ^= iv2[n]; - AES_decrypt(tmp, out, key); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= iv[n]; - memcpy(tmp3, tmp2, AES_BLOCK_SIZE); - iv = tmp3; - iv2 = out; - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - } -} diff --git a/lib/libssl/src/crypto/aes/aes.h b/lib/libssl/src/crypto/aes/aes.h index d05f803494b..0b3db6420ba 100644 --- a/lib/libssl/src/crypto/aes/aes.h +++ b/lib/libssl/src/crypto/aes/aes.h @@ -117,10 +117,6 @@ void AES_ctr128_encrypt(const unsigned char *in, unsigned char *out, /* NB: the IV is _two_ blocks long */ void AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc); -/* NB: the IV is _four_ blocks long */ -void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, - size_t length, const AES_KEY *key, const AES_KEY *key2, - const unsigned char *ivec, const int enc); int AES_wrap_key(AES_KEY *key, const unsigned char *iv, unsigned char *out, const unsigned char *in, unsigned int inlen); diff --git a/lib/libssl/src/crypto/aes/aes_ige.c b/lib/libssl/src/crypto/aes/aes_ige.c index 0882a3d853a..883dff7d295 100644 --- a/lib/libssl/src/crypto/aes/aes_ige.c +++ b/lib/libssl/src/crypto/aes/aes_ige.c @@ -194,115 +194,3 @@ AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, } } } - -/* - * Note that its effectively impossible to do biIGE in anything other - * than a single pass, so no provision is made for chaining. - */ - -/* N.B. The IV for this mode is _four times_ the block size */ - -void -AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, - const AES_KEY *key, const AES_KEY *key2, const unsigned char *ivec, - const int enc) -{ - size_t n; - size_t len = length; - unsigned char tmp[AES_BLOCK_SIZE]; - unsigned char tmp2[AES_BLOCK_SIZE]; - unsigned char tmp3[AES_BLOCK_SIZE]; - unsigned char prev[AES_BLOCK_SIZE]; - const unsigned char *iv; - const unsigned char *iv2; - - OPENSSL_assert(in && out && key && ivec); - OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc)); - OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); - - if (AES_ENCRYPT == enc) { - /* XXX: Do a separate case for when in != out (strictly should - check for overlap, too) */ - - /* First the forward pass */ - iv = ivec; - iv2 = ivec + AES_BLOCK_SIZE; - while (len >= AES_BLOCK_SIZE) { - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] = in[n] ^ iv[n]; - AES_encrypt(out, out, key); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= iv2[n]; - iv = out; - memcpy(prev, in, AES_BLOCK_SIZE); - iv2 = prev; - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - - /* And now backwards */ - iv = ivec + AES_BLOCK_SIZE*2; - iv2 = ivec + AES_BLOCK_SIZE*3; - len = length; - while (len >= AES_BLOCK_SIZE) { - out -= AES_BLOCK_SIZE; - /* XXX: reduce copies by alternating between buffers */ - memcpy(tmp, out, AES_BLOCK_SIZE); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= iv[n]; - /* hexdump(stdout, "out ^ 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, tmp, AES_BLOCK_SIZE); - iv2 = prev; - len -= AES_BLOCK_SIZE; - } - } else { - /* First backwards */ - iv = ivec + AES_BLOCK_SIZE*2; - iv2 = ivec + AES_BLOCK_SIZE*3; - in += length; - out += length; - while (len >= AES_BLOCK_SIZE) { - in -= AES_BLOCK_SIZE; - out -= AES_BLOCK_SIZE; - memcpy(tmp, in, AES_BLOCK_SIZE); - memcpy(tmp2, in, AES_BLOCK_SIZE); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - tmp[n] ^= iv2[n]; - AES_decrypt(tmp, out, key); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= iv[n]; - memcpy(tmp3, tmp2, AES_BLOCK_SIZE); - iv = tmp3; - iv2 = out; - len -= AES_BLOCK_SIZE; - } - - /* And now forwards */ - iv = ivec; - iv2 = ivec + AES_BLOCK_SIZE; - len = length; - while (len >= AES_BLOCK_SIZE) { - memcpy(tmp, out, AES_BLOCK_SIZE); - memcpy(tmp2, out, AES_BLOCK_SIZE); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - tmp[n] ^= iv2[n]; - AES_decrypt(tmp, out, key); - for (n = 0; n < AES_BLOCK_SIZE; ++n) - out[n] ^= iv[n]; - memcpy(tmp3, tmp2, AES_BLOCK_SIZE); - iv = tmp3; - iv2 = out; - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - } -} diff --git a/regress/lib/libcrypto/ige/igetest.c b/regress/lib/libcrypto/ige/igetest.c index 1ba900244de..b3e7280bbd0 100644 --- a/regress/lib/libcrypto/ige/igetest.c +++ b/regress/lib/libcrypto/ige/igetest.c @@ -118,76 +118,6 @@ static struct ige_test const ige_test_vectors[] = { 32, AES_DECRYPT }, /* test vector 1 */ }; -struct bi_ige_test - { - const unsigned char key1[32]; - const unsigned char key2[32]; - const unsigned char iv[64]; - const unsigned char in[MAX_VECTOR_SIZE]; - const unsigned char out[MAX_VECTOR_SIZE]; - const size_t keysize; - const size_t length; - const int encrypt; - }; - -static struct bi_ige_test const bi_ige_test_vectors[] = { -{ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* key1 */ - { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, /* key2 */ - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f }, /* iv */ - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* in */ - { 0x14, 0x40, 0x6f, 0xae, 0xa2, 0x79, 0xf2, 0x56, - 0x1f, 0x86, 0xeb, 0x3b, 0x7d, 0xff, 0x53, 0xdc, - 0x4e, 0x27, 0x0c, 0x03, 0xde, 0x7c, 0xe5, 0x16, - 0x6a, 0x9c, 0x20, 0x33, 0x9d, 0x33, 0xfe, 0x12 }, /* out */ - 16, 32, AES_ENCRYPT }, /* test vector 0 */ -{ { 0x58, 0x0a, 0x06, 0xe9, 0x97, 0x07, 0x59, 0x5c, - 0x9e, 0x19, 0xd2, 0xa7, 0xbb, 0x40, 0x2b, 0x7a, - 0xc7, 0xd8, 0x11, 0x9e, 0x4c, 0x51, 0x35, 0x75, - 0x64, 0x28, 0x0f, 0x23, 0xad, 0x74, 0xac, 0x37 }, /* key1 */ - { 0xd1, 0x80, 0xa0, 0x31, 0x47, 0xa3, 0x11, 0x13, - 0x86, 0x26, 0x9e, 0x6d, 0xff, 0xaf, 0x72, 0x74, - 0x5b, 0xa2, 0x35, 0x81, 0xd2, 0xa6, 0x3d, 0x21, - 0x67, 0x7b, 0x58, 0xa8, 0x18, 0xf9, 0x72, 0xe4 }, /* key2 */ - { 0x80, 0x3d, 0xbd, 0x4c, 0xe6, 0x7b, 0x06, 0xa9, - 0x53, 0x35, 0xd5, 0x7e, 0x71, 0xc1, 0x70, 0x70, - 0x74, 0x9a, 0x00, 0x28, 0x0c, 0xbf, 0x6c, 0x42, - 0x9b, 0xa4, 0xdd, 0x65, 0x11, 0x77, 0x7c, 0x67, - 0xfe, 0x76, 0x0a, 0xf0, 0xd5, 0xc6, 0x6e, 0x6a, - 0xe7, 0x5e, 0x4c, 0xf2, 0x7e, 0x9e, 0xf9, 0x20, - 0x0e, 0x54, 0x6f, 0x2d, 0x8a, 0x8d, 0x7e, 0xbd, - 0x48, 0x79, 0x37, 0x99, 0xff, 0x27, 0x93, 0xa3 }, /* iv */ - { 0xf1, 0x54, 0x3d, 0xca, 0xfe, 0xb5, 0xef, 0x1c, - 0x4f, 0xa6, 0x43, 0xf6, 0xe6, 0x48, 0x57, 0xf0, - 0xee, 0x15, 0x7f, 0xe3, 0xe7, 0x2f, 0xd0, 0x2f, - 0x11, 0x95, 0x7a, 0x17, 0x00, 0xab, 0xa7, 0x0b, - 0xbe, 0x44, 0x09, 0x9c, 0xcd, 0xac, 0xa8, 0x52, - 0xa1, 0x8e, 0x7b, 0x75, 0xbc, 0xa4, 0x92, 0x5a, - 0xab, 0x46, 0xd3, 0x3a, 0xa0, 0xd5, 0x35, 0x1c, - 0x55, 0xa4, 0xb3, 0xa8, 0x40, 0x81, 0xa5, 0x0b}, /* in */ - { 0x42, 0xe5, 0x28, 0x30, 0x31, 0xc2, 0xa0, 0x23, - 0x68, 0x49, 0x4e, 0xb3, 0x24, 0x59, 0x92, 0x79, - 0xc1, 0xa5, 0xcc, 0xe6, 0x76, 0x53, 0xb1, 0xcf, - 0x20, 0x86, 0x23, 0xe8, 0x72, 0x55, 0x99, 0x92, - 0x0d, 0x16, 0x1c, 0x5a, 0x2f, 0xce, 0xcb, 0x51, - 0xe2, 0x67, 0xfa, 0x10, 0xec, 0xcd, 0x3d, 0x67, - 0xa5, 0xe6, 0xf7, 0x31, 0x26, 0xb0, 0x0d, 0x76, - 0x5e, 0x28, 0xdc, 0x7f, 0x01, 0xc5, 0xa5, 0x4c}, /* out */ - 32, 64, AES_ENCRYPT }, /* test vector 1 */ - -}; - static int run_test_vectors(void) { unsigned int n; @@ -239,44 +169,6 @@ static int run_test_vectors(void) } } - for(n=0 ; n < sizeof(bi_ige_test_vectors)/sizeof(bi_ige_test_vectors[0]) - ; ++n) - { - const struct bi_ige_test * const v = &bi_ige_test_vectors[n]; - AES_KEY key1; - AES_KEY key2; - unsigned char buf[MAX_VECTOR_SIZE]; - - assert(v->length <= MAX_VECTOR_SIZE); - - if(v->encrypt == AES_ENCRYPT) - { - AES_set_encrypt_key(v->key1, 8*v->keysize, &key1); - AES_set_encrypt_key(v->key2, 8*v->keysize, &key2); - } - else - { - AES_set_decrypt_key(v->key1, 8*v->keysize, &key1); - AES_set_decrypt_key(v->key2, 8*v->keysize, &key2); - } - - AES_bi_ige_encrypt(v->in, buf, v->length, &key1, &key2, v->iv, - v->encrypt); - - if(memcmp(v->out, buf, v->length)) - { - printf("Bidirectional IGE test vector %d failed\n", n); - hexdump(stdout, "key 1", v->key1, sizeof v->key1); - hexdump(stdout, "key 2", v->key2, sizeof v->key2); - 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; - } - } - return errs; } @@ -399,32 +291,6 @@ int main(int argc, char **argv) ++err; } - /* Bi-directional IGE */ - - /* Note that we don't have to recover the IV, because chaining isn't */ - /* possible with biIGE, so the IV is not updated. */ - - RAND_pseudo_bytes(rkey2, sizeof rkey2); - - /* Straight encrypt/decrypt */ - AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); - AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2); - AES_bi_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, &key2, iv, - AES_ENCRYPT); - - AES_set_decrypt_key(rkey, 8*sizeof rkey, &key); - AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2); - AES_bi_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, &key2, iv, - AES_DECRYPT); - - if(memcmp(checktext, plaintext, TEST_SIZE)) - { - printf("Encrypt+decrypt doesn't match\n"); - hexdump(stdout, "Plaintext", plaintext, TEST_SIZE); - hexdump(stdout, "Checktext", checktext, TEST_SIZE); - ++err; - } - /* make sure garble extends both ways */ AES_set_encrypt_key(rkey, 8*sizeof rkey, &key); AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2); -- 2.20.1