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
#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 = {
"3des-cbc",
8, /* blocksize */
8, /* initial value length */
24, /* secret length */
LIBSSH2_CRYPT_METHOD_FLAG_EVP,
NULL,
(void*)EVP_des_ede3_cbc,
NULL,
0, /* flags */
&des3_init,
&crypt,
&dtor
};
#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, /* initial value length */
16, /* secret length -- 16*8 == 128bit */
LIBSSH2_CRYPT_METHOD_FLAG_EVP,
NULL,
(void*)EVP_aes_128_cbc,
NULL,
0, /* flags */
&aes128_init,
&crypt,
&dtor
};
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, /* initial value length */
24, /* secret length -- 24*8 == 192bit */
LIBSSH2_CRYPT_METHOD_FLAG_EVP,
NULL,
(void*)EVP_aes_192_cbc,
NULL,
0, /* flags */
&aes192_init,
&crypt,
&dtor
};
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, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
LIBSSH2_CRYPT_METHOD_FLAG_EVP,
NULL,
(void*)EVP_aes_256_cbc,
NULL,
0, /* flags */
&aes256_init,
&crypt,
&dtor
};
/* 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, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
LIBSSH2_CRYPT_METHOD_FLAG_EVP,
NULL,
(void*)EVP_aes_256_cbc,
NULL,
0, /* flags */
&aes256_init,
&crypt,
&dtor
};
#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, /* initial value length */
16, /* secret length */
LIBSSH2_CRYPT_METHOD_FLAG_EVP,
NULL,
(void*)EVP_bf_cbc,
NULL,
0, /* flags */
&blowfish_init,
&crypt,
&dtor
};
#endif /* ! OPENSSL_NO_BLOWFISH */
@ -138,10 +189,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_cast128_cbc = {
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
LIBSSH2_CRYPT_METHOD_FLAG_EVP,
NULL,
(void*)EVP_cast5_cbc,
NULL,
0, /* flags */
&cast128_init,
&crypt,
&dtor
};
#endif /* ! OPENSSL_NO_CAST */
@ -151,10 +202,10 @@ static LIBSSH2_CRYPT_METHOD libssh2_crypt_method_arcfour = {
8, /* blocksize */
8, /* initial value length */
16, /* secret length */
LIBSSH2_CRYPT_METHOD_FLAG_EVP,
NULL,
(void*)EVP_rc4,
NULL,
0, /* flags */
&arcfour_init,
&crypt,
&dtor
};
#endif /* ! OPENSSL_NO_RC4 */

Просмотреть файл

@ -38,7 +38,6 @@
#include "libssh2_priv.h"
#include <openssl/bn.h>
#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
/* TODO: Switch this to an inline and handle alloc() failures */
@ -331,46 +330,24 @@ static int libssh2_kex_method_diffie_hellman_groupGP_sha1_key_exchange(LIBSSH2_S
#endif
}
/* Calculate IV/Secret/Key for each direction */
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
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) {
/* Cleanup any existing cipher */
if (session->local.crypt->dtor) {
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;
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(secret, session->local.crypt->secret_len, "C");
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
EVP_CIPHER *(*get_cipher)(void) = (void*)session->local.crypt->crypt;
EVP_CIPHER *cipher = get_cipher();
EVP_CIPHER_CTX *ctx;
ctx = LIBSSH2_ALLOC(session, sizeof(EVP_CIPHER_CTX));
if (!ctx) {
if (session->local.crypt->init(session, iv, &free_iv, secret, &free_secret, 1, &session->local.crypt_abstract)) {
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) {
memset(iv, 0, session->local.crypt->iv_len);
@ -386,45 +363,23 @@ 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");
#endif
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
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) {
/* 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;
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(secret, session->remote.crypt->secret_len, "D");
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
EVP_CIPHER *(*get_cipher)(void) = (void*)session->remote.crypt->crypt;
EVP_CIPHER *cipher = get_cipher();
EVP_CIPHER_CTX *ctx;
ctx = LIBSSH2_ALLOC(session, sizeof(EVP_CIPHER_CTX));
if (!ctx) {
if (session->remote.crypt->init(session, iv, &free_iv, secret, &free_secret, 0, &session->remote.crypt_abstract)) {
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) {
memset(iv, 0, session->remote.crypt->iv_len);

Просмотреть файл

@ -282,12 +282,6 @@ struct _LIBSSH2_HOSTKEY_METHOD {
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 {
char *name;

Просмотреть файл

@ -41,7 +41,6 @@
#ifndef WIN32
#include <unistd.h>
#endif
#include <openssl/evp.h>
#include <openssl/rand.h>
/* Needed for struct iovec on some platforms */
@ -754,9 +753,6 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
int macstate;
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
* For now, all blocksize sizes are 8+
*/
@ -780,15 +776,10 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
return (session->socket_state == LIBSSH2_SOCKET_DISCONNECTED) ? 0 : -1;
}
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
EVP_Cipher(ctx, block + blocksize, block, blocksize);
memcpy(block, block + blocksize, blocksize);
} 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);
@ -838,17 +829,12 @@ int libssh2_packet_read(LIBSSH2_SESSION *session, int should_block)
while (s < p) {
memcpy(block, s, blocksize);
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
EVP_Cipher(ctx, block + blocksize, block, blocksize);
memcpy(s, block + blocksize, blocksize);
} else {
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);
}
s += blocksize;
}
@ -1225,9 +1211,6 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
unsigned char *encbuf, *s;
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 */
encbuf = LIBSSH2_ALLOC(session, 4 + packet_length + session->local.mac->mac_len);
if (!encbuf) {
@ -1251,13 +1234,8 @@ int libssh2_packet_write(LIBSSH2_SESSION *session, unsigned char *data, unsigned
/* Encrypt data */
for(s = encbuf; (s - encbuf) < (4 + packet_length) ; s += session->local.crypt->blocksize) {
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
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++;

Просмотреть файл

@ -410,17 +410,9 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
/* Client to Server */
/* crypt */
if (session->local.crypt) {
if (session->local.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
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) {
if (session->local.crypt && session->local.crypt->dtor) {
session->local.crypt->dtor(session, &session->local.crypt_abstract);
}
}
/* comp */
if (session->local.comp && session->local.comp->dtor) {
session->local.comp->dtor(session, 1, &session->local.comp_abstract);
@ -432,17 +424,9 @@ LIBSSH2_API void libssh2_session_free(LIBSSH2_SESSION *session)
/* Server to Client */
/* crypt */
if (session->remote.crypt) {
if (session->remote.crypt->flags & LIBSSH2_CRYPT_METHOD_FLAG_EVP) {
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) {
if (session->remote.crypt && session->remote.crypt->dtor) {
session->remote.crypt->dtor(session, &session->remote.crypt_abstract);
}
}
/* comp */
if (session->remote.comp && session->remote.comp->dtor) {
session->remote.comp->dtor(session, 0, &session->remote.comp_abstract);