-/* $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.
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);
}
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 *