int generate_session_keys(ssh_session session) { ssh_string k_string = NULL; struct ssh_crypto_struct *crypto = session->next_crypto; unsigned char *tmp; int rc = -1; k_string = make_bignum_string(crypto->k); if (k_string == NULL) { ssh_set_error_oom(session); goto error; } crypto->encryptIV = malloc(crypto->digest_len); crypto->decryptIV = malloc(crypto->digest_len); crypto->encryptkey = malloc(crypto->digest_len); crypto->decryptkey = malloc(crypto->digest_len); crypto->encryptMAC = malloc(crypto->digest_len); crypto->decryptMAC = malloc(crypto->digest_len); if(crypto->encryptIV == NULL || crypto->decryptIV == NULL || crypto->encryptkey == NULL || crypto->decryptkey == NULL || crypto->encryptMAC == NULL || crypto->decryptMAC == NULL){ ssh_set_error_oom(session); goto error; } /* IV */ if (session->client) { rc = generate_one_key(k_string, crypto, &crypto->encryptIV, 'A', crypto->digest_len); if (rc < 0) { goto error; } rc = generate_one_key(k_string, crypto, &crypto->decryptIV, 'B', crypto->digest_len); if (rc < 0) { goto error; } } else { rc = generate_one_key(k_string, crypto, &crypto->decryptIV, 'A', crypto->digest_len); if (rc < 0) { goto error; } rc = generate_one_key(k_string, crypto, &crypto->encryptIV, 'B', crypto->digest_len); if (rc < 0) { goto error; } } if (session->client) { rc = generate_one_key(k_string, crypto, &crypto->encryptkey, 'C', crypto->out_cipher->keysize / 8); if (rc < 0) { goto error; } rc = generate_one_key(k_string, crypto, &crypto->decryptkey, 'D', crypto->in_cipher->keysize / 8); if (rc < 0) { 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) { rc = generate_one_key(k_string, crypto, &crypto->encryptMAC, 'E', hmac_digest_len(crypto->out_hmac)); if (rc < 0) { goto error; } rc = generate_one_key(k_string, crypto, &crypto->decryptMAC, 'F', hmac_digest_len(crypto->in_hmac)); if (rc < 0) { goto error; } } else { rc = generate_one_key(k_string, crypto, &crypto->decryptMAC, 'E', hmac_digest_len(crypto->in_hmac)); if (rc < 0) { 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 ssh_print_hexa("Encrypt IV", crypto->encryptIV, crypto->digest_len); ssh_print_hexa("Decrypt IV", crypto->decryptIV, crypto->digest_len); ssh_print_hexa("Encryption key", crypto->encryptkey, crypto->out_cipher->keysize / 8); ssh_print_hexa("Decryption key", 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 rc = 0; error: ssh_string_free(k_string); return rc; }
int generate_session_keys(ssh_session session) { ssh_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 (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, ssh_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, ssh_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); #endif rc = 0; error: ssh_string_free(k_string); leave_function(); return rc; }