1
1

Move symmetric OpenSSL EVP crypto calls to crypt.c.

Этот коммит содержится в:
Simon Josefsson 2006-12-07 15:44:07 +00:00
родитель 82d762cae5
Коммит 14b9deef24
5 изменённых файлов: 115 добавлений и 153 удалений

@ -61,15 +61,66 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_none = {
}; };
#endif #endif
#define MAKE_INIT(name, cipher) \
static int name (LIBSSH2_SESSION *session, \
unsigned char *iv, int *free_iv, \
unsigned char *secret, int *free_secret, \
int encrypt, void **abstract) \
{ \
EVP_CIPHER_CTX *ctx = LIBSSH2_ALLOC(session, sizeof(EVP_CIPHER_CTX)); \
if (!ctx) \
return -1; \
EVP_CIPHER_CTX_init(ctx); \
EVP_CipherInit(ctx, cipher, secret, iv, encrypt); \
*abstract = ctx; \
*free_iv = 1; \
*free_secret = 1; \
return 0; \
}
MAKE_INIT(aes256_init, EVP_aes_256_cbc())
MAKE_INIT(aes192_init, EVP_aes_192_cbc())
MAKE_INIT(aes128_init, EVP_aes_128_cbc())
MAKE_INIT(blowfish_init, EVP_bf_cbc())
MAKE_INIT(arcfour_init, EVP_rc4())
MAKE_INIT(cast128_init, EVP_cast5_cbc())
MAKE_INIT(des3_init, EVP_des_ede3_cbc())
int crypt(LIBSSH2_SESSION *session, unsigned char *block, void **abstract)
{
EVP_CIPHER_CTX *ctx = *(EVP_CIPHER_CTX **)abstract;
int blocksize = ctx->cipher->block_size;
unsigned char buf[EVP_MAX_BLOCK_LENGTH];
int ret;
if (blocksize == 1) /* Hack for arcfour. */
blocksize = 8;
ret = EVP_Cipher(ctx, buf, block, blocksize);
if (ret == 1)
memcpy(block, buf, blocksize);
return ret == 1 ? 0 : 1;
}
int dtor(LIBSSH2_SESSION *session, void **abstract)
{
EVP_CIPHER_CTX **ctx = (EVP_CIPHER_CTX **)abstract;
if (ctx && *ctx)
{
EVP_CIPHER_CTX_cleanup(*ctx);
LIBSSH2_FREE(session, *ctx);
*abstract = NULL;
}
return 0;
}
static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = { static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = {
"3des-cbc", "3des-cbc",
8, /* blocksize */ 8, /* blocksize */
8, /* initial value length */ 8, /* initial value length */
24, /* secret length */ 24, /* secret length */
LIBSSH2_CRYPT_METHOD_FLAG_EVP, 0, /* flags */
NULL, &des3_init,
(void*)EVP_des_ede3_cbc, &crypt,
NULL, &dtor
}; };
#if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES) #if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)
@ -78,10 +129,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
16, /* blocksize */ 16, /* blocksize */
16, /* initial value length */ 16, /* initial value length */
16, /* secret length -- 16*8 == 128bit */ 16, /* secret length -- 16*8 == 128bit */
LIBSSH2_CRYPT_METHOD_FLAG_EVP, 0, /* flags */
NULL, &aes128_init,
(void*)EVP_aes_128_cbc, &crypt,
NULL, &dtor
}; };
static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = { static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = {
@ -89,10 +140,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_cbc = {
16, /* blocksize */ 16, /* blocksize */
16, /* initial value length */ 16, /* initial value length */
24, /* secret length -- 24*8 == 192bit */ 24, /* secret length -- 24*8 == 192bit */
LIBSSH2_CRYPT_METHOD_FLAG_EVP, 0, /* flags */
NULL, &aes192_init,
(void*)EVP_aes_192_cbc, &crypt,
NULL, &dtor
}; };
static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = { static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = {
@ -100,10 +151,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_cbc = {
16, /* blocksize */ 16, /* blocksize */
16, /* initial value length */ 16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */ 32, /* secret length -- 32*8 == 256bit */
LIBSSH2_CRYPT_METHOD_FLAG_EVP, 0, /* flags */
NULL, &aes256_init,
(void*)EVP_aes_256_cbc, &crypt,
NULL, &dtor
}; };
/* rijndael-cbc@lysator.liu.se == aes256-cbc */ /* rijndael-cbc@lysator.liu.se == aes256-cbc */
@ -112,10 +163,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_rijndael_cbc_lysator_liu_se = {
16, /* blocksize */ 16, /* blocksize */
16, /* initial value length */ 16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */ 32, /* secret length -- 32*8 == 256bit */
LIBSSH2_CRYPT_METHOD_FLAG_EVP, 0, /* flags */
NULL, &aes256_init,
(void*)EVP_aes_256_cbc, &crypt,
NULL, &dtor
}; };
#endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)*/ #endif /* OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)*/
@ -125,10 +176,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_blowfish_cbc = {
8, /* blocksize */ 8, /* blocksize */
8, /* initial value length */ 8, /* initial value length */
16, /* secret length */ 16, /* secret length */
LIBSSH2_CRYPT_METHOD_FLAG_EVP, 0, /* flags */
NULL, &blowfish_init,
(void*)EVP_bf_cbc, &crypt,
NULL, &dtor
}; };
#endif /* ! OPENSSL_NO_BLOWFISH */ #endif /* ! OPENSSL_NO_BLOWFISH */
@ -138,10 +189,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = {
8, /* blocksize */ 8, /* blocksize */
8, /* initial value length */ 8, /* initial value length */
16, /* secret length */ 16, /* secret length */
LIBSSH2_CRYPT_METHOD_FLAG_EVP, 0, /* flags */
NULL, &cast128_init,
(void*)EVP_cast5_cbc, &crypt,
NULL, &dtor
}; };
#endif /* ! OPENSSL_NO_CAST */ #endif /* ! OPENSSL_NO_CAST */
@ -151,10 +202,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = {
8, /* blocksize */ 8, /* blocksize */
8, /* initial value length */ 8, /* initial value length */
16, /* secret length */ 16, /* secret length */
LIBSSH2_CRYPT_METHOD_FLAG_EVP, 0, /* flags */
NULL, &arcfour_init,
(void*)EVP_rc4, &crypt,
NULL, &dtor
}; };
#endif /* ! OPENSSL_NO_RC4 */ #endif /* ! OPENSSL_NO_RC4 */

@ -38,7 +38,6 @@
#include "libssh2_priv.h" #include "libssh2_priv.h"
#include <openssl/bn.h> #include <openssl/bn.h>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/rand.h> #include <openssl/rand.h>
/* TODO: Switch this to an inline and handle alloc() failures */ /* TODO: Switch this to an inline and handle alloc() failures */
@ -331,45 +330,23 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
#endif #endif
} }
/* Calculate IV/Secret/Key for each direction */ /* Cleanup any existing cipher */
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { if (session->local.crypt->dtor) {
if (session->local.crypt_abstract) { session->local.crypt->dtor(session, &session->local.crypt_abstract);
EVP_CIPHER_CTX_cleanup(session->local.crypt_abstract);
LIBSSH2_FREE(session, session->local.crypt_abstract);
session->local.crypt_abstract = NULL;
}
} else {
if (session->local.crypt->dtor) {
/* Cleanup any existing cipher */
session->local.crypt->dtor(session, &session->local.crypt_abstract);
}
} }
if (session->local.crypt->init || (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP)) { /* Calculate IV/Secret/Key for each direction */
if (session->local.crypt->init) {
unsigned char *iv = NULL, *secret = NULL; unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0; int free_iv = 0, free_secret = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv, session->local.crypt->iv_len, "A"); LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv, session->local.crypt->iv_len, "A");
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, session->local.crypt->secret_len, "C"); LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, session->local.crypt->secret_len, "C");
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { if (session->local.crypt->init(session, iv, &free_iv, secret, &free_secret, 1, &session->local.crypt_abstract)) {
EVP_CIPHER *(*get_cipher)(void) = (void*)session->local.crypt->crypt; LIBSSH2_FREE(session, iv);
EVP_CIPHER *cipher = get_cipher(); LIBSSH2_FREE(session, secret);
EVP_CIPHER_CTX *ctx; ret = -1;
goto clean_exit;
ctx = LIBSSH2_ALLOC(session, sizeof(EVP_CIPHER_CTX));
if (!ctx) {
LIBSSH2_FREE(session, iv);
LIBSSH2_FREE(session, secret);
ret = -1;
goto clean_exit;
}
EVP_CIPHER_CTX_init(ctx);
EVP_CipherInit(ctx, cipher, secret, iv, 1);
session->local.crypt_abstract = ctx;
free_iv = 1;
free_secret = 1;
} else {
session->local.crypt->init(session, iv, &free_iv, secret, &free_secret, 1, &session->local.crypt_abstract);
} }
if (free_iv) { if (free_iv) {
@ -386,44 +363,22 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
_libssh2_debug(session, LIBSSH2_DBG_KEX, "Client to Server IV and Key calculated"); _libssh2_debug(session, LIBSSH2_DBG_KEX, "Client to Server IV and Key calculated");
#endif #endif
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { if (session->remote.crypt->dtor) {
if (session->remote.crypt_abstract) { /* Cleanup any existing cipher */
EVP_CIPHER_CTX_cleanup(session->remote.crypt_abstract); session->remote.crypt->dtor(session, &session->remote.crypt_abstract);
LIBSSH2_FREE(session, session->remote.crypt_abstract);
session->remote.crypt_abstract = NULL;
}
} else {
if (session->remote.crypt->dtor) {
/* Cleanup any existing cipher */
session->remote.crypt->dtor(session, &session->remote.crypt_abstract);
}
} }
if (session->remote.crypt->init || (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP)) { if (session->remote.crypt->init) {
unsigned char *iv = NULL, *secret = NULL; unsigned char *iv = NULL, *secret = NULL;
int free_iv = 0, free_secret = 0; int free_iv = 0, free_secret = 0;
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv, session->remote.crypt->iv_len, "B"); LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(iv, session->remote.crypt->iv_len, "B");
LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, session->remote.crypt->secret_len, "D"); LIBSSH2_KEX_METHOD_DIFFIE_HELLMAN_SHA1_HASH(secret, session->remote.crypt->secret_len, "D");
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { if (session->remote.crypt->init(session, iv, &free_iv, secret, &free_secret, 0, &session->remote.crypt_abstract)) {
EVP_CIPHER *(*get_cipher)(void) = (void*)session->remote.crypt->crypt; LIBSSH2_FREE(session, iv);
EVP_CIPHER *cipher = get_cipher(); LIBSSH2_FREE(session, secret);
EVP_CIPHER_CTX *ctx; ret = -1;
goto clean_exit;
ctx = LIBSSH2_ALLOC(session, sizeof(EVP_CIPHER_CTX));
if (!ctx) {
LIBSSH2_FREE(session, iv);
LIBSSH2_FREE(session, secret);
ret = -1;
goto clean_exit;
}
EVP_CIPHER_CTX_init(ctx);
EVP_CipherInit(ctx, cipher, secret, iv, 0);
session->remote.crypt_abstract = ctx;
free_iv = 1;
free_secret = 1;
} else {
session->remote.crypt->init(session, iv, &free_iv, secret, &free_secret, 0, &session->remote.crypt_abstract);
} }
if (free_iv) { if (free_iv) {

@ -282,12 +282,6 @@ struct _LIBSSH2_HOSTKEY_METHOD {
int (*dtor)(LIBSSH2_SESSION *session, void **abstract); int (*dtor)(LIBSSH2_SESSION *session, void **abstract);
}; };
/* When FLAG_EVP is set, crypt contains a pointer to an EVP_CIPHER generator and init and dtor are ignored
* Yes, I know it's a hack.
*/
#define LIBSSH2_CRYPT_METHOD_FLAG_EVP 0x0001
struct _LIBSSH2_CRYPT_METHOD { struct _LIBSSH2_CRYPT_METHOD {
char *name; char *name;

@ -41,7 +41,6 @@
#ifndef WIN32 #ifndef WIN32
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <openssl/evp.h>
#include <openssl/rand.h> #include <openssl/rand.h>
/* Needed for struct iovec on some platforms */ /* Needed for struct iovec on some platforms */
@ -754,9 +753,6 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
int macstate; int macstate;
int free_payload = 1; int free_payload = 1;
/* Safely ignored in CUSTOM cipher mode */
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)session->remote.crypt_abstract;
/* Note: If we add any cipher with a blocksize less than 6 we'll need to get more creative with this /* Note: If we add any cipher with a blocksize less than 6 we'll need to get more creative with this
* For now, all blocksize sizes are 8+ * For now, all blocksize sizes are 8+
*/ */
@ -780,14 +776,9 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1; return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1;
} }
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) {
EVP_Cipher(ctx, block + blocksize, block, blocksize); libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0);
memcpy(block, block + blocksize, blocksize); return -1;
} else {
if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0);
return -1;
}
} }
packet_len = libssh2_ntohu32(block); packet_len = libssh2_ntohu32(block);
@ -838,17 +829,12 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
while (s < p) { while (s < p) {
memcpy(block, s, blocksize); memcpy(block, s, blocksize);
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) {
EVP_Cipher(ctx, block + blocksize, block, blocksize); libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0);
memcpy(s, block + blocksize, blocksize); LIBSSH2_FREE(session, payload);
} else { return -1;
if (session->remote.crypt->crypt(session, block, &session->remote.crypt_abstract)) {
libssh2_error(session, LIBSSH2_ERROR_DECRYPT, "Error decrypting packet preamble", 0);
LIBSSH2_FREE(session, payload);
return -1;
}
memcpy(s, block, blocksize);
} }
memcpy(s, block, blocksize);
s += blocksize; s += blocksize;
} }
@ -1225,9 +1211,6 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
unsigned char *encbuf, *s; unsigned char *encbuf, *s;
int ret, size, written = 0; int ret, size, written = 0;
/* Safely ignored in CUSTOM cipher mode */
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX *)session->local.crypt_abstract;
/* include packet_length(4) itself and room for the hash at the end */ /* include packet_length(4) itself and room for the hash at the end */
encbuf = LIBSSH2_ALLOC(session, 4 + packet_length + session->local.mac->mac_len); encbuf = LIBSSH2_ALLOC(session, 4 + packet_length + session->local.mac->mac_len);
if (!encbuf) { if (!encbuf) {
@ -1251,12 +1234,7 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
/* Encrypt data */ /* Encrypt data */
for(s = encbuf; (s - encbuf) < (4 + packet_length) ; s += session->local.crypt->blocksize) { for(s = encbuf; (s - encbuf) < (4 + packet_length) ; s += session->local.crypt->blocksize) {
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { session->local.crypt->crypt(session, s, &session->local.crypt_abstract);
EVP_Cipher(ctx, buf, s, session->local.crypt->blocksize);
memcpy(s, buf, session->local.crypt->blocksize);
} else {
session->local.crypt->crypt(session, s, &session->local.crypt_abstract);
}
} }
session->local.seqno++; session->local.seqno++;

@ -410,16 +410,8 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
/* Client to Server */ /* Client to Server */
/* crypt */ /* crypt */
if (session->local.crypt) { if (session->local.crypt && session->local.crypt->dtor) {
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { session->local.crypt->dtor(session, &session->local.crypt_abstract);
if (session->local.crypt_abstract) {
EVP_CIPHER_CTX_cleanup(session->local.crypt_abstract);
LIBSSH2_FREE(session, session->local.crypt_abstract);
session->local.crypt_abstract = NULL;
}
} else if (session->local.crypt->dtor) {
session->local.crypt->dtor(session, &session->local.crypt_abstract);
}
} }
/* comp */ /* comp */
if (session->local.comp && session->local.comp->dtor) { if (session->local.comp && session->local.comp->dtor) {
@ -432,16 +424,8 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
/* Server to Client */ /* Server to Client */
/* crypt */ /* crypt */
if (session->remote.crypt) { if (session->remote.crypt && session->remote.crypt->dtor) {
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) { session->remote.crypt->dtor(session, &session->remote.crypt_abstract);
if (session->remote.crypt_abstract) {
EVP_CIPHER_CTX_cleanup(session->remote.crypt_abstract);
LIBSSH2_FREE(session, session->remote.crypt_abstract);
session->remote.crypt_abstract = NULL;
}
} else if (session->remote.crypt->dtor) {
session->remote.crypt->dtor(session, &session->remote.crypt_abstract);
}
} }
/* comp */ /* comp */
if (session->remote.comp && session->remote.comp->dtor) { if (session->remote.comp && session->remote.comp->dtor) {