len = lseek(fd, (off_t) 0, SEEK_END); lseek(fd, (off_t) 0, SEEK_SET);  buffer_init(&buffer); buffer_append_space(&buffer, &cp, len);  if (read(fd, cp, (size_t) len) != (size_t) len) { debug("Read from key file %.200s failed: %.100s", filename, strerror(errno)); buffer_free(&buffer); close(fd); return 0;
switch (key->type) { case KEY_RSA: if (key->rsa->e != NULL) { BN_clear_free(key->rsa->e); key->rsa->e = NULL; } if (key->rsa->n != NULL) { BN_clear_free(key->rsa->n); key->rsa->n = NULL; } ret = load_private_key_rsa(fd, filename, passphrase, key->rsa, comment_return); break; case KEY_DSA: ret = load_private_key_dsa(fd, passphrase, key, comment_return); default: break;
load_private_key(const char *filename, const char *passphrase,		 RSA * prv, char **comment_return){	int fd, i, check1, check2, cipher_type;	off_t len;	Buffer buffer, decrypted;	char *cp;	CipherContext cipher;	BN_CTX *ctx;	BIGNUM *aux;	struct stat st;	fd = open(filename, O_RDONLY);	if (fd < 0)		return 0;	/* check owner and modes */	if (fstat(fd, &st) < 0 ||	    (st.st_uid != 0 && st.st_uid != getuid()) ||	    (st.st_mode & 077) != 0) {		close(fd);		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");		error("@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @");		error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");		error("Bad ownership or mode(0%3.3o) for '%s'.",		      st.st_mode & 0777, filename);		error("It is recommended that your private key files are NOT accessible by others.");		return 0;	}	len = lseek(fd, (off_t) 0, SEEK_END);	lseek(fd, (off_t) 0, SEEK_SET);	buffer_init(&buffer);	buffer_append_space(&buffer, &cp, len);	if (read(fd, cp, (size_t) len) != (size_t) len) {		debug("Read from key file %.200s failed: %.100s", filename,		      strerror(errno));		buffer_free(&buffer);		close(fd);		return 0;	}	close(fd);	/* Check that it is at least big enought to contain the ID string. */	if (len < strlen(AUTHFILE_ID_STRING) + 1) {		debug("Bad key file %.200s.", filename);		buffer_free(&buffer);		return 0;	}	/*	 * Make sure it begins with the id string.  Consume the id string	 * from the buffer.	 */	for (i = 0; i < (unsigned int) strlen(AUTHFILE_ID_STRING) + 1; i++)		if (buffer_get_char(&buffer) != (unsigned char) AUTHFILE_ID_STRING[i]) {			debug("Bad key file %.200s.", filename);			buffer_free(&buffer);			return 0;		}	/* Read cipher type. */	cipher_type = buffer_get_char(&buffer);	(void) buffer_get_int(&buffer);	/* Reserved data. */	/* Read the public key from the buffer. */	buffer_get_int(&buffer);	prv->n = BN_new();	buffer_get_bignum(&buffer, prv->n);	prv->e = BN_new();	buffer_get_bignum(&buffer, prv->e);	if (comment_return)		*comment_return = buffer_get_string(&buffer, NULL);	else		xfree(buffer_get_string(&buffer, NULL));	/* Check that it is a supported cipher. */	if (((cipher_mask1() | SSH_CIPHER_NONE | SSH_AUTHFILE_CIPHER) &	     (1 << cipher_type)) == 0) {		debug("Unsupported cipher %.100s used in key file %.200s.",		      cipher_name(cipher_type), filename);		buffer_free(&buffer);		goto fail;	}	/* Initialize space for decrypted data. */	buffer_init(&decrypted);	buffer_append_space(&decrypted, &cp, buffer_len(&buffer));	/* Rest of the buffer is encrypted.  Decrypt it using the passphrase. */	cipher_set_key_string(&cipher, cipher_type, passphrase);	cipher_decrypt(&cipher, (unsigned char *) cp,		       (unsigned char *) buffer_ptr(&buffer),		       buffer_len(&buffer));	buffer_free(&buffer);	check1 = buffer_get_char(&decrypted);	check2 = buffer_get_char(&decrypted);	if (check1 != buffer_get_char(&decrypted) ||	    check2 != buffer_get_char(&decrypted)) {		if (strcmp(passphrase, "") != 0)			debug("Bad passphrase supplied for key file %.200s.", filename);		/* Bad passphrase. */		buffer_free(&decrypted);fail:		BN_clear_free(prv->n);		BN_clear_free(prv->e);		if (comment_return)			xfree(*comment_return);		return 0;	}	/* Read the rest of the private key. */	prv->d = BN_new();	buffer_get_bignum(&decrypted, prv->d);	prv->iqmp = BN_new();	buffer_get_bignum(&decrypted, prv->iqmp);	/* u */	/* in SSL and SSH p and q are exchanged */	prv->q = BN_new();	buffer_get_bignum(&decrypted, prv->q);		/* p */	prv->p = BN_new();	buffer_get_bignum(&decrypted, prv->p);		/* q */	ctx = BN_CTX_new();	aux = BN_new();	BN_sub(aux, prv->q, BN_value_one());	prv->dmq1 = BN_new();	BN_mod(prv->dmq1, prv->d, aux, ctx);	BN_sub(aux, prv->p, BN_value_one());	prv->dmp1 = BN_new();	BN_mod(prv->dmp1, prv->d, aux, ctx);	BN_clear_free(aux);	BN_CTX_free(ctx);	buffer_free(&decrypted);	return 1;}