1
0
mirror of https://git.libssh.org/projects/libssh.git synced 2025-05-28 17:41:28 +03:00

crypto: old-fashioned aes_ctr when evp_aes_ctr is missing

This commit is contained in:
Aris Adamantiadis 2015-09-25 11:51:45 +02:00
parent d46fe6a51c
commit 84a85803b4
4 changed files with 108 additions and 0 deletions

View File

@ -89,6 +89,15 @@ if (OPENSSL_FOUND)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
check_include_file(openssl/ecdsa.h HAVE_OPENSSL_ECDSA_H)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
check_symbol_exists(EVP_aes_128_ctr openssl/evp.h HAVE_OPENSSL_EVP_AES_CTR)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY})
check_symbol_exists(EVP_aes_128_cbc openssl/evp.h HAVE_OPENSSL_EVP_AES_CBC)
endif()
if (CMAKE_HAVE_PTHREAD_H)

View File

@ -76,6 +76,12 @@
/*************************** FUNCTIONS ***************************/
/* Define to 1 if you have the `EVP_aes128_ctr' function. */
#cmakedefine HAVE_OPENSSL_EVP_AES_CTR 1
/* Define to 1 if you have the `EVP_aes128_cbc' function. */
#cmakedefine HAVE_OPENSSL_EVP_AES_CBC 1
/* Define to 1 if you have the `snprintf' function. */
#cmakedefine HAVE_SNPRINTF 1

View File

@ -124,6 +124,7 @@ struct ssh_cipher_struct {
gcry_cipher_hd_t *key;
#elif defined HAVE_LIBCRYPTO
struct ssh_3des_key_schedule *des3_key;
struct ssh_aes_key_schedule *aes_key;
const EVP_CIPHER *cipher;
EVP_CIPHER_CTX ctx;
#endif

View File

@ -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",