for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) { if (i % 4 == 0) rand = arc4random(); session_key[i] = rand & 0xff; rand >>= 8; } }
BN_bn2bin(session_key_int, buf); MD5_Init(&md); MD5_Update(&md, buf, bytes); MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); MD5_Final(session_key, &md); MD5_Init(&md); MD5_Update(&md, session_key, 16); MD5_Update(&md, buf, bytes); MD5_Update(&md, sensitive_data.ssh1_cookie, SSH_SESSION_KEY_LENGTH); MD5_Final(session_key + 16, &md); memset(buf, 0, bytes); xfree(buf); }  destroy_sensitive_data();
do_ssh1_kex(void){	int i, len;	int plen, slen;	int rsafail = 0;	BIGNUM *session_key_int;	u_char session_key[SSH_SESSION_KEY_LENGTH];	u_char cookie[8];	u_int cipher_type, auth_mask, protocol_flags;	u_int32_t rand = 0;	/*	 * Generate check bytes that the client must send back in the user	 * packet in order for it to be accepted; this is used to defy ip	 * spoofing attacks.  Note that this only works against somebody	 * doing IP spoofing from a remote machine; any machine on the local	 * network can still see outgoing packets and catch the random	 * cookie.  This only affects rhosts authentication, and this is one	 * of the reasons why it is inherently insecure.	 */	for (i = 0; i < 8; i++) {		if (i % 4 == 0)			rand = arc4random();		cookie[i] = rand & 0xff;		rand >>= 8;	}	/*	 * Send our public key.  We include in the packet 64 bits of random	 * data that must be matched in the reply in order to prevent IP	 * spoofing.	 */	packet_start(SSH_SMSG_PUBLIC_KEY);	for (i = 0; i < 8; i++)		packet_put_char(cookie[i]);	/* Store our public server RSA key. */	packet_put_int(BN_num_bits(sensitive_data.server_key->rsa->n));	packet_put_bignum(sensitive_data.server_key->rsa->e);	packet_put_bignum(sensitive_data.server_key->rsa->n);	/* Store our public host RSA key. */	packet_put_int(BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));	packet_put_bignum(sensitive_data.ssh1_host_key->rsa->e);	packet_put_bignum(sensitive_data.ssh1_host_key->rsa->n);	/* Put protocol flags. */	packet_put_int(SSH_PROTOFLAG_HOST_IN_FWD_OPEN);	/* Declare which ciphers we support. */	packet_put_int(cipher_mask_ssh1(0));	/* Declare supported authentication types. */	auth_mask = 0;	if (options.rhosts_authentication)		auth_mask |= 1 << SSH_AUTH_RHOSTS;	if (options.rhosts_rsa_authentication)		auth_mask |= 1 << SSH_AUTH_RHOSTS_RSA;	if (options.rsa_authentication)		auth_mask |= 1 << SSH_AUTH_RSA;#ifdef KRB4	if (options.kerberos_authentication)		auth_mask |= 1 << SSH_AUTH_KERBEROS;#endif#ifdef AFS	if (options.kerberos_tgt_passing)		auth_mask |= 1 << SSH_PASS_KERBEROS_TGT;	if (options.afs_token_passing)		auth_mask |= 1 << SSH_PASS_AFS_TOKEN;#endif	if (options.challenge_reponse_authentication == 1)		auth_mask |= 1 << SSH_AUTH_TIS;	if (options.password_authentication)		auth_mask |= 1 << SSH_AUTH_PASSWORD;	packet_put_int(auth_mask);	/* Send the packet and wait for it to be sent. */	packet_send();	packet_write_wait();	debug("Sent %d bit server key and %d bit host key.",	    BN_num_bits(sensitive_data.server_key->rsa->n),	    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n));	/* Read clients reply (cipher type and session key). */	packet_read_expect(&plen, SSH_CMSG_SESSION_KEY);	/* Get cipher type and check whether we accept this. */	cipher_type = packet_get_char();	if (!(cipher_mask_ssh1(0) & (1 << cipher_type)))		packet_disconnect("Warning: client selects unsupported cipher.");	/* Get check bytes from the packet.  These must match those we	   sent earlier with the public key packet. */	for (i = 0; i < 8; i++)		if (cookie[i] != packet_get_char())			packet_disconnect("IP Spoofing check bytes do not match.");	debug("Encryption type: %.200s", cipher_name(cipher_type));	/* Get the encrypted integer. */	session_key_int = BN_new();	packet_get_bignum(session_key_int, &slen);	protocol_flags = packet_get_int();	packet_set_protocol_flags(protocol_flags);	packet_integrity_check(plen, 1 + 8 + slen + 4, SSH_CMSG_SESSION_KEY);	/*	 * Decrypt it using our private server key and private host key (key	 * with larger modulus first).	 */	if (BN_cmp(sensitive_data.server_key->rsa->n, sensitive_data.ssh1_host_key->rsa->n) > 0) {		/* Server key has bigger modulus. */		if (BN_num_bits(sensitive_data.server_key->rsa->n) <		    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) + SSH_KEY_BITS_RESERVED) {			fatal("do_connection: %s: server_key %d < host_key %d + SSH_KEY_BITS_RESERVED %d",			    get_remote_ipaddr(),			    BN_num_bits(sensitive_data.server_key->rsa->n),			    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),			    SSH_KEY_BITS_RESERVED);		}		if (rsa_private_decrypt(session_key_int, session_key_int,		    sensitive_data.server_key->rsa) <= 0)			rsafail++;		if (rsa_private_decrypt(session_key_int, session_key_int,		    sensitive_data.ssh1_host_key->rsa) <= 0)			rsafail++;	} else {		/* Host key has bigger modulus (or they are equal). */		if (BN_num_bits(sensitive_data.ssh1_host_key->rsa->n) <		    BN_num_bits(sensitive_data.server_key->rsa->n) + SSH_KEY_BITS_RESERVED) {			fatal("do_connection: %s: host_key %d < server_key %d + SSH_KEY_BITS_RESERVED %d",			    get_remote_ipaddr(),			    BN_num_bits(sensitive_data.ssh1_host_key->rsa->n),			    BN_num_bits(sensitive_data.server_key->rsa->n),			    SSH_KEY_BITS_RESERVED);		}		if (rsa_private_decrypt(session_key_int, session_key_int,		    sensitive_data.ssh1_host_key->rsa) < 0)			rsafail++;		if (rsa_private_decrypt(session_key_int, session_key_int,		    sensitive_data.server_key->rsa) < 0)			rsafail++;	}	compute_session_id(session_id, cookie,	    sensitive_data.ssh1_host_key->rsa->n,	    sensitive_data.server_key->rsa->n);	/* Destroy the private and public keys.  They will no longer be needed. */	destroy_sensitive_data();	/*	 * Extract session key from the decrypted integer.  The key is in the	 * least significant 256 bits of the integer; the first byte of the	 * key is in the highest bits.	 */	if (!rsafail) {		BN_mask_bits(session_key_int, sizeof(session_key) * 8);		len = BN_num_bytes(session_key_int);		if (len < 0 || len > sizeof(session_key)) {			error("do_connection: bad session key len from %s: "			    "session_key_int %d > sizeof(session_key) %lu",			    get_remote_ipaddr(), len, (u_long)sizeof(session_key));			rsafail++;		} else {			memset(session_key, 0, sizeof(session_key));			BN_bn2bin(session_key_int,			    session_key + sizeof(session_key) - len);		}	}	if (rsafail) {		log("do_connection: generating a fake encryption key");		for (i = 0; i < SSH_SESSION_KEY_LENGTH; i++) {			if (i % 4 == 0)				rand = arc4random();			session_key[i] = rand & 0xff;			rand >>= 8;		}	}	/* Destroy the decrypted integer.  It is no longer needed. */	BN_clear_free(session_key_int);	/* Xor the first 16 bytes of the session key with the session id. */	for (i = 0; i < 16; i++)		session_key[i] ^= session_id[i];	/* Set the session key.  From this on all communications will be encrypted. */	packet_set_encryption_key(session_key, SSH_SESSION_KEY_LENGTH, cipher_type);	/* Destroy our copy of the session key.  It is no longer needed. */	memset(session_key, 0, sizeof(session_key));	debug("Received session key; encryption turned on.");	/* Send an acknowledgement packet.  Note that this packet is sent encrypted. */	packet_start(SSH_SMSG_SUCCESS);	packet_send();	packet_write_wait();}