From 3f5e687717abe8c6d6abe5fd1aba8c0b7d6f0d9a Mon Sep 17 00:00:00 2001 From: djm Date: Thu, 21 May 2015 04:55:51 +0000 Subject: [PATCH] refactor: split base64 encoding of pubkey into its own sshkey_to_base64() function and out of sshkey_write(); ok markus@ --- usr.bin/ssh/sshkey.c | 174 ++++++++++++++++++++++++------------------- usr.bin/ssh/sshkey.h | 3 +- 2 files changed, 101 insertions(+), 76 deletions(-) diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c index e9a23e715aa..50782cb1e5f 100644 --- a/usr.bin/ssh/sshkey.c +++ b/usr.bin/ssh/sshkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.18 2015/05/08 03:17:49 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.19 2015/05/21 04:55:51 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -737,6 +737,12 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain) if (key == NULL) return SSH_ERR_INVALID_ARGUMENT; + if (sshkey_is_cert(key)) { + if (key->cert == NULL) + return SSH_ERR_EXPECTED_CERT; + if (sshbuf_len(key->cert->certblob) == 0) + return SSH_ERR_KEY_LACKS_CERTBLOB; + } type = force_plain ? sshkey_type_plain(key->type) : key->type; typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid); @@ -1381,98 +1387,116 @@ sshkey_read(struct sshkey *ret, char **cpp) } int -sshkey_write(const struct sshkey *key, FILE *f) +sshkey_to_base64(const struct sshkey *key, char **b64p) { - int ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL, *bb = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; char *uu = NULL; + + if (b64p != NULL) + *b64p = NULL; + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_putb(key, b)) != 0) + goto out; + if ((uu = sshbuf_dtob64(b)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* Success */ + if (b64p != NULL) { + *b64p = uu; + uu = NULL; + } + r = 0; + out: + sshbuf_free(b); + free(uu); + return r; +} + +static int +sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b) +{ + int r = SSH_ERR_INTERNAL_ERROR; #ifdef WITH_SSH1 u_int bits = 0; char *dec_e = NULL, *dec_n = NULL; -#endif /* WITH_SSH1 */ - if (sshkey_is_cert(key)) { - if (key->cert == NULL) - return SSH_ERR_EXPECTED_CERT; - if (sshbuf_len(key->cert->certblob) == 0) - return SSH_ERR_KEY_LACKS_CERTBLOB; + if (key->rsa == NULL || key->rsa->e == NULL || + key->rsa->n == NULL) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; } - if ((b = sshbuf_new()) == NULL) - return SSH_ERR_ALLOC_FAIL; - switch (key->type) { -#ifdef WITH_SSH1 - case KEY_RSA1: - if (key->rsa == NULL || key->rsa->e == NULL || - key->rsa->n == NULL) { - ret = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || - (dec_n = BN_bn2dec(key->rsa->n)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - /* size of modulus 'n' */ - if ((bits = BN_num_bits(key->rsa->n)) <= 0) { - ret = SSH_ERR_INVALID_ARGUMENT; - goto out; - } - if ((ret = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0) - goto out; + if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL || + (dec_n = BN_bn2dec(key->rsa->n)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* size of modulus 'n' */ + if ((bits = BN_num_bits(key->rsa->n)) <= 0) { + r = SSH_ERR_INVALID_ARGUMENT; + goto out; + } + if ((r = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0) + goto out; + + /* Success */ + r = 0; + out: + if (dec_e != NULL) + OPENSSL_free(dec_e); + if (dec_n != NULL) + OPENSSL_free(dec_n); #endif /* WITH_SSH1 */ - break; -#ifdef WITH_OPENSSL - case KEY_DSA: - case KEY_DSA_CERT_V00: - case KEY_DSA_CERT: - case KEY_ECDSA: - case KEY_ECDSA_CERT: - case KEY_RSA: - case KEY_RSA_CERT_V00: - case KEY_RSA_CERT: -#endif /* WITH_OPENSSL */ - case KEY_ED25519: - case KEY_ED25519_CERT: - if ((bb = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } - if ((ret = sshkey_putb(key, bb)) != 0) - goto out; - if ((uu = sshbuf_dtob64(bb)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; + + return r; +} + +static int +sshkey_format_text(const struct sshkey *key, struct sshbuf *b) +{ + int r = SSH_ERR_INTERNAL_ERROR; + char *uu = NULL; + + if (key->type == KEY_RSA1) { + if ((r = sshkey_format_rsa1(key, b)) != 0) goto out; - } - if ((ret = sshbuf_putf(b, "%s ", sshkey_ssh_name(key))) != 0) + } else { + /* Unsupported key types handled in sshkey_to_base64() */ + if ((r = sshkey_to_base64(key, &uu)) != 0) goto out; - if ((ret = sshbuf_put(b, uu, strlen(uu))) != 0) + if ((r = sshbuf_putf(b, "%s %s", + sshkey_ssh_name(key), uu)) != 0) goto out; - break; - default: - ret = SSH_ERR_KEY_TYPE_UNKNOWN; - goto out; } + r = 0; + out: + free(uu); + return r; +} + +int +sshkey_write(const struct sshkey *key, FILE *f) +{ + struct sshbuf *b = NULL; + int r = SSH_ERR_INTERNAL_ERROR; + + if ((b = sshbuf_new()) == NULL) + return SSH_ERR_ALLOC_FAIL; + if ((r = sshkey_format_text(key, b)) != 0) + goto out; if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) { if (feof(f)) errno = EPIPE; - ret = SSH_ERR_SYSTEM_ERROR; + r = SSH_ERR_SYSTEM_ERROR; goto out; } - ret = 0; + /* Success */ + r = 0; out: - if (b != NULL) - sshbuf_free(b); - if (bb != NULL) - sshbuf_free(bb); - if (uu != NULL) - free(uu); -#ifdef WITH_SSH1 - if (dec_e != NULL) - OPENSSL_free(dec_e); - if (dec_n != NULL) - OPENSSL_free(dec_n); -#endif /* WITH_SSH1 */ - return ret; + sshbuf_free(b); + return r; } const char * diff --git a/usr.bin/ssh/sshkey.h b/usr.bin/ssh/sshkey.h index e05b4077d3c..e656b4a619f 100644 --- a/usr.bin/ssh/sshkey.h +++ b/usr.bin/ssh/sshkey.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.h,v 1.5 2015/01/26 02:59:11 djm Exp $ */ +/* $OpenBSD: sshkey.h,v 1.6 2015/05/21 04:55:51 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. @@ -157,6 +157,7 @@ int sshkey_from_blob(const u_char *, size_t, struct sshkey **); int sshkey_fromb(struct sshbuf *, struct sshkey **); int sshkey_froms(struct sshbuf *, struct sshkey **); int sshkey_to_blob(const struct sshkey *, u_char **, size_t *); +int sshkey_to_base64(const struct sshkey *, char **); int sshkey_putb(const struct sshkey *, struct sshbuf *); int sshkey_puts(const struct sshkey *, struct sshbuf *); int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *); -- 2.20.1