diff options
author | Aris Adamantiadis <aris@0xbadc0de.be> | 2015-09-25 11:51:45 +0200 |
---|---|---|
committer | Aris Adamantiadis <aris@0xbadc0de.be> | 2015-09-25 11:51:45 +0200 |
commit | 84a85803b4c83b8dac03b0d0aba58b48c98253e6 (patch) | |
tree | 49a81eadd56dce1152ac405c1ddc8b62dbe82369 /src/libcrypto.c | |
parent | d46fe6a51c0e18a3d23e05c7cc81186acc319271 (diff) | |
download | libssh-84a85803b4c83b8dac03b0d0aba58b48c98253e6.tar.gz libssh-84a85803b4c83b8dac03b0d0aba58b48c98253e6.tar.xz libssh-84a85803b4c83b8dac03b0d0aba58b48c98253e6.zip |
crypto: old-fashioned aes_ctr when evp_aes_ctr is missing
Diffstat (limited to 'src/libcrypto.c')
-rw-r--r-- | src/libcrypto.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/src/libcrypto.c b/src/libcrypto.c index 4524628b..bf75f261 100644 --- a/src/libcrypto.c +++ b/src/libcrypto.c @@ -438,6 +438,7 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) { case SSH_AES256_CBC: cipher->cipher = EVP_aes_256_cbc(); break; +#ifdef HAVE_OPENSSL_EVP_AES_CTR case SSH_AES128_CTR: cipher->cipher = EVP_aes_128_ctr(); break; @@ -447,6 +448,13 @@ static void evp_cipher_init(struct ssh_cipher_struct *cipher) { case SSH_AES256_CTR: cipher->cipher = EVP_aes_256_ctr(); break; +#else + case SSH_AES128_CTR: + case SSH_AES192_CTR: + case SSH_AES256_CTR: + SSH_LOG(SSH_LOG_WARNING, "This cipher is not available in evp_cipher_init"); + break; +#endif case SSH_3DES_CBC: cipher->cipher = EVP_des_ede3_cbc(); break; @@ -540,6 +548,54 @@ static void evp_cipher_cleanup(struct ssh_cipher_struct *cipher) { EVP_CIPHER_CTX_cleanup(&cipher->ctx); } +#ifndef HAVE_EVP_AES_CTR +/* Some OS (osx, OpenIndiana, ...) have no support for CTR ciphers in EVP_aes */ + +struct ssh_aes_key_schedule { + AES_KEY key; + uint8_t IV[AES_BLOCK_SIZE]; +}; + +static int aes_ctr_set_key(struct ssh_cipher_struct *cipher, void *key, + void *IV) { + int rc; + + if (cipher->aes_key == NULL) { + cipher->aes_key = malloc(sizeof (struct ssh_aes_key_schedule)); + } + if (cipher->aes_key == NULL) { + return SSH_ERROR; + } + ZERO_STRUCTP(cipher->aes_key); + /* CTR doesn't need a decryption key */ + rc = AES_set_encrypt_key(key, cipher->keysize, &cipher->aes_key->key); + if (rc < 0) { + SAFE_FREE(cipher->aes_key); + return SSH_ERROR; + } + memcpy(cipher->aes_key->IV, IV, AES_BLOCK_SIZE); + return SSH_OK; +} + +static void aes_ctr_encrypt(struct ssh_cipher_struct *cipher, void *in, void *out, + unsigned long len) { + unsigned char tmp_buffer[AES_BLOCK_SIZE]; + unsigned int num=0; + /* Some things are special with ctr128 : + * In this case, tmp_buffer is not being used, because it is used to store temporary data + * when an encryption is made on lengths that are not multiple of blocksize. + * Same for num, which is being used to store the current offset in blocksize in CTR + * function. + */ + AES_ctr128_encrypt(in, out, len, &cipher->aes_key->key, cipher->aes_key->IV, tmp_buffer, &num); +} + +static void aes_ctr_cleanup(struct ssh_cipher_struct *cipher){ + BURN_BUFFER(cipher->aes_key, sizeof(*cipher->aes_key)); + SAFE_FREE(cipher->aes_key); +} + +#endif /* HAVE_EVP_AES_CTR */ #ifdef HAS_DES typedef uint8_t des_iv_t[8]; @@ -647,6 +703,7 @@ static struct ssh_cipher_struct ssh_ciphertab[] = { /* OpenSSL until 0.9.7c has a broken AES_ctr128_encrypt implementation which * increments the counter from 2^64 instead of 1. It's better not to use it */ +#ifdef HAVE_OPENSSL_EVP_AES_CTR { .name = "aes128-ctr", .blocksize = 16, @@ -680,6 +737,41 @@ static struct ssh_cipher_struct ssh_ciphertab[] = { .decrypt = evp_cipher_decrypt, .cleanup = evp_cipher_cleanup }, +#else /* HAVE_OPENSSL_EVP_AES_CTR */ + { + .name = "aes128-ctr", + .blocksize = 16, + .ciphertype = SSH_AES128_CTR, + .keysize = 128, + .set_encrypt_key = aes_ctr_set_key, + .set_decrypt_key = aes_ctr_set_key, + .encrypt = aes_ctr_encrypt, + .decrypt = aes_ctr_encrypt, + .cleanup = aes_ctr_cleanup + }, + { + .name = "aes192-ctr", + .blocksize = 16, + .ciphertype = SSH_AES192_CTR, + .keysize = 192, + .set_encrypt_key = aes_ctr_set_key, + .set_decrypt_key = aes_ctr_set_key, + .encrypt = aes_ctr_encrypt, + .decrypt = aes_ctr_encrypt, + .cleanup = aes_ctr_cleanup + }, + { + .name = "aes256-ctr", + .blocksize = 16, + .ciphertype = SSH_AES256_CTR, + .keysize = 256, + .set_encrypt_key = aes_ctr_set_key, + .set_decrypt_key = aes_ctr_set_key, + .encrypt = aes_ctr_encrypt, + .decrypt = aes_ctr_encrypt, + .cleanup = aes_ctr_cleanup + }, +#endif /* HAVE_OPENSSL_EVP_AES_CTR */ #endif /* BROKEN_AES_CTR */ { .name = "aes128-cbc", |