aboutsummaryrefslogtreecommitdiff
path: root/sshkey.c
diff options
context:
space:
mode:
authorDag-Erling Smørgrav <des@FreeBSD.org>2016-03-10 20:10:25 +0000
committerDag-Erling Smørgrav <des@FreeBSD.org>2016-03-10 20:10:25 +0000
commitff4b04e0d6105849f2b141c035ecd92a4ebc6d97 (patch)
tree3d2e6235900570f05cfbdbc81f01095fa38bd1e7 /sshkey.c
parent4cb2962809c63c51f6f7e029b95f2bdb622f1e4a (diff)
downloadsrc-ff4b04e0d6105849f2b141c035ecd92a4ebc6d97.tar.gz
src-ff4b04e0d6105849f2b141c035ecd92a4ebc6d97.zip
Notes
Diffstat (limited to 'sshkey.c')
-rw-r--r--sshkey.c210
1 files changed, 112 insertions, 98 deletions
diff --git a/sshkey.c b/sshkey.c
index 32dd8f2254a2..87b093e91d26 100644
--- a/sshkey.c
+++ b/sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sshkey.c,v 1.21 2015/08/19 23:19:01 djm Exp $ */
+/* $OpenBSD: sshkey.c,v 1.31 2015/12/11 04:21:12 mmcc Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* Copyright (c) 2008 Alexander von Gernler. All rights reserved.
@@ -83,36 +83,39 @@ struct keytype {
int type;
int nid;
int cert;
+ int sigonly;
};
static const struct keytype keytypes[] = {
- { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },
+ { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0, 0 },
{ "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
- KEY_ED25519_CERT, 0, 1 },
+ KEY_ED25519_CERT, 0, 1, 0 },
#ifdef WITH_OPENSSL
- { NULL, "RSA1", KEY_RSA1, 0, 0 },
- { "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
- { "ssh-dss", "DSA", KEY_DSA, 0, 0 },
+ { NULL, "RSA1", KEY_RSA1, 0, 0, 0 },
+ { "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 },
+ { "ssh-dss", "DSA", KEY_DSA, 0, 0, 0 },
# ifdef OPENSSL_HAS_ECC
- { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
- { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
+ { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0, 0 },
+ { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0, 0 },
# ifdef OPENSSL_HAS_NISTP521
- { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
+ { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
# endif /* OPENSSL_HAS_ECC */
- { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
- { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
+ { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1, 0 },
+ { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1, 0 },
# ifdef OPENSSL_HAS_ECC
{ "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
- KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
+ KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1, 0 },
{ "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
- KEY_ECDSA_CERT, NID_secp384r1, 1 },
+ KEY_ECDSA_CERT, NID_secp384r1, 1, 0 },
# ifdef OPENSSL_HAS_NISTP521
{ "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
- KEY_ECDSA_CERT, NID_secp521r1, 1 },
+ KEY_ECDSA_CERT, NID_secp521r1, 1, 0 },
# endif /* OPENSSL_HAS_NISTP521 */
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
- { NULL, NULL, -1, -1, 0 }
+ { NULL, NULL, -1, -1, 0, 0 }
};
const char *
@@ -200,7 +203,7 @@ key_alg_list(int certs_only, int plain_only)
const struct keytype *kt;
for (kt = keytypes; kt->type != -1; kt++) {
- if (kt->name == NULL)
+ if (kt->name == NULL || kt->sigonly)
continue;
if ((certs_only && !kt->cert) || (plain_only && kt->cert))
continue;
@@ -417,20 +420,14 @@ cert_free(struct sshkey_cert *cert)
if (cert == NULL)
return;
- if (cert->certblob != NULL)
- sshbuf_free(cert->certblob);
- if (cert->critical != NULL)
- sshbuf_free(cert->critical);
- if (cert->extensions != NULL)
- sshbuf_free(cert->extensions);
- if (cert->key_id != NULL)
- free(cert->key_id);
+ sshbuf_free(cert->certblob);
+ sshbuf_free(cert->critical);
+ sshbuf_free(cert->extensions);
+ free(cert->key_id);
for (i = 0; i < cert->nprincipals; i++)
free(cert->principals[i]);
- if (cert->principals != NULL)
- free(cert->principals);
- if (cert->signature_key != NULL)
- sshkey_free(cert->signature_key);
+ free(cert->principals);
+ sshkey_free(cert->signature_key);
explicit_bzero(cert, sizeof(*cert));
free(cert);
}
@@ -1216,7 +1213,7 @@ read_decimal_bignum(char **cpp, BIGNUM *v)
return SSH_ERR_BIGNUM_TOO_LARGE;
if (cp[e] == '\0')
skip = 0;
- else if (index(" \t\r\n", cp[e]) == NULL)
+ else if (strchr(" \t\r\n", cp[e]) == NULL)
return SSH_ERR_INVALID_FORMAT;
cp[e] = '\0';
if (BN_dec2bn(&v, cp) <= 0)
@@ -1232,11 +1229,10 @@ sshkey_read(struct sshkey *ret, char **cpp)
{
struct sshkey *k;
int retval = SSH_ERR_INVALID_FORMAT;
- char *cp, *space;
+ char *ep, *cp, *space;
int r, type, curve_nid = -1;
struct sshbuf *blob;
#ifdef WITH_SSH1
- char *ep;
u_long bits;
#endif /* WITH_SSH1 */
@@ -1247,7 +1243,7 @@ sshkey_read(struct sshkey *ret, char **cpp)
#ifdef WITH_SSH1
/* Get number of bits. */
bits = strtoul(cp, &ep, 10);
- if (*cp == '\0' || index(" \t\r\n", *ep) == NULL ||
+ 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. */
@@ -1255,10 +1251,10 @@ sshkey_read(struct sshkey *ret, char **cpp)
return r;
if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0)
return r;
- *cpp = ep;
/* 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;
@@ -1296,9 +1292,9 @@ sshkey_read(struct sshkey *ret, char **cpp)
*space++ = '\0';
while (*space == ' ' || *space == '\t')
space++;
- *cpp = space;
+ ep = space;
} else
- *cpp = cp + strlen(cp);
+ ep = cp + strlen(cp);
if ((r = sshbuf_b64tod(blob, cp)) != 0) {
sshbuf_free(blob);
return r;
@@ -1329,8 +1325,9 @@ sshkey_read(struct sshkey *ret, char **cpp)
ret->cert = k->cert;
k->cert = NULL;
}
+ switch (sshkey_type_plain(ret->type)) {
#ifdef WITH_OPENSSL
- if (sshkey_type_plain(ret->type) == KEY_RSA) {
+ case KEY_RSA:
if (ret->rsa != NULL)
RSA_free(ret->rsa);
ret->rsa = k->rsa;
@@ -1338,8 +1335,8 @@ sshkey_read(struct sshkey *ret, char **cpp)
#ifdef DEBUG_PK
RSA_print_fp(stderr, ret->rsa, 8);
#endif
- }
- if (sshkey_type_plain(ret->type) == KEY_DSA) {
+ break;
+ case KEY_DSA:
if (ret->dsa != NULL)
DSA_free(ret->dsa);
ret->dsa = k->dsa;
@@ -1347,9 +1344,9 @@ sshkey_read(struct sshkey *ret, char **cpp)
#ifdef DEBUG_PK
DSA_print_fp(stderr, ret->dsa, 8);
#endif
- }
+ break;
# ifdef OPENSSL_HAS_ECC
- if (sshkey_type_plain(ret->type) == KEY_ECDSA) {
+ case KEY_ECDSA:
if (ret->ecdsa != NULL)
EC_KEY_free(ret->ecdsa);
ret->ecdsa = k->ecdsa;
@@ -1359,17 +1356,19 @@ sshkey_read(struct sshkey *ret, char **cpp)
#ifdef DEBUG_PK
sshkey_dump_ec_key(ret->ecdsa);
#endif
- }
+ break;
# endif /* OPENSSL_HAS_ECC */
#endif /* WITH_OPENSSL */
- if (sshkey_type_plain(ret->type) == KEY_ED25519) {
+ case KEY_ED25519:
free(ret->ed25519_pk);
ret->ed25519_pk = k->ed25519_pk;
k->ed25519_pk = NULL;
#ifdef DEBUG_PK
/* XXX */
#endif
+ break;
}
+ *cpp = ep;
retval = 0;
/*XXXX*/
sshkey_free(k);
@@ -1717,7 +1716,7 @@ sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
(ret = sshbuf_putb(to->critical, from->critical)) != 0 ||
- (ret = sshbuf_putb(to->extensions, from->extensions) != 0))
+ (ret = sshbuf_putb(to->extensions, from->extensions)) != 0)
return ret;
to->serial = from->serial;
@@ -1758,9 +1757,7 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
struct sshkey *n = NULL;
int ret = SSH_ERR_INTERNAL_ERROR;
- if (pkp != NULL)
- *pkp = NULL;
-
+ *pkp = NULL;
switch (k->type) {
#ifdef WITH_OPENSSL
case KEY_DSA:
@@ -2174,7 +2171,7 @@ sshkey_froms(struct sshbuf *buf, struct sshkey **keyp)
int
sshkey_sign(const struct sshkey *key,
u_char **sigp, size_t *lenp,
- const u_char *data, size_t datalen, u_int compat)
+ const u_char *data, size_t datalen, const char *alg, u_int compat)
{
if (sigp != NULL)
*sigp = NULL;
@@ -2194,7 +2191,7 @@ sshkey_sign(const struct sshkey *key,
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA_CERT:
case KEY_RSA:
- return ssh_rsa_sign(key, sigp, lenp, data, datalen, compat);
+ return ssh_rsa_sign(key, sigp, lenp, data, datalen, alg);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
@@ -2226,7 +2223,7 @@ sshkey_verify(const struct sshkey *key,
# endif /* OPENSSL_HAS_ECC */
case KEY_RSA_CERT:
case KEY_RSA:
- return ssh_rsa_verify(key, sig, siglen, data, dlen, compat);
+ return ssh_rsa_verify(key, sig, siglen, data, dlen);
#endif /* WITH_OPENSSL */
case KEY_ED25519:
case KEY_ED25519_CERT:
@@ -2243,9 +2240,7 @@ sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
struct sshkey *pk;
int ret = SSH_ERR_INTERNAL_ERROR;
- if (dkp != NULL)
- *dkp = NULL;
-
+ *dkp = NULL;
if ((pk = calloc(1, sizeof(*pk))) == NULL)
return SSH_ERR_ALLOC_FAIL;
pk->type = k->type;
@@ -2462,7 +2457,7 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca)
/* Sign the whole mess */
if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
- sshbuf_len(cert), 0)) != 0)
+ sshbuf_len(cert), NULL, 0)) != 0)
goto out;
/* Append signature and we are done */
@@ -2472,12 +2467,9 @@ sshkey_certify(struct sshkey *k, struct sshkey *ca)
out:
if (ret != 0)
sshbuf_reset(cert);
- if (sig_blob != NULL)
- free(sig_blob);
- if (ca_blob != NULL)
- free(ca_blob);
- if (principals != NULL)
- sshbuf_free(principals);
+ free(sig_blob);
+ free(ca_blob);
+ sshbuf_free(principals);
return ret;
}
@@ -2538,6 +2530,43 @@ sshkey_cert_check_authority(const struct sshkey *k,
return 0;
}
+size_t
+sshkey_format_cert_validity(const struct sshkey_cert *cert, char *s, size_t l)
+{
+ char from[32], to[32], ret[64];
+ time_t tt;
+ struct tm *tm;
+
+ *from = *to = '\0';
+ if (cert->valid_after == 0 &&
+ cert->valid_before == 0xffffffffffffffffULL)
+ return strlcpy(s, "forever", l);
+
+ if (cert->valid_after != 0) {
+ /* XXX revisit INT_MAX in 2038 :) */
+ tt = cert->valid_after > INT_MAX ?
+ INT_MAX : cert->valid_after;
+ tm = localtime(&tt);
+ strftime(from, sizeof(from), "%Y-%m-%dT%H:%M:%S", tm);
+ }
+ if (cert->valid_before != 0xffffffffffffffffULL) {
+ /* XXX revisit INT_MAX in 2038 :) */
+ tt = cert->valid_before > INT_MAX ?
+ INT_MAX : cert->valid_before;
+ tm = localtime(&tt);
+ strftime(to, sizeof(to), "%Y-%m-%dT%H:%M:%S", tm);
+ }
+
+ if (cert->valid_after == 0)
+ snprintf(ret, sizeof(ret), "before %s", to);
+ else if (cert->valid_before == 0xffffffffffffffffULL)
+ snprintf(ret, sizeof(ret), "after %s", from);
+ else
+ snprintf(ret, sizeof(ret), "from %s to %s", from, to);
+
+ return strlcpy(s, ret, l);
+}
+
int
sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
{
@@ -2701,7 +2730,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
goto out;
}
if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
- EC_KEY_get0_public_key(k->ecdsa)) != 0) ||
+ EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
(r = sshkey_ec_validate_private(k->ecdsa)) != 0)
goto out;
break;
@@ -2719,7 +2748,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
goto out;
}
if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
- EC_KEY_get0_public_key(k->ecdsa)) != 0) ||
+ EC_KEY_get0_public_key(k->ecdsa))) != 0 ||
(r = sshkey_ec_validate_private(k->ecdsa)) != 0)
goto out;
break;
@@ -2741,10 +2770,10 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
case KEY_RSA_CERT:
if ((r = sshkey_froms(buf, &k)) != 0 ||
(r = sshkey_add_private(k)) != 0 ||
- (r = sshbuf_get_bignum2(buf, k->rsa->d) != 0) ||
- (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 = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
+ (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)
goto out;
break;
@@ -3431,9 +3460,9 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
/* 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))
+ (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. */
@@ -3454,10 +3483,8 @@ sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
out:
explicit_bzero(&ciphercontext, sizeof(ciphercontext));
explicit_bzero(buf, sizeof(buf));
- if (buffer != NULL)
- sshbuf_free(buffer);
- if (encrypted != NULL)
- sshbuf_free(encrypted);
+ sshbuf_free(buffer);
+ sshbuf_free(encrypted);
return r;
}
@@ -3611,10 +3638,8 @@ sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
pub = NULL;
out:
- if (copy != NULL)
- sshbuf_free(copy);
- if (pub != NULL)
- sshkey_free(pub);
+ sshbuf_free(copy);
+ sshkey_free(pub);
return r;
}
@@ -3726,14 +3751,10 @@ sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
}
out:
explicit_bzero(&ciphercontext, sizeof(ciphercontext));
- if (comment != NULL)
- free(comment);
- if (prv != NULL)
- sshkey_free(prv);
- if (copy != NULL)
- sshbuf_free(copy);
- if (decrypted != NULL)
- sshbuf_free(decrypted);
+ free(comment);
+ sshkey_free(prv);
+ sshbuf_free(copy);
+ sshbuf_free(decrypted);
return r;
}
#endif /* WITH_SSH1 */
@@ -3823,8 +3844,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
BIO_free(bio);
if (pk != NULL)
EVP_PKEY_free(pk);
- if (prv != NULL)
- sshkey_free(prv);
+ sshkey_free(prv);
return r;
}
#endif /* WITH_OPENSSL */
@@ -3833,8 +3853,6 @@ int
sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
const char *passphrase, struct sshkey **keyp, char **commentp)
{
- int r;
-
*keyp = NULL;
if (commentp != NULL)
*commentp = NULL;
@@ -3856,8 +3874,8 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
return sshkey_parse_private2(blob, type, passphrase,
keyp, commentp);
case KEY_UNSPEC:
- if ((r = sshkey_parse_private2(blob, type, passphrase, keyp,
- commentp)) == 0)
+ if (sshkey_parse_private2(blob, type, passphrase, keyp,
+ commentp) == 0)
return 0;
#ifdef WITH_OPENSSL
return sshkey_parse_private_pem_fileblob(blob, type,
@@ -3872,10 +3890,8 @@ sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
int
sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
- const char *filename, struct sshkey **keyp, char **commentp)
+ struct sshkey **keyp, char **commentp)
{
- int r;
-
if (keyp != NULL)
*keyp = NULL;
if (commentp != NULL)
@@ -3883,13 +3899,11 @@ sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
#ifdef WITH_SSH1
/* it's a SSH v1 key if the public key part is readable */
- if ((r = sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL)) == 0) {
+ 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 */
- if ((r = sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
- passphrase, keyp, commentp)) == 0)
- return 0;
- return r;
+ return sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
+ passphrase, keyp, commentp);
}