diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | kex.c | 10 | ||||
-rw-r--r-- | kex.h | 5 | ||||
-rw-r--r-- | kexecdh.c | 14 | ||||
-rw-r--r-- | key.c | 47 | ||||
-rw-r--r-- | key.h | 4 | ||||
-rw-r--r-- | monitor.c | 8 | ||||
-rw-r--r-- | ssh-ecdsa.c | 10 |
8 files changed, 80 insertions, 31 deletions
@@ -49,6 +49,19 @@ | |||
49 | gcc, at least in earlier versions, but this does not forgive your current | 49 | gcc, at least in earlier versions, but this does not forgive your current |
50 | transgressions) seen between zlib and openssl | 50 | transgressions) seen between zlib and openssl |
51 | ok djm | 51 | ok djm |
52 | - djm@cvs.openbsd.org 2010/09/09 10:45:45 | ||
53 | [kex.c kex.h kexecdh.c key.c key.h monitor.c ssh-ecdsa.c] | ||
54 | ECDH/ECDSA compliance fix: these methods vary the hash function they use | ||
55 | (SHA256/384/512) depending on the length of the curve in use. The previous | ||
56 | code incorrectly used SHA256 in all cases. | ||
57 | |||
58 | This fix will cause authentication failure when using 384 or 521-bit curve | ||
59 | keys if one peer hasn't been upgraded and the other has. (256-bit curve | ||
60 | keys work ok). In particular you may need to specify HostkeyAlgorithms | ||
61 | when connecting to a server that has not been upgraded from an upgraded | ||
62 | client. | ||
63 | |||
64 | ok naddy@ | ||
52 | 65 | ||
53 | 20100831 | 66 | 20100831 |
54 | - OpenBSD CVS Sync | 67 | - OpenBSD CVS Sync |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.c,v 1.84 2010/08/31 11:54:45 djm Exp $ */ | 1 | /* $OpenBSD: kex.c,v 1.85 2010/09/09 10:45:45 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 | * | 4 | * |
@@ -325,10 +325,10 @@ choose_kex(Kex *k, char *client, char *server) | |||
325 | } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) { | 325 | } else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) { |
326 | k->kex_type = KEX_DH_GEX_SHA256; | 326 | k->kex_type = KEX_DH_GEX_SHA256; |
327 | k->evp_md = evp_ssh_sha256(); | 327 | k->evp_md = evp_ssh_sha256(); |
328 | } else if (strncmp(k->name, KEX_ECDH_SHA256, | 328 | } else if (strncmp(k->name, KEX_ECDH_SHA2_STEM, |
329 | sizeof(KEX_ECDH_SHA256) - 1) == 0) { | 329 | sizeof(KEX_ECDH_SHA2_STEM) - 1) == 0) { |
330 | k->kex_type = KEX_ECDH_SHA2; | 330 | k->kex_type = KEX_ECDH_SHA2; |
331 | k->evp_md = evp_ssh_sha256(); | 331 | k->evp_md = kex_ecdh_name_to_evpmd(k->name); |
332 | #endif | 332 | #endif |
333 | } else | 333 | } else |
334 | fatal("bad kex alg %s", k->name); | 334 | fatal("bad kex alg %s", k->name); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kex.h,v 1.50 2010/08/31 11:54:45 djm Exp $ */ | 1 | /* $OpenBSD: kex.h,v 1.51 2010/09/09 10:45:45 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. |
@@ -39,7 +39,7 @@ | |||
39 | #define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" | 39 | #define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256" |
40 | #define KEX_RESUME "resume@appgate.com" | 40 | #define KEX_RESUME "resume@appgate.com" |
41 | /* The following represents the family of ECDH methods */ | 41 | /* The following represents the family of ECDH methods */ |
42 | #define KEX_ECDH_SHA256 "ecdh-sha2-" | 42 | #define KEX_ECDH_SHA2_STEM "ecdh-sha2-" |
43 | 43 | ||
44 | #define COMP_NONE 0 | 44 | #define COMP_NONE 0 |
45 | #define COMP_ZLIB 1 | 45 | #define COMP_ZLIB 1 |
@@ -165,6 +165,7 @@ kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int, | |||
165 | const BIGNUM *, u_char **, u_int *); | 165 | const BIGNUM *, u_char **, u_int *); |
166 | 166 | ||
167 | int kex_ecdh_name_to_nid(const char *); | 167 | int kex_ecdh_name_to_nid(const char *); |
168 | const EVP_MD *kex_ecdh_name_to_evpmd(const char *); | ||
168 | 169 | ||
169 | void | 170 | void |
170 | derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); | 171 | derive_ssh1_session_id(BIGNUM *, BIGNUM *, u_int8_t[8], u_int8_t[16]); |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: kexecdh.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */ | 1 | /* $OpenBSD: kexecdh.c,v 1.2 2010/09/09 10:45:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2001 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2010 Damien Miller. All rights reserved. |
@@ -48,15 +48,23 @@ kex_ecdh_name_to_nid(const char *kexname) | |||
48 | { | 48 | { |
49 | int ret; | 49 | int ret; |
50 | 50 | ||
51 | if (strlen(kexname) < sizeof(KEX_ECDH_SHA256) - 1) | 51 | if (strlen(kexname) < sizeof(KEX_ECDH_SHA2_STEM) - 1) |
52 | fatal("%s: kexname too short \"%s\"", __func__, kexname); | 52 | fatal("%s: kexname too short \"%s\"", __func__, kexname); |
53 | ret = key_curve_name_to_nid(kexname + sizeof(KEX_ECDH_SHA256) - 1); | 53 | ret = key_curve_name_to_nid(kexname + sizeof(KEX_ECDH_SHA2_STEM) - 1); |
54 | if (ret == -1) | 54 | if (ret == -1) |
55 | fatal("%s: unsupported curve negotiated \"%s\"", __func__, | 55 | fatal("%s: unsupported curve negotiated \"%s\"", __func__, |
56 | kexname); | 56 | kexname); |
57 | return ret; | 57 | return ret; |
58 | } | 58 | } |
59 | 59 | ||
60 | const EVP_MD * | ||
61 | kex_ecdh_name_to_evpmd(const char *kexname) | ||
62 | { | ||
63 | int nid = kex_ecdh_name_to_nid(kexname); | ||
64 | |||
65 | return key_ec_nid_to_evpmd(nid); | ||
66 | } | ||
67 | |||
60 | void | 68 | void |
61 | kex_ecdh_hash( | 69 | kex_ecdh_hash( |
62 | const EVP_MD *evp_md, | 70 | const EVP_MD *evp_md, |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.c,v 1.92 2010/08/31 11:54:45 djm Exp $ */ | 1 | /* $OpenBSD: key.c,v 1.93 2010/09/09 10:45:45 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 |
@@ -978,17 +978,7 @@ key_size(const Key *k) | |||
978 | return BN_num_bits(k->dsa->p); | 978 | return BN_num_bits(k->dsa->p); |
979 | case KEY_ECDSA: | 979 | case KEY_ECDSA: |
980 | case KEY_ECDSA_CERT: | 980 | case KEY_ECDSA_CERT: |
981 | switch (k->ecdsa_nid) { | 981 | return key_curve_nid_to_bits(k->ecdsa_nid); |
982 | case NID_X9_62_prime256v1: | ||
983 | return 256; | ||
984 | case NID_secp384r1: | ||
985 | return 384; | ||
986 | case NID_secp521r1: | ||
987 | return 521; | ||
988 | default: | ||
989 | break; | ||
990 | } | ||
991 | break; | ||
992 | } | 982 | } |
993 | return 0; | 983 | return 0; |
994 | } | 984 | } |
@@ -1961,6 +1951,7 @@ key_cert_is_legacy(Key *k) | |||
1961 | } | 1951 | } |
1962 | } | 1952 | } |
1963 | 1953 | ||
1954 | /* XXX: these are really begging for a table-driven approach */ | ||
1964 | int | 1955 | int |
1965 | key_curve_name_to_nid(const char *name) | 1956 | key_curve_name_to_nid(const char *name) |
1966 | { | 1957 | { |
@@ -1975,6 +1966,22 @@ key_curve_name_to_nid(const char *name) | |||
1975 | return -1; | 1966 | return -1; |
1976 | } | 1967 | } |
1977 | 1968 | ||
1969 | u_int | ||
1970 | key_curve_nid_to_bits(int nid) | ||
1971 | { | ||
1972 | switch (nid) { | ||
1973 | case NID_X9_62_prime256v1: | ||
1974 | return 256; | ||
1975 | case NID_secp384r1: | ||
1976 | return 384; | ||
1977 | case NID_secp521r1: | ||
1978 | return 521; | ||
1979 | default: | ||
1980 | error("%s: unsupported EC curve nid %d", __func__, nid); | ||
1981 | return 0; | ||
1982 | } | ||
1983 | } | ||
1984 | |||
1978 | const char * | 1985 | const char * |
1979 | key_curve_nid_to_name(int nid) | 1986 | key_curve_nid_to_name(int nid) |
1980 | { | 1987 | { |
@@ -1989,6 +1996,22 @@ key_curve_nid_to_name(int nid) | |||
1989 | return NULL; | 1996 | return NULL; |
1990 | } | 1997 | } |
1991 | 1998 | ||
1999 | const EVP_MD * | ||
2000 | key_ec_nid_to_evpmd(int nid) | ||
2001 | { | ||
2002 | int kbits = key_curve_nid_to_bits(nid); | ||
2003 | |||
2004 | if (kbits == 0) | ||
2005 | fatal("%s: invalid nid %d", __func__, nid); | ||
2006 | /* RFC5656 section 6.2.1 */ | ||
2007 | if (kbits <= 256) | ||
2008 | return EVP_sha256(); | ||
2009 | else if (kbits <= 384) | ||
2010 | return EVP_sha384(); | ||
2011 | else | ||
2012 | return EVP_sha512(); | ||
2013 | } | ||
2014 | |||
1992 | int | 2015 | int |
1993 | key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) | 2016 | key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) |
1994 | { | 2017 | { |
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: key.h,v 1.31 2010/08/31 11:54:45 djm Exp $ */ | 1 | /* $OpenBSD: key.h,v 1.32 2010/09/09 10:45:45 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. |
@@ -112,8 +112,10 @@ int key_cert_is_legacy(Key *); | |||
112 | int key_ecdsa_nid_from_name(const char *); | 112 | int key_ecdsa_nid_from_name(const char *); |
113 | int key_curve_name_to_nid(const char *); | 113 | int key_curve_name_to_nid(const char *); |
114 | const char * key_curve_nid_to_name(int); | 114 | const char * key_curve_nid_to_name(int); |
115 | u_int key_curve_nid_to_bits(int); | ||
115 | int key_ecdsa_bits_to_nid(int); | 116 | int key_ecdsa_bits_to_nid(int); |
116 | int key_ecdsa_group_to_nid(const EC_GROUP *); | 117 | int key_ecdsa_group_to_nid(const EC_GROUP *); |
118 | const EVP_MD * key_ec_nid_to_evpmd(int nid); | ||
117 | int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); | 119 | int key_ec_validate_public(const EC_GROUP *, const EC_POINT *); |
118 | int key_ec_validate_private(const EC_KEY *); | 120 | int key_ec_validate_private(const EC_KEY *); |
119 | 121 | ||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: monitor.c,v 1.109 2010/08/31 11:54:45 djm Exp $ */ | 1 | /* $OpenBSD: monitor.c,v 1.110 2010/09/09 10:45:45 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> | 3 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> | 4 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
@@ -590,10 +590,10 @@ mm_answer_sign(int sock, Buffer *m) | |||
590 | p = buffer_get_string(m, &datlen); | 590 | p = buffer_get_string(m, &datlen); |
591 | 591 | ||
592 | /* | 592 | /* |
593 | * Supported KEX types will only return SHA1 (20 byte) or | 593 | * Supported KEX types use SHA1 (20 bytes), SHA256 (32 bytes), |
594 | * SHA256 (32 byte) hashes | 594 | * SHA384 (48 bytes) and SHA512 (64 bytes). |
595 | */ | 595 | */ |
596 | if (datlen != 20 && datlen != 32) | 596 | if (datlen != 20 && datlen != 32 && datlen != 48 && datlen != 64) |
597 | fatal("%s: data length incorrect: %u", __func__, datlen); | 597 | fatal("%s: data length incorrect: %u", __func__, datlen); |
598 | 598 | ||
599 | /* save session id, it will be passed on the first call */ | 599 | /* save session id, it will be passed on the first call */ |
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c index 0627ee5c0..5c4ce2311 100644 --- a/ssh-ecdsa.c +++ b/ssh-ecdsa.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD$ */ | 1 | /* $OpenBSD: ssh-ecdsa.c,v 1.4 2010/09/10 01:04:10 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2010 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2010 Damien Miller. All rights reserved. |
@@ -46,7 +46,7 @@ ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, | |||
46 | const u_char *data, u_int datalen) | 46 | const u_char *data, u_int datalen) |
47 | { | 47 | { |
48 | ECDSA_SIG *sig; | 48 | ECDSA_SIG *sig; |
49 | const EVP_MD *evp_md = EVP_sha256(); | 49 | const EVP_MD *evp_md; |
50 | EVP_MD_CTX md; | 50 | EVP_MD_CTX md; |
51 | u_char digest[EVP_MAX_MD_SIZE]; | 51 | u_char digest[EVP_MAX_MD_SIZE]; |
52 | u_int len, dlen; | 52 | u_int len, dlen; |
@@ -57,6 +57,7 @@ ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, | |||
57 | error("%s: no ECDSA key", __func__); | 57 | error("%s: no ECDSA key", __func__); |
58 | return -1; | 58 | return -1; |
59 | } | 59 | } |
60 | evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid); | ||
60 | EVP_DigestInit(&md, evp_md); | 61 | EVP_DigestInit(&md, evp_md); |
61 | EVP_DigestUpdate(&md, data, datalen); | 62 | EVP_DigestUpdate(&md, data, datalen); |
62 | EVP_DigestFinal(&md, digest, &dlen); | 63 | EVP_DigestFinal(&md, digest, &dlen); |
@@ -94,21 +95,22 @@ ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, | |||
94 | const u_char *data, u_int datalen) | 95 | const u_char *data, u_int datalen) |
95 | { | 96 | { |
96 | ECDSA_SIG *sig; | 97 | ECDSA_SIG *sig; |
97 | const EVP_MD *evp_md = EVP_sha256(); | 98 | const EVP_MD *evp_md; |
98 | EVP_MD_CTX md; | 99 | EVP_MD_CTX md; |
99 | u_char digest[EVP_MAX_MD_SIZE], *sigblob; | 100 | u_char digest[EVP_MAX_MD_SIZE], *sigblob; |
100 | u_int len, dlen; | 101 | u_int len, dlen; |
101 | int rlen, ret; | 102 | int rlen, ret; |
102 | Buffer b, bb; | 103 | Buffer b, bb; |
104 | char *ktype; | ||
103 | 105 | ||
104 | if (key == NULL || key->ecdsa == NULL || | 106 | if (key == NULL || key->ecdsa == NULL || |
105 | (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) { | 107 | (key->type != KEY_ECDSA && key->type != KEY_ECDSA_CERT)) { |
106 | error("%s: no ECDSA key", __func__); | 108 | error("%s: no ECDSA key", __func__); |
107 | return -1; | 109 | return -1; |
108 | } | 110 | } |
111 | evp_md = key_ec_nid_to_evpmd(key->ecdsa_nid); | ||
109 | 112 | ||
110 | /* fetch signature */ | 113 | /* fetch signature */ |
111 | char *ktype; | ||
112 | buffer_init(&b); | 114 | buffer_init(&b); |
113 | buffer_append(&b, signature, signaturelen); | 115 | buffer_append(&b, signature, signaturelen); |
114 | ktype = buffer_get_string(&b, NULL); | 116 | ktype = buffer_get_string(&b, NULL); |