diff options
author | djm@openbsd.org <djm@openbsd.org> | 2020-04-08 00:08:46 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2020-04-08 10:14:21 +1000 |
commit | f290ab0833e44355fc006e4e67b92446c14673ef (patch) | |
tree | a561fa46ca1ec8e24fa809e977584800bebf5c81 /sshkey.c | |
parent | 8d514eea4ae089626a55e11c7bc1745c8d9683e4 (diff) |
upstream: add sshkey_parse_pubkey_from_private_fileblob_type()
Extracts a public key from the unencrypted envelope of a new-style
OpenSSH private key.
ok markus@
OpenBSD-Commit-ID: 44d7ab446e5e8c686aee96d5897b26b3939939aa
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 66 |
1 files changed, 65 insertions, 1 deletions
@@ -1,4 +1,4 @@ -/* $OpenBSD: sshkey.c,v 1.106 2020/04/08 00:07:19 djm Exp $ */ +/* $OpenBSD: sshkey.c,v 1.107 2020/04/08 00:08:46 djm Exp $ */ /* * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2008 Alexander von Gernler. All rights reserved. @@ -4366,6 +4366,56 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase, return r; } +static int +sshkey_parse_private2_pubkey(struct sshbuf *blob, int type, + struct sshkey **keyp) +{ + int r = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *decoded = NULL; + struct sshkey *pubkey = NULL; + u_int nkeys = 0; + + if (keyp != NULL) + *keyp = NULL; + + if ((r = private2_uudecode(blob, &decoded)) != 0) + goto out; + /* parse public key from unencrypted envelope */ + if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 || + (r = sshbuf_skip_string(decoded)) != 0 || /* cipher */ + (r = sshbuf_skip_string(decoded)) != 0 || /* KDF alg */ + (r = sshbuf_skip_string(decoded)) != 0 || /* KDF hint */ + (r = sshbuf_get_u32(decoded, &nkeys)) != 0) + goto out; + + if (nkeys != 1) { + /* XXX only one key supported at present */ + r = SSH_ERR_INVALID_FORMAT; + goto out; + } + + /* Parse the public key */ + if ((r = sshkey_froms(decoded, &pubkey)) != 0) + goto out; + + if (type != KEY_UNSPEC && + sshkey_type_plain(type) != sshkey_type_plain(pubkey->type)) { + r = SSH_ERR_KEY_TYPE_MISMATCH; + goto out; + } + + /* success */ + r = 0; + if (keyp != NULL) { + *keyp = pubkey; + pubkey = NULL; + } + out: + sshbuf_free(decoded); + sshkey_free(pubkey); + return r; +} + #ifdef WITH_OPENSSL /* convert SSH v2 key to PEM or PKCS#8 format */ static int @@ -4730,6 +4780,20 @@ sshkey_sig_details_free(struct sshkey_sig_details *details) freezero(details, sizeof(*details)); } +int +sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, int type, + struct sshkey **pubkeyp) +{ + int r = SSH_ERR_INTERNAL_ERROR; + + if (pubkeyp != NULL) + *pubkeyp = NULL; + /* only new-format private keys bundle a public key inside */ + if ((r = sshkey_parse_private2_pubkey(blob, type, pubkeyp)) != 0) + return r; + return 0; +} + #ifdef WITH_XMSS /* * serialize the key with the current state and forward the state |