diff options
Diffstat (limited to 'src/kex.c')
-rw-r--r-- | src/kex.c | 78 |
1 files changed, 20 insertions, 58 deletions
@@ -1196,7 +1196,7 @@ int ssh_make_sessionid(ssh_session session) case SSH_KEX_DH_GEX_SHA1: #endif /* WITH_GEX */ session->next_crypto->digest_len = SHA_DIGEST_LENGTH; - session->next_crypto->mac_type = SSH_MAC_SHA1; + session->next_crypto->digest_type = SSH_KDF_SHA1; session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); if (session->next_crypto->secret_hash == NULL) { ssh_set_error_oom(session); @@ -1212,7 +1212,7 @@ int ssh_make_sessionid(ssh_session session) case SSH_KEX_DH_GEX_SHA256: #endif /* WITH_GEX */ session->next_crypto->digest_len = SHA256_DIGEST_LENGTH; - session->next_crypto->mac_type = SSH_MAC_SHA256; + session->next_crypto->digest_type = SSH_KDF_SHA256; session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); if (session->next_crypto->secret_hash == NULL) { ssh_set_error_oom(session); @@ -1223,7 +1223,7 @@ int ssh_make_sessionid(ssh_session session) break; case SSH_KEX_ECDH_SHA2_NISTP384: session->next_crypto->digest_len = SHA384_DIGEST_LENGTH; - session->next_crypto->mac_type = SSH_MAC_SHA384; + session->next_crypto->digest_type = SSH_KDF_SHA384; session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); if (session->next_crypto->secret_hash == NULL) { ssh_set_error_oom(session); @@ -1236,7 +1236,7 @@ int ssh_make_sessionid(ssh_session session) case SSH_KEX_DH_GROUP18_SHA512: case SSH_KEX_ECDH_SHA2_NISTP521: session->next_crypto->digest_len = SHA512_DIGEST_LENGTH; - session->next_crypto->mac_type = SSH_MAC_SHA512; + session->next_crypto->digest_type = SSH_KDF_SHA512; session->next_crypto->secret_hash = malloc(session->next_crypto->digest_len); if (session->next_crypto->secret_hash == NULL) { ssh_set_error_oom(session); @@ -1346,60 +1346,18 @@ int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie) return 0; } -static int generate_one_key(ssh_string k, struct ssh_crypto_struct *crypto, - unsigned char *output, char letter, - size_t requested_size) -{ - ssh_mac_ctx ctx; - size_t size = crypto->digest_len; - unsigned char digest[size]; - - ctx = ssh_mac_ctx_init(crypto->mac_type); - if (ctx == NULL) { - return -1; - } - - ssh_mac_update(ctx, k, ssh_string_len(k) + 4); - ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); - ssh_mac_update(ctx, &letter, 1); - ssh_mac_update(ctx, crypto->session_id, crypto->digest_len); - ssh_mac_final(digest, ctx); - - if (requested_size < size) { - size = requested_size; - } - memcpy(output, digest, size); - - while (requested_size > size) { - ctx = ssh_mac_ctx_init(crypto->mac_type); - if (ctx == NULL) { - return -1; - } - ssh_mac_update(ctx, k, ssh_string_len(k) + 4); - ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len); - ssh_mac_update(ctx, output, size); - ssh_mac_final(digest, ctx); - if (requested_size < size + crypto->digest_len) { - memcpy(output+size, digest, requested_size - size); - } else { - memcpy(output+size, digest, crypto->digest_len); - } - size += crypto->digest_len; - } - - return 0; -} - int ssh_generate_session_keys(ssh_session session) { ssh_string k_string = NULL; struct ssh_crypto_struct *crypto = session->next_crypto; + unsigned char *key = NULL; unsigned char *IV_cli_to_srv = NULL; unsigned char *IV_srv_to_cli = NULL; unsigned char *enckey_cli_to_srv = NULL; unsigned char *enckey_srv_to_cli = NULL; unsigned char *intkey_cli_to_srv = NULL; unsigned char *intkey_srv_to_cli = NULL; + size_t key_len = 0; size_t IV_len = 0; size_t enckey_cli_to_srv_len = 0; size_t enckey_srv_to_cli_len = 0; @@ -1412,6 +1370,10 @@ int ssh_generate_session_keys(ssh_session session) ssh_set_error_oom(session); goto error; } + /* See RFC4251 Section 5 for the definition of mpint which is the + * encoding we need to use for key in the SSH KDF */ + key = (unsigned char *)k_string; + key_len = ssh_string_len(k_string) + 4; IV_len = crypto->digest_len; if (session->client) { @@ -1440,33 +1402,33 @@ int ssh_generate_session_keys(ssh_session session) } /* IV */ - rc = generate_one_key(k_string, crypto, IV_cli_to_srv, 'A', IV_len); + rc = ssh_kdf(crypto, key, key_len, 'A', IV_cli_to_srv, IV_len); if (rc < 0) { goto error; } - rc = generate_one_key(k_string, crypto, IV_srv_to_cli, 'B', IV_len); + rc = ssh_kdf(crypto, key, key_len, 'B', IV_srv_to_cli, IV_len); if (rc < 0) { goto error; } /* Encryption Key */ - rc = generate_one_key(k_string, crypto, enckey_cli_to_srv, 'C', - enckey_cli_to_srv_len); + rc = ssh_kdf(crypto, key, key_len, 'C', enckey_cli_to_srv, + enckey_cli_to_srv_len); if (rc < 0) { goto error; } - rc = generate_one_key(k_string, crypto, enckey_srv_to_cli, 'D', - enckey_srv_to_cli_len); + rc = ssh_kdf(crypto, key, key_len, 'D', enckey_srv_to_cli, + enckey_srv_to_cli_len); if (rc < 0) { goto error; } /* Integrity Key */ - rc = generate_one_key(k_string, crypto, intkey_cli_to_srv, 'E', - intkey_cli_to_srv_len); + rc = ssh_kdf(crypto, key, key_len, 'E', intkey_cli_to_srv, + intkey_cli_to_srv_len); if (rc < 0) { goto error; } - rc = generate_one_key(k_string, crypto, intkey_srv_to_cli, 'F', - intkey_srv_to_cli_len); + rc = ssh_kdf(crypto, key, key_len, 'F', intkey_srv_to_cli, + intkey_srv_to_cli_len); if (rc < 0) { goto error; } |