summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
authordjm@openbsd.org <djm@openbsd.org>2017-06-09 06:40:24 +0000
committerDamien Miller <djm@mindrot.org>2017-06-10 16:40:10 +1000
commit2076e4adb986512ce8c415dd194fd4e52136c4b4 (patch)
treeacf43f2d480390738e02805f6adbd1f63298a8c4 /sshkey.c
parentad0531614cbe8ec424af3c0fa90c34a8e1ebee4c (diff)
upstream commit
better translate libcrypto errors by looking deeper in the accursed error stack for codes that indicate the wrong passphrase was supplied for a PEM key. bz#2699 ok dtucker@ Upstream-ID: 4da4286326d570f4f0489459bb71f6297e54b681
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c104
1 files changed, 62 insertions, 42 deletions
diff --git a/sshkey.c b/sshkey.c
index 9a3f0be58..a138a6f66 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshkey.c,v 1.51 2017/05/31 09:15:42 deraadt Exp $ */ 1/* $OpenBSD: sshkey.c,v 1.52 2017/06/09 06:40:24 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.
@@ -1331,7 +1331,7 @@ sshkey_to_base64(const struct sshkey *key, char **b64p)
1331 return r; 1331 return r;
1332} 1332}
1333 1333
1334static int 1334int
1335sshkey_format_text(const struct sshkey *key, struct sshbuf *b) 1335sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
1336{ 1336{
1337 int r = SSH_ERR_INTERNAL_ERROR; 1337 int r = SSH_ERR_INTERNAL_ERROR;
@@ -3366,6 +3366,64 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3366 3366
3367#ifdef WITH_OPENSSL 3367#ifdef WITH_OPENSSL
3368static int 3368static int
3369translate_libcrypto_error(unsigned long pem_err)
3370{
3371 int pem_reason = ERR_GET_REASON(pem_err);
3372
3373 switch (ERR_GET_LIB(pem_err)) {
3374 case ERR_LIB_PEM:
3375 switch (pem_reason) {
3376 case PEM_R_BAD_PASSWORD_READ:
3377 case PEM_R_PROBLEMS_GETTING_PASSWORD:
3378 case PEM_R_BAD_DECRYPT:
3379 return SSH_ERR_KEY_WRONG_PASSPHRASE;
3380 default:
3381 return SSH_ERR_INVALID_FORMAT;
3382 }
3383 case ERR_LIB_EVP:
3384 switch (pem_reason) {
3385 case EVP_R_BAD_DECRYPT:
3386 return SSH_ERR_KEY_WRONG_PASSPHRASE;
3387 case EVP_R_BN_DECODE_ERROR:
3388 case EVP_R_DECODE_ERROR:
3389#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
3390 case EVP_R_PRIVATE_KEY_DECODE_ERROR:
3391#endif
3392 return SSH_ERR_INVALID_FORMAT;
3393 default:
3394 return SSH_ERR_LIBCRYPTO_ERROR;
3395 }
3396 case ERR_LIB_ASN1:
3397 return SSH_ERR_INVALID_FORMAT;
3398 }
3399 return SSH_ERR_LIBCRYPTO_ERROR;
3400}
3401
3402static void
3403clear_libcrypto_errors(void)
3404{
3405 while (ERR_get_error() != 0)
3406 ;
3407}
3408
3409/*
3410 * Translate OpenSSL error codes to determine whether
3411 * passphrase is required/incorrect.
3412 */
3413static int
3414convert_libcrypto_error(void)
3415{
3416 /*
3417 * Some password errors are reported at the beginning
3418 * of the error queue.
3419 */
3420 if (translate_libcrypto_error(ERR_peek_error()) ==
3421 SSH_ERR_KEY_WRONG_PASSPHRASE)
3422 return SSH_ERR_KEY_WRONG_PASSPHRASE;
3423 return translate_libcrypto_error(ERR_peek_last_error());
3424}
3425
3426static int
3369sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, 3427sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
3370 const char *passphrase, struct sshkey **keyp) 3428 const char *passphrase, struct sshkey **keyp)
3371{ 3429{
@@ -3385,48 +3443,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
3385 goto out; 3443 goto out;
3386 } 3444 }
3387 3445
3446 clear_libcrypto_errors();
3388 if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, 3447 if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
3389 (char *)passphrase)) == NULL) { 3448 (char *)passphrase)) == NULL) {
3390 unsigned long pem_err = ERR_peek_last_error(); 3449 r = convert_libcrypto_error();
3391 int pem_reason = ERR_GET_REASON(pem_err);
3392
3393 /*
3394 * Translate OpenSSL error codes to determine whether
3395 * passphrase is required/incorrect.
3396 */
3397 switch (ERR_GET_LIB(pem_err)) {
3398 case ERR_LIB_PEM:
3399 switch (pem_reason) {
3400 case PEM_R_BAD_PASSWORD_READ:
3401 case PEM_R_PROBLEMS_GETTING_PASSWORD:
3402 case PEM_R_BAD_DECRYPT:
3403 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3404 goto out;
3405 default:
3406 r = SSH_ERR_INVALID_FORMAT;
3407 goto out;
3408 }
3409 case ERR_LIB_EVP:
3410 switch (pem_reason) {
3411 case EVP_R_BAD_DECRYPT:
3412 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3413 goto out;
3414 case EVP_R_BN_DECODE_ERROR:
3415 case EVP_R_DECODE_ERROR:
3416#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
3417 case EVP_R_PRIVATE_KEY_DECODE_ERROR:
3418#endif
3419 r = SSH_ERR_INVALID_FORMAT;
3420 goto out;
3421 default:
3422 r = SSH_ERR_LIBCRYPTO_ERROR;
3423 goto out;
3424 }
3425 case ERR_LIB_ASN1:
3426 r = SSH_ERR_INVALID_FORMAT;
3427 goto out;
3428 }
3429 r = SSH_ERR_LIBCRYPTO_ERROR;
3430 goto out; 3450 goto out;
3431 } 3451 }
3432 if (pk->type == EVP_PKEY_RSA && 3452 if (pk->type == EVP_PKEY_RSA &&