aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAris Adamantiadis <aris@0xbadc0de.be>2015-09-25 11:51:45 +0200
committerAris Adamantiadis <aris@0xbadc0de.be>2015-09-25 11:51:45 +0200
commit84a85803b4c83b8dac03b0d0aba58b48c98253e6 (patch)
tree49a81eadd56dce1152ac405c1ddc8b62dbe82369
parentd46fe6a51c0e18a3d23e05c7cc81186acc319271 (diff)
downloadlibssh-84a85803b4c83b8dac03b0d0aba58b48c98253e6.tar.gz
libssh-84a85803b4c83b8dac03b0d0aba58b48c98253e6.tar.xz
libssh-84a85803b4c83b8dac03b0d0aba58b48c98253e6.zip
crypto: old-fashioned aes_ctr when evp_aes_ctr is missing
-rw-r--r--ConfigureChecks.cmake9
-rw-r--r--config.h.cmake6
-rw-r--r--include/libssh/crypto.h1
-rw-r--r--src/libcrypto.c92
4 files changed, 108 insertions, 0 deletions
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index c0326c20..0d068b9c 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -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)
diff --git a/config.h.cmake b/config.h.cmake
index 0685f10c..8d9bfd21 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -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
diff --git a/include/libssh/crypto.h b/include/libssh/crypto.h
index eed93710..e370c748 100644
--- a/include/libssh/crypto.h
+++ b/include/libssh/crypto.h
@@ -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
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",