summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2015-05-08 03:17:49 +0000
committerDamien Miller <djm@mindrot.org>2015-05-08 13:32:58 +1000
commit63ebf019be863b2d90492a85e248cf55a6e87403 (patch)
tree1decfe09c21db0ced09dd8724244cb0cdfeb1d92
parentf8484dac678ab3098ae522a5f03bb2530f822987 (diff)
upstream commit
don't choke on new-format private keys encrypted with an AEAD cipher; bz#2366, patch from Ron Frederick; ok markus@
-rw-r--r--sshkey.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/sshkey.c b/sshkey.c
index 3cc3f444a..a36004671 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.16 2015/04/03 22:17:27 djm Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.18 2015/05/08 03:17:49 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.
@@ -3201,7 +3201,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3201 const u_char *cp; 3201 const u_char *cp;
3202 int r = SSH_ERR_INTERNAL_ERROR; 3202 int r = SSH_ERR_INTERNAL_ERROR;
3203 size_t encoded_len; 3203 size_t encoded_len;
3204 size_t i, keylen = 0, ivlen = 0, slen = 0; 3204 size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
3205 struct sshbuf *encoded = NULL, *decoded = NULL; 3205 struct sshbuf *encoded = NULL, *decoded = NULL;
3206 struct sshbuf *kdf = NULL, *decrypted = NULL; 3206 struct sshbuf *kdf = NULL, *decrypted = NULL;
3207 struct sshcipher_ctx ciphercontext; 3207 struct sshcipher_ctx ciphercontext;
@@ -3311,6 +3311,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3311 /* setup key */ 3311 /* setup key */
3312 keylen = cipher_keylen(cipher); 3312 keylen = cipher_keylen(cipher);
3313 ivlen = cipher_ivlen(cipher); 3313 ivlen = cipher_ivlen(cipher);
3314 authlen = cipher_authlen(cipher);
3314 if ((key = calloc(1, keylen + ivlen)) == NULL) { 3315 if ((key = calloc(1, keylen + ivlen)) == NULL) {
3315 r = SSH_ERR_ALLOC_FAIL; 3316 r = SSH_ERR_ALLOC_FAIL;
3316 goto out; 3317 goto out;
@@ -3326,19 +3327,25 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3326 } 3327 }
3327 } 3328 }
3328 3329
3330 /* check that an appropriate amount of auth data is present */
3331 if (sshbuf_len(decoded) < encrypted_len + authlen) {
3332 r = SSH_ERR_INVALID_FORMAT;
3333 goto out;
3334 }
3335
3329 /* decrypt private portion of key */ 3336 /* decrypt private portion of key */
3330 if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 || 3337 if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
3331 (r = cipher_init(&ciphercontext, cipher, key, keylen, 3338 (r = cipher_init(&ciphercontext, cipher, key, keylen,
3332 key + keylen, ivlen, 0)) != 0) 3339 key + keylen, ivlen, 0)) != 0)
3333 goto out; 3340 goto out;
3334 if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded), 3341 if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded),
3335 sshbuf_len(decoded), 0, cipher_authlen(cipher))) != 0) { 3342 encrypted_len, 0, authlen)) != 0) {
3336 /* an integrity error here indicates an incorrect passphrase */ 3343 /* an integrity error here indicates an incorrect passphrase */
3337 if (r == SSH_ERR_MAC_INVALID) 3344 if (r == SSH_ERR_MAC_INVALID)
3338 r = SSH_ERR_KEY_WRONG_PASSPHRASE; 3345 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3339 goto out; 3346 goto out;
3340 } 3347 }
3341 if ((r = sshbuf_consume(decoded, encrypted_len)) != 0) 3348 if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
3342 goto out; 3349 goto out;
3343 /* there should be no trailing data */ 3350 /* there should be no trailing data */
3344 if (sshbuf_len(decoded) != 0) { 3351 if (sshbuf_len(decoded) != 0) {