aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/priv.h2
-rw-r--r--libssh/client.c5
-rw-r--r--libssh/dh.c183
-rw-r--r--libssh/server.c4
4 files changed, 127 insertions, 67 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);
-
- /* 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');
+int generate_session_keys(SSH_SESSION *session) {
+ STRING *k_string = NULL;
+ SHACTX ctx = NULL;
+ int rc = -1;
+
+ enter_function();
+
+ 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->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');
+ if (generate_one_key(k_string, session->next_crypto->session_id,
+ session->next_crypto->decryptIV, 'B') < 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) {
- 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);
+ } 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;
+ }
+ }
- 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);
+ /* 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(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->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);
-#endif
- free(k_string);
- leave_function();
+ 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
+
+ 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);