upstream commit

sync ssh-keysign, ssh-keygen and some dependencies to the
 new buffer/key API; mostly mechanical, ok markus@
diff --git a/dns.c b/dns.c
index 4b8ae44..f45bec0 100644
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.c,v 1.32 2014/12/21 22:27:56 djm Exp $ */
+/* $OpenBSD: dns.c,v 1.33 2015/01/15 09:40:00 djm Exp $ */
 
 /*
  * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -38,7 +38,8 @@
 #include <stdlib.h>
 
 #include "xmalloc.h"
-#include "key.h"
+#include "sshkey.h"
+#include "ssherr.h"
 #include "dns.h"
 #include "log.h"
 #include "digest.h"
@@ -78,9 +79,9 @@
  */
 static int
 dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
-    u_char **digest, u_int *digest_len, Key *key)
+    u_char **digest, size_t *digest_len, struct sshkey *key)
 {
-	int success = 0;
+	int r, success = 0;
 	int fp_alg = -1;
 
 	switch (key->type) {
@@ -121,9 +122,10 @@
 	}
 
 	if (*algorithm && *digest_type) {
-		*digest = key_fingerprint_raw(key, fp_alg, digest_len);
-		if (*digest == NULL)
-			fatal("dns_read_key: null from key_fingerprint_raw()");
+		if ((r = sshkey_fingerprint_raw(key, fp_alg, digest,
+		    digest_len)) != 0)
+			fatal("%s: sshkey_fingerprint_raw: %s", __func__,
+			   ssh_err(r));
 		success = 1;
 	} else {
 		*digest = NULL;
@@ -139,7 +141,7 @@
  */
 static int
 dns_read_rdata(u_int8_t *algorithm, u_int8_t *digest_type,
-    u_char **digest, u_int *digest_len, u_char *rdata, int rdata_len)
+    u_char **digest, size_t *digest_len, u_char *rdata, int rdata_len)
 {
 	int success = 0;
 
@@ -200,7 +202,7 @@
  */
 int
 verify_host_key_dns(const char *hostname, struct sockaddr *address,
-    Key *hostkey, int *flags)
+    struct sshkey *hostkey, int *flags)
 {
 	u_int counter;
 	int result;
@@ -209,12 +211,12 @@
 	u_int8_t hostkey_algorithm;
 	u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED;
 	u_char *hostkey_digest;
-	u_int hostkey_digest_len;
+	size_t hostkey_digest_len;
 
 	u_int8_t dnskey_algorithm;
 	u_int8_t dnskey_digest_type;
 	u_char *dnskey_digest;
-	u_int dnskey_digest_len;
+	size_t dnskey_digest_len;
 
 	*flags = 0;
 
@@ -310,13 +312,13 @@
  * Export the fingerprint of a key as a DNS resource record
  */
 int
-export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
+export_dns_rr(const char *hostname, struct sshkey *key, FILE *f, int generic)
 {
 	u_int8_t rdata_pubkey_algorithm = 0;
 	u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED;
 	u_int8_t dtype;
 	u_char *rdata_digest;
-	u_int i, rdata_digest_len;
+	size_t i, rdata_digest_len;
 	int success = 0;
 
 	for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) {
@@ -324,7 +326,7 @@
 		if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
 		    &rdata_digest, &rdata_digest_len, key)) {
 			if (generic) {
-				fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ",
+				fprintf(f, "%s IN TYPE%d \\# %zu %02x %02x ",
 				    hostname, DNS_RDATATYPE_SSHFP,
 				    2 + rdata_digest_len,
 				    rdata_pubkey_algorithm, rdata_digest_type);
diff --git a/dns.h b/dns.h
index b9feae6..815f073 100644
--- a/dns.h
+++ b/dns.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.h,v 1.13 2014/04/20 09:24:26 logan Exp $ */
+/* $OpenBSD: dns.h,v 1.14 2015/01/15 09:40:00 djm Exp $ */
 
 /*
  * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -50,7 +50,8 @@
 #define DNS_VERIFY_MATCH	0x00000002
 #define DNS_VERIFY_SECURE	0x00000004
 
-int	verify_host_key_dns(const char *, struct sockaddr *, Key *, int *);
-int	export_dns_rr(const char *, Key *, FILE *, int);
+int	verify_host_key_dns(const char *, struct sockaddr *,
+    struct sshkey *, int *);
+int	export_dns_rr(const char *, struct sshkey *, FILE *, int);
 
 #endif /* DNS_H */
diff --git a/hostfile.c b/hostfile.c
index ad5acb6..40dbbd4 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.c,v 1.58 2014/10/20 03:43:01 djm Exp $ */
+/* $OpenBSD: hostfile.c,v 1.59 2015/01/15 09:40:00 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -51,10 +51,11 @@
 
 #include "xmalloc.h"
 #include "match.h"
-#include "key.h"
+#include "sshkey.h"
 #include "hostfile.h"
 #include "log.h"
 #include "misc.h"
+#include "ssherr.h"
 #include "digest.h"
 #include "hmac.h"
 
@@ -155,15 +156,16 @@
  */
 
 int
-hostfile_read_key(char **cpp, int *bitsp, Key *ret)
+hostfile_read_key(char **cpp, u_int *bitsp, struct sshkey *ret)
 {
 	char *cp;
+	int r;
 
 	/* Skip leading whitespace. */
 	for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)
 		;
 
-	if (key_read(ret, &cp) != 1)
+	if ((r = sshkey_read(ret, &cp)) != 0)
 		return 0;
 
 	/* Skip trailing whitespace. */
@@ -172,15 +174,13 @@
 
 	/* Return results. */
 	*cpp = cp;
-	if (bitsp != NULL) {
-		if ((*bitsp = key_size(ret)) <= 0)
-			return 0;
-	}
+	if (bitsp != NULL)
+		*bitsp = sshkey_size(ret);
 	return 1;
 }
 
 static int
-hostfile_check_key(int bits, const Key *key, const char *host,
+hostfile_check_key(int bits, const struct sshkey *key, const char *host,
     const char *filename, u_long linenum)
 {
 #ifdef WITH_SSH1
@@ -249,8 +249,8 @@
 	u_long linenum = 0, num_loaded = 0;
 	char *cp, *cp2, *hashed_host;
 	HostkeyMarker marker;
-	Key *key;
-	int kbits;
+	struct sshkey *key;
+	u_int kbits;
 
 	if ((f = fopen(path, "r")) == NULL)
 		return;
@@ -296,13 +296,19 @@
 		 * Extract the key from the line.  This will skip any leading
 		 * whitespace.  Ignore badly formatted lines.
 		 */
-		key = key_new(KEY_UNSPEC);
+		if ((key = sshkey_new(KEY_UNSPEC)) == NULL) {
+			error("%s: sshkey_new failed", __func__);
+			break;
+		}
 		if (!hostfile_read_key(&cp, &kbits, key)) {
-			key_free(key);
+			sshkey_free(key);
 #ifdef WITH_SSH1
-			key = key_new(KEY_RSA1);
+			if ((key = sshkey_new(KEY_RSA1)) == NULL) {
+				error("%s: sshkey_new failed", __func__);
+				break;
+			}
 			if (!hostfile_read_key(&cp, &kbits, key)) {
-				key_free(key);
+				sshkey_free(key);
 				continue;
 			}
 #else
@@ -315,7 +321,7 @@
 		debug3("%s: found %skey type %s in file %s:%lu", __func__,
 		    marker == MRK_NONE ? "" :
 		    (marker == MRK_CA ? "ca " : "revoked "),
-		    key_type(key), path, linenum);
+		    sshkey_type(key), path, linenum);
 		hostkeys->entries = xrealloc(hostkeys->entries,
 		    hostkeys->num_entries + 1, sizeof(*hostkeys->entries));
 		hostkeys->entries[hostkeys->num_entries].host = xstrdup(host);
@@ -339,7 +345,7 @@
 	for (i = 0; i < hostkeys->num_entries; i++) {
 		free(hostkeys->entries[i].host);
 		free(hostkeys->entries[i].file);
-		key_free(hostkeys->entries[i].key);
+		sshkey_free(hostkeys->entries[i].key);
 		explicit_bzero(hostkeys->entries + i, sizeof(*hostkeys->entries));
 	}
 	free(hostkeys->entries);
@@ -348,18 +354,18 @@
 }
 
 static int
-check_key_not_revoked(struct hostkeys *hostkeys, Key *k)
+check_key_not_revoked(struct hostkeys *hostkeys, struct sshkey *k)
 {
-	int is_cert = key_is_cert(k);
+	int is_cert = sshkey_is_cert(k);
 	u_int i;
 
 	for (i = 0; i < hostkeys->num_entries; i++) {
 		if (hostkeys->entries[i].marker != MRK_REVOKE)
 			continue;
-		if (key_equal_public(k, hostkeys->entries[i].key))
+		if (sshkey_equal_public(k, hostkeys->entries[i].key))
 			return -1;
 		if (is_cert &&
-		    key_equal_public(k->cert->signature_key,
+		    sshkey_equal_public(k->cert->signature_key,
 		    hostkeys->entries[i].key))
 			return -1;
 	}
@@ -383,11 +389,11 @@
  */
 static HostStatus
 check_hostkeys_by_key_or_type(struct hostkeys *hostkeys,
-    Key *k, int keytype, const struct hostkey_entry **found)
+    struct sshkey *k, int keytype, const struct hostkey_entry **found)
 {
 	u_int i;
 	HostStatus end_return = HOST_NEW;
-	int want_cert = key_is_cert(k);
+	int want_cert = sshkey_is_cert(k);
 	HostkeyMarker want_marker = want_cert ? MRK_CA : MRK_NONE;
 	int proto = (k ? k->type : keytype) == KEY_RSA1 ? 1 : 2;
 
@@ -411,7 +417,7 @@
 			break;
 		}
 		if (want_cert) {
-			if (key_equal_public(k->cert->signature_key,
+			if (sshkey_equal_public(k->cert->signature_key,
 			    hostkeys->entries[i].key)) {
 				/* A matching CA exists */
 				end_return = HOST_OK;
@@ -420,7 +426,7 @@
 				break;
 			}
 		} else {
-			if (key_equal(k, hostkeys->entries[i].key)) {
+			if (sshkey_equal(k, hostkeys->entries[i].key)) {
 				end_return = HOST_OK;
 				if (found != NULL)
 					*found = hostkeys->entries + i;
@@ -441,7 +447,7 @@
 }
 
 HostStatus
-check_key_in_hostkeys(struct hostkeys *hostkeys, Key *key,
+check_key_in_hostkeys(struct hostkeys *hostkeys, struct sshkey *key,
     const struct hostkey_entry **found)
 {
 	if (key == NULL)
@@ -463,11 +469,11 @@
  */
 
 int
-add_host_to_hostfile(const char *filename, const char *host, const Key *key,
-    int store_hash)
+add_host_to_hostfile(const char *filename, const char *host,
+    const struct sshkey *key, int store_hash)
 {
 	FILE *f;
-	int success = 0;
+	int r, success = 0;
 	char *hashed_host = NULL;
 
 	if (key == NULL)
@@ -485,12 +491,12 @@
 	}
 	fprintf(f, "%s ", store_hash ? hashed_host : host);
 
-	if (key_write(key, f)) {
+	if ((r = sshkey_write(key, f)) != 0) {
+		error("%s: saving key in %s failed: %s",
+		    __func__, filename, ssh_err(r));
+	} else
 		success = 1;
-	} else {
-		error("add_host_to_hostfile: saving key in %s failed", filename);
-	}
-	fprintf(f, "\n");
+	fputs("\n", f);
 	fclose(f);
 	return success;
 }
diff --git a/hostfile.h b/hostfile.h
index 679c034..d90973f 100644
--- a/hostfile.h
+++ b/hostfile.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: hostfile.h,v 1.20 2013/07/12 00:19:58 djm Exp $ */
+/* $OpenBSD: hostfile.h,v 1.21 2015/01/15 09:40:00 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -26,7 +26,7 @@
 	char *host;
 	char *file;
 	u_long line;
-	Key *key;
+	struct sshkey *key;
 	HostkeyMarker marker;
 };
 struct hostkeys;
@@ -35,13 +35,14 @@
 void	 load_hostkeys(struct hostkeys *, const char *, const char *);
 void	 free_hostkeys(struct hostkeys *);
 
-HostStatus check_key_in_hostkeys(struct hostkeys *, Key *,
+HostStatus check_key_in_hostkeys(struct hostkeys *, struct sshkey *,
     const struct hostkey_entry **);
 int	 lookup_key_in_hostkeys_by_type(struct hostkeys *, int,
     const struct hostkey_entry **);
 
-int	 hostfile_read_key(char **, int *, Key *);
-int	 add_host_to_hostfile(const char *, const char *, const Key *, int);
+int	 hostfile_read_key(char **, u_int *, struct sshkey *);
+int	 add_host_to_hostfile(const char *, const char *,
+    const struct sshkey *, int);
 
 #define HASH_MAGIC	"|1|"
 #define HASH_DELIM	'|'
diff --git a/kex.h b/kex.h
index dbcc081..ef4a1f0 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: kex.h,v 1.65 2015/01/13 19:31:40 markus Exp $ */
+/* $OpenBSD: kex.h,v 1.66 2015/01/15 09:40:00 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -27,6 +27,8 @@
 #define KEX_H
 
 #include "mac.h"
+#include "buffer.h" /* XXX for typedef */
+#include "key.h" /* XXX for typedef */
 
 #if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
 #include <openssl/ec.h>
diff --git a/msg.c b/msg.c
index cd5f98c..5a7b8ca 100644
--- a/msg.c
+++ b/msg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msg.c,v 1.15 2006/08/03 03:34:42 deraadt Exp $ */
+/* $OpenBSD: msg.c,v 1.16 2015/01/15 09:40:00 djm Exp $ */
 /*
  * Copyright (c) 2002 Markus Friedl.  All rights reserved.
  *
@@ -34,17 +34,18 @@
 #include <unistd.h>
 #include <stdarg.h>
 
-#include "buffer.h"
+#include "sshbuf.h"
+#include "ssherr.h"
 #include "log.h"
 #include "atomicio.h"
 #include "msg.h"
 #include "misc.h"
 
 int
-ssh_msg_send(int fd, u_char type, Buffer *m)
+ssh_msg_send(int fd, u_char type, struct sshbuf *m)
 {
 	u_char buf[5];
-	u_int mlen = buffer_len(m);
+	u_int mlen = sshbuf_len(m);
 
 	debug3("ssh_msg_send: type %u", (unsigned int)type & 0xff);
 
@@ -54,7 +55,7 @@
 		error("ssh_msg_send: write");
 		return (-1);
 	}
-	if (atomicio(vwrite, fd, buffer_ptr(m), mlen) != mlen) {
+	if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(m), mlen) != mlen) {
 		error("ssh_msg_send: write");
 		return (-1);
 	}
@@ -62,10 +63,11 @@
 }
 
 int
-ssh_msg_recv(int fd, Buffer *m)
+ssh_msg_recv(int fd, struct sshbuf *m)
 {
-	u_char buf[4];
+	u_char buf[4], *p;
 	u_int msg_len;
+	int r;
 
 	debug3("ssh_msg_recv entering");
 
@@ -79,9 +81,12 @@
 		error("ssh_msg_recv: read: bad msg_len %u", msg_len);
 		return (-1);
 	}
-	buffer_clear(m);
-	buffer_append_space(m, msg_len);
-	if (atomicio(read, fd, buffer_ptr(m), msg_len) != msg_len) {
+	sshbuf_reset(m);
+	if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) {
+		error("%s: buffer error: %s", __func__, ssh_err(r));
+		return -1;
+	}
+	if (atomicio(read, fd, p, msg_len) != msg_len) {
 		error("ssh_msg_recv: read: %s", strerror(errno));
 		return (-1);
 	}
diff --git a/msg.h b/msg.h
index b0cb9b5..dfb3424 100644
--- a/msg.h
+++ b/msg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: msg.h,v 1.4 2006/03/25 22:22:43 djm Exp $ */
+/* $OpenBSD: msg.h,v 1.5 2015/01/15 09:40:00 djm Exp $ */
 /*
  * Copyright (c) 2002 Markus Friedl.  All rights reserved.
  *
@@ -25,7 +25,8 @@
 #ifndef SSH_MSG_H
 #define SSH_MSG_H
 
-int	 ssh_msg_send(int, u_char, Buffer *);
-int	 ssh_msg_recv(int, Buffer *);
+struct sshbuf;
+int	 ssh_msg_send(int, u_char, struct sshbuf *);
+int	 ssh_msg_recv(int, struct sshbuf *);
 
 #endif
diff --git a/readconf.c b/readconf.c
index d7f1cf0..a122d17 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.c,v 1.226 2015/01/13 07:39:19 djm Exp $ */
+/* $OpenBSD: readconf.c,v 1.227 2015/01/15 09:40:00 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -51,11 +51,10 @@
 #include "cipher.h"
 #include "pathnames.h"
 #include "log.h"
-#include "key.h"
+#include "sshkey.h"
 #include "misc.h"
 #include "readconf.h"
 #include "match.h"
-#include "buffer.h"
 #include "kex.h"
 #include "mac.h"
 #include "uidswap.h"
diff --git a/readconf.h b/readconf.h
index 11a7332..a23da11 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: readconf.h,v 1.105 2014/12/21 22:27:56 djm Exp $ */
+/* $OpenBSD: readconf.h,v 1.106 2015/01/15 09:40:00 djm Exp $ */
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -93,7 +93,7 @@
 	int     num_identity_files;	/* Number of files for RSA/DSA identities. */
 	char   *identity_files[SSH_MAX_IDENTITY_FILES];
 	int    identity_file_userprovided[SSH_MAX_IDENTITY_FILES];
-	Key    *identity_keys[SSH_MAX_IDENTITY_FILES];
+	struct sshkey *identity_keys[SSH_MAX_IDENTITY_FILES];
 
 	/* Local TCP/IP forward requests. */
 	int     num_local_forwards;
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 7f775ff..c8b05e0 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.251 2014/12/21 22:27:56 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.252 2015/01/15 09:40:00 djm Exp $ */
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -39,11 +39,11 @@
 #include <unistd.h>
 
 #include "xmalloc.h"
-#include "key.h"
+#include "sshkey.h"
 #include "rsa.h"
 #include "authfile.h"
 #include "uuencode.h"
-#include "buffer.h"
+#include "sshbuf.h"
 #include "pathnames.h"
 #include "log.h"
 #include "misc.h"
@@ -52,6 +52,7 @@
 #include "dns.h"
 #include "ssh.h"
 #include "ssh2.h"
+#include "ssherr.h"
 #include "ssh-pkcs11.h"
 #include "atomicio.h"
 #include "krl.h"
@@ -208,7 +209,7 @@
 		fatal("DSA keys must be 1024 bits");
 	else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768)
 		fatal("Key must at least be 768 bits");
-	else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1)
+	else if (type == KEY_ECDSA && sshkey_ecdsa_bits_to_nid(*bitsp) == -1)
 		fatal("Invalid ECDSA key length - valid lengths are "
 		    "256, 384 or 521 bits");
 #endif
@@ -223,7 +224,7 @@
 	if (key_type_name == NULL)
 		name = _PATH_SSH_CLIENT_ID_RSA;
 	else {
-		switch (key_type_from_name(key_type_name)) {
+		switch (sshkey_type_from_name(key_type_name)) {
 		case KEY_RSA1:
 			name = _PATH_SSH_CLIENT_IDENTITY;
 			break;
@@ -263,23 +264,26 @@
 	have_identity = 1;
 }
 
-static Key *
+static struct sshkey *
 load_identity(char *filename)
 {
 	char *pass;
-	Key *prv;
+	struct sshkey *prv;
+	int r;
 
-	prv = key_load_private(filename, "", NULL);
-	if (prv == NULL) {
-		if (identity_passphrase)
-			pass = xstrdup(identity_passphrase);
-		else
-			pass = read_passphrase("Enter passphrase: ",
-			    RP_ALLOW_STDIN);
-		prv = key_load_private(filename, pass, NULL);
-		explicit_bzero(pass, strlen(pass));
-		free(pass);
-	}
+	if ((r = sshkey_load_private(filename, "", &prv, NULL)) == 0)
+		return prv;
+	if (r != SSH_ERR_KEY_WRONG_PASSPHRASE)
+		fatal("Load key \"%s\": %s", filename, ssh_err(r));
+	if (identity_passphrase)
+		pass = xstrdup(identity_passphrase);
+	else
+		pass = read_passphrase("Enter passphrase: ", RP_ALLOW_STDIN);
+	r = sshkey_load_private(filename, pass, &prv, NULL);
+	explicit_bzero(pass, strlen(pass));
+	free(pass);
+	if (r != 0)
+		fatal("Load key \"%s\": %s", filename, ssh_err(r));
 	return prv;
 }
 
@@ -290,39 +294,40 @@
 
 #ifdef WITH_OPENSSL
 static void
-do_convert_to_ssh2(struct passwd *pw, Key *k)
+do_convert_to_ssh2(struct passwd *pw, struct sshkey *k)
 {
-	u_int len;
+	size_t len;
 	u_char *blob;
 	char comment[61];
+	int r;
 
 	if (k->type == KEY_RSA1) {
 		fprintf(stderr, "version 1 keys are not supported\n");
 		exit(1);
 	}
-	if (key_to_blob(k, &blob, &len) <= 0) {
-		fprintf(stderr, "key_to_blob failed\n");
+	if ((r = sshkey_to_blob(k, &blob, &len)) != 0) {
+		fprintf(stderr, "key_to_blob failed: %s\n", ssh_err(r));
 		exit(1);
 	}
 	/* Comment + surrounds must fit into 72 chars (RFC 4716 sec 3.3) */
 	snprintf(comment, sizeof(comment),
 	    "%u-bit %s, converted by %s@%s from OpenSSH",
-	    key_size(k), key_type(k),
+	    sshkey_size(k), sshkey_type(k),
 	    pw->pw_name, hostname);
 
 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_BEGIN);
 	fprintf(stdout, "Comment: \"%s\"\n", comment);
 	dump_base64(stdout, blob, len);
 	fprintf(stdout, "%s\n", SSH_COM_PUBLIC_END);
-	key_free(k);
+	sshkey_free(k);
 	free(blob);
 	exit(0);
 }
 
 static void
-do_convert_to_pkcs8(Key *k)
+do_convert_to_pkcs8(struct sshkey *k)
 {
-	switch (key_type_plain(k->type)) {
+	switch (sshkey_type_plain(k->type)) {
 	case KEY_RSA1:
 	case KEY_RSA:
 		if (!PEM_write_RSA_PUBKEY(stdout, k->rsa))
@@ -339,15 +344,15 @@
 		break;
 #endif
 	default:
-		fatal("%s: unsupported key type %s", __func__, key_type(k));
+		fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
 	}
 	exit(0);
 }
 
 static void
-do_convert_to_pem(Key *k)
+do_convert_to_pem(struct sshkey *k)
 {
-	switch (key_type_plain(k->type)) {
+	switch (sshkey_type_plain(k->type)) {
 	case KEY_RSA1:
 	case KEY_RSA:
 		if (!PEM_write_RSAPublicKey(stdout, k->rsa))
@@ -361,7 +366,7 @@
 #endif
 	/* XXX ECDSA? */
 	default:
-		fatal("%s: unsupported key type %s", __func__, key_type(k));
+		fatal("%s: unsupported key type %s", __func__, sshkey_type(k));
 	}
 	exit(0);
 }
@@ -369,20 +374,16 @@
 static void
 do_convert_to(struct passwd *pw)
 {
-	Key *k;
+	struct sshkey *k;
 	struct stat st;
+	int r;
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which the key is");
 	if (stat(identity_file, &st) < 0)
 		fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
-	if ((k = key_load_public(identity_file, NULL)) == NULL) {
-		if ((k = load_identity(identity_file)) == NULL) {
-			fprintf(stderr, "load failed\n");
-			exit(1);
-		}
-	}
-
+	if ((r = sshkey_load_public(identity_file, &k, NULL)) != 0)
+		k = load_identity(identity_file);
 	switch (convert_format) {
 	case FMT_RFC4716:
 		do_convert_to_ssh2(pw, k);
@@ -399,51 +400,63 @@
 	exit(0);
 }
 
+/*
+ * This is almost exactly the bignum1 encoding, but with 32 bit for length
+ * instead of 16.
+ */
 static void
-buffer_get_bignum_bits(Buffer *b, BIGNUM *value)
+buffer_get_bignum_bits(struct sshbuf *b, BIGNUM *value)
 {
-	u_int bignum_bits = buffer_get_int(b);
-	u_int bytes = (bignum_bits + 7) / 8;
+	u_int bytes, bignum_bits;
+	int r;
 
-	if (buffer_len(b) < bytes)
-		fatal("buffer_get_bignum_bits: input buffer too small: "
-		    "need %d have %d", bytes, buffer_len(b));
-	if (BN_bin2bn(buffer_ptr(b), bytes, value) == NULL)
-		fatal("buffer_get_bignum_bits: BN_bin2bn failed");
-	buffer_consume(b, bytes);
+	if ((r = sshbuf_get_u32(b, &bignum_bits)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	bytes = (bignum_bits + 7) / 8;
+	if (sshbuf_len(b) < bytes)
+		fatal("%s: input buffer too small: need %d have %zu",
+		    __func__, bytes, sshbuf_len(b));
+	if (BN_bin2bn(sshbuf_ptr(b), bytes, value) == NULL)
+		fatal("%s: BN_bin2bn failed", __func__);
+	if ((r = sshbuf_consume(b, bytes)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 }
 
-static Key *
+static struct sshkey *
 do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
 {
-	Buffer b;
-	Key *key = NULL;
+	struct sshbuf *b;
+	struct sshkey *key = NULL;
 	char *type, *cipher;
-	u_char *sig = NULL, data[] = "abcde12345";
-	int magic, rlen, ktype, i1, i2, i3, i4;
-	u_int slen;
+	u_char e1, e2, e3, *sig = NULL, data[] = "abcde12345";
+	int r, rlen, ktype;
+	u_int magic, i1, i2, i3, i4;
+	size_t slen;
 	u_long e;
 
-	buffer_init(&b);
-	buffer_append(&b, blob, blen);
+	if ((b = sshbuf_from(blob, blen)) == NULL)
+		fatal("%s: sshbuf_from failed", __func__);
+	if ((r = sshbuf_get_u32(b, &magic)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-	magic = buffer_get_int(&b);
 	if (magic != SSH_COM_PRIVATE_KEY_MAGIC) {
-		error("bad magic 0x%x != 0x%x", magic, SSH_COM_PRIVATE_KEY_MAGIC);
-		buffer_free(&b);
+		error("bad magic 0x%x != 0x%x", magic,
+		    SSH_COM_PRIVATE_KEY_MAGIC);
+		sshbuf_free(b);
 		return NULL;
 	}
-	i1 = buffer_get_int(&b);
-	type   = buffer_get_string(&b, NULL);
-	cipher = buffer_get_string(&b, NULL);
-	i2 = buffer_get_int(&b);
-	i3 = buffer_get_int(&b);
-	i4 = buffer_get_int(&b);
+	if ((r = sshbuf_get_u32(b, &i1)) != 0 ||
+	    (r = sshbuf_get_cstring(b, &type, NULL)) != 0 ||
+	    (r = sshbuf_get_cstring(b, &cipher, NULL)) != 0 ||
+	    (r = sshbuf_get_u32(b, &i2)) != 0 ||
+	    (r = sshbuf_get_u32(b, &i3)) != 0 ||
+	    (r = sshbuf_get_u32(b, &i4)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 	debug("ignore (%d %d %d %d)", i1, i2, i3, i4);
 	if (strcmp(cipher, "none") != 0) {
 		error("unsupported cipher %s", cipher);
 		free(cipher);
-		buffer_free(&b);
+		sshbuf_free(b);
 		free(type);
 		return NULL;
 	}
@@ -454,56 +467,64 @@
 	} else if (strstr(type, "rsa")) {
 		ktype = KEY_RSA;
 	} else {
-		buffer_free(&b);
+		sshbuf_free(b);
 		free(type);
 		return NULL;
 	}
-	key = key_new_private(ktype);
+	if ((key = sshkey_new_private(ktype)) == NULL)
+		fatal("key_new_private failed");
 	free(type);
 
 	switch (key->type) {
 	case KEY_DSA:
-		buffer_get_bignum_bits(&b, key->dsa->p);
-		buffer_get_bignum_bits(&b, key->dsa->g);
-		buffer_get_bignum_bits(&b, key->dsa->q);
-		buffer_get_bignum_bits(&b, key->dsa->pub_key);
-		buffer_get_bignum_bits(&b, key->dsa->priv_key);
+		buffer_get_bignum_bits(b, key->dsa->p);
+		buffer_get_bignum_bits(b, key->dsa->g);
+		buffer_get_bignum_bits(b, key->dsa->q);
+		buffer_get_bignum_bits(b, key->dsa->pub_key);
+		buffer_get_bignum_bits(b, key->dsa->priv_key);
 		break;
 	case KEY_RSA:
-		e = buffer_get_char(&b);
+		if ((r = sshbuf_get_u8(b, &e1)) != 0 ||
+		    (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) ||
+		    (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0))
+			fatal("%s: buffer error: %s", __func__, ssh_err(r));
+		e = e1;
 		debug("e %lx", e);
 		if (e < 30) {
 			e <<= 8;
-			e += buffer_get_char(&b);
+			e += e2;
 			debug("e %lx", e);
 			e <<= 8;
-			e += buffer_get_char(&b);
+			e += e3;
 			debug("e %lx", e);
 		}
 		if (!BN_set_word(key->rsa->e, e)) {
-			buffer_free(&b);
-			key_free(key);
+			sshbuf_free(b);
+			sshkey_free(key);
 			return NULL;
 		}
-		buffer_get_bignum_bits(&b, key->rsa->d);
-		buffer_get_bignum_bits(&b, key->rsa->n);
-		buffer_get_bignum_bits(&b, key->rsa->iqmp);
-		buffer_get_bignum_bits(&b, key->rsa->q);
-		buffer_get_bignum_bits(&b, key->rsa->p);
-		if (rsa_generate_additional_parameters(key->rsa) != 0)
-			fatal("%s: rsa_generate_additional_parameters "
-			    "error", __func__);
+		buffer_get_bignum_bits(b, key->rsa->d);
+		buffer_get_bignum_bits(b, key->rsa->n);
+		buffer_get_bignum_bits(b, key->rsa->iqmp);
+		buffer_get_bignum_bits(b, key->rsa->q);
+		buffer_get_bignum_bits(b, key->rsa->p);
+		if ((r = rsa_generate_additional_parameters(key->rsa)) != 0)
+			fatal("generate RSA parameters failed: %s", ssh_err(r));
 		break;
 	}
-	rlen = buffer_len(&b);
+	rlen = sshbuf_len(b);
 	if (rlen != 0)
 		error("do_convert_private_ssh2_from_blob: "
 		    "remaining bytes in key blob %d", rlen);
-	buffer_free(&b);
+	sshbuf_free(b);
 
 	/* try the key */
-	key_sign(key, &sig, &slen, data, sizeof(data));
-	key_verify(key, sig, slen, data, sizeof(data));
+	if (sshkey_sign(key, &sig, &slen, data, sizeof(data), 0) != 0 ||
+	    sshkey_verify(key, sig, slen, data, sizeof(data), 0) != 0) {
+		sshkey_free(key);
+		free(sig);
+		return NULL;
+	}
 	free(sig);
 	return key;
 }
@@ -539,14 +560,13 @@
 }
 
 static void
-do_convert_from_ssh2(struct passwd *pw, Key **k, int *private)
+do_convert_from_ssh2(struct passwd *pw, struct sshkey **k, int *private)
 {
-	int blen;
+	int r, blen, escaped = 0;
 	u_int len;
 	char line[1024];
 	u_char blob[8096];
 	char encoded[8096];
-	int escaped = 0;
 	FILE *fp;
 
 	if ((fp = fopen(identity_file, "r")) == NULL)
@@ -583,18 +603,17 @@
 		fprintf(stderr, "uudecode failed.\n");
 		exit(1);
 	}
-	*k = *private ?
-	    do_convert_private_ssh2_from_blob(blob, blen) :
-	    key_from_blob(blob, blen);
-	if (*k == NULL) {
-		fprintf(stderr, "decode blob failed.\n");
+	if (*private)
+		*k = do_convert_private_ssh2_from_blob(blob, blen);
+	else if ((r = sshkey_from_blob(blob, blen, k)) != 0) {
+		fprintf(stderr, "decode blob failed: %s\n", ssh_err(r));
 		exit(1);
 	}
 	fclose(fp);
 }
 
 static void
-do_convert_from_pkcs8(Key **k, int *private)
+do_convert_from_pkcs8(struct sshkey **k, int *private)
 {
 	EVP_PKEY *pubkey;
 	FILE *fp;
@@ -608,21 +627,24 @@
 	fclose(fp);
 	switch (EVP_PKEY_type(pubkey->type)) {
 	case EVP_PKEY_RSA:
-		*k = key_new(KEY_UNSPEC);
+		if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
+			fatal("sshkey_new failed");
 		(*k)->type = KEY_RSA;
 		(*k)->rsa = EVP_PKEY_get1_RSA(pubkey);
 		break;
 	case EVP_PKEY_DSA:
-		*k = key_new(KEY_UNSPEC);
+		if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
+			fatal("sshkey_new failed");
 		(*k)->type = KEY_DSA;
 		(*k)->dsa = EVP_PKEY_get1_DSA(pubkey);
 		break;
 #ifdef OPENSSL_HAS_ECC
 	case EVP_PKEY_EC:
-		*k = key_new(KEY_UNSPEC);
+		if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
+			fatal("sshkey_new failed");
 		(*k)->type = KEY_ECDSA;
 		(*k)->ecdsa = EVP_PKEY_get1_EC_KEY(pubkey);
-		(*k)->ecdsa_nid = key_ecdsa_key_to_nid((*k)->ecdsa);
+		(*k)->ecdsa_nid = sshkey_ecdsa_key_to_nid((*k)->ecdsa);
 		break;
 #endif
 	default:
@@ -634,7 +656,7 @@
 }
 
 static void
-do_convert_from_pem(Key **k, int *private)
+do_convert_from_pem(struct sshkey **k, int *private)
 {
 	FILE *fp;
 	RSA *rsa;
@@ -645,7 +667,8 @@
 	if ((fp = fopen(identity_file, "r")) == NULL)
 		fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
 	if ((rsa = PEM_read_RSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
-		*k = key_new(KEY_UNSPEC);
+		if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
+			fatal("sshkey_new failed");
 		(*k)->type = KEY_RSA;
 		(*k)->rsa = rsa;
 		fclose(fp);
@@ -654,7 +677,8 @@
 #if notyet /* OpenSSH 0.9.8 lacks this function */
 	rewind(fp);
 	if ((dsa = PEM_read_DSAPublicKey(fp, NULL, NULL, NULL)) != NULL) {
-		*k = key_new(KEY_UNSPEC);
+		if ((*k = sshkey_new(KEY_UNSPEC)) == NULL)
+			fatal("sshkey_new failed");
 		(*k)->type = KEY_DSA;
 		(*k)->dsa = dsa;
 		fclose(fp);
@@ -668,8 +692,8 @@
 static void
 do_convert_from(struct passwd *pw)
 {
-	Key *k = NULL;
-	int private = 0, ok = 0;
+	struct sshkey *k = NULL;
+	int r, private = 0, ok = 0;
 	struct stat st;
 
 	if (!have_identity)
@@ -692,7 +716,8 @@
 	}
 
 	if (!private)
-		ok = key_write(k, stdout);
+		if ((r = sshkey_write(k, stdout)) == 0)
+			ok = 1;
 		if (ok)
 			fprintf(stdout, "\n");
 	else {
@@ -713,7 +738,7 @@
 			break;
 		default:
 			fatal("%s: unsupported key type %s", __func__,
-			    key_type(k));
+			    sshkey_type(k));
 		}
 	}
 
@@ -721,7 +746,7 @@
 		fprintf(stderr, "key write failed\n");
 		exit(1);
 	}
-	key_free(k);
+	sshkey_free(k);
 	exit(0);
 }
 #endif
@@ -729,8 +754,9 @@
 static void
 do_print_public(struct passwd *pw)
 {
-	Key *prv;
+	struct sshkey *prv;
 	struct stat st;
+	int r;
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which the key is");
@@ -739,13 +765,9 @@
 		exit(1);
 	}
 	prv = load_identity(identity_file);
-	if (prv == NULL) {
-		fprintf(stderr, "load failed\n");
-		exit(1);
-	}
-	if (!key_write(prv, stdout))
-		fprintf(stderr, "key_write failed");
-	key_free(prv);
+	if ((r = sshkey_write(prv, stdout)) != 0)
+		fprintf(stderr, "key_write failed: %s", ssh_err(r));
+	sshkey_free(prv);
 	fprintf(stdout, "\n");
 	exit(0);
 }
@@ -754,9 +776,9 @@
 do_download(struct passwd *pw)
 {
 #ifdef ENABLE_PKCS11
-	Key **keys = NULL;
+	struct sshkey **keys = NULL;
 	int i, nkeys;
-	enum fp_rep rep;
+	enum sshkey_fp_rep rep;
 	int fptype;
 	char *fp, *ra;
 
@@ -769,20 +791,20 @@
 		fatal("cannot read public key from pkcs11");
 	for (i = 0; i < nkeys; i++) {
 		if (print_fingerprint) {
-			fp = key_fingerprint(keys[i], fptype, rep);
-			ra = key_fingerprint(keys[i], fingerprint_hash,
+			fp = sshkey_fingerprint(keys[i], fptype, rep);
+			ra = sshkey_fingerprint(keys[i], fingerprint_hash,
 			    SSH_FP_RANDOMART);
-			printf("%u %s %s (PKCS11 key)\n", key_size(keys[i]),
-			    fp, key_type(keys[i]));
+			printf("%u %s %s (PKCS11 key)\n", sshkey_size(keys[i]),
+			    fp, sshkey_type(keys[i]));
 			if (log_level >= SYSLOG_LEVEL_VERBOSE)
 				printf("%s\n", ra);
 			free(ra);
 			free(fp);
 		} else {
-			key_write(keys[i], stdout);
+			(void) sshkey_write(keys[i], stdout); /* XXX check */
 			fprintf(stdout, "\n");
 		}
-		key_free(keys[i]);
+		sshkey_free(keys[i]);
 	}
 	free(keys);
 	pkcs11_terminate();
@@ -796,10 +818,10 @@
 do_fingerprint(struct passwd *pw)
 {
 	FILE *f;
-	Key *public;
+	struct sshkey *public;
 	char *comment = NULL, *cp, *ep, line[16*1024], *fp, *ra;
-	int i, skip = 0, num = 0, invalid = 1;
-	enum fp_rep rep;
+	int r, i, skip = 0, num = 0, invalid = 1;
+	enum sshkey_fp_rep rep;
 	int fptype;
 	struct stat st;
 
@@ -811,16 +833,18 @@
 		perror(identity_file);
 		exit(1);
 	}
-	public = key_load_public(identity_file, &comment);
-	if (public != NULL) {
-		fp = key_fingerprint(public, fptype, rep);
-		ra = key_fingerprint(public, fingerprint_hash,
+	if ((r = sshkey_load_public(identity_file, &public, &comment)) != 0)
+		error("Error loading public key \"%s\": %s",
+		    identity_file, ssh_err(r));
+	else {
+		fp = sshkey_fingerprint(public, fptype, rep);
+		ra = sshkey_fingerprint(public, fingerprint_hash,
 		    SSH_FP_RANDOMART);
-		printf("%u %s %s (%s)\n", key_size(public), fp, comment,
-		    key_type(public));
+		printf("%u %s %s (%s)\n", sshkey_size(public), fp, comment,
+		    sshkey_type(public));
 		if (log_level >= SYSLOG_LEVEL_VERBOSE)
 			printf("%s\n", ra);
-		key_free(public);
+		sshkey_free(public);
 		free(comment);
 		free(ra);
 		free(fp);
@@ -869,27 +893,29 @@
 			*cp++ = '\0';
 		}
 		ep = cp;
-		public = key_new(KEY_RSA1);
-		if (key_read(public, &cp) != 1) {
+		if ((public = sshkey_new(KEY_RSA1)) == NULL)
+			fatal("sshkey_new failed");
+		if ((r = sshkey_read(public, &cp)) != 0) {
 			cp = ep;
-			key_free(public);
-			public = key_new(KEY_UNSPEC);
-			if (key_read(public, &cp) != 1) {
-				key_free(public);
+			sshkey_free(public);
+			if ((public = sshkey_new(KEY_UNSPEC)) == NULL)
+				fatal("sshkey_new failed");
+			if ((r = sshkey_read(public, &cp)) != 0) {
+				sshkey_free(public);
 				continue;
 			}
 		}
 		comment = *cp ? cp : comment;
-		fp = key_fingerprint(public, fptype, rep);
-		ra = key_fingerprint(public, fingerprint_hash,
+		fp = sshkey_fingerprint(public, fptype, rep);
+		ra = sshkey_fingerprint(public, fingerprint_hash,
 		    SSH_FP_RANDOMART);
-		printf("%u %s %s (%s)\n", key_size(public), fp,
-		    comment ? comment : "no comment", key_type(public));
+		printf("%u %s %s (%s)\n", sshkey_size(public), fp,
+		    comment ? comment : "no comment", sshkey_type(public));
 		if (log_level >= SYSLOG_LEVEL_VERBOSE)
 			printf("%s\n", ra);
 		free(ra);
 		free(fp);
-		key_free(public);
+		sshkey_free(public);
 		invalid = 0;
 	}
 	fclose(f);
@@ -921,9 +947,9 @@
 
 	int first = 0;
 	struct stat st;
-	Key *private, *public;
+	struct sshkey *private, *public;
 	char comment[1024];
-	int i, type, fd;
+	int i, type, fd, r;
 	FILE *f;
 
 	for (i = 0; key_types[i].key_type; i++) {
@@ -942,34 +968,36 @@
 		}
 		printf("%s ", key_types[i].key_type_display);
 		fflush(stdout);
-		type = key_type_from_name(key_types[i].key_type);
+		type = sshkey_type_from_name(key_types[i].key_type);
 		strlcpy(identity_file, key_types[i].path, sizeof(identity_file));
 		bits = 0;
 		type_bits_valid(type, &bits);
-		private = key_generate(type, bits);
-		if (private == NULL) {
-			fprintf(stderr, "key_generate failed\n");
+		if ((r = sshkey_generate(type, bits, &private)) != 0) {
+			fprintf(stderr, "key_generate failed: %s\n",
+			    ssh_err(r));
 			first = 0;
 			continue;
 		}
-		public  = key_from_private(private);
+		if ((r = sshkey_from_private(private, &public)) != 0)
+			fatal("sshkey_from_private failed: %s", ssh_err(r));
 		snprintf(comment, sizeof comment, "%s@%s", pw->pw_name,
 		    hostname);
-		if (!key_save_private(private, identity_file, "", comment,
-		    use_new_format, new_format_cipher, rounds)) {
-			printf("Saving the key failed: %s.\n", identity_file);
-			key_free(private);
-			key_free(public);
+		if ((r = sshkey_save_private(private, identity_file, "",
+		    comment, use_new_format, new_format_cipher, rounds)) != 0) {
+			printf("Saving key \"%s\" failed: %s\n", identity_file,
+			    ssh_err(r));
+			sshkey_free(private);
+			sshkey_free(public);
 			first = 0;
 			continue;
 		}
-		key_free(private);
+		sshkey_free(private);
 		strlcat(identity_file, ".pub", sizeof(identity_file));
 		fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 		if (fd == -1) {
 			printf("Could not save your public key in %s\n",
 			    identity_file);
-			key_free(public);
+			sshkey_free(public);
 			first = 0;
 			continue;
 		}
@@ -977,20 +1005,20 @@
 		if (f == NULL) {
 			printf("fdopen %s failed\n", identity_file);
 			close(fd);
-			key_free(public);
+			sshkey_free(public);
 			first = 0;
 			continue;
 		}
-		if (!key_write(public, f)) {
+		if (!sshkey_write(public, f)) {
 			fprintf(stderr, "write key failed\n");
 			fclose(f);
-			key_free(public);
+			sshkey_free(public);
 			first = 0;
 			continue;
 		}
 		fprintf(f, " %s\n", comment);
 		fclose(f);
-		key_free(public);
+		sshkey_free(public);
 
 	}
 	if (first != 0)
@@ -998,32 +1026,35 @@
 }
 
 static void
-printhost(FILE *f, const char *name, Key *public, int ca, int revoked, int hash)
+printhost(FILE *f, const char *name, struct sshkey *public,
+    int ca, int revoked, int hash)
 {
 	if (print_fingerprint) {
-		enum fp_rep rep;
+		enum sshkey_fp_rep rep;
 		int fptype;
 		char *fp, *ra;
 
 		fptype = print_bubblebabble ?
 		    SSH_DIGEST_SHA1 : fingerprint_hash;
 		rep = print_bubblebabble ? SSH_FP_BUBBLEBABBLE : SSH_FP_DEFAULT;
-		fp = key_fingerprint(public, fptype, rep);
-		ra = key_fingerprint(public, fingerprint_hash,
+		fp = sshkey_fingerprint(public, fptype, rep);
+		ra = sshkey_fingerprint(public, fingerprint_hash,
 		    SSH_FP_RANDOMART);
-		printf("%u %s %s (%s)\n", key_size(public), fp, name,
-		    key_type(public));
+		printf("%u %s %s (%s)\n", sshkey_size(public), fp, name,
+		    sshkey_type(public));
 		if (log_level >= SYSLOG_LEVEL_VERBOSE)
 			printf("%s\n", ra);
 		free(ra);
 		free(fp);
 	} else {
+		int r;
+
 		if (hash && (name = host_hash(name, NULL, 0)) == NULL)
 			fatal("hash_host failed");
 		fprintf(f, "%s%s%s ", ca ? CA_MARKER " " : "",
 		    revoked ? REVOKE_MARKER " " : "" , name);
-		if (!key_write(public, f))
-			fatal("key_write failed");
+		if ((r = sshkey_write(public, f)) != 0)
+			fatal("key_write failed: %s", ssh_err(r));
 		fprintf(f, "\n");
 	}
 }
@@ -1032,11 +1063,11 @@
 do_known_hosts(struct passwd *pw, const char *name)
 {
 	FILE *in, *out = stdout;
-	Key *pub;
+	struct sshkey *pub;
 	char *cp, *cp2, *kp, *kp2;
 	char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
 	int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
-	int ca, revoked;
+	int r, ca, revoked;
 	int found_key = 0;
 
 	if (!have_identity) {
@@ -1106,7 +1137,7 @@
 		    sizeof(REVOKE_MARKER) - 1) == 0 &&
 		    (cp[sizeof(REVOKE_MARKER) - 1] == ' ' ||
 		    cp[sizeof(REVOKE_MARKER) - 1] == '\t')) {
- 			revoked = 1;
+			revoked = 1;
 			cp += sizeof(REVOKE_MARKER);
 		} else
 			revoked = 0;
@@ -1124,15 +1155,17 @@
 		*kp++ = '\0';
 		kp2 = kp;
 
-		pub = key_new(KEY_RSA1);
-		if (key_read(pub, &kp) != 1) {
+		if ((pub = sshkey_new(KEY_RSA1)) == NULL)
+			fatal("sshkey_new failed");
+		if ((r = sshkey_read(pub, &kp)) != 0) {
 			kp = kp2;
-			key_free(pub);
-			pub = key_new(KEY_UNSPEC);
-			if (key_read(pub, &kp) != 1) {
+			sshkey_free(pub);
+			if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
+				fatal("sshkey_new failed");
+			if ((r = sshkey_read(pub, &kp)) != 0) {
 				error("line %d invalid key: %.40s...",
 				    num, line);
-				key_free(pub);
+				sshkey_free(pub);
 				invalid = 1;
 				continue;
 			}
@@ -1152,7 +1185,7 @@
 					if (!quiet)
 						printf("# Host %s found: "
 						    "line %d type %s%s\n", name,
-						    num, key_type(pub),
+						    num, sshkey_type(pub),
 						    ca ? " (CA key)" :
 						    revoked? " (revoked)" : "");
 					printhost(out, cp, pub, ca, revoked, 0);
@@ -1165,7 +1198,7 @@
 					} else {
 						printf("# Host %s found: "
 						    "line %d type %s\n", name,
-						    num, key_type(pub));
+						    num, sshkey_type(pub));
 					}
 				}
 			} else if (hash_hosts)
@@ -1178,7 +1211,7 @@
 					if (!quiet)
 						printf("# Host %s found: "
 						    "line %d type %s%s\n", name,
-						    num, key_type(pub),
+						    num, sshkey_type(pub),
 						    ca ? " (CA key)" : "");
 					printhost(out, name, pub, ca, revoked,
 					    hash_hosts && !(ca || revoked));
@@ -1191,7 +1224,7 @@
 					} else {
 						printf("# Host %s found: "
 						    "line %d type %s\n", name,
-						    num, key_type(pub));
+						    num, sshkey_type(pub));
 					}
 				}
 			} else if (hash_hosts && (ca || revoked)) {
@@ -1219,7 +1252,7 @@
 				}
 			}
 		}
-		key_free(pub);
+		sshkey_free(pub);
 	}
 	fclose(in);
 
@@ -1276,7 +1309,8 @@
 	char *comment;
 	char *old_passphrase, *passphrase1, *passphrase2;
 	struct stat st;
-	Key *private;
+	struct sshkey *private;
+	int r;
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which the key is");
@@ -1285,22 +1319,25 @@
 		exit(1);
 	}
 	/* Try to load the file with empty passphrase. */
-	private = key_load_private(identity_file, "", &comment);
-	if (private == NULL) {
+	r = sshkey_load_private(identity_file, "", &private, &comment);
+	if (r == SSH_ERR_KEY_WRONG_PASSPHRASE) {
 		if (identity_passphrase)
 			old_passphrase = xstrdup(identity_passphrase);
 		else
 			old_passphrase =
 			    read_passphrase("Enter old passphrase: ",
 			    RP_ALLOW_STDIN);
-		private = key_load_private(identity_file, old_passphrase,
-		    &comment);
+		r = sshkey_load_private(identity_file, old_passphrase,
+		    &private, &comment);
 		explicit_bzero(old_passphrase, strlen(old_passphrase));
 		free(old_passphrase);
-		if (private == NULL) {
-			printf("Bad passphrase.\n");
-			exit(1);
-		}
+		if (r != 0)
+			goto badkey;
+	} else if (r != 0) {
+ badkey:
+		fprintf(stderr, "Failed to load key \"%s\": %s\n",
+		    identity_file, ssh_err(r));
+		exit(1);
 	}
 	printf("Key has comment '%s'\n", comment);
 
@@ -1330,19 +1367,20 @@
 	}
 
 	/* Save the file using the new passphrase. */
-	if (!key_save_private(private, identity_file, passphrase1, comment,
-	    use_new_format, new_format_cipher, rounds)) {
-		printf("Saving the key failed: %s.\n", identity_file);
+	if ((r = sshkey_save_private(private, identity_file, passphrase1,
+	    comment, use_new_format, new_format_cipher, rounds)) != 0) {
+		printf("Saving key \"%s\" failed: %s.\n",
+		    identity_file, ssh_err(r));
 		explicit_bzero(passphrase1, strlen(passphrase1));
 		free(passphrase1);
-		key_free(private);
+		sshkey_free(private);
 		free(comment);
 		exit(1);
 	}
 	/* Destroy the passphrase and the copy of the key in memory. */
 	explicit_bzero(passphrase1, strlen(passphrase1));
 	free(passphrase1);
-	key_free(private);		 /* Destroys contents */
+	sshkey_free(private);		 /* Destroys contents */
 	free(comment);
 
 	printf("Your identification has been saved with the new passphrase.\n");
@@ -1355,9 +1393,10 @@
 static int
 do_print_resource_record(struct passwd *pw, char *fname, char *hname)
 {
-	Key *public;
+	struct sshkey *public;
 	char *comment = NULL;
 	struct stat st;
+	int r;
 
 	if (fname == NULL)
 		fatal("%s: no filename", __func__);
@@ -1367,18 +1406,15 @@
 		perror(fname);
 		exit(1);
 	}
-	public = key_load_public(fname, &comment);
-	if (public != NULL) {
-		export_dns_rr(hname, public, stdout, print_generic);
-		key_free(public);
-		free(comment);
-		return 1;
+	if ((r = sshkey_load_public(fname, &public, &comment)) != 0) {
+		printf("Failed to read v2 public key from \"%s\": %s.\n",
+		    fname, ssh_err(r));
+		exit(1);
 	}
-	if (comment)
-		free(comment);
-
-	printf("failed to read v2 public key from %s.\n", fname);
-	exit(1);
+	export_dns_rr(hname, public, stdout, print_generic);
+	sshkey_free(public);
+	free(comment);
+	return 1;
 }
 
 /*
@@ -1388,11 +1424,11 @@
 do_change_comment(struct passwd *pw)
 {
 	char new_comment[1024], *comment, *passphrase;
-	Key *private;
-	Key *public;
+	struct sshkey *private;
+	struct sshkey *public;
 	struct stat st;
 	FILE *f;
-	int fd;
+	int r, fd;
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which the key is");
@@ -1400,8 +1436,14 @@
 		perror(identity_file);
 		exit(1);
 	}
-	private = key_load_private(identity_file, "", &comment);
-	if (private == NULL) {
+	if ((r = sshkey_load_private(identity_file, "",
+	    &private, &comment)) == 0)
+		passphrase = xstrdup("");
+	else if (r != SSH_ERR_KEY_WRONG_PASSPHRASE) {
+		printf("Cannot load private key \"%s\": %s.\n",
+		    identity_file, ssh_err(r));
+		exit(1);
+	} else {
 		if (identity_passphrase)
 			passphrase = xstrdup(identity_passphrase);
 		else if (identity_new_passphrase)
@@ -1410,19 +1452,18 @@
 			passphrase = read_passphrase("Enter passphrase: ",
 			    RP_ALLOW_STDIN);
 		/* Try to load using the passphrase. */
-		private = key_load_private(identity_file, passphrase, &comment);
-		if (private == NULL) {
+		if ((r = sshkey_load_private(identity_file, passphrase,
+		    &private, &comment)) != 0) {
 			explicit_bzero(passphrase, strlen(passphrase));
 			free(passphrase);
-			printf("Bad passphrase.\n");
+			printf("Cannot load private key \"%s\": %s.\n",
+			    identity_file, ssh_err(r));
 			exit(1);
 		}
-	} else {
-		passphrase = xstrdup("");
 	}
 	if (private->type != KEY_RSA1) {
 		fprintf(stderr, "Comments are only supported for RSA1 keys.\n");
-		key_free(private);
+		sshkey_free(private);
 		exit(1);
 	}
 	printf("Key now has comment '%s'\n", comment);
@@ -1434,26 +1475,28 @@
 		fflush(stdout);
 		if (!fgets(new_comment, sizeof(new_comment), stdin)) {
 			explicit_bzero(passphrase, strlen(passphrase));
-			key_free(private);
+			sshkey_free(private);
 			exit(1);
 		}
 		new_comment[strcspn(new_comment, "\n")] = '\0';
 	}
 
 	/* Save the file using the new passphrase. */
-	if (!key_save_private(private, identity_file, passphrase, new_comment,
-	    use_new_format, new_format_cipher, rounds)) {
-		printf("Saving the key failed: %s.\n", identity_file);
+	if ((r = sshkey_save_private(private, identity_file, passphrase,
+	    new_comment, use_new_format, new_format_cipher, rounds)) != 0) {
+		printf("Saving key \"%s\" failed: %s\n",
+		    identity_file, ssh_err(r));
 		explicit_bzero(passphrase, strlen(passphrase));
 		free(passphrase);
-		key_free(private);
+		sshkey_free(private);
 		free(comment);
 		exit(1);
 	}
 	explicit_bzero(passphrase, strlen(passphrase));
 	free(passphrase);
-	public = key_from_private(private);
-	key_free(private);
+	if ((r = sshkey_from_private(private, &public)) != 0)
+		fatal("key_from_private failed: %s", ssh_err(r));
+	sshkey_free(private);
 
 	strlcat(identity_file, ".pub", sizeof(identity_file));
 	fd = open(identity_file, O_WRONLY | O_CREAT | O_TRUNC, 0644);
@@ -1466,9 +1509,9 @@
 		printf("fdopen %s failed\n", identity_file);
 		exit(1);
 	}
-	if (!key_write(public, f))
-		fprintf(stderr, "write key failed\n");
-	key_free(public);
+	if ((r = sshkey_write(public, f)) != 0)
+		fprintf(stderr, "write key failed: %s\n", ssh_err(r));
+	sshkey_free(public);
 	fprintf(f, " %s\n", new_comment);
 	fclose(f);
 
@@ -1517,34 +1560,39 @@
 }
 
 static void
-add_flag_option(Buffer *c, const char *name)
+add_flag_option(struct sshbuf *c, const char *name)
 {
+	int r;
+
 	debug3("%s: %s", __func__, name);
-	buffer_put_cstring(c, name);
-	buffer_put_string(c, NULL, 0);
+	if ((r = sshbuf_put_cstring(c, name)) != 0 ||
+	    (r = sshbuf_put_string(c, NULL, 0)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 }
 
 static void
-add_string_option(Buffer *c, const char *name, const char *value)
+add_string_option(struct sshbuf *c, const char *name, const char *value)
 {
-	Buffer b;
+	struct sshbuf *b;
+	int r;
 
 	debug3("%s: %s=%s", __func__, name, value);
-	buffer_init(&b);
-	buffer_put_cstring(&b, value);
+	if ((b = sshbuf_new()) == NULL)
+		fatal("%s: sshbuf_new failed", __func__);
+	if ((r = sshbuf_put_cstring(b, value)) != 0 ||
+	    (r = sshbuf_put_cstring(c, name)) != 0 ||
+	    (r = sshbuf_put_stringb(c, b)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-	buffer_put_cstring(c, name);
-	buffer_put_string(c, buffer_ptr(&b), buffer_len(&b));
-
-	buffer_free(&b);
+	sshbuf_free(b);
 }
 
 #define OPTIONS_CRITICAL	1
 #define OPTIONS_EXTENSIONS	2
 static void
-prepare_options_buf(Buffer *c, int which)
+prepare_options_buf(struct sshbuf *c, int which)
 {
-	buffer_clear(c);
+	sshbuf_reset(c);
 	if ((which & OPTIONS_CRITICAL) != 0 &&
 	    certflags_command != NULL)
 		add_string_option(c, "force-command", certflags_command);
@@ -1568,29 +1616,30 @@
 		add_string_option(c, "source-address", certflags_src_addr);
 }
 
-static Key *
+static struct sshkey *
 load_pkcs11_key(char *path)
 {
 #ifdef ENABLE_PKCS11
-	Key **keys = NULL, *public, *private = NULL;
-	int i, nkeys;
+	struct sshkey **keys = NULL, *public, *private = NULL;
+	int r, i, nkeys;
 
-	if ((public = key_load_public(path, NULL)) == NULL)
-		fatal("Couldn't load CA public key \"%s\"", path);
+	if ((r = sshkey_load_public(path, &public, NULL)) != 0)
+		fatal("Couldn't load CA public key \"%s\": %s",
+		    path, ssh_err(r));
 
 	nkeys = pkcs11_add_provider(pkcs11provider, identity_passphrase, &keys);
 	debug3("%s: %d keys", __func__, nkeys);
 	if (nkeys <= 0)
 		fatal("cannot read public key from pkcs11");
 	for (i = 0; i < nkeys; i++) {
-		if (key_equal_public(public, keys[i])) {
+		if (sshkey_equal_public(public, keys[i])) {
 			private = keys[i];
 			continue;
 		}
-		key_free(keys[i]);
+		sshkey_free(keys[i]);
 	}
 	free(keys);
-	key_free(public);
+	sshkey_free(public);
 	return private;
 #else
 	fatal("no pkcs11 support");
@@ -1600,15 +1649,15 @@
 static void
 do_ca_sign(struct passwd *pw, int argc, char **argv)
 {
-	int i, fd;
+	int r, i, fd;
 	u_int n;
-	Key *ca, *public;
+	struct sshkey *ca, *public;
 	char *otmp, *tmp, *cp, *out, *comment, **plist = NULL;
 	FILE *f;
 	int v00 = 0; /* legacy keys */
 
 	if (key_type_name != NULL) {
-		switch (key_type_from_name(key_type_name)) {
+		switch (sshkey_type_from_name(key_type_name)) {
 		case KEY_RSA_CERT_V00:
 		case KEY_DSA_CERT_V00:
 			v00 = 1;
@@ -1633,8 +1682,8 @@
 	if (pkcs11provider != NULL) {
 		if ((ca = load_pkcs11_key(tmp)) == NULL)
 			fatal("No PKCS#11 key matching %s found", ca_key_path);
-	} else if ((ca = load_identity(tmp)) == NULL)
-		fatal("Couldn't load CA key \"%s\"", tmp);
+	} else
+		ca = load_identity(tmp);
 	free(tmp);
 
 	for (i = 0; i < argc; i++) {
@@ -1652,16 +1701,18 @@
 		}
 	
 		tmp = tilde_expand_filename(argv[i], pw->pw_uid);
-		if ((public = key_load_public(tmp, &comment)) == NULL)
-			fatal("%s: unable to open \"%s\"", __func__, tmp);
+		if ((r = sshkey_load_public(tmp, &public, &comment)) != 0)
+			fatal("%s: unable to open \"%s\": %s",
+			    __func__, tmp, ssh_err(r));
 		if (public->type != KEY_RSA && public->type != KEY_DSA &&
 		    public->type != KEY_ECDSA && public->type != KEY_ED25519)
 			fatal("%s: key \"%s\" type %s cannot be certified",
-			    __func__, tmp, key_type(public));
+			    __func__, tmp, sshkey_type(public));
 
 		/* Prepare certificate to sign */
-		if (key_to_certified(public, v00) != 0)
-			fatal("Could not upgrade key %s to certificate", tmp);
+		if ((r = sshkey_to_certified(public, v00)) != 0)
+			fatal("Could not upgrade key %s to certificate: %s",
+			    tmp, ssh_err(r));
 		public->cert->type = cert_key_type;
 		public->cert->serial = (u_int64_t)cert_serial;
 		public->cert->key_id = xstrdup(cert_key_id);
@@ -1678,9 +1729,11 @@
 			prepare_options_buf(public->cert->extensions,
 			    OPTIONS_EXTENSIONS);
 		}
-		public->cert->signature_key = key_from_private(ca);
+		if ((r = sshkey_from_private(ca,
+		    &public->cert->signature_key)) != 0)
+			fatal("key_from_private (ca key): %s", ssh_err(r));
 
-		if (key_certify(public, ca) != 0)
+		if (sshkey_certify(public, ca) != 0)
 			fatal("Couldn't not certify key %s", tmp);
 
 		if ((cp = strrchr(tmp, '.')) != NULL && strcmp(cp, ".pub") == 0)
@@ -1693,14 +1746,15 @@
 			    strerror(errno));
 		if ((f = fdopen(fd, "w")) == NULL)
 			fatal("%s: fdopen: %s", __func__, strerror(errno));
-		if (!key_write(public, f))
-			fatal("Could not write certified key to %s", out);
+		if ((r = sshkey_write(public, f)) != 0)
+			fatal("Could not write certified key to %s: %s",
+			    out, ssh_err(r));
 		fprintf(f, " %s\n", comment);
 		fclose(f);
 
 		if (!quiet) {
 			logit("Signed %s key %s: id \"%s\" serial %llu%s%s "
-			    "valid %s", key_cert_type(public), 
+			    "valid %s", sshkey_cert_type(public), 
 			    out, public->cert->key_id,
 			    (unsigned long long)public->cert->serial,
 			    cert_principals != NULL ? " for " : "",
@@ -1708,7 +1762,7 @@
 			    fmt_validity(cert_valid_from, cert_valid_to));
 		}
 
-		key_free(public);
+		sshkey_free(public);
 		free(out);
 	}
 #ifdef ENABLE_PKCS11
@@ -1859,21 +1913,20 @@
 }
 
 static void
-show_options(const Buffer *optbuf, int v00, int in_critical)
+show_options(struct sshbuf *optbuf, int v00, int in_critical)
 {
 	char *name, *arg;
-	const u_char *data;
-	u_int dlen;
-	Buffer options, option;
+	struct sshbuf *options, *option = NULL;
+	int r;
 
-	buffer_init(&options);
-	buffer_append(&options, buffer_ptr(optbuf), buffer_len(optbuf));
-
-	buffer_init(&option);
-	while (buffer_len(&options) != 0) {
-		name = buffer_get_string(&options, NULL);
-		data = buffer_get_string_ptr(&options, &dlen);
-		buffer_append(&option, data, dlen);
+	if ((options = sshbuf_fromb(optbuf)) == NULL)
+		fatal("%s: sshbuf_fromb failed", __func__);
+	while (sshbuf_len(options) != 0) {
+		sshbuf_free(option);
+		option = NULL;
+		if ((r = sshbuf_get_cstring(options, &name, NULL)) != 0 ||
+		    (r = sshbuf_froms(options, &option)) != 0)
+			fatal("%s: buffer error: %s", __func__, ssh_err(r));
 		printf("                %s", name);
 		if ((v00 || !in_critical) && 
 		    (strcmp(name, "permit-X11-forwarding") == 0 ||
@@ -1885,50 +1938,54 @@
 		else if ((v00 || in_critical) &&
 		    (strcmp(name, "force-command") == 0 ||
 		    strcmp(name, "source-address") == 0)) {
-			arg = buffer_get_cstring(&option, NULL);
+			if ((r = sshbuf_get_cstring(option, &arg, NULL)) != 0)
+				fatal("%s: buffer error: %s",
+				    __func__, ssh_err(r));
 			printf(" %s\n", arg);
 			free(arg);
 		} else {
-			printf(" UNKNOWN OPTION (len %u)\n",
-			    buffer_len(&option));
-			buffer_clear(&option);
+			printf(" UNKNOWN OPTION (len %zu)\n",
+			    sshbuf_len(option));
+			sshbuf_reset(option);
 		}
 		free(name);
-		if (buffer_len(&option) != 0)
+		if (sshbuf_len(option) != 0)
 			fatal("Option corrupt: extra data at end");
 	}
-	buffer_free(&option);
-	buffer_free(&options);
+	sshbuf_free(option);
+	sshbuf_free(options);
 }
 
 static void
 do_show_cert(struct passwd *pw)
 {
-	Key *key;
+	struct sshkey *key;
 	struct stat st;
 	char *key_fp, *ca_fp;
 	u_int i, v00;
+	int r;
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which the key is");
 	if (stat(identity_file, &st) < 0)
 		fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
-	if ((key = key_load_public(identity_file, NULL)) == NULL)
-		fatal("%s is not a public key", identity_file);
-	if (!key_is_cert(key))
+	if ((r = sshkey_load_public(identity_file, &key, NULL)) != 0)
+		fatal("Cannot load public key \"%s\": %s",
+		    identity_file, ssh_err(r));
+	if (!sshkey_is_cert(key))
 		fatal("%s is not a certificate", identity_file);
 	v00 = key->type == KEY_RSA_CERT_V00 || key->type == KEY_DSA_CERT_V00;
 
-	key_fp = key_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
-	ca_fp = key_fingerprint(key->cert->signature_key,
+	key_fp = sshkey_fingerprint(key, fingerprint_hash, SSH_FP_DEFAULT);
+	ca_fp = sshkey_fingerprint(key->cert->signature_key,
 	    fingerprint_hash, SSH_FP_DEFAULT);
 
 	printf("%s:\n", identity_file);
-	printf("        Type: %s %s certificate\n", key_ssh_name(key),
-	    key_cert_type(key));
-	printf("        Public key: %s %s\n", key_type(key), key_fp);
+	printf("        Type: %s %s certificate\n", sshkey_ssh_name(key),
+	    sshkey_cert_type(key));
+	printf("        Public key: %s %s\n", sshkey_type(key), key_fp);
 	printf("        Signing CA: %s %s\n",
-	    key_type(key->cert->signature_key), ca_fp);
+	    sshkey_type(key->cert->signature_key), ca_fp);
 	printf("        Key ID: \"%s\"\n", key->cert->key_id);
 	if (!v00) {
 		printf("        Serial: %llu\n",
@@ -1946,7 +2003,7 @@
 		printf("\n");
 	}
 	printf("        Critical Options: ");
-	if (buffer_len(key->cert->critical) == 0)
+	if (sshbuf_len(key->cert->critical) == 0)
 		printf("(none)\n");
 	else {
 		printf("\n");
@@ -1954,7 +2011,7 @@
 	}
 	if (!v00) {
 		printf("        Extensions: ");
-		if (buffer_len(key->cert->extensions) == 0)
+		if (sshbuf_len(key->cert->extensions) == 0)
 			printf("(none)\n");
 		else {
 			printf("\n");
@@ -1967,27 +2024,28 @@
 static void
 load_krl(const char *path, struct ssh_krl **krlp)
 {
-	Buffer krlbuf;
-	int fd;
+	struct sshbuf *krlbuf;
+	int r, fd;
 
-	buffer_init(&krlbuf);
+	if ((krlbuf = sshbuf_new()) == NULL)
+		fatal("sshbuf_new failed");
 	if ((fd = open(path, O_RDONLY)) == -1)
 		fatal("open %s: %s", path, strerror(errno));
-	if (!key_load_file(fd, path, &krlbuf))
-		fatal("Unable to load KRL");
+	if ((r = sshkey_load_file(fd, krlbuf)) != 0)
+		fatal("Unable to load KRL: %s", ssh_err(r));
 	close(fd);
 	/* XXX check sigs */
-	if (ssh_krl_from_blob(&krlbuf, krlp, NULL, 0) != 0 ||
+	if ((r = ssh_krl_from_blob(krlbuf, krlp, NULL, 0)) != 0 ||
 	    *krlp == NULL)
-		fatal("Invalid KRL file");
-	buffer_free(&krlbuf);
+		fatal("Invalid KRL file: %s", ssh_err(r));
+	sshbuf_free(krlbuf);
 }
 
 static void
-update_krl_from_file(struct passwd *pw, const char *file, const Key *ca,
-    struct ssh_krl *krl)
+update_krl_from_file(struct passwd *pw, const char *file,
+    const struct sshkey *ca, struct ssh_krl *krl)
 {
-	Key *key = NULL;
+	struct sshkey *key = NULL;
 	u_long lnum = 0;
 	char *path, *cp, *ep, line[SSH_MAX_PUBKEY_BYTES];
 	unsigned long long serial, serial2;
@@ -2086,10 +2144,11 @@
 				 * Parsing will fail if it isn't.
 				 */
 			}
-			if ((key = key_new(KEY_UNSPEC)) == NULL)
+			if ((key = sshkey_new(KEY_UNSPEC)) == NULL)
 				fatal("key_new");
-			if (key_read(key, &cp) != 1)
-				fatal("%s:%lu: invalid key", path, lnum);
+			if ((r = sshkey_read(key, &cp)) != 0)
+				fatal("%s:%lu: invalid key: %s",
+				    path, lnum, ssh_err(r));
 			if (was_explicit_key)
 				r = ssh_krl_revoke_key_explicit(krl, key);
 			else if (was_sha1)
@@ -2097,8 +2156,9 @@
 			else
 				r = ssh_krl_revoke_key(krl, key);
 			if (r != 0)
-				fatal("%s: revoke key failed", __func__);
-			key_free(key);
+				fatal("%s: revoke key failed: %s",
+				    __func__, ssh_err(r));
+			sshkey_free(key);
 		}
 	}
 	if (strcmp(path, "-") != 0)
@@ -2111,10 +2171,10 @@
 {
 	struct ssh_krl *krl;
 	struct stat sb;
-	Key *ca = NULL;
-	int fd, i;
+	struct sshkey *ca = NULL;
+	int fd, i, r;
 	char *tmp;
-	Buffer kbuf;
+	struct sshbuf *kbuf;
 
 	if (*identity_file == '\0')
 		fatal("KRL generation requires an output file");
@@ -2127,8 +2187,9 @@
 	}
 	if (ca_key_path != NULL) {
 		tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
-		if ((ca = key_load_public(tmp, NULL)) == NULL)
-			fatal("Cannot load CA public key %s", tmp);
+		if ((r = sshkey_load_public(tmp, &ca, NULL)) != 0)
+			fatal("Cannot load CA public key %s: %s",
+			    tmp, ssh_err(r));
 		free(tmp);
 	}
 
@@ -2145,19 +2206,20 @@
 	for (i = 0; i < argc; i++)
 		update_krl_from_file(pw, argv[i], ca, krl);
 
-	buffer_init(&kbuf);
-	if (ssh_krl_to_blob(krl, &kbuf, NULL, 0) != 0)
+	if ((kbuf = sshbuf_new()) == NULL)
+		fatal("sshbuf_new failed");
+	if (ssh_krl_to_blob(krl, kbuf, NULL, 0) != 0)
 		fatal("Couldn't generate KRL");
 	if ((fd = open(identity_file, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
 		fatal("open %s: %s", identity_file, strerror(errno));
-	if (atomicio(vwrite, fd, buffer_ptr(&kbuf), buffer_len(&kbuf)) !=
-	    buffer_len(&kbuf))
+	if (atomicio(vwrite, fd, (void *)sshbuf_ptr(kbuf), sshbuf_len(kbuf)) !=
+	    sshbuf_len(kbuf))
 		fatal("write %s: %s", identity_file, strerror(errno));
 	close(fd);
-	buffer_free(&kbuf);
+	sshbuf_free(kbuf);
 	ssh_krl_free(krl);
 	if (ca != NULL)
-		key_free(ca);
+		sshkey_free(ca);
 }
 
 static void
@@ -2166,21 +2228,22 @@
 	int i, r, ret = 0;
 	char *comment;
 	struct ssh_krl *krl;
-	Key *k;
+	struct sshkey *k;
 
 	if (*identity_file == '\0')
 		fatal("KRL checking requires an input file");
 	load_krl(identity_file, &krl);
 	for (i = 0; i < argc; i++) {
-		if ((k = key_load_public(argv[i], &comment)) == NULL)
-			fatal("Cannot load public key %s", argv[i]);
+		if ((r = sshkey_load_public(argv[i], &k, &comment)) != 0)
+			fatal("Cannot load public key %s: %s",
+			    argv[i], ssh_err(r));
 		r = ssh_krl_check_key(krl, k);
 		printf("%s%s%s%s: %s\n", argv[i],
 		    *comment ? " (" : "", comment, *comment ? ")" : "",
 		    r == 0 ? "ok" : "REVOKED");
 		if (r != 0)
 			ret = 1;
-		key_free(k);
+		sshkey_free(k);
 		free(comment);
 	}
 	ssh_krl_free(krl);
@@ -2230,11 +2293,11 @@
 {
 	char dotsshdir[MAXPATHLEN], comment[1024], *passphrase1, *passphrase2;
 	char *checkpoint = NULL;
-	char out_file[MAXPATHLEN], *ep, *rr_hostname = NULL;
-	Key *private, *public;
+	char out_file[MAXPATHLEN], *rr_hostname = NULL, *ep;
+	struct sshkey *private, *public;
 	struct passwd *pw;
 	struct stat st;
-	int opt, type, fd;
+	int r, opt, type, fd;
 	u_int32_t memory = 0, generator_wanted = 0;
 	int do_gen_candidates = 0, do_screen_candidates = 0;
 	int gen_all_hostkeys = 0, gen_krl = 0, update_krl = 0, check_krl = 0;
@@ -2607,17 +2670,20 @@
 	if (key_type_name == NULL)
 		key_type_name = "rsa";
 
-	type = key_type_from_name(key_type_name);
+	type = sshkey_type_from_name(key_type_name);
 	type_bits_valid(type, &bits);
 
 	if (!quiet)
-		printf("Generating public/private %s key pair.\n", key_type_name);
-	private = key_generate(type, bits);
-	if (private == NULL) {
+		printf("Generating public/private %s key pair.\n",
+		    key_type_name);
+	if ((r = sshkey_generate(type, bits, &private)) != 0) {
 		fprintf(stderr, "key_generate failed\n");
 		exit(1);
 	}
-	public  = key_from_private(private);
+	if ((r = sshkey_from_private(private, &public)) != 0) {
+		fprintf(stderr, "key_from_private failed: %s\n", ssh_err(r));
+		exit(1);
+	}
 
 	if (!have_identity)
 		ask_filename(pw, "Enter file in which to save the key");
@@ -2685,9 +2751,10 @@
 	}
 
 	/* Save the key with the given passphrase and comment. */
-	if (!key_save_private(private, identity_file, passphrase1, comment,
-	    use_new_format, new_format_cipher, rounds)) {
-		printf("Saving the key failed: %s.\n", identity_file);
+	if ((r = sshkey_save_private(private, identity_file, passphrase1,
+	    comment, use_new_format, new_format_cipher, rounds)) != 0) {
+		printf("Saving key \"%s\" failed: %s\n",
+		    identity_file, ssh_err(r));
 		explicit_bzero(passphrase1, strlen(passphrase1));
 		free(passphrase1);
 		exit(1);
@@ -2697,7 +2764,7 @@
 	free(passphrase1);
 
 	/* Clear the private key and the random number generator. */
-	key_free(private);
+	sshkey_free(private);
 
 	if (!quiet)
 		printf("Your identification has been saved in %s.\n", identity_file);
@@ -2713,15 +2780,15 @@
 		printf("fdopen %s failed\n", identity_file);
 		exit(1);
 	}
-	if (!key_write(public, f))
-		fprintf(stderr, "write key failed\n");
+	if ((r = sshkey_write(public, f)) != 0)
+		fprintf(stderr, "write key failed: %s\n", ssh_err(r));
 	fprintf(f, " %s\n", comment);
 	fclose(f);
 
 	if (!quiet) {
-		char *fp = key_fingerprint(public, fingerprint_hash,
+		char *fp = sshkey_fingerprint(public, fingerprint_hash,
 		    SSH_FP_DEFAULT);
-		char *ra = key_fingerprint(public, fingerprint_hash,
+		char *ra = sshkey_fingerprint(public, fingerprint_hash,
 		    SSH_FP_RANDOMART);
 		printf("Your public key has been saved in %s.\n",
 		    identity_file);
@@ -2733,6 +2800,6 @@
 		free(fp);
 	}
 
-	key_free(public);
+	sshkey_free(public);
 	exit(0);
 }
diff --git a/ssh-keysign.c b/ssh-keysign.c
index 8219399..8af13fa 100644
--- a/ssh-keysign.c
+++ b/ssh-keysign.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keysign.c,v 1.45 2015/01/08 10:14:08 djm Exp $ */
+/* $OpenBSD: ssh-keysign.c,v 1.46 2015/01/15 09:40:00 djm Exp $ */
 /*
  * Copyright (c) 2002 Markus Friedl.  All rights reserved.
  *
@@ -43,11 +43,11 @@
 
 #include "xmalloc.h"
 #include "log.h"
-#include "key.h"
+#include "sshkey.h"
 #include "ssh.h"
 #include "ssh2.h"
 #include "misc.h"
-#include "buffer.h"
+#include "sshbuf.h"
 #include "authfile.h"
 #include "msg.h"
 #include "canohost.h"
@@ -63,64 +63,73 @@
 extern char *__progname;
 
 static int
-valid_request(struct passwd *pw, char *host, Key **ret, u_char *data,
-    u_int datalen)
+valid_request(struct passwd *pw, char *host, struct sshkey **ret,
+    u_char *data, size_t datalen)
 {
-	Buffer b;
-	Key *key = NULL;
-	u_char *pkblob;
-	u_int blen, len;
-	char *pkalg, *p;
-	int pktype, fail;
+	struct sshbuf *b;
+	struct sshkey *key = NULL;
+	u_char type, *pkblob;
+	char *p;
+	size_t blen, len;
+	char *pkalg, *luser;
+	int r, pktype, fail;
 
 	if (ret != NULL)
 		*ret = NULL;
 	fail = 0;
 
-	buffer_init(&b);
-	buffer_append(&b, data, datalen);
+	if ((b = sshbuf_from(data, datalen)) == NULL)
+		fatal("%s: sshbuf_from failed", __func__);
 
 	/* session id, currently limited to SHA1 (20 bytes) or SHA256 (32) */
-	p = buffer_get_string(&b, &len);
+	if ((r = sshbuf_get_string(b, NULL, &len)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 	if (len != 20 && len != 32)
 		fail++;
-	free(p);
 
-	if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
+	if ((r = sshbuf_get_u8(b, &type)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	if (type != SSH2_MSG_USERAUTH_REQUEST)
 		fail++;
 
 	/* server user */
-	buffer_skip_string(&b);
+	if ((r = sshbuf_skip_string(b)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
 	/* service */
-	p = buffer_get_string(&b, NULL);
+	if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 	if (strcmp("ssh-connection", p) != 0)
 		fail++;
 	free(p);
 
 	/* method */
-	p = buffer_get_string(&b, NULL);
+	if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 	if (strcmp("hostbased", p) != 0)
 		fail++;
 	free(p);
 
 	/* pubkey */
-	pkalg = buffer_get_string(&b, NULL);
-	pkblob = buffer_get_string(&b, &blen);
+	if ((r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 ||
+	    (r = sshbuf_get_string(b, &pkblob, &blen)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-	pktype = key_type_from_name(pkalg);
+	pktype = sshkey_type_from_name(pkalg);
 	if (pktype == KEY_UNSPEC)
 		fail++;
-	else if ((key = key_from_blob(pkblob, blen)) == NULL)
+	else if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) {
+		error("%s: bad key blob: %s", __func__, ssh_err(r));
 		fail++;
-	else if (key->type != pktype)
+	} else if (key->type != pktype)
 		fail++;
 	free(pkalg);
 	free(pkblob);
 
 	/* client host name, handle trailing dot */
-	p = buffer_get_string(&b, &len);
-	debug2("valid_request: check expect chost %s got %s", host, p);
+	if ((r = sshbuf_get_cstring(b, &p, &len)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	debug2("%s: check expect chost %s got %s", __func__, host, p);
 	if (strlen(host) != len - 1)
 		fail++;
 	else if (p[len - 1] != '.')
@@ -130,21 +139,22 @@
 	free(p);
 
 	/* local user */
-	p = buffer_get_string(&b, NULL);
+	if ((r = sshbuf_get_cstring(b, &luser, NULL)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 
-	if (strcmp(pw->pw_name, p) != 0)
+	if (strcmp(pw->pw_name, luser) != 0)
 		fail++;
-	free(p);
+	free(luser);
 
 	/* end of message */
-	if (buffer_len(&b) != 0)
+	if (sshbuf_len(b) != 0)
 		fail++;
-	buffer_free(&b);
+	sshbuf_free(b);
 
-	debug3("valid_request: fail %d", fail);
+	debug3("%s: fail %d", __func__, fail);
 
 	if (fail && key != NULL)
-		key_free(key);
+		sshkey_free(key);
 	else
 		*ret = key;
 
@@ -154,15 +164,15 @@
 int
 main(int argc, char **argv)
 {
-	Buffer b;
+	struct sshbuf *b;
 	Options options;
 #define NUM_KEYTYPES 4
-	Key *keys[NUM_KEYTYPES], *key = NULL;
+	struct sshkey *keys[NUM_KEYTYPES], *key = NULL;
 	struct passwd *pw;
 	int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
-	u_char *signature, *data;
+	u_char *signature, *data, rver;
 	char *host, *fp;
-	u_int slen, dlen;
+	size_t slen, dlen;
 #ifdef WITH_OPENSSL
 	u_int32_t rnd[256];
 #endif
@@ -232,18 +242,23 @@
 	if (!found)
 		fatal("no hostkey found");
 
-	buffer_init(&b);
-	if (ssh_msg_recv(STDIN_FILENO, &b) < 0)
+	if ((b = sshbuf_new()) == NULL)
+		fatal("%s: sshbuf_new failed", __func__);
+	if (ssh_msg_recv(STDIN_FILENO, b) < 0)
 		fatal("ssh_msg_recv failed");
-	if (buffer_get_char(&b) != version)
-		fatal("bad version");
-	fd = buffer_get_int(&b);
-	if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO))
+	if ((r = sshbuf_get_u8(b, &rver)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	if (rver != version)
+		fatal("bad version: received %d, expected %d", rver, version);
+	if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO)
 		fatal("bad fd");
 	if ((host = get_local_name(fd)) == NULL)
 		fatal("cannot get local name for fd");
 
-	data = buffer_get_string(&b, &dlen);
+	if ((r = sshbuf_get_string(b, &data, &dlen)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
 	if (valid_request(pw, host, &key, data, dlen) < 0)
 		fatal("not a valid request");
 	free(host);
@@ -251,26 +266,27 @@
 	found = 0;
 	for (i = 0; i < NUM_KEYTYPES; i++) {
 		if (keys[i] != NULL &&
-		    key_equal_public(key, keys[i])) {
+		    sshkey_equal_public(key, keys[i])) {
 			found = 1;
 			break;
 		}
 	}
 	if (!found) {
-		fp = key_fingerprint(key, options.fingerprint_hash,
+		fp = sshkey_fingerprint(key, options.fingerprint_hash,
 		    SSH_FP_DEFAULT);
 		fatal("no matching hostkey found for key %s %s",
-		    key_type(key), fp);
+		    sshkey_type(key), fp ? fp : "");
 	}
 
-	if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
-		fatal("key_sign failed");
+	if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, 0)) != 0)
+		fatal("sshkey_sign failed: %s", ssh_err(r));
 	free(data);
 
 	/* send reply */
-	buffer_clear(&b);
-	buffer_put_string(&b, signature, slen);
-	if (ssh_msg_send(STDOUT_FILENO, version, &b) == -1)
+	sshbuf_reset(b);
+	if ((r = sshbuf_put_string(b, signature, slen)) != 0)
+		fatal("%s: buffer error: %s", __func__, ssh_err(r));
+	if (ssh_msg_send(STDOUT_FILENO, version, b) == -1)
 		fatal("ssh_msg_send failed");
 
 	return (0);
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index c96be3b..e91df8b 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-pkcs11.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
+/* $OpenBSD: ssh-pkcs11.c,v 1.15 2015/01/15 09:40:00 djm Exp $ */
 /*
  * Copyright (c) 2010 Markus Friedl.  All rights reserved.
  *
@@ -38,7 +38,7 @@
 
 #include "log.h"
 #include "misc.h"
-#include "key.h"
+#include "sshkey.h"
 #include "ssh-pkcs11.h"
 #include "xmalloc.h"
 
@@ -385,12 +385,12 @@
  * keysp points to an (possibly empty) array with *nkeys keys.
  */
 static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG,
-    CK_ATTRIBUTE [], CK_ATTRIBUTE [3], Key ***, int *)
+    CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *)
 	__attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE))));
 
 static int
 pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx,
-    Key ***keysp, int *nkeys)
+    struct sshkey ***keysp, int *nkeys)
 {
 	CK_OBJECT_CLASS	pubkey_class = CKO_PUBLIC_KEY;
 	CK_OBJECT_CLASS	cert_class = CKO_CERTIFICATE;
@@ -422,12 +422,12 @@
 }
 
 static int
-pkcs11_key_included(Key ***keysp, int *nkeys, Key *key)
+pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key)
 {
 	int i;
 
 	for (i = 0; i < *nkeys; i++)
-		if (key_equal(key, (*keysp)[i]))
+		if (sshkey_equal(key, (*keysp)[i]))
 			return (1);
 	return (0);
 }
@@ -435,9 +435,9 @@
 static int
 pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
     CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3],
-    Key ***keysp, int *nkeys)
+    struct sshkey ***keysp, int *nkeys)
 {
-	Key			*key;
+	struct sshkey		*key;
 	RSA			*rsa;
 	X509 			*x509;
 	EVP_PKEY		*evp;
@@ -517,16 +517,16 @@
 		}
 		if (rsa && rsa->n && rsa->e &&
 		    pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) {
-			key = key_new(KEY_UNSPEC);
+			key = sshkey_new(KEY_UNSPEC);
 			key->rsa = rsa;
 			key->type = KEY_RSA;
 			key->flags |= SSHKEY_FLAG_EXT;
 			if (pkcs11_key_included(keysp, nkeys, key)) {
-				key_free(key);
+				sshkey_free(key);
 			} else {
 				/* expand key array and add key */
 				*keysp = xrealloc(*keysp, *nkeys + 1,
-				    sizeof(Key *));
+				    sizeof(struct sshkey *));
 				(*keysp)[*nkeys] = key;
 				*nkeys = *nkeys + 1;
 				debug("have %d keys", *nkeys);
@@ -544,7 +544,7 @@
 
 /* register a new provider, fails if provider already exists */
 int
-pkcs11_add_provider(char *provider_id, char *pin, Key ***keyp)
+pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp)
 {
 	int nkeys, need_finalize = 0;
 	struct pkcs11_provider *p = NULL;
diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h
index 4d2efda..0ced74f 100644
--- a/ssh-pkcs11.h
+++ b/ssh-pkcs11.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-pkcs11.h,v 1.3 2014/04/29 18:01:49 markus Exp $ */
+/* $OpenBSD: ssh-pkcs11.h,v 1.4 2015/01/15 09:40:00 djm Exp $ */
 /*
  * Copyright (c) 2010 Markus Friedl.  All rights reserved.
  *
@@ -16,7 +16,7 @@
  */
 int	pkcs11_init(int);
 void	pkcs11_terminate(void);
-int	pkcs11_add_provider(char *, char *, Key ***);
+int	pkcs11_add_provider(char *, char *, struct sshkey ***);
 int	pkcs11_del_provider(char *);
 
 #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11)