summaryrefslogtreecommitdiff
path: root/usr.bin/ssh/sshkey.c
diff options
context:
space:
mode:
authorDamien Miller <djm@cvs.openbsd.org>2015-05-08 03:17:50 +0000
committerDamien Miller <djm@cvs.openbsd.org>2015-05-08 03:17:50 +0000
commita2d98681eaf05ce5bd51d653c63066268e769944 (patch)
treea653fd0293048e34c8a1a3b8ddbffc8ec002bd33 /usr.bin/ssh/sshkey.c
parentad11144277fedbf5bfcb876ca96adcf560f6e5b1 (diff)
don't choke on new-format private keys encrypted with an AEAD cipher;
bz#2366, patch from Ron Frederick; ok markus@
Diffstat (limited to 'usr.bin/ssh/sshkey.c')
-rw-r--r--usr.bin/ssh/sshkey.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/usr.bin/ssh/sshkey.c b/usr.bin/ssh/sshkey.c
index 7eb41f8c2bb..e9a23e715aa 100644
--- a/usr.bin/ssh/sshkey.c
+++ b/usr.bin/ssh/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.17 2015/05/04 06:10:48 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.18 2015/05/08 03:17:49 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -3151,7 +3151,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
const u_char *cp;
int r = SSH_ERR_INTERNAL_ERROR;
size_t encoded_len;
- size_t i, keylen = 0, ivlen = 0, slen = 0;
+ size_t i, keylen = 0, ivlen = 0, authlen = 0, slen = 0;
struct sshbuf *encoded = NULL, *decoded = NULL;
struct sshbuf *kdf = NULL, *decrypted = NULL;
struct sshcipher_ctx ciphercontext;
@@ -3261,6 +3261,7 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
/* setup key */
keylen = cipher_keylen(cipher);
ivlen = cipher_ivlen(cipher);
+ authlen = cipher_authlen(cipher);
if ((key = calloc(1, keylen + ivlen)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
goto out;
@@ -3276,19 +3277,25 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
}
}
+ /* check that an appropriate amount of auth data is present */
+ if (sshbuf_len(decoded) < encrypted_len + authlen) {
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+
/* decrypt private portion of key */
if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
(r = cipher_init(&ciphercontext, cipher, key, keylen,
key + keylen, ivlen, 0)) != 0)
goto out;
if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded),
- sshbuf_len(decoded), 0, cipher_authlen(cipher))) != 0) {
+ encrypted_len, 0, authlen)) != 0) {
/* an integrity error here indicates an incorrect passphrase */
if (r == SSH_ERR_MAC_INVALID)
r = SSH_ERR_KEY_WRONG_PASSPHRASE;
goto out;
}
- if ((r = sshbuf_consume(decoded, encrypted_len)) != 0)
+ if ((r = sshbuf_consume(decoded, encrypted_len + authlen)) != 0)
goto out;
/* there should be no trailing data */
if (sshbuf_len(decoded) != 0) {