diff options
-rw-r--r-- | sshkey.c | 104 |
1 files changed, 62 insertions, 42 deletions
@@ -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 | ||
1334 | static int | 1334 | int |
1335 | sshkey_format_text(const struct sshkey *key, struct sshbuf *b) | 1335 | sshkey_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 |
3368 | static int | 3368 | static int |
3369 | translate_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 | |||
3402 | static void | ||
3403 | clear_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 | */ | ||
3413 | static int | ||
3414 | convert_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 | |||
3426 | static int | ||
3369 | sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | 3427 | sshkey_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 && |