summaryrefslogtreecommitdiffstats
path: root/usr.bin/ssh/sshkey.c
diff options
context:
space:
mode:
authordjm <djm@openbsd.org>2020-04-08 00:04:32 +0000
committerdjm <djm@openbsd.org>2020-04-08 00:04:32 +0000
commitc3be6246a4bdc210e0c63b83f53e944cb6c1ca88 (patch)
tree6a0488639f7a67b20404de11965adad69a9bdb4e /usr.bin/ssh/sshkey.c
parentrefactor private key parsing a little (diff)
downloadwireguard-openbsd-c3be6246a4bdc210e0c63b83f53e944cb6c1ca88.tar.xz
wireguard-openbsd-c3be6246a4bdc210e0c63b83f53e944cb6c1ca88.zip
check that pubkey in private key envelope matches actual private key
(this public key is currently unusued) ok markus@
Diffstat (limited to 'usr.bin/ssh/sshkey.c')
-rw-r--r--usr.bin/ssh/sshkey.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c
index 3580470751e..1bc794e49e0 100644
--- a/usr.bin/ssh/sshkey.c
+++ b/usr.bin/ssh/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.103 2020/04/08 00:01:52 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.104 2020/04/08 00:04:32 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -4080,8 +4080,8 @@ private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp)
}
static int
-private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp,
- const char *passphrase)
+private2_decrypt(struct sshbuf *decoded, const char *passphrase,
+ struct sshbuf **decryptedp, struct sshkey **pubkeyp)
{
char *ciphername = NULL, *kdfname = NULL;
const struct sshcipher *cipher = NULL;
@@ -4089,13 +4089,15 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp,
size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0;
struct sshbuf *kdf = NULL, *decrypted = NULL;
struct sshcipher_ctx *ciphercontext = NULL;
+ struct sshkey *pubkey = NULL;
u_char *key = NULL, *salt = NULL, *dp;
u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
- if (decoded == NULL || decryptedp == NULL)
+ if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL)
return SSH_ERR_INVALID_ARGUMENT;
*decryptedp = NULL;
+ *pubkeyp = NULL;
if ((decrypted = sshbuf_new()) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -4116,7 +4118,7 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp,
goto out;
}
- if ((r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
+ if ((r = sshkey_froms(decoded, &pubkey)) != 0 ||
(r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
goto out;
@@ -4203,11 +4205,14 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp,
/* success */
*decryptedp = decrypted;
decrypted = NULL;
+ *pubkeyp = pubkey;
+ pubkey = NULL;
r = 0;
out:
cipher_free(ciphercontext);
free(ciphername);
free(kdfname);
+ sshkey_free(pubkey);
if (salt != NULL) {
explicit_bzero(salt, slen);
free(salt);
@@ -4253,7 +4258,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
char *comment = NULL;
int r = SSH_ERR_INTERNAL_ERROR;
struct sshbuf *decoded = NULL, *decrypted = NULL;
- struct sshkey *k = NULL;
+ struct sshkey *k = NULL, *pubkey = NULL;
if (keyp != NULL)
*keyp = NULL;
@@ -4262,7 +4267,8 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
/* Undo base64 encoding and decrypt the private section */
if ((r = private2_uudecode(blob, &decoded)) != 0 ||
- (r = private2_decrypt(decoded, &decrypted, passphrase)) != 0)
+ (r = private2_decrypt(decoded, passphrase,
+ &decrypted, &pubkey)) != 0)
goto out;
/* Load the private key and comment */
@@ -4274,7 +4280,11 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
if ((r = private2_check_padding(decrypted)) != 0)
goto out;
- /* XXX decode pubkey and check against private */
+ /* Check that the public key in the envelope matches the private key */
+ if (!sshkey_equal(pubkey, k)) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
/* success */
r = 0;
@@ -4291,6 +4301,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
sshbuf_free(decoded);
sshbuf_free(decrypted);
sshkey_free(k);
+ sshkey_free(pubkey);
return r;
}