diff options
Diffstat (limited to 'sshkey.c')
-rw-r--r-- | sshkey.c | 64 |
1 files changed, 57 insertions, 7 deletions
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshkey.c,v 1.41 2016/10/24 01:09:17 dtucker Exp $ */ | 1 | /* $OpenBSD: sshkey.c,v 1.45 2017/03/10 04:07:20 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. |
@@ -89,7 +89,9 @@ static const struct keytype keytypes[] = { | |||
89 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", | 89 | { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT", |
90 | KEY_ED25519_CERT, 0, 1, 0 }, | 90 | KEY_ED25519_CERT, 0, 1, 0 }, |
91 | #ifdef WITH_OPENSSL | 91 | #ifdef WITH_OPENSSL |
92 | # ifdef WITH_SSH1 | ||
92 | { NULL, "RSA1", KEY_RSA1, 0, 0, 0 }, | 93 | { NULL, "RSA1", KEY_RSA1, 0, 0, 0 }, |
94 | # endif | ||
93 | { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, | 95 | { "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 }, |
94 | { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, | 96 | { "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 }, |
95 | { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, | 97 | { "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 }, |
@@ -196,14 +198,16 @@ sshkey_ecdsa_nid_from_name(const char *name) | |||
196 | } | 198 | } |
197 | 199 | ||
198 | char * | 200 | char * |
199 | sshkey_alg_list(int certs_only, int plain_only, char sep) | 201 | sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) |
200 | { | 202 | { |
201 | char *tmp, *ret = NULL; | 203 | char *tmp, *ret = NULL; |
202 | size_t nlen, rlen = 0; | 204 | size_t nlen, rlen = 0; |
203 | const struct keytype *kt; | 205 | const struct keytype *kt; |
204 | 206 | ||
205 | for (kt = keytypes; kt->type != -1; kt++) { | 207 | for (kt = keytypes; kt->type != -1; kt++) { |
206 | if (kt->name == NULL || kt->sigonly || kt->type == KEY_NULL) | 208 | if (kt->name == NULL || kt->type == KEY_NULL) |
209 | continue; | ||
210 | if (!include_sigonly && kt->sigonly) | ||
207 | continue; | 211 | continue; |
208 | if ((certs_only && !kt->cert) || (plain_only && kt->cert)) | 212 | if ((certs_only && !kt->cert) || (plain_only && kt->cert)) |
209 | continue; | 213 | continue; |
@@ -1238,6 +1242,9 @@ sshkey_read(struct sshkey *ret, char **cpp) | |||
1238 | u_long bits; | 1242 | u_long bits; |
1239 | #endif /* WITH_SSH1 */ | 1243 | #endif /* WITH_SSH1 */ |
1240 | 1244 | ||
1245 | if (ret == NULL) | ||
1246 | return SSH_ERR_INVALID_ARGUMENT; | ||
1247 | |||
1241 | cp = *cpp; | 1248 | cp = *cpp; |
1242 | 1249 | ||
1243 | switch (ret->type) { | 1250 | switch (ret->type) { |
@@ -3787,7 +3794,46 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, | |||
3787 | 3794 | ||
3788 | if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, | 3795 | if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, |
3789 | (char *)passphrase)) == NULL) { | 3796 | (char *)passphrase)) == NULL) { |
3790 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | 3797 | unsigned long pem_err = ERR_peek_last_error(); |
3798 | int pem_reason = ERR_GET_REASON(pem_err); | ||
3799 | |||
3800 | /* | ||
3801 | * Translate OpenSSL error codes to determine whether | ||
3802 | * passphrase is required/incorrect. | ||
3803 | */ | ||
3804 | switch (ERR_GET_LIB(pem_err)) { | ||
3805 | case ERR_LIB_PEM: | ||
3806 | switch (pem_reason) { | ||
3807 | case PEM_R_BAD_PASSWORD_READ: | ||
3808 | case PEM_R_PROBLEMS_GETTING_PASSWORD: | ||
3809 | case PEM_R_BAD_DECRYPT: | ||
3810 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3811 | goto out; | ||
3812 | default: | ||
3813 | r = SSH_ERR_INVALID_FORMAT; | ||
3814 | goto out; | ||
3815 | } | ||
3816 | case ERR_LIB_EVP: | ||
3817 | switch (pem_reason) { | ||
3818 | case EVP_R_BAD_DECRYPT: | ||
3819 | r = SSH_ERR_KEY_WRONG_PASSPHRASE; | ||
3820 | goto out; | ||
3821 | case EVP_R_BN_DECODE_ERROR: | ||
3822 | case EVP_R_DECODE_ERROR: | ||
3823 | #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR | ||
3824 | case EVP_R_PRIVATE_KEY_DECODE_ERROR: | ||
3825 | #endif | ||
3826 | r = SSH_ERR_INVALID_FORMAT; | ||
3827 | goto out; | ||
3828 | default: | ||
3829 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3830 | goto out; | ||
3831 | } | ||
3832 | case ERR_LIB_ASN1: | ||
3833 | r = SSH_ERR_INVALID_FORMAT; | ||
3834 | goto out; | ||
3835 | } | ||
3836 | r = SSH_ERR_LIBCRYPTO_ERROR; | ||
3791 | goto out; | 3837 | goto out; |
3792 | } | 3838 | } |
3793 | if (pk->type == EVP_PKEY_RSA && | 3839 | if (pk->type == EVP_PKEY_RSA && |
@@ -3861,6 +3907,8 @@ int | |||
3861 | sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, | 3907 | sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, |
3862 | const char *passphrase, struct sshkey **keyp, char **commentp) | 3908 | const char *passphrase, struct sshkey **keyp, char **commentp) |
3863 | { | 3909 | { |
3910 | int r = SSH_ERR_INTERNAL_ERROR; | ||
3911 | |||
3864 | if (keyp != NULL) | 3912 | if (keyp != NULL) |
3865 | *keyp = NULL; | 3913 | *keyp = NULL; |
3866 | if (commentp != NULL) | 3914 | if (commentp != NULL) |
@@ -3883,9 +3931,11 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, | |||
3883 | return sshkey_parse_private2(blob, type, passphrase, | 3931 | return sshkey_parse_private2(blob, type, passphrase, |
3884 | keyp, commentp); | 3932 | keyp, commentp); |
3885 | case KEY_UNSPEC: | 3933 | case KEY_UNSPEC: |
3886 | if (sshkey_parse_private2(blob, type, passphrase, keyp, | 3934 | r = sshkey_parse_private2(blob, type, passphrase, keyp, |
3887 | commentp) == 0) | 3935 | commentp); |
3888 | return 0; | 3936 | /* Do not fallback to PEM parser if only passphrase is wrong. */ |
3937 | if (r == 0 || r == SSH_ERR_KEY_WRONG_PASSPHRASE) | ||
3938 | return r; | ||
3889 | #ifdef WITH_OPENSSL | 3939 | #ifdef WITH_OPENSSL |
3890 | return sshkey_parse_private_pem_fileblob(blob, type, | 3940 | return sshkey_parse_private_pem_fileblob(blob, type, |
3891 | passphrase, keyp); | 3941 | passphrase, keyp); |