summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2012-06-20 21:51:11 +1000
committerDamien Miller <djm@mindrot.org>2012-06-20 21:51:11 +1000
commit3bde12aeef60c9e1221316aff1fe1aca78eca027 (patch)
tree391e98a1c7a72c4f02afb0407dbcc9a4ef6174aa
parentac58ce86e6f4dcb245d5e1aa28a5c7a9f4a56072 (diff)
downloadopenssh-git-3bde12aeef60c9e1221316aff1fe1aca78eca027.tar.gz
- djm@cvs.openbsd.org 2012/05/23 03:28:28
[dns.c dns.h key.c key.h ssh-keygen.c] add support for RFC6594 SSHFP DNS records for ECDSA key types. patch from bugzilla-m67 AT nulld.me in bz#1978; ok + tweak markus@
-rw-r--r--ChangeLog4
-rw-r--r--dns.c103
-rw-r--r--dns.h15
-rw-r--r--key.c5
-rw-r--r--key.h5
-rw-r--r--ssh-keygen.c4
6 files changed, 92 insertions, 44 deletions
diff --git a/ChangeLog b/ChangeLog
index 419640c2..f0356d32 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,6 +16,10 @@
[mux.c]
fix double-free in new session handler
NB. Id sync only
+ - djm@cvs.openbsd.org 2012/05/23 03:28:28
+ [dns.c dns.h key.c key.h ssh-keygen.c]
+ add support for RFC6594 SSHFP DNS records for ECDSA key types.
+ patch from bugzilla-m67 AT nulld.me in bz#1978; ok + tweak markus@
20120519
- (dtucker) [configure.ac] bz#2010: fix non-portable shell construct. Patch
diff --git a/dns.c b/dns.c
index 131cb3d8..9e3084ba 100644
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 djm Exp $ */
+/* $OpenBSD: dns.c,v 1.28 2012/05/23 03:28:28 djm Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -78,27 +78,46 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
u_char **digest, u_int *digest_len, Key *key)
{
int success = 0;
+ enum fp_type fp_type = 0;
switch (key->type) {
case KEY_RSA:
*algorithm = SSHFP_KEY_RSA;
+ if (!*digest_type)
+ *digest_type = SSHFP_HASH_SHA1;
break;
case KEY_DSA:
*algorithm = SSHFP_KEY_DSA;
+ if (!*digest_type)
+ *digest_type = SSHFP_HASH_SHA1;
+ break;
+ case KEY_ECDSA:
+ *algorithm = SSHFP_KEY_ECDSA;
+ if (!*digest_type)
+ *digest_type = SSHFP_HASH_SHA256;
break;
- /* XXX KEY_ECDSA */
default:
*algorithm = SSHFP_KEY_RESERVED; /* 0 */
+ *digest_type = SSHFP_HASH_RESERVED; /* 0 */
+ }
+
+ switch (*digest_type) {
+ case SSHFP_HASH_SHA1:
+ fp_type = SSH_FP_SHA1;
+ break;
+ case SSHFP_HASH_SHA256:
+ fp_type = SSH_FP_SHA256;
+ break;
+ default:
+ *digest_type = SSHFP_HASH_RESERVED; /* 0 */
}
- if (*algorithm) {
- *digest_type = SSHFP_HASH_SHA1;
- *digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len);
+ if (*algorithm && *digest_type) {
+ *digest = key_fingerprint_raw(key, fp_type, digest_len);
if (*digest == NULL)
fatal("dns_read_key: null from key_fingerprint_raw()");
success = 1;
} else {
- *digest_type = SSHFP_HASH_RESERVED;
*digest = NULL;
*digest_len = 0;
success = 0;
@@ -180,7 +199,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
struct rrsetinfo *fingerprints = NULL;
u_int8_t hostkey_algorithm;
- u_int8_t hostkey_digest_type;
+ u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED;
u_char *hostkey_digest;
u_int hostkey_digest_len;
@@ -216,7 +235,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
fingerprints->rri_nrdatas);
}
- /* Initialize host key parameters */
+ /* Initialize default host key parameters */
if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
&hostkey_digest, &hostkey_digest_len, hostkey)) {
error("Error calculating host key fingerprint.");
@@ -240,16 +259,27 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
continue;
}
+ if (hostkey_digest_type != dnskey_digest_type) {
+ hostkey_digest_type = dnskey_digest_type;
+ xfree(hostkey_digest);
+
+ /* Initialize host key parameters */
+ if (!dns_read_key(&hostkey_algorithm,
+ &hostkey_digest_type, &hostkey_digest,
+ &hostkey_digest_len, hostkey)) {
+ error("Error calculating key fingerprint.");
+ freerrset(fingerprints);
+ return -1;
+ }
+ }
+
/* Check if the current key is the same as the given key */
if (hostkey_algorithm == dnskey_algorithm &&
hostkey_digest_type == dnskey_digest_type) {
-
if (hostkey_digest_len == dnskey_digest_len &&
- memcmp(hostkey_digest, dnskey_digest,
- hostkey_digest_len) == 0) {
-
+ timingsafe_bcmp(hostkey_digest, dnskey_digest,
+ hostkey_digest_len) == 0)
*flags |= DNS_VERIFY_MATCH;
- }
}
xfree(dnskey_digest);
}
@@ -275,31 +305,36 @@ int
export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
{
u_int8_t rdata_pubkey_algorithm = 0;
- u_int8_t rdata_digest_type = SSHFP_HASH_SHA1;
+ u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED;
+ u_int8_t dtype;
u_char *rdata_digest;
- u_int rdata_digest_len;
-
- u_int i;
+ u_int i, rdata_digest_len;
int success = 0;
- if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
- &rdata_digest, &rdata_digest_len, key)) {
-
- if (generic)
- fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname,
- DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len,
- rdata_pubkey_algorithm, rdata_digest_type);
- else
- fprintf(f, "%s IN SSHFP %d %d ", hostname,
- rdata_pubkey_algorithm, rdata_digest_type);
+ for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) {
+ rdata_digest_type = dtype;
+ if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
+ &rdata_digest, &rdata_digest_len, key)) {
+ if (generic) {
+ fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ",
+ hostname, DNS_RDATATYPE_SSHFP,
+ 2 + rdata_digest_len,
+ rdata_pubkey_algorithm, rdata_digest_type);
+ } else {
+ fprintf(f, "%s IN SSHFP %d %d ", hostname,
+ rdata_pubkey_algorithm, rdata_digest_type);
+ }
+ for (i = 0; i < rdata_digest_len; i++)
+ fprintf(f, "%02x", rdata_digest[i]);
+ fprintf(f, "\n");
+ xfree(rdata_digest); /* from key_fingerprint_raw() */
+ success = 1;
+ }
+ }
- for (i = 0; i < rdata_digest_len; i++)
- fprintf(f, "%02x", rdata_digest[i]);
- fprintf(f, "\n");
- xfree(rdata_digest); /* from key_fingerprint_raw() */
- success = 1;
- } else {
- error("export_dns_rr: unsupported algorithm");
+ /* No SSHFP record was generated at all */
+ if (success == 0) {
+ error("%s: unsupported algorithm and/or digest_type", __func__);
}
return success;
diff --git a/dns.h b/dns.h
index 90cfd7b9..d5f42817 100644
--- a/dns.h
+++ b/dns.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.h,v 1.11 2010/02/26 20:29:54 djm Exp $ */
+/* $OpenBSD: dns.h,v 1.12 2012/05/23 03:28:28 djm Exp $ */
/*
* Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -29,14 +29,17 @@
#define DNS_H
enum sshfp_types {
- SSHFP_KEY_RESERVED,
- SSHFP_KEY_RSA,
- SSHFP_KEY_DSA
+ SSHFP_KEY_RESERVED = 0,
+ SSHFP_KEY_RSA = 1,
+ SSHFP_KEY_DSA = 2,
+ SSHFP_KEY_ECDSA = 3
};
enum sshfp_hashes {
- SSHFP_HASH_RESERVED,
- SSHFP_HASH_SHA1
+ SSHFP_HASH_RESERVED = 0,
+ SSHFP_HASH_SHA1 = 1,
+ SSHFP_HASH_SHA256 = 2,
+ SSHFP_HASH_MAX = 3
};
#define DNS_RDATACLASS_IN 1
diff --git a/key.c b/key.c
index 5cc4132c..8ef0b7e3 100644
--- a/key.c
+++ b/key.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.c,v 1.98 2011/10/18 04:58:26 djm Exp $ */
+/* $OpenBSD: key.c,v 1.99 2012/05/23 03:28:28 djm Exp $ */
/*
* read_bignum():
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -342,6 +342,9 @@ key_fingerprint_raw(Key *k, enum fp_type dgst_type, u_int *dgst_raw_length)
case SSH_FP_SHA1:
md = EVP_sha1();
break;
+ case SSH_FP_SHA256:
+ md = EVP_sha256();
+ break;
default:
fatal("key_fingerprint_raw: bad digest type %d",
dgst_type);
diff --git a/key.h b/key.h
index ec5ac5eb..39e5577f 100644
--- a/key.h
+++ b/key.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: key.h,v 1.33 2010/10/28 11:22:09 djm Exp $ */
+/* $OpenBSD: key.h,v 1.34 2012/05/23 03:28:28 djm Exp $ */
/*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -48,7 +48,8 @@ enum types {
};
enum fp_type {
SSH_FP_SHA1,
- SSH_FP_MD5
+ SSH_FP_MD5,
+ SSH_FP_SHA256
};
enum fp_rep {
SSH_FP_HEX,
diff --git a/ssh-keygen.c b/ssh-keygen.c
index c5130c86..9407321d 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssh-keygen.c,v 1.213 2012/02/29 11:21:26 djm Exp $ */
+/* $OpenBSD: ssh-keygen.c,v 1.214 2012/05/23 03:28:28 djm Exp $ */
/*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2194,6 +2194,8 @@ main(int argc, char **argv)
_PATH_HOST_RSA_KEY_FILE, rr_hostname);
n += do_print_resource_record(pw,
_PATH_HOST_DSA_KEY_FILE, rr_hostname);
+ n += do_print_resource_record(pw,
+ _PATH_HOST_ECDSA_KEY_FILE, rr_hostname);
if (n == 0)
fatal("no keys found.");