Make dh crypto functions thread safe.

git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@491 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
Andreas Schneider
2009-04-16 12:08:11 +00:00
parent c608883205
commit 24fc1b2028
5 changed files with 68 additions and 40 deletions

View File

@@ -339,6 +339,10 @@ struct ssh_session {
int dh_handshake_state; int dh_handshake_state;
STRING *dh_server_signature; //information used by dh_handshake. STRING *dh_server_signature; //information used by dh_handshake.
/* dh crypto */
bignum dh_g;
bignum dh_p;
KEX server_kex; KEX server_kex;
KEX client_kex; KEX client_kex;
BUFFER *in_hashbuf; BUFFER *in_hashbuf;
@@ -520,9 +524,8 @@ void dh_generate_x(SSH_SESSION *session);
void dh_generate_y(SSH_SESSION *session); void dh_generate_y(SSH_SESSION *session);
void dh_generate_f(SSH_SESSION *session); void dh_generate_f(SSH_SESSION *session);
/* FIXME: replace me with a thread safe function */ int ssh_crypto_init(SSH_SESSION *session);
void ssh_crypto_init(void); void ssh_crypto_finalize(SSH_SESSION *session);
void ssh_crypto_finalize(void);
STRING *dh_get_e(SSH_SESSION *session); STRING *dh_get_e(SSH_SESSION *session);
STRING *dh_get_f(SSH_SESSION *session); STRING *dh_get_f(SSH_SESSION *session);

View File

@@ -449,7 +449,11 @@ int ssh_connect(SSH_SESSION *session) {
session->alive = 0; session->alive = 0;
session->client = 1; session->client = 1;
ssh_crypto_init(); if (ssh_crypto_init(session) < 0) {
ssh_set_error(session, SSH_FATAL, "Initializing crypto functions failed");
leave_function();
return SSH_ERROR;
}
ssh_socket_init(); ssh_socket_init();
if (options->fd == -1 && options->host == NULL) { if (options->fd == -1 && options->host == NULL) {
@@ -628,6 +632,7 @@ void ssh_disconnect(SSH_SESSION *session) {
error: error:
leave_function(); leave_function();
ssh_crypto_finalize(session);
ssh_cleanup(session); ssh_cleanup(session);
} }

View File

@@ -69,9 +69,6 @@ static unsigned char p_value[] = {
#define P_LEN 128 /* Size in bytes of the p number */ #define P_LEN 128 /* Size in bytes of the p number */
static unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */ static unsigned long g_int = 2 ; /* G is defined as 2 by the ssh2 standards */
static bignum g;
static bignum p;
static int ssh_crypto_inited=0;
int ssh_get_random(void *where, int len, int strong){ int ssh_get_random(void *where, int len, int strong){
@@ -96,35 +93,49 @@ int ssh_get_random(void *where, int len, int strong){
/* it inits the values g and p which are used for DH key agreement */ /* it inits the values g and p which are used for DH key agreement */
void ssh_crypto_init(void){ int ssh_crypto_init(struct ssh_session *session) {
if(ssh_crypto_inited == 0){
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_check_version(NULL); gcry_check_version(NULL);
if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P,0))
{ if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P,0)) {
gcry_control(GCRYCTL_INIT_SECMEM, 4096); gcry_control(GCRYCTL_INIT_SECMEM, 4096);
gcry_control(GCRYCTL_INITIALIZATION_FINISHED,0); gcry_control(GCRYCTL_INITIALIZATION_FINISHED,0);
} }
#endif #endif
g=bignum_new();
bignum_set_word(g,g_int); session->dh_g = bignum_new();
if (session->dh_g == NULL) {
return -1;
}
bignum_set_word(session->dh_g, g_int);
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
bignum_bin2bn(p_value,P_LEN,&p); bignum_bin2bn(p_value, P_LEN, &session->dh_p);
if (session->dh_p == NULL) {
bignum_free(session->dh_g);
session->dh_g = NULL;
return -1;
}
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
p=bignum_new(); session->dh_p = bignum_new();
bignum_bin2bn(p_value,P_LEN,p); if (session->dh_p == NULL) {
OpenSSL_add_all_algorithms(); bignum_free(session->dh_g);
session->dh_g = NULL;
return -1;
}
bignum_bin2bn(p_value, P_LEN, session->dh_p);
OpenSSL_add_all_algorithms();
#endif #endif
ssh_crypto_inited++;
} return 0;
} }
void ssh_crypto_finalize(void){ void ssh_crypto_finalize(struct ssh_session *session) {
if(ssh_crypto_inited){ bignum_free(session->dh_g);
bignum_free(g); session->dh_g = NULL;
bignum_free(p);
ssh_crypto_inited=0; bignum_free(session->dh_p);
} session->dh_p = NULL;
} }
/* prints the bignum on stderr */ /* prints the bignum on stderr */
@@ -223,9 +234,11 @@ void dh_generate_e(SSH_SESSION *session){
#endif #endif
session->next_crypto->e=bignum_new(); session->next_crypto->e=bignum_new();
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
bignum_mod_exp(session->next_crypto->e,g,session->next_crypto->x,p); bignum_mod_exp(session->next_crypto->e, session->dh_g,
session->next_crypto->x, session->dh_p);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
bignum_mod_exp(session->next_crypto->e,g,session->next_crypto->x,p,ctx); bignum_mod_exp(session->next_crypto->e, session->dh_g,
session->next_crypto->x, session->dh_p, ctx);
#endif #endif
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_bignum("e",session->next_crypto->e); ssh_print_bignum("e",session->next_crypto->e);
@@ -241,9 +254,11 @@ void dh_generate_f(SSH_SESSION *session){
#endif #endif
session->next_crypto->f=bignum_new(); session->next_crypto->f=bignum_new();
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
bignum_mod_exp(session->next_crypto->f,g,session->next_crypto->y,p); bignum_mod_exp(session->next_crypto->f, session->dh_g,
session->next_crypto->y, session->dh_p);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
bignum_mod_exp(session->next_crypto->f,g,session->next_crypto->y,p,ctx); bignum_mod_exp(session->next_crypto->f, session->dh_g,
session->next_crypto->y, session->dh_p, ctx);
#endif #endif
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO
ssh_print_bignum("f",session->next_crypto->f); ssh_print_bignum("f",session->next_crypto->f);
@@ -327,15 +342,19 @@ void dh_build_k(SSH_SESSION *session){
/* the server and clients don't use the same numbers */ /* the server and clients don't use the same numbers */
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
if(session->client){ if(session->client){
bignum_mod_exp(session->next_crypto->k,session->next_crypto->f,session->next_crypto->x,p); bignum_mod_exp(session->next_crypto->k, session->next_crypto->f,
session->next_crypto->x, session->dh_p);
} else { } else {
bignum_mod_exp(session->next_crypto->k,session->next_crypto->e,session->next_crypto->y,p); bignum_mod_exp(session->next_crypto->k, session->next_crypto->e,
session->next_crypto->y, session->dh_p);
} }
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO
if(session->client){ if(session->client){
bignum_mod_exp(session->next_crypto->k,session->next_crypto->f,session->next_crypto->x,p,ctx); bignum_mod_exp(session->next_crypto->k, session->next_crypto->f,
session->next_crypto->x, session->dh_p, ctx);
} else { } else {
bignum_mod_exp(session->next_crypto->k,session->next_crypto->e,session->next_crypto->y,p,ctx); bignum_mod_exp(session->next_crypto->k, session->next_crypto->e,
session->next_crypto->y, session->dh_p, ctx);
} }
#endif #endif
#ifdef DEBUG_CRYPTO #ifdef DEBUG_CRYPTO

View File

@@ -38,7 +38,6 @@
*/ */
int ssh_finalize(void) int ssh_finalize(void)
{ {
ssh_crypto_finalize();
#ifdef HAVE_LIBGCRYPT #ifdef HAVE_LIBGCRYPT
gcry_control(GCRYCTL_TERM_SECMEM); gcry_control(GCRYCTL_TERM_SECMEM);
#elif defined HAVE_LIBCRYPTO #elif defined HAVE_LIBCRYPTO

View File

@@ -332,7 +332,9 @@ static int dh_handshake_server(SSH_SESSION *session){
/* do the banner and key exchange */ /* do the banner and key exchange */
int ssh_accept(SSH_SESSION *session){ int ssh_accept(SSH_SESSION *session){
ssh_send_banner(session,1); ssh_send_banner(session,1);
ssh_crypto_init(); if (ssh_crypto_init(session) < 0) {
return -1;
}
session->alive=1; session->alive=1;
session->clientbanner=ssh_get_banner(session); session->clientbanner=ssh_get_banner(session);
if (server_set_kex(session) < 0) { if (server_set_kex(session) < 0) {