summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 419640c2a..f0356d32e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -16,6 +16,10 @@
16 [mux.c] 16 [mux.c]
17 fix double-free in new session handler 17 fix double-free in new session handler
18 NB. Id sync only 18 NB. Id sync only
19 - djm@cvs.openbsd.org 2012/05/23 03:28:28
20 [dns.c dns.h key.c key.h ssh-keygen.c]
21 add support for RFC6594 SSHFP DNS records for ECDSA key types.
22 patch from bugzilla-m67 AT nulld.me in bz#1978; ok + tweak markus@
19 23
2020120519 2420120519
21 - (dtucker) [configure.ac] bz#2010: fix non-portable shell construct. Patch 25 - (dtucker) [configure.ac] bz#2010: fix non-portable shell construct. Patch
diff --git a/dns.c b/dns.c
index 131cb3d8b..9e3084ba5 100644
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: dns.c,v 1.27 2010/08/31 11:54:45 djm Exp $ */ 1/* $OpenBSD: dns.c,v 1.28 2012/05/23 03:28:28 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wesley Griffin. All rights reserved. 4 * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -78,27 +78,46 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
78 u_char **digest, u_int *digest_len, Key *key) 78 u_char **digest, u_int *digest_len, Key *key)
79{ 79{
80 int success = 0; 80 int success = 0;
81 enum fp_type fp_type = 0;
81 82
82 switch (key->type) { 83 switch (key->type) {
83 case KEY_RSA: 84 case KEY_RSA:
84 *algorithm = SSHFP_KEY_RSA; 85 *algorithm = SSHFP_KEY_RSA;
86 if (!*digest_type)
87 *digest_type = SSHFP_HASH_SHA1;
85 break; 88 break;
86 case KEY_DSA: 89 case KEY_DSA:
87 *algorithm = SSHFP_KEY_DSA; 90 *algorithm = SSHFP_KEY_DSA;
91 if (!*digest_type)
92 *digest_type = SSHFP_HASH_SHA1;
93 break;
94 case KEY_ECDSA:
95 *algorithm = SSHFP_KEY_ECDSA;
96 if (!*digest_type)
97 *digest_type = SSHFP_HASH_SHA256;
88 break; 98 break;
89 /* XXX KEY_ECDSA */
90 default: 99 default:
91 *algorithm = SSHFP_KEY_RESERVED; /* 0 */ 100 *algorithm = SSHFP_KEY_RESERVED; /* 0 */
101 *digest_type = SSHFP_HASH_RESERVED; /* 0 */
102 }
103
104 switch (*digest_type) {
105 case SSHFP_HASH_SHA1:
106 fp_type = SSH_FP_SHA1;
107 break;
108 case SSHFP_HASH_SHA256:
109 fp_type = SSH_FP_SHA256;
110 break;
111 default:
112 *digest_type = SSHFP_HASH_RESERVED; /* 0 */
92 } 113 }
93 114
94 if (*algorithm) { 115 if (*algorithm && *digest_type) {
95 *digest_type = SSHFP_HASH_SHA1; 116 *digest = key_fingerprint_raw(key, fp_type, digest_len);
96 *digest = key_fingerprint_raw(key, SSH_FP_SHA1, digest_len);
97 if (*digest == NULL) 117 if (*digest == NULL)
98 fatal("dns_read_key: null from key_fingerprint_raw()"); 118 fatal("dns_read_key: null from key_fingerprint_raw()");
99 success = 1; 119 success = 1;
100 } else { 120 } else {
101 *digest_type = SSHFP_HASH_RESERVED;
102 *digest = NULL; 121 *digest = NULL;
103 *digest_len = 0; 122 *digest_len = 0;
104 success = 0; 123 success = 0;
@@ -180,7 +199,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
180 struct rrsetinfo *fingerprints = NULL; 199 struct rrsetinfo *fingerprints = NULL;
181 200
182 u_int8_t hostkey_algorithm; 201 u_int8_t hostkey_algorithm;
183 u_int8_t hostkey_digest_type; 202 u_int8_t hostkey_digest_type = SSHFP_HASH_RESERVED;
184 u_char *hostkey_digest; 203 u_char *hostkey_digest;
185 u_int hostkey_digest_len; 204 u_int hostkey_digest_len;
186 205
@@ -216,7 +235,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
216 fingerprints->rri_nrdatas); 235 fingerprints->rri_nrdatas);
217 } 236 }
218 237
219 /* Initialize host key parameters */ 238 /* Initialize default host key parameters */
220 if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type, 239 if (!dns_read_key(&hostkey_algorithm, &hostkey_digest_type,
221 &hostkey_digest, &hostkey_digest_len, hostkey)) { 240 &hostkey_digest, &hostkey_digest_len, hostkey)) {
222 error("Error calculating host key fingerprint."); 241 error("Error calculating host key fingerprint.");
@@ -240,16 +259,27 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
240 continue; 259 continue;
241 } 260 }
242 261
262 if (hostkey_digest_type != dnskey_digest_type) {
263 hostkey_digest_type = dnskey_digest_type;
264 xfree(hostkey_digest);
265
266 /* Initialize host key parameters */
267 if (!dns_read_key(&hostkey_algorithm,
268 &hostkey_digest_type, &hostkey_digest,
269 &hostkey_digest_len, hostkey)) {
270 error("Error calculating key fingerprint.");
271 freerrset(fingerprints);
272 return -1;
273 }
274 }
275
243 /* Check if the current key is the same as the given key */ 276 /* Check if the current key is the same as the given key */
244 if (hostkey_algorithm == dnskey_algorithm && 277 if (hostkey_algorithm == dnskey_algorithm &&
245 hostkey_digest_type == dnskey_digest_type) { 278 hostkey_digest_type == dnskey_digest_type) {
246
247 if (hostkey_digest_len == dnskey_digest_len && 279 if (hostkey_digest_len == dnskey_digest_len &&
248 memcmp(hostkey_digest, dnskey_digest, 280 timingsafe_bcmp(hostkey_digest, dnskey_digest,
249 hostkey_digest_len) == 0) { 281 hostkey_digest_len) == 0)
250
251 *flags |= DNS_VERIFY_MATCH; 282 *flags |= DNS_VERIFY_MATCH;
252 }
253 } 283 }
254 xfree(dnskey_digest); 284 xfree(dnskey_digest);
255 } 285 }
@@ -275,31 +305,36 @@ int
275export_dns_rr(const char *hostname, Key *key, FILE *f, int generic) 305export_dns_rr(const char *hostname, Key *key, FILE *f, int generic)
276{ 306{
277 u_int8_t rdata_pubkey_algorithm = 0; 307 u_int8_t rdata_pubkey_algorithm = 0;
278 u_int8_t rdata_digest_type = SSHFP_HASH_SHA1; 308 u_int8_t rdata_digest_type = SSHFP_HASH_RESERVED;
309 u_int8_t dtype;
279 u_char *rdata_digest; 310 u_char *rdata_digest;
280 u_int rdata_digest_len; 311 u_int i, rdata_digest_len;
281
282 u_int i;
283 int success = 0; 312 int success = 0;
284 313
285 if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type, 314 for (dtype = SSHFP_HASH_SHA1; dtype < SSHFP_HASH_MAX; dtype++) {
286 &rdata_digest, &rdata_digest_len, key)) { 315 rdata_digest_type = dtype;
287 316 if (dns_read_key(&rdata_pubkey_algorithm, &rdata_digest_type,
288 if (generic) 317 &rdata_digest, &rdata_digest_len, key)) {
289 fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ", hostname, 318 if (generic) {
290 DNS_RDATATYPE_SSHFP, 2 + rdata_digest_len, 319 fprintf(f, "%s IN TYPE%d \\# %d %02x %02x ",
291 rdata_pubkey_algorithm, rdata_digest_type); 320 hostname, DNS_RDATATYPE_SSHFP,
292 else 321 2 + rdata_digest_len,
293 fprintf(f, "%s IN SSHFP %d %d ", hostname, 322 rdata_pubkey_algorithm, rdata_digest_type);
294 rdata_pubkey_algorithm, rdata_digest_type); 323 } else {
324 fprintf(f, "%s IN SSHFP %d %d ", hostname,
325 rdata_pubkey_algorithm, rdata_digest_type);
326 }
327 for (i = 0; i < rdata_digest_len; i++)
328 fprintf(f, "%02x", rdata_digest[i]);
329 fprintf(f, "\n");
330 xfree(rdata_digest); /* from key_fingerprint_raw() */
331 success = 1;
332 }
333 }
295 334
296 for (i = 0; i < rdata_digest_len; i++) 335 /* No SSHFP record was generated at all */
297 fprintf(f, "%02x", rdata_digest[i]); 336 if (success == 0) {
298 fprintf(f, "\n"); 337 error("%s: unsupported algorithm and/or digest_type", __func__);
299 xfree(rdata_digest); /* from key_fingerprint_raw() */
300 success = 1;
301 } else {
302 error("export_dns_rr: unsupported algorithm");
303 } 338 }
304 339
305 return success; 340 return success;
diff --git a/dns.h b/dns.h
index 90cfd7b92..d5f428177 100644
--- a/dns.h
+++ b/dns.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: dns.h,v 1.11 2010/02/26 20:29:54 djm Exp $ */ 1/* $OpenBSD: dns.h,v 1.12 2012/05/23 03:28:28 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wesley Griffin. All rights reserved. 4 * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -29,14 +29,17 @@
29#define DNS_H 29#define DNS_H
30 30
31enum sshfp_types { 31enum sshfp_types {
32 SSHFP_KEY_RESERVED, 32 SSHFP_KEY_RESERVED = 0,
33 SSHFP_KEY_RSA, 33 SSHFP_KEY_RSA = 1,
34 SSHFP_KEY_DSA 34 SSHFP_KEY_DSA = 2,
35 SSHFP_KEY_ECDSA = 3
35}; 36};
36 37
37enum sshfp_hashes { 38enum sshfp_hashes {
38 SSHFP_HASH_RESERVED, 39 SSHFP_HASH_RESERVED = 0,
39 SSHFP_HASH_SHA1 40 SSHFP_HASH_SHA1 = 1,
41 SSHFP_HASH_SHA256 = 2,
42 SSHFP_HASH_MAX = 3
40}; 43};
41 44
42#define DNS_RDATACLASS_IN 1 45#define DNS_RDATACLASS_IN 1
diff --git a/key.c b/key.c
index 5cc4132c0..8ef0b7e3c 100644
--- a/key.c
+++ b/key.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.c,v 1.98 2011/10/18 04:58:26 djm Exp $ */ 1/* $OpenBSD: key.c,v 1.99 2012/05/23 03:28:28 djm Exp $ */
2/* 2/*
3 * read_bignum(): 3 * read_bignum():
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * 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)
342 case SSH_FP_SHA1: 342 case SSH_FP_SHA1:
343 md = EVP_sha1(); 343 md = EVP_sha1();
344 break; 344 break;
345 case SSH_FP_SHA256:
346 md = EVP_sha256();
347 break;
345 default: 348 default:
346 fatal("key_fingerprint_raw: bad digest type %d", 349 fatal("key_fingerprint_raw: bad digest type %d",
347 dgst_type); 350 dgst_type);
diff --git a/key.h b/key.h
index ec5ac5eb8..39e5577f6 100644
--- a/key.h
+++ b/key.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.h,v 1.33 2010/10/28 11:22:09 djm Exp $ */ 1/* $OpenBSD: key.h,v 1.34 2012/05/23 03:28:28 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -48,7 +48,8 @@ enum types {
48}; 48};
49enum fp_type { 49enum fp_type {
50 SSH_FP_SHA1, 50 SSH_FP_SHA1,
51 SSH_FP_MD5 51 SSH_FP_MD5,
52 SSH_FP_SHA256
52}; 53};
53enum fp_rep { 54enum fp_rep {
54 SSH_FP_HEX, 55 SSH_FP_HEX,
diff --git a/ssh-keygen.c b/ssh-keygen.c
index c5130c86e..9407321d5 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.213 2012/02/29 11:21:26 djm Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.214 2012/05/23 03:28:28 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -2194,6 +2194,8 @@ main(int argc, char **argv)
2194 _PATH_HOST_RSA_KEY_FILE, rr_hostname); 2194 _PATH_HOST_RSA_KEY_FILE, rr_hostname);
2195 n += do_print_resource_record(pw, 2195 n += do_print_resource_record(pw,
2196 _PATH_HOST_DSA_KEY_FILE, rr_hostname); 2196 _PATH_HOST_DSA_KEY_FILE, rr_hostname);
2197 n += do_print_resource_record(pw,
2198 _PATH_HOST_ECDSA_KEY_FILE, rr_hostname);
2197 2199
2198 if (n == 0) 2200 if (n == 0)
2199 fatal("no keys found."); 2201 fatal("no keys found.");