mirror of
https://git.libssh.org/projects/libssh.git
synced 2025-11-30 13:01:23 +03:00
Clean up code that generates session keys
This patch simply reworks the code to make it more understandable and reduce if() branches. It also avoids reallocs, and instead uses a support buffer to hold intermediate results of the hmac function so that no buffer overrides happen when the requested size is not an exact mutiple of the digest_len. Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com> Reviewed-by: Andreas Schneider <asn@cryptomilk.org>
This commit is contained in:
committed by
Andreas Schneider
parent
c235841436
commit
c180211c6b
223
src/kex.c
223
src/kex.c
@@ -1346,17 +1346,15 @@ int ssh_hashbufin_add_cookie(ssh_session session, unsigned char *cookie)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int generate_one_key(ssh_string k,
|
static int generate_one_key(ssh_string k, struct ssh_crypto_struct *crypto,
|
||||||
struct ssh_crypto_struct *crypto,
|
unsigned char *output, char letter,
|
||||||
unsigned char **output,
|
|
||||||
char letter,
|
|
||||||
size_t requested_size)
|
size_t requested_size)
|
||||||
{
|
{
|
||||||
ssh_mac_ctx ctx;
|
ssh_mac_ctx ctx;
|
||||||
unsigned char *tmp;
|
|
||||||
size_t size = crypto->digest_len;
|
size_t size = crypto->digest_len;
|
||||||
ctx = ssh_mac_ctx_init(crypto->mac_type);
|
unsigned char digest[size];
|
||||||
|
|
||||||
|
ctx = ssh_mac_ctx_init(crypto->mac_type);
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -1365,25 +1363,27 @@ static int generate_one_key(ssh_string k,
|
|||||||
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||||
ssh_mac_update(ctx, &letter, 1);
|
ssh_mac_update(ctx, &letter, 1);
|
||||||
ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
|
ssh_mac_update(ctx, crypto->session_id, crypto->digest_len);
|
||||||
ssh_mac_final(*output, ctx);
|
ssh_mac_final(digest, ctx);
|
||||||
|
|
||||||
while(requested_size > size) {
|
if (requested_size < size) {
|
||||||
tmp = realloc(*output, size + crypto->digest_len);
|
size = requested_size;
|
||||||
if (tmp == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
*output = tmp;
|
memcpy(output, digest, size);
|
||||||
|
|
||||||
|
while (requested_size > size) {
|
||||||
ctx = ssh_mac_ctx_init(crypto->mac_type);
|
ctx = ssh_mac_ctx_init(crypto->mac_type);
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ssh_mac_update(ctx, k, ssh_string_len(k) + 4);
|
ssh_mac_update(ctx, k, ssh_string_len(k) + 4);
|
||||||
ssh_mac_update(ctx,
|
ssh_mac_update(ctx, crypto->secret_hash, crypto->digest_len);
|
||||||
crypto->secret_hash,
|
ssh_mac_update(ctx, output, size);
|
||||||
crypto->digest_len);
|
ssh_mac_final(digest, ctx);
|
||||||
ssh_mac_update(ctx, tmp, size);
|
if (requested_size < size + crypto->digest_len) {
|
||||||
ssh_mac_final(tmp + size, ctx);
|
memcpy(output+size, digest, requested_size - size);
|
||||||
|
} else {
|
||||||
|
memcpy(output+size, digest, crypto->digest_len);
|
||||||
|
}
|
||||||
size += crypto->digest_len;
|
size += crypto->digest_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1394,6 +1394,17 @@ int ssh_generate_session_keys(ssh_session session)
|
|||||||
{
|
{
|
||||||
ssh_string k_string = NULL;
|
ssh_string k_string = NULL;
|
||||||
struct ssh_crypto_struct *crypto = session->next_crypto;
|
struct ssh_crypto_struct *crypto = session->next_crypto;
|
||||||
|
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 IV_len = 0;
|
||||||
|
size_t enckey_cli_to_srv_len = 0;
|
||||||
|
size_t enckey_srv_to_cli_len = 0;
|
||||||
|
size_t intkey_cli_to_srv_len = 0;
|
||||||
|
size_t intkey_srv_to_cli_len = 0;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
|
|
||||||
k_string = ssh_make_bignum_string(crypto->k);
|
k_string = ssh_make_bignum_string(crypto->k);
|
||||||
@@ -1402,153 +1413,105 @@ int ssh_generate_session_keys(ssh_session session)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
crypto->encryptIV = malloc(crypto->digest_len);
|
IV_len = crypto->digest_len;
|
||||||
crypto->decryptIV = malloc(crypto->digest_len);
|
if (session->client) {
|
||||||
crypto->encryptkey = malloc(crypto->digest_len);
|
enckey_cli_to_srv_len = crypto->out_cipher->keysize / 8;
|
||||||
crypto->decryptkey = malloc(crypto->digest_len);
|
enckey_srv_to_cli_len = crypto->in_cipher->keysize / 8;
|
||||||
crypto->encryptMAC = malloc(crypto->digest_len);
|
intkey_cli_to_srv_len = hmac_digest_len(crypto->out_hmac);
|
||||||
crypto->decryptMAC = malloc(crypto->digest_len);
|
intkey_srv_to_cli_len = hmac_digest_len(crypto->in_hmac);
|
||||||
if (crypto->encryptIV == NULL ||
|
} else {
|
||||||
crypto->decryptIV == NULL ||
|
enckey_cli_to_srv_len = crypto->in_cipher->keysize / 8;
|
||||||
crypto->encryptkey == NULL || crypto->decryptkey == NULL ||
|
enckey_srv_to_cli_len = crypto->out_cipher->keysize / 8;
|
||||||
crypto->encryptMAC == NULL || crypto->decryptMAC == NULL){
|
intkey_cli_to_srv_len = hmac_digest_len(crypto->in_hmac);
|
||||||
|
intkey_srv_to_cli_len = hmac_digest_len(crypto->out_hmac);
|
||||||
|
}
|
||||||
|
|
||||||
|
IV_cli_to_srv = malloc(IV_len);
|
||||||
|
IV_srv_to_cli = malloc(IV_len);
|
||||||
|
enckey_cli_to_srv = malloc(enckey_cli_to_srv_len);
|
||||||
|
enckey_srv_to_cli = malloc(enckey_srv_to_cli_len);
|
||||||
|
intkey_cli_to_srv = malloc(intkey_cli_to_srv_len);
|
||||||
|
intkey_srv_to_cli = malloc(intkey_srv_to_cli_len);
|
||||||
|
if (IV_cli_to_srv == NULL || IV_srv_to_cli == NULL ||
|
||||||
|
enckey_cli_to_srv == NULL || enckey_srv_to_cli == NULL ||
|
||||||
|
intkey_cli_to_srv == NULL || intkey_srv_to_cli == NULL) {
|
||||||
ssh_set_error_oom(session);
|
ssh_set_error_oom(session);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IV */
|
/* IV */
|
||||||
if (session->client) {
|
rc = generate_one_key(k_string, crypto, IV_cli_to_srv, 'A', IV_len);
|
||||||
rc = generate_one_key(k_string,
|
|
||||||
crypto,
|
|
||||||
&crypto->encryptIV,
|
|
||||||
'A',
|
|
||||||
crypto->digest_len);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rc = generate_one_key(k_string,
|
rc = generate_one_key(k_string, crypto, IV_srv_to_cli, 'B', IV_len);
|
||||||
crypto,
|
|
||||||
&crypto->decryptIV,
|
|
||||||
'B',
|
|
||||||
crypto->digest_len);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
/* Encryption Key */
|
||||||
rc = generate_one_key(k_string,
|
rc = generate_one_key(k_string, crypto, enckey_cli_to_srv, 'C',
|
||||||
crypto,
|
enckey_cli_to_srv_len);
|
||||||
&crypto->decryptIV,
|
|
||||||
'A',
|
|
||||||
crypto->digest_len);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rc = generate_one_key(k_string,
|
rc = generate_one_key(k_string, crypto, enckey_srv_to_cli, 'D',
|
||||||
crypto,
|
enckey_srv_to_cli_len);
|
||||||
&crypto->encryptIV,
|
|
||||||
'B',
|
|
||||||
crypto->digest_len);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
/* Integrity Key */
|
||||||
if (session->client) {
|
rc = generate_one_key(k_string, crypto, intkey_cli_to_srv, 'E',
|
||||||
rc = generate_one_key(k_string,
|
intkey_cli_to_srv_len);
|
||||||
crypto,
|
|
||||||
&crypto->encryptkey,
|
|
||||||
'C',
|
|
||||||
crypto->out_cipher->keysize / 8);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
rc = generate_one_key(k_string,
|
rc = generate_one_key(k_string, crypto, intkey_srv_to_cli, 'F',
|
||||||
crypto,
|
intkey_srv_to_cli_len);
|
||||||
&crypto->decryptkey,
|
|
||||||
'D',
|
|
||||||
crypto->in_cipher->keysize / 8);
|
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
rc = generate_one_key(k_string,
|
|
||||||
crypto,
|
|
||||||
&crypto->decryptkey,
|
|
||||||
'C',
|
|
||||||
crypto->in_cipher->keysize / 8);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
rc = generate_one_key(k_string,
|
|
||||||
crypto,
|
|
||||||
&crypto->encryptkey,
|
|
||||||
'D',
|
|
||||||
crypto->out_cipher->keysize / 8);
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(session->client) {
|
if (session->client) {
|
||||||
rc = generate_one_key(k_string,
|
crypto->encryptIV = IV_cli_to_srv;
|
||||||
crypto,
|
crypto->decryptIV = IV_srv_to_cli;
|
||||||
&crypto->encryptMAC,
|
crypto->encryptkey = enckey_cli_to_srv;
|
||||||
'E',
|
crypto->decryptkey = enckey_srv_to_cli;
|
||||||
hmac_digest_len(crypto->out_hmac));
|
crypto->encryptMAC = intkey_cli_to_srv;
|
||||||
if (rc < 0) {
|
crypto->decryptMAC = intkey_srv_to_cli;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
rc = generate_one_key(k_string,
|
|
||||||
crypto,
|
|
||||||
&crypto->decryptMAC,
|
|
||||||
'F',
|
|
||||||
hmac_digest_len(crypto->in_hmac));
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
rc = generate_one_key(k_string,
|
crypto->encryptIV = IV_srv_to_cli;
|
||||||
crypto,
|
crypto->decryptIV = IV_cli_to_srv;
|
||||||
&crypto->decryptMAC,
|
crypto->encryptkey = enckey_srv_to_cli;
|
||||||
'E',
|
crypto->decryptkey = enckey_cli_to_srv;
|
||||||
hmac_digest_len(crypto->in_hmac));
|
crypto->encryptMAC = intkey_srv_to_cli;
|
||||||
if (rc < 0) {
|
crypto->decryptMAC = intkey_cli_to_srv;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
rc = generate_one_key(k_string,
|
|
||||||
crypto,
|
|
||||||
&crypto->encryptMAC,
|
|
||||||
'F',
|
|
||||||
hmac_digest_len(crypto->out_hmac));
|
|
||||||
if (rc < 0) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_CRYPTO
|
#ifdef DEBUG_CRYPTO
|
||||||
ssh_print_hexa("Encrypt IV",
|
ssh_print_hexa("Client to Server IV", IV_cli_to_srv, IV_len);
|
||||||
crypto->encryptIV,
|
ssh_print_hexa("Server to Client IV", IV_srv_to_cli, IV_len);
|
||||||
crypto->digest_len);
|
ssh_print_hexa("Client to Server Encryption Key", enckey_cli_to_srv,
|
||||||
ssh_print_hexa("Decrypt IV",
|
enckey_cli_to_srv_len);
|
||||||
crypto->decryptIV,
|
ssh_print_hexa("Server to Client Encryption Key", enckey_srv_to_cli,
|
||||||
crypto->digest_len);
|
enckey_srv_to_cli_len);
|
||||||
ssh_print_hexa("Encryption key",
|
ssh_print_hexa("Client to Server Integrity Key", intkey_cli_to_srv,
|
||||||
crypto->encryptkey,
|
intkey_cli_to_srv_len);
|
||||||
crypto->out_cipher->keysize / 8);
|
ssh_print_hexa("Server to Client Integrity Key", intkey_srv_to_cli,
|
||||||
ssh_print_hexa("Decryption key",
|
intkey_srv_to_cli_len);
|
||||||
crypto->decryptkey,
|
|
||||||
crypto->in_cipher->keysize / 8);
|
|
||||||
ssh_print_hexa("Encryption MAC",
|
|
||||||
crypto->encryptMAC,
|
|
||||||
hmac_digest_len(crypto->out_hmac));
|
|
||||||
ssh_print_hexa("Decryption MAC",
|
|
||||||
crypto->decryptMAC,
|
|
||||||
hmac_digest_len(crypto->in_hmac));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
error:
|
error:
|
||||||
ssh_string_burn(k_string);
|
ssh_string_burn(k_string);
|
||||||
ssh_string_free(k_string);
|
ssh_string_free(k_string);
|
||||||
|
if (rc != 0) {
|
||||||
|
free(IV_cli_to_srv);
|
||||||
|
free(IV_srv_to_cli);
|
||||||
|
free(enckey_cli_to_srv);
|
||||||
|
free(enckey_srv_to_cli);
|
||||||
|
free(intkey_cli_to_srv);
|
||||||
|
free(intkey_srv_to_cli);
|
||||||
|
}
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user