]> git.ipfire.org Git - thirdparty/openssh-portable.git/commitdiff
upstream: add sshkey_parse_pubkey_from_private_fileblob_type()
authordjm@openbsd.org <djm@openbsd.org>
Wed, 8 Apr 2020 00:08:46 +0000 (00:08 +0000)
committerDamien Miller <djm@mindrot.org>
Wed, 8 Apr 2020 00:14:21 +0000 (10:14 +1000)
Extracts a public key from the unencrypted envelope of a new-style
OpenSSH private key.

ok markus@

OpenBSD-Commit-ID: 44d7ab446e5e8c686aee96d5897b26b3939939aa

sshkey.c
sshkey.h

index e87572c175f6612da1b5f4f0dbe47c16b346205f..d6cc6365f0daf21200ae33a26e38f193298b593f 100644 (file)
--- a/sshkey.c
+++ b/sshkey.c
@@ -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
index 71a3fddcb517a9b5d5475b2c8a5b1bfdb50d8e9d..9c1d4f6372f6144458994436010a6d4f6da752eb 100644 (file)
--- a/sshkey.h
+++ b/sshkey.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.h,v 1.44 2019/12/30 09:23:28 djm Exp $ */
+/* $OpenBSD: sshkey.h,v 1.45 2020/04/08 00:08:46 djm Exp $ */
 
 /*
  * Copyright (c) 2000, 2001 Markus Friedl.  All rights reserved.
@@ -259,6 +259,8 @@ int sshkey_parse_private_fileblob(struct sshbuf *buffer,
     const char *passphrase, struct sshkey **keyp, char **commentp);
 int    sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
     const char *passphrase, struct sshkey **keyp, char **commentp);
+int    sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
+    int type, struct sshkey **pubkeyp);
 
 /* XXX should be internal, but used by ssh-keygen */
 int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);