diff options
author | djm@openbsd.org <djm@openbsd.org> | 2015-05-08 03:17:49 +0000 |
---|---|---|
committer | Damien Miller <djm@mindrot.org> | 2015-05-08 13:32:58 +1000 |
commit | 63ebf019be863b2d90492a85e248cf55a6e87403 (patch) | |
tree | 1decfe09c21db0ced09dd8724244cb0cdfeb1d92 | |
parent | f8484dac678ab3098ae522a5f03bb2530f822987 (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.c | 15 |
1 files changed, 11 insertions, 4 deletions
@@ -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) { |