summaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c609
1 files changed, 113 insertions, 496 deletions
diff --git a/sshkey.c b/sshkey.c
index 53a7674b5e74..e91c54f53bbd 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.45 2017/03/10 04:07:20 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.56 2017/08/12 06:42:52 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -51,7 +51,6 @@
#include "ssherr.h"
#include "misc.h"
#include "sshbuf.h"
-#include "rsa.h"
#include "cipher.h"
#include "digest.h"
#define SSHKEY_INTERNAL
@@ -66,7 +65,7 @@
#define KDFNAME "bcrypt"
#define AUTH_MAGIC "openssh-key-v1"
#define SALT_LEN 16
-#define DEFAULT_CIPHERNAME "aes256-cbc"
+#define DEFAULT_CIPHERNAME "aes256-ctr"
#define DEFAULT_ROUNDS 16
/* Version identification string for SSH v1 identity files. */
@@ -89,9 +88,6 @@ static const struct keytype keytypes[] = {
{ "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
KEY_ED25519_CERT, 0, 1, 0 },
#ifdef WITH_OPENSSL
-# ifdef WITH_SSH1
- { NULL, "RSA1", KEY_RSA1, 0, 0, 0 },
-# endif
{ "ssh-rsa", "RSA", KEY_RSA, 0, 0, 0 },
{ "rsa-sha2-256", "RSA", KEY_RSA, 0, 0, 1 },
{ "rsa-sha2-512", "RSA", KEY_RSA, 0, 0, 1 },
@@ -238,10 +234,6 @@ sshkey_names_valid2(const char *names, int allow_wildcard)
for ((p = strsep(&cp, ",")); p && *p != '\0';
(p = strsep(&cp, ","))) {
type = sshkey_type_from_name(p);
- if (type == KEY_RSA1) {
- free(s);
- return 0;
- }
if (type == KEY_UNSPEC) {
if (allow_wildcard) {
/*
@@ -250,8 +242,6 @@ sshkey_names_valid2(const char *names, int allow_wildcard)
* the component is accepted.
*/
for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->type == KEY_RSA1)
- continue;
if (match_pattern_list(kt->name,
p, 0) != 0)
break;
@@ -272,7 +262,6 @@ sshkey_size(const struct sshkey *k)
{
switch (k->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
case KEY_RSA:
case KEY_RSA_CERT:
return BN_num_bits(k->rsa->n);
@@ -475,7 +464,6 @@ sshkey_new(int type)
k->ed25519_pk = NULL;
switch (k->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
case KEY_RSA:
case KEY_RSA_CERT:
if ((rsa = RSA_new()) == NULL ||
@@ -533,7 +521,6 @@ sshkey_add_private(struct sshkey *k)
{
switch (k->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
case KEY_RSA:
case KEY_RSA_CERT:
#define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
@@ -589,7 +576,6 @@ sshkey_free(struct sshkey *k)
return;
switch (k->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
case KEY_RSA:
case KEY_RSA_CERT:
if (k->rsa != NULL)
@@ -667,7 +653,6 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
switch (a->type) {
#ifdef WITH_OPENSSL
- case KEY_RSA1:
case KEY_RSA_CERT:
case KEY_RSA:
return a->rsa != NULL && b->rsa != NULL &&
@@ -884,25 +869,7 @@ sshkey_fingerprint_raw(const struct sshkey *k, int dgst_alg,
r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
-
- if (k->type == KEY_RSA1) {
-#ifdef WITH_OPENSSL
- int nlen = BN_num_bytes(k->rsa->n);
- int elen = BN_num_bytes(k->rsa->e);
-
- if (nlen < 0 || elen < 0 || nlen >= INT_MAX - elen) {
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- blob_len = nlen + elen;
- if ((blob = malloc(blob_len)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- BN_bn2bin(k->rsa->n, blob);
- BN_bn2bin(k->rsa->e, blob + nlen);
-#endif /* WITH_OPENSSL */
- } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0)
+ if ((r = to_blob(k, &blob, &blob_len, 1)) != 0)
goto out;
if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
r = SSH_ERR_ALLOC_FAIL;
@@ -1194,39 +1161,6 @@ sshkey_fingerprint(const struct sshkey *k, int dgst_alg,
return retval;
}
-#ifdef WITH_SSH1
-/*
- * Reads a multiple-precision integer in decimal from the buffer, and advances
- * the pointer. The integer must already be initialized. This function is
- * permitted to modify the buffer. This leaves *cpp to point just beyond the
- * last processed character.
- */
-static int
-read_decimal_bignum(char **cpp, BIGNUM *v)
-{
- char *cp;
- size_t e;
- int skip = 1; /* skip white space */
-
- cp = *cpp;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- e = strspn(cp, "0123456789");
- if (e == 0)
- return SSH_ERR_INVALID_FORMAT;
- if (e > SSHBUF_MAX_BIGNUM * 3)
- return SSH_ERR_BIGNUM_TOO_LARGE;
- if (cp[e] == '\0')
- skip = 0;
- else if (strchr(" \t\r\n", cp[e]) == NULL)
- return SSH_ERR_INVALID_FORMAT;
- cp[e] = '\0';
- if (BN_dec2bn(&v, cp) <= 0)
- return SSH_ERR_INVALID_FORMAT;
- *cpp = cp + e + skip;
- return 0;
-}
-#endif /* WITH_SSH1 */
/* returns 0 ok, and < 0 error */
int
@@ -1237,9 +1171,6 @@ sshkey_read(struct sshkey *ret, char **cpp)
char *ep, *cp, *space;
int r, type, curve_nid = -1;
struct sshbuf *blob;
-#ifdef WITH_SSH1
- u_long bits;
-#endif /* WITH_SSH1 */
if (ret == NULL)
return SSH_ERR_INVALID_ARGUMENT;
@@ -1247,25 +1178,6 @@ sshkey_read(struct sshkey *ret, char **cpp)
cp = *cpp;
switch (ret->type) {
- case KEY_RSA1:
-#ifdef WITH_SSH1
- /* Get number of bits. */
- bits = strtoul(cp, &ep, 10);
- if (*cp == '\0' || strchr(" \t\r\n", *ep) == NULL ||
- bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8)
- return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */
- /* Get public exponent, public modulus. */
- if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0)
- return r;
- if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0)
- return r;
- /* validate the claimed number of bits */
- if (BN_num_bits(ret->rsa->n) != (int)bits)
- return SSH_ERR_KEY_BITS_MISMATCH;
- *cpp = ep;
- retval = 0;
-#endif /* WITH_SSH1 */
- break;
case KEY_UNSPEC:
case KEY_RSA:
case KEY_DSA:
@@ -1418,61 +1330,17 @@ sshkey_to_base64(const struct sshkey *key, char **b64p)
return r;
}
-static int
-sshkey_format_rsa1(const struct sshkey *key, struct sshbuf *b)
-{
- int r = SSH_ERR_INTERNAL_ERROR;
-#ifdef WITH_SSH1
- u_int bits = 0;
- char *dec_e = NULL, *dec_n = NULL;
-
- if (key->rsa == NULL || key->rsa->e == NULL ||
- key->rsa->n == NULL) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL ||
- (dec_n = BN_bn2dec(key->rsa->n)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- /* size of modulus 'n' */
- if ((bits = BN_num_bits(key->rsa->n)) <= 0) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
- if ((r = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0)
- goto out;
-
- /* Success */
- r = 0;
- out:
- if (dec_e != NULL)
- OPENSSL_free(dec_e);
- if (dec_n != NULL)
- OPENSSL_free(dec_n);
-#endif /* WITH_SSH1 */
-
- return r;
-}
-
-static int
+int
sshkey_format_text(const struct sshkey *key, struct sshbuf *b)
{
int r = SSH_ERR_INTERNAL_ERROR;
char *uu = NULL;
- if (key->type == KEY_RSA1) {
- if ((r = sshkey_format_rsa1(key, b)) != 0)
- goto out;
- } else {
- /* Unsupported key types handled in sshkey_to_base64() */
- if ((r = sshkey_to_base64(key, &uu)) != 0)
- goto out;
- if ((r = sshbuf_putf(b, "%s %s",
- sshkey_ssh_name(key), uu)) != 0)
- goto out;
- }
+ if ((r = sshkey_to_base64(key, &uu)) != 0)
+ goto out;
+ if ((r = sshbuf_putf(b, "%s %s",
+ sshkey_ssh_name(key), uu)) != 0)
+ goto out;
r = 0;
out:
free(uu);
@@ -1523,10 +1391,11 @@ rsa_generate_private_key(u_int bits, RSA **rsap)
BIGNUM *f4 = NULL;
int ret = SSH_ERR_INTERNAL_ERROR;
- if (rsap == NULL ||
- bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
- bits > SSHBUF_MAX_BIGNUM * 8)
+ if (rsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
+ bits > SSHBUF_MAX_BIGNUM * 8)
+ return SSH_ERR_KEY_LENGTH;
*rsap = NULL;
if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
@@ -1554,8 +1423,10 @@ dsa_generate_private_key(u_int bits, DSA **dsap)
DSA *private;
int ret = SSH_ERR_INTERNAL_ERROR;
- if (dsap == NULL || bits != 1024)
+ if (dsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ if (bits != 1024)
+ return SSH_ERR_KEY_LENGTH;
if ((private = DSA_new()) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
goto out;
@@ -1632,9 +1503,10 @@ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
EC_KEY *private;
int ret = SSH_ERR_INTERNAL_ERROR;
- if (nid == NULL || ecdsap == NULL ||
- (*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
+ if (nid == NULL || ecdsap == NULL)
return SSH_ERR_INVALID_ARGUMENT;
+ if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
+ return SSH_ERR_KEY_LENGTH;
*ecdsap = NULL;
if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
ret = SSH_ERR_ALLOC_FAIL;
@@ -1688,7 +1560,6 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp)
break;
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA:
- case KEY_RSA1:
ret = rsa_generate_private_key(bits, &k->rsa);
break;
#endif /* WITH_OPENSSL */
@@ -1799,7 +1670,6 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
break;
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA:
- case KEY_RSA1:
case KEY_RSA_CERT:
if ((n = sshkey_new(k->type)) == NULL)
return SSH_ERR_ALLOC_FAIL;
@@ -1893,8 +1763,9 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
goto out;
}
oprincipals = key->cert->principals;
- key->cert->principals = reallocarray(key->cert->principals,
- key->cert->nprincipals + 1, sizeof(*key->cert->principals));
+ key->cert->principals = recallocarray(key->cert->principals,
+ key->cert->nprincipals, key->cert->nprincipals + 1,
+ sizeof(*key->cert->principals));
if (key->cert->principals == NULL) {
free(principal);
key->cert->principals = oprincipals;
@@ -2009,6 +1880,10 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
ret = SSH_ERR_INVALID_FORMAT;
goto out;
}
+ if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ ret = SSH_ERR_KEY_LENGTH;
+ goto out;
+ }
#ifdef DEBUG_PK
RSA_print_fp(stderr, key->rsa, 8);
#endif
@@ -2111,11 +1986,6 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
pk = NULL;
break;
case KEY_UNSPEC:
- if ((key = sshkey_new(type)) == NULL) {
- ret = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- break;
default:
ret = SSH_ERR_KEY_TYPE_UNKNOWN;
goto out;
@@ -2269,7 +2139,6 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
if ((ret = sshkey_cert_copy(k, pk)) != 0)
goto fail;
/* FALLTHROUGH */
- case KEY_RSA1:
case KEY_RSA:
if ((pk->rsa = RSA_new()) == NULL ||
(pk->rsa->e = BN_dup(k->rsa->e)) == NULL ||
@@ -2378,7 +2247,8 @@ sshkey_drop_cert(struct sshkey *k)
/* Sign a certified key, (re-)generating the signed certblob. */
int
-sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
+sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg,
+ sshkey_certify_signer *signer, void *signer_ctx)
{
struct sshbuf *principals = NULL;
u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
@@ -2467,8 +2337,8 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
goto out;
/* Sign the whole mess */
- if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
- sshbuf_len(cert), alg, 0)) != 0)
+ if ((ret = signer(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
+ sshbuf_len(cert), alg, 0, signer_ctx)) != 0)
goto out;
/* Append signature and we are done */
@@ -2484,6 +2354,22 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
return ret;
}
+static int
+default_key_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
+ const u_char *data, size_t datalen,
+ const char *alg, u_int compat, void *ctx)
+{
+ if (ctx != NULL)
+ return SSH_ERR_INVALID_ARGUMENT;
+ return sshkey_sign(key, sigp, lenp, data, datalen, alg, compat);
+}
+
+int
+sshkey_certify(struct sshkey *k, struct sshkey *ca, const char *alg)
+{
+ return sshkey_certify_custom(k, ca, alg, default_key_sign, NULL);
+}
+
int
sshkey_cert_check_authority(const struct sshkey *k,
int want_host, int require_principal,
@@ -2775,8 +2661,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
- (r = rsa_generate_additional_parameters(k->rsa)) != 0)
+ (r = ssh_rsa_generate_additional_parameters(k)) != 0)
goto out;
+ if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ r = SSH_ERR_KEY_LENGTH;
+ goto out;
+ }
break;
case KEY_RSA_CERT:
if ((r = sshkey_froms(buf, &k)) != 0 ||
@@ -2785,8 +2675,12 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
(r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
(r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
- (r = rsa_generate_additional_parameters(k->rsa)) != 0)
+ (r = ssh_rsa_generate_additional_parameters(k)) != 0)
goto out;
+ if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ r = SSH_ERR_KEY_LENGTH;
+ goto out;
+ }
break;
#endif /* WITH_OPENSSL */
case KEY_ED25519:
@@ -2828,7 +2722,6 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
switch (k->type) {
case KEY_RSA:
case KEY_RSA_CERT:
- case KEY_RSA1:
if (RSA_blinding_on(k->rsa, NULL) != 1) {
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
@@ -3057,12 +2950,8 @@ sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
kdfname = "none";
} else if (ciphername == NULL)
ciphername = DEFAULT_CIPHERNAME;
- else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) {
- r = SSH_ERR_INVALID_ARGUMENT;
- goto out;
- }
if ((cipher = cipher_by_name(ciphername)) == NULL) {
- r = SSH_ERR_INTERNAL_ERROR;
+ r = SSH_ERR_INVALID_ARGUMENT;
goto out;
}
@@ -3404,105 +3293,6 @@ sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
return r;
}
-#if WITH_SSH1
-/*
- * Serialises the authentication (private) key to a blob, encrypting it with
- * passphrase. The identification of the blob (lowest 64 bits of n) will
- * precede the key to provide identification of the key without needing a
- * passphrase.
- */
-static int
-sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
- const char *passphrase, const char *comment)
-{
- struct sshbuf *buffer = NULL, *encrypted = NULL;
- u_char buf[8];
- int r, cipher_num;
- struct sshcipher_ctx *ciphercontext = NULL;
- const struct sshcipher *cipher;
- u_char *cp;
-
- /*
- * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
- * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
- */
- cipher_num = (strcmp(passphrase, "") == 0) ?
- SSH_CIPHER_NONE : SSH_CIPHER_3DES;
- if ((cipher = cipher_by_number(cipher_num)) == NULL)
- return SSH_ERR_INTERNAL_ERROR;
-
- /* This buffer is used to build the secret part of the private key. */
- if ((buffer = sshbuf_new()) == NULL)
- return SSH_ERR_ALLOC_FAIL;
-
- /* Put checkbytes for checking passphrase validity. */
- if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0)
- goto out;
- arc4random_buf(cp, 2);
- memcpy(cp + 2, cp, 2);
-
- /*
- * Store the private key (n and e will not be stored because they
- * will be stored in plain text, and storing them also in encrypted
- * format would just give known plaintext).
- * Note: q and p are stored in reverse order to SSL.
- */
- if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 ||
- (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 ||
- (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 ||
- (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0)
- goto out;
-
- /* Pad the part to be encrypted to a size that is a multiple of 8. */
- explicit_bzero(buf, 8);
- if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0)
- goto out;
-
- /* This buffer will be used to contain the data in the file. */
- if ((encrypted = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
-
- /* First store keyfile id string. */
- if ((r = sshbuf_put(encrypted, LEGACY_BEGIN,
- sizeof(LEGACY_BEGIN))) != 0)
- goto out;
-
- /* Store cipher type and "reserved" field. */
- if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 ||
- (r = sshbuf_put_u32(encrypted, 0)) != 0)
- goto out;
-
- /* Store public key. This will be in plain text. */
- if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 ||
- (r = sshbuf_put_bignum1(encrypted, key->rsa->n)) != 0 ||
- (r = sshbuf_put_bignum1(encrypted, key->rsa->e)) != 0 ||
- (r = sshbuf_put_cstring(encrypted, comment)) != 0)
- goto out;
-
- /* Allocate space for the private part of the key in the buffer. */
- if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0)
- goto out;
-
- if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
- CIPHER_ENCRYPT)) != 0)
- goto out;
- if ((r = cipher_crypt(ciphercontext, 0, cp,
- sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0)
- goto out;
-
- r = sshbuf_putb(blob, encrypted);
-
- out:
- cipher_free(ciphercontext);
- explicit_bzero(buf, sizeof(buf));
- sshbuf_free(buffer);
- sshbuf_free(encrypted);
-
- return r;
-}
-#endif /* WITH_SSH1 */
#ifdef WITH_OPENSSL
/* convert SSH v2 key in OpenSSL PEM format */
@@ -3513,11 +3303,7 @@ sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
int success, r;
int blen, len = strlen(_passphrase);
u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
-#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
- const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
-#else
- const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
-#endif
+ const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
const u_char *bptr;
BIO *bio = NULL;
@@ -3569,11 +3355,6 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
int force_new_format, const char *new_format_cipher, int new_format_rounds)
{
switch (key->type) {
-#ifdef WITH_SSH1
- case KEY_RSA1:
- return sshkey_private_rsa1_to_blob(key, blob,
- passphrase, comment);
-#endif /* WITH_SSH1 */
#ifdef WITH_OPENSSL
case KEY_DSA:
case KEY_ECDSA:
@@ -3593,184 +3374,66 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
}
}
-#ifdef WITH_SSH1
-/*
- * Parse the public, unencrypted portion of a RSA1 key.
- */
-int
-sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
- struct sshkey **keyp, char **commentp)
-{
- int r;
- struct sshkey *pub = NULL;
- struct sshbuf *copy = NULL;
-
- if (keyp != NULL)
- *keyp = NULL;
- if (commentp != NULL)
- *commentp = NULL;
-
- /* Check that it is at least big enough to contain the ID string. */
- if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
- return SSH_ERR_INVALID_FORMAT;
- /*
- * Make sure it begins with the id string. Consume the id string
- * from the buffer.
- */
- if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
+#ifdef WITH_OPENSSL
+static int
+translate_libcrypto_error(unsigned long pem_err)
+{
+ int pem_reason = ERR_GET_REASON(pem_err);
+
+ switch (ERR_GET_LIB(pem_err)) {
+ case ERR_LIB_PEM:
+ switch (pem_reason) {
+ case PEM_R_BAD_PASSWORD_READ:
+ case PEM_R_PROBLEMS_GETTING_PASSWORD:
+ case PEM_R_BAD_DECRYPT:
+ return SSH_ERR_KEY_WRONG_PASSPHRASE;
+ default:
+ return SSH_ERR_INVALID_FORMAT;
+ }
+ case ERR_LIB_EVP:
+ switch (pem_reason) {
+ case EVP_R_BAD_DECRYPT:
+ return SSH_ERR_KEY_WRONG_PASSPHRASE;
+ case EVP_R_BN_DECODE_ERROR:
+ case EVP_R_DECODE_ERROR:
+#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
+ case EVP_R_PRIVATE_KEY_DECODE_ERROR:
+#endif
+ return SSH_ERR_INVALID_FORMAT;
+ default:
+ return SSH_ERR_LIBCRYPTO_ERROR;
+ }
+ case ERR_LIB_ASN1:
return SSH_ERR_INVALID_FORMAT;
- /* Make a working copy of the keyblob and skip past the magic */
- if ((copy = sshbuf_fromb(blob)) == NULL)
- return SSH_ERR_ALLOC_FAIL;
- if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
- goto out;
-
- /* Skip cipher type, reserved data and key bits. */
- if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */
- (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */
- (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */
- goto out;
-
- /* Read the public key from the buffer. */
- if ((pub = sshkey_new(KEY_RSA1)) == NULL ||
- (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 ||
- (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0)
- goto out;
-
- /* Finally, the comment */
- if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0)
- goto out;
-
- /* The encrypted private part is not parsed by this function. */
-
- r = 0;
- if (keyp != NULL) {
- *keyp = pub;
- pub = NULL;
}
- out:
- sshbuf_free(copy);
- sshkey_free(pub);
- return r;
+ return SSH_ERR_LIBCRYPTO_ERROR;
}
-static int
-sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
- struct sshkey **keyp, char **commentp)
+static void
+clear_libcrypto_errors(void)
{
- int r;
- u_int16_t check1, check2;
- u_int8_t cipher_type;
- struct sshbuf *decrypted = NULL, *copy = NULL;
- u_char *cp;
- char *comment = NULL;
- struct sshcipher_ctx *ciphercontext = NULL;
- const struct sshcipher *cipher;
- struct sshkey *prv = NULL;
-
- if (keyp != NULL)
- *keyp = NULL;
- if (commentp != NULL)
- *commentp = NULL;
-
- /* Check that it is at least big enough to contain the ID string. */
- if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
- return SSH_ERR_INVALID_FORMAT;
+ while (ERR_get_error() != 0)
+ ;
+}
+/*
+ * Translate OpenSSL error codes to determine whether
+ * passphrase is required/incorrect.
+ */
+static int
+convert_libcrypto_error(void)
+{
/*
- * Make sure it begins with the id string. Consume the id string
- * from the buffer.
+ * Some password errors are reported at the beginning
+ * of the error queue.
*/
- if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
- return SSH_ERR_INVALID_FORMAT;
-
- if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((copy = sshbuf_fromb(blob)) == NULL ||
- (decrypted = sshbuf_new()) == NULL) {
- r = SSH_ERR_ALLOC_FAIL;
- goto out;
- }
- if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
- goto out;
-
- /* Read cipher type. */
- if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 ||
- (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */
- goto out;
-
- /* Read the public key and comment from the buffer. */
- if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */
- (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 ||
- (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 ||
- (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0)
- goto out;
-
- /* Check that it is a supported cipher. */
- cipher = cipher_by_number(cipher_type);
- if (cipher == NULL) {
- r = SSH_ERR_KEY_UNKNOWN_CIPHER;
- goto out;
- }
- /* Initialize space for decrypted data. */
- if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0)
- goto out;
-
- /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
- if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
- CIPHER_DECRYPT)) != 0)
- goto out;
- if ((r = cipher_crypt(ciphercontext, 0, cp,
- sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0)
- goto out;
-
- if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 ||
- (r = sshbuf_get_u16(decrypted, &check2)) != 0)
- goto out;
- if (check1 != check2) {
- r = SSH_ERR_KEY_WRONG_PASSPHRASE;
- goto out;
- }
-
- /* Read the rest of the private key. */
- if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 ||
- (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 ||
- (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 ||
- (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0)
- goto out;
-
- /* calculate p-1 and q-1 */
- if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0)
- goto out;
-
- /* enable blinding */
- if (RSA_blinding_on(prv->rsa, NULL) != 1) {
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- r = 0;
- if (keyp != NULL) {
- *keyp = prv;
- prv = NULL;
- }
- if (commentp != NULL) {
- *commentp = comment;
- comment = NULL;
- }
- out:
- cipher_free(ciphercontext);
- free(comment);
- sshkey_free(prv);
- sshbuf_free(copy);
- sshbuf_free(decrypted);
- return r;
+ if (translate_libcrypto_error(ERR_peek_error()) ==
+ SSH_ERR_KEY_WRONG_PASSPHRASE)
+ return SSH_ERR_KEY_WRONG_PASSPHRASE;
+ return translate_libcrypto_error(ERR_peek_last_error());
}
-#endif /* WITH_SSH1 */
-#ifdef WITH_OPENSSL
static int
sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
const char *passphrase, struct sshkey **keyp)
@@ -3791,48 +3454,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
goto out;
}
+ clear_libcrypto_errors();
if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
(char *)passphrase)) == NULL) {
- unsigned long pem_err = ERR_peek_last_error();
- int pem_reason = ERR_GET_REASON(pem_err);
-
- /*
- * Translate OpenSSL error codes to determine whether
- * passphrase is required/incorrect.
- */
- switch (ERR_GET_LIB(pem_err)) {
- case ERR_LIB_PEM:
- switch (pem_reason) {
- case PEM_R_BAD_PASSWORD_READ:
- case PEM_R_PROBLEMS_GETTING_PASSWORD:
- case PEM_R_BAD_DECRYPT:
- r = SSH_ERR_KEY_WRONG_PASSPHRASE;
- goto out;
- default:
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- case ERR_LIB_EVP:
- switch (pem_reason) {
- case EVP_R_BAD_DECRYPT:
- r = SSH_ERR_KEY_WRONG_PASSPHRASE;
- goto out;
- case EVP_R_BN_DECODE_ERROR:
- case EVP_R_DECODE_ERROR:
-#ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR
- case EVP_R_PRIVATE_KEY_DECODE_ERROR:
-#endif
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- default:
- r = SSH_ERR_LIBCRYPTO_ERROR;
- goto out;
- }
- case ERR_LIB_ASN1:
- r = SSH_ERR_INVALID_FORMAT;
- goto out;
- }
- r = SSH_ERR_LIBCRYPTO_ERROR;
+ r = convert_libcrypto_error();
goto out;
}
if (pk->type == EVP_PKEY_RSA &&
@@ -3850,6 +3475,10 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
r = SSH_ERR_LIBCRYPTO_ERROR;
goto out;
}
+ if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) {
+ r = SSH_ERR_KEY_LENGTH;
+ goto out;
+ }
} else if (pk->type == EVP_PKEY_DSA &&
(type == KEY_UNSPEC || type == KEY_DSA)) {
if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
@@ -3914,11 +3543,6 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
*commentp = NULL;
switch (type) {
-#ifdef WITH_SSH1
- case KEY_RSA1:
- return sshkey_parse_private_rsa1(blob, passphrase,
- keyp, commentp);
-#endif /* WITH_SSH1 */
#ifdef WITH_OPENSSL
case KEY_DSA:
case KEY_ECDSA:
@@ -3955,13 +3579,6 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
if (commentp != NULL)
*commentp = NULL;
-#ifdef WITH_SSH1
- /* it's a SSH v1 key if the public key part is readable */
- if (sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL) == 0) {
- return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1,
- passphrase, keyp, commentp);
- }
-#endif /* WITH_SSH1 */
return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
passphrase, keyp, commentp);
}