From 5b2586312a8793ca056294665fed597c7fc6791a Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Thu, 16 Apr 2009 15:14:15 +0000 Subject: [PATCH] Add return values to generate_session_keys() and generate_one_key(). git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@508 7dcaeef0-15fb-0310-b436-a5af3365683c --- include/libssh/priv.h | 2 +- libssh/client.c | 5 +- libssh/dh.c | 185 +++++++++++++++++++++++++++--------------- libssh/server.c | 4 +- 4 files changed, 128 insertions(+), 68 deletions(-) diff --git a/include/libssh/priv.h b/include/libssh/priv.h index 704f0b1c..5e069450 100644 --- a/include/libssh/priv.h +++ b/include/libssh/priv.h @@ -533,7 +533,7 @@ int make_sessionid(SSH_SESSION *session); /* add data for the final cookie */ int hashbufin_add_cookie(SSH_SESSION *session, unsigned char *cookie); int hashbufout_add_cookie(SSH_SESSION *session); -void generate_session_keys(SSH_SESSION *session); +int generate_session_keys(SSH_SESSION *session); /* returns 1 if server signature ok, 0 otherwise. The NEXT crypto is checked, not the current one */ int signature_verify(SSH_SESSION *session,STRING *signature); bignum make_string_bn(STRING *string); diff --git a/libssh/client.c b/libssh/client.c index f8d95d9b..a7e695f4 100644 --- a/libssh/client.c +++ b/libssh/client.c @@ -313,7 +313,10 @@ static int dh_handshake(SSH_SESSION *session) { goto error; } - generate_session_keys(session); + if (generate_session_keys(session) < 0) { + rc = SSH_ERROR; + goto error; + } /* Verify the host's signature. FIXME do it sooner */ signature = session->dh_server_signature; diff --git a/libssh/dh.c b/libssh/dh.c index 2e766526..9a70eb4c 100644 --- a/libssh/dh.c +++ b/libssh/dh.c @@ -662,80 +662,135 @@ int hashbufin_add_cookie(SSH_SESSION *session, unsigned char *cookie) { return 0; } -/* TODO FIXME add return value for memory checks */ -static void generate_one_key(STRING *k,unsigned char session_id[SHA_DIGEST_LEN],unsigned char output[SHA_DIGEST_LEN],char letter){ - SHACTX ctx=sha1_init(); - if (ctx == NULL) { - return; - } - sha1_update(ctx,k,string_len(k)+4); - sha1_update(ctx,session_id,SHA_DIGEST_LEN); - sha1_update(ctx,&letter,1); - sha1_update(ctx,session_id,SHA_DIGEST_LEN); - sha1_final(output,ctx); +static int generate_one_key(STRING *k, + unsigned char session_id[SHA_DIGEST_LEN], + unsigned char output[SHA_DIGEST_LEN], + char letter) { + SHACTX ctx = NULL; + + ctx = sha1_init(); + if (ctx == NULL) { + return -1; + } + + sha1_update(ctx, k, string_len(k) + 4); + sha1_update(ctx, session_id, SHA_DIGEST_LEN); + sha1_update(ctx, &letter, 1); + sha1_update(ctx, session_id, SHA_DIGEST_LEN); + sha1_final(output, ctx); + + return 0; } -/* TODO FIXME add return value for memory checks */ -void generate_session_keys(SSH_SESSION *session){ - STRING *k_string; - SHACTX ctx; - enter_function(); - k_string=make_bignum_string(session->next_crypto->k); +int generate_session_keys(SSH_SESSION *session) { + STRING *k_string = NULL; + SHACTX ctx = NULL; + int rc = -1; - /* IV */ - if(session->client){ - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptIV,'A'); - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptIV,'B'); - } else { - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptIV,'A'); - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptIV,'B'); - } - if(session->client){ - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptkey,'C'); - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptkey,'D'); - } else { - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptkey,'C'); - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptkey,'D'); - } - /* some ciphers need more than 20 bytes of input key */ - /* XXX verify it's ok for server implementation */ - if(session->next_crypto->out_cipher->keysize > SHA_DIGEST_LEN*8){ - ctx=sha1_init(); - if (ctx == NULL) { - leave_function(); - return; - } - sha1_update(ctx,k_string,string_len(k_string)+4); - sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LEN); - sha1_update(ctx,session->next_crypto->encryptkey,SHA_DIGEST_LEN); - sha1_final(session->next_crypto->encryptkey+SHA_DIGEST_LEN,ctx); - } + enter_function(); - if(session->next_crypto->in_cipher->keysize > SHA_DIGEST_LEN*8){ - ctx=sha1_init(); - sha1_update(ctx,k_string,string_len(k_string)+4); - sha1_update(ctx,session->next_crypto->session_id,SHA_DIGEST_LEN); - sha1_update(ctx,session->next_crypto->decryptkey,SHA_DIGEST_LEN); - sha1_final(session->next_crypto->decryptkey+SHA_DIGEST_LEN,ctx); + k_string = make_bignum_string(session->next_crypto->k); + if (k_string == NULL) { + goto error; + } + + /* IV */ + if (session->client) { + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->encryptIV, 'A') < 0) { + goto error; } - if(session->client){ - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptMAC,'E'); - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptMAC,'F'); - } else { - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->decryptMAC,'E'); - generate_one_key(k_string,session->next_crypto->session_id,session->next_crypto->encryptMAC,'F'); + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->decryptIV, 'B') < 0) { + goto error; } + } else { + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->decryptIV, 'A') < 0) { + goto error; + } + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->encryptIV, 'B') < 0) { + goto error; + } + } + if (session->client) { + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->encryptkey, 'C') < 0) { + goto error; + } + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->decryptkey, 'D') < 0) { + goto error; + } + } else { + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->decryptkey, 'C') < 0) { + goto error; + } + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->encryptkey, 'D') < 0) { + goto error; + } + } + + /* some ciphers need more than 20 bytes of input key */ + /* XXX verify it's ok for server implementation */ + if (session->next_crypto->out_cipher->keysize > SHA_DIGEST_LEN * 8) { + ctx = sha1_init(); + if (ctx == NULL) { + goto error; + } + sha1_update(ctx, k_string, string_len(k_string) + 4); + sha1_update(ctx, session->next_crypto->session_id, SHA_DIGEST_LEN); + sha1_update(ctx, session->next_crypto->encryptkey, SHA_DIGEST_LEN); + sha1_final(session->next_crypto->encryptkey + SHA_DIGEST_LEN, ctx); + } + + if (session->next_crypto->in_cipher->keysize > SHA_DIGEST_LEN * 8) { + ctx = sha1_init(); + sha1_update(ctx, k_string, string_len(k_string) + 4); + sha1_update(ctx, session->next_crypto->session_id, SHA_DIGEST_LEN); + sha1_update(ctx, session->next_crypto->decryptkey, SHA_DIGEST_LEN); + sha1_final(session->next_crypto->decryptkey + SHA_DIGEST_LEN, ctx); + } + if(session->client) { + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->encryptMAC, 'E') < 0) { + goto error; + } + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->decryptMAC, 'F') < 0) { + goto error; + } + } else { + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->decryptMAC, 'E') < 0) { + goto error; + } + if (generate_one_key(k_string, session->next_crypto->session_id, + session->next_crypto->encryptMAC, 'F') < 0) { + goto error; + } + } #ifdef DEBUG_CRYPTO - ssh_print_hexa("encrypt IV",session->next_crypto->encryptIV,SHA_DIGEST_LEN); - ssh_print_hexa("decrypt IV",session->next_crypto->decryptIV,SHA_DIGEST_LEN); - ssh_print_hexa("encryption key",session->next_crypto->encryptkey,session->next_crypto->out_cipher->keysize); - ssh_print_hexa("decryption key",session->next_crypto->decryptkey,session->next_crypto->in_cipher->keysize); - ssh_print_hexa("Encryption MAC",session->next_crypto->encryptMAC,SHA_DIGEST_LEN); - ssh_print_hexa("Decryption MAC",session->next_crypto->decryptMAC,20); + ssh_print_hexa("Encrypt IV", session->next_crypto->encryptIV, SHA_DIGEST_LEN); + ssh_print_hexa("Decrypt IV", session->next_crypto->decryptIV, SHA_DIGEST_LEN); + ssh_print_hexa("Encryption key", session->next_crypto->encryptkey, + session->next_crypto->out_cipher->keysize); + ssh_print_hexa("Decryption key", session->next_crypto->decryptkey, + session->next_crypto->in_cipher->keysize); + ssh_print_hexa("Encryption MAC", session->next_crypto->encryptMAC, SHA_DIGEST_LEN); + ssh_print_hexa("Decryption MAC", session->next_crypto->decryptMAC, 20); #endif - free(k_string); - leave_function(); + + rc = 0; +error: + string_free(k_string); + leave_function(); + + return rc; } /** \addtogroup ssh_session diff --git a/libssh/server.c b/libssh/server.c index 0a2f13fe..b1f5e3bf 100644 --- a/libssh/server.c +++ b/libssh/server.c @@ -330,7 +330,9 @@ static int dh_handshake_server(SSH_SESSION *session){ packet_wait(session,SSH2_MSG_NEWKEYS,1); ssh_log(session, SSH_LOG_PACKET, "Got SSH_MSG_NEWKEYS"); - generate_session_keys(session); + if (generate_session_keys(session) < 0) { + return -1; + } /* once we got SSH2_MSG_NEWKEYS we can switch next_crypto and current_crypto */ if(session->current_crypto) crypto_free(session->current_crypto);