summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2020-04-08 00:04:32 +0000
committerDamien Miller <djm@mindrot.org>2020-04-08 10:14:21 +1000
commit6aabfb6d22b36d07f584cba97f4cdc4363a829da (patch)
tree90c09b71a5727b21abb61a61868ed852e527c93a
parentc0f5b2294796451001fd328c44f0d00f1114eddf (diff)
upstream: check that pubkey in private key envelope matches actual
private key (this public key is currently unusued) ok markus@ OpenBSD-Commit-ID: 634a60b5e135d75f48249ccdf042f3555112049c
-rw-r--r--sshkey.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/sshkey.c b/sshkey.c
index 0fc0f97ca..7ff61c85b 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.103 2020/04/08 00:01:52 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.104 2020/04/08 00:04:32 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved. 4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -4135,8 +4135,8 @@ private2_uudecode(struct sshbuf *blob, struct sshbuf **decodedp)
4135} 4135}
4136 4136
4137static int 4137static int
4138private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp, 4138private2_decrypt(struct sshbuf *decoded, const char *passphrase,
4139 const char *passphrase) 4139 struct sshbuf **decryptedp, struct sshkey **pubkeyp)
4140{ 4140{
4141 char *ciphername = NULL, *kdfname = NULL; 4141 char *ciphername = NULL, *kdfname = NULL;
4142 const struct sshcipher *cipher = NULL; 4142 const struct sshcipher *cipher = NULL;
@@ -4144,13 +4144,15 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp,
4144 size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0; 4144 size_t keylen = 0, ivlen = 0, authlen = 0, slen = 0;
4145 struct sshbuf *kdf = NULL, *decrypted = NULL; 4145 struct sshbuf *kdf = NULL, *decrypted = NULL;
4146 struct sshcipher_ctx *ciphercontext = NULL; 4146 struct sshcipher_ctx *ciphercontext = NULL;
4147 struct sshkey *pubkey = NULL;
4147 u_char *key = NULL, *salt = NULL, *dp; 4148 u_char *key = NULL, *salt = NULL, *dp;
4148 u_int blocksize, rounds, nkeys, encrypted_len, check1, check2; 4149 u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
4149 4150
4150 if (decoded == NULL || decryptedp == NULL) 4151 if (decoded == NULL || decryptedp == NULL || pubkeyp == NULL)
4151 return SSH_ERR_INVALID_ARGUMENT; 4152 return SSH_ERR_INVALID_ARGUMENT;
4152 4153
4153 *decryptedp = NULL; 4154 *decryptedp = NULL;
4155 *pubkeyp = NULL;
4154 4156
4155 if ((decrypted = sshbuf_new()) == NULL) { 4157 if ((decrypted = sshbuf_new()) == NULL) {
4156 r = SSH_ERR_ALLOC_FAIL; 4158 r = SSH_ERR_ALLOC_FAIL;
@@ -4171,7 +4173,7 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp,
4171 goto out; 4173 goto out;
4172 } 4174 }
4173 4175
4174 if ((r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */ 4176 if ((r = sshkey_froms(decoded, &pubkey)) != 0 ||
4175 (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0) 4177 (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
4176 goto out; 4178 goto out;
4177 4179
@@ -4258,11 +4260,14 @@ private2_decrypt(struct sshbuf *decoded, struct sshbuf **decryptedp,
4258 /* success */ 4260 /* success */
4259 *decryptedp = decrypted; 4261 *decryptedp = decrypted;
4260 decrypted = NULL; 4262 decrypted = NULL;
4263 *pubkeyp = pubkey;
4264 pubkey = NULL;
4261 r = 0; 4265 r = 0;
4262 out: 4266 out:
4263 cipher_free(ciphercontext); 4267 cipher_free(ciphercontext);
4264 free(ciphername); 4268 free(ciphername);
4265 free(kdfname); 4269 free(kdfname);
4270 sshkey_free(pubkey);
4266 if (salt != NULL) { 4271 if (salt != NULL) {
4267 explicit_bzero(salt, slen); 4272 explicit_bzero(salt, slen);
4268 free(salt); 4273 free(salt);
@@ -4308,7 +4313,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4308 char *comment = NULL; 4313 char *comment = NULL;
4309 int r = SSH_ERR_INTERNAL_ERROR; 4314 int r = SSH_ERR_INTERNAL_ERROR;
4310 struct sshbuf *decoded = NULL, *decrypted = NULL; 4315 struct sshbuf *decoded = NULL, *decrypted = NULL;
4311 struct sshkey *k = NULL; 4316 struct sshkey *k = NULL, *pubkey = NULL;
4312 4317
4313 if (keyp != NULL) 4318 if (keyp != NULL)
4314 *keyp = NULL; 4319 *keyp = NULL;
@@ -4317,7 +4322,8 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4317 4322
4318 /* Undo base64 encoding and decrypt the private section */ 4323 /* Undo base64 encoding and decrypt the private section */
4319 if ((r = private2_uudecode(blob, &decoded)) != 0 || 4324 if ((r = private2_uudecode(blob, &decoded)) != 0 ||
4320 (r = private2_decrypt(decoded, &decrypted, passphrase)) != 0) 4325 (r = private2_decrypt(decoded, passphrase,
4326 &decrypted, &pubkey)) != 0)
4321 goto out; 4327 goto out;
4322 4328
4323 /* Load the private key and comment */ 4329 /* Load the private key and comment */
@@ -4329,7 +4335,11 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4329 if ((r = private2_check_padding(decrypted)) != 0) 4335 if ((r = private2_check_padding(decrypted)) != 0)
4330 goto out; 4336 goto out;
4331 4337
4332 /* XXX decode pubkey and check against private */ 4338 /* Check that the public key in the envelope matches the private key */
4339 if (!sshkey_equal(pubkey, k)) {
4340 r = SSH_ERR_INVALID_FORMAT;
4341 goto out;
4342 }
4333 4343
4334 /* success */ 4344 /* success */
4335 r = 0; 4345 r = 0;
@@ -4346,6 +4356,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
4346 sshbuf_free(decoded); 4356 sshbuf_free(decoded);
4347 sshbuf_free(decrypted); 4357 sshbuf_free(decrypted);
4348 sshkey_free(k); 4358 sshkey_free(k);
4359 sshkey_free(pubkey);
4349 return r; 4360 return r;
4350} 4361}
4351 4362