version 1.88, 2013/01/08 18:49:04 |
version 1.89, 2013/04/19 01:06:50 |
|
|
static void kex_kexinit_finish(Kex *); |
static void kex_kexinit_finish(Kex *); |
static void kex_choose_conf(Kex *); |
static void kex_choose_conf(Kex *); |
|
|
|
struct kexalg { |
|
char *name; |
|
int type; |
|
int ec_nid; |
|
const EVP_MD *(*mdfunc)(void); |
|
}; |
|
static const struct kexalg kexalgs[] = { |
|
{ KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 }, |
|
{ KEX_DH14, KEX_DH_GRP14_SHA1, 0, EVP_sha1 }, |
|
{ KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, EVP_sha1 }, |
|
{ KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 }, |
|
{ KEX_DH1, KEX_DH_GRP1_SHA1, 0, EVP_sha1 }, |
|
{ KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, NID_X9_62_prime256v1, EVP_sha256 }, |
|
{ KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, EVP_sha384 }, |
|
{ KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, EVP_sha512 }, |
|
{ NULL, -1, -1, NULL}, |
|
}; |
|
|
|
char * |
|
kex_alg_list(void) |
|
{ |
|
char *ret = NULL; |
|
size_t nlen, rlen = 0; |
|
const struct kexalg *k; |
|
|
|
for (k = kexalgs; k->name != NULL; k++) { |
|
if (ret != NULL) |
|
ret[rlen++] = '\n'; |
|
nlen = strlen(k->name); |
|
ret = xrealloc(ret, 1, rlen + nlen + 2); |
|
memcpy(ret + rlen, k->name, nlen + 1); |
|
rlen += nlen; |
|
} |
|
return ret; |
|
} |
|
|
|
static const struct kexalg * |
|
kex_alg_by_name(const char *name) |
|
{ |
|
const struct kexalg *k; |
|
|
|
for (k = kexalgs; k->name != NULL; k++) { |
|
if (strcmp(k->name, name) == 0) |
|
return k; |
|
} |
|
return NULL; |
|
} |
|
|
/* Validate KEX method name list */ |
/* Validate KEX method name list */ |
int |
int |
kex_names_valid(const char *names) |
kex_names_valid(const char *names) |
|
|
s = cp = xstrdup(names); |
s = cp = xstrdup(names); |
for ((p = strsep(&cp, ",")); p && *p != '\0'; |
for ((p = strsep(&cp, ",")); p && *p != '\0'; |
(p = strsep(&cp, ","))) { |
(p = strsep(&cp, ","))) { |
if (strcmp(p, KEX_DHGEX_SHA256) != 0 && |
if (kex_alg_by_name(p) == NULL) { |
strcmp(p, KEX_DHGEX_SHA1) != 0 && |
|
strcmp(p, KEX_DH14) != 0 && |
|
strcmp(p, KEX_DH1) != 0 && |
|
(strncmp(p, KEX_ECDH_SHA2_STEM, |
|
sizeof(KEX_ECDH_SHA2_STEM) - 1) != 0 || |
|
kex_ecdh_name_to_nid(p) == -1)) { |
|
error("Unsupported KEX algorithm \"%.100s\"", p); |
error("Unsupported KEX algorithm \"%.100s\"", p); |
xfree(s); |
xfree(s); |
return 0; |
return 0; |
|
|
static void |
static void |
choose_kex(Kex *k, char *client, char *server) |
choose_kex(Kex *k, char *client, char *server) |
{ |
{ |
|
const struct kexalg *kexalg; |
|
|
k->name = match_list(client, server, NULL); |
k->name = match_list(client, server, NULL); |
if (k->name == NULL) |
if (k->name == NULL) |
fatal("Unable to negotiate a key exchange method"); |
fatal("Unable to negotiate a key exchange method"); |
if (strcmp(k->name, KEX_DH1) == 0) { |
if ((kexalg = kex_alg_by_name(k->name)) == NULL) |
k->kex_type = KEX_DH_GRP1_SHA1; |
fatal("unsupported kex alg %s", k->name); |
k->evp_md = EVP_sha1(); |
k->kex_type = kexalg->type; |
} else if (strcmp(k->name, KEX_DH14) == 0) { |
k->evp_md = kexalg->mdfunc(); |
k->kex_type = KEX_DH_GRP14_SHA1; |
k->ec_nid = kexalg->ec_nid; |
k->evp_md = EVP_sha1(); |
|
} else if (strcmp(k->name, KEX_DHGEX_SHA1) == 0) { |
|
k->kex_type = KEX_DH_GEX_SHA1; |
|
k->evp_md = EVP_sha1(); |
|
} else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) { |
|
k->kex_type = KEX_DH_GEX_SHA256; |
|
k->evp_md = EVP_sha256(); |
|
} else if (strncmp(k->name, KEX_ECDH_SHA2_STEM, |
|
sizeof(KEX_ECDH_SHA2_STEM) - 1) == 0) { |
|
k->kex_type = KEX_ECDH_SHA2; |
|
k->evp_md = kex_ecdh_name_to_evpmd(k->name); |
|
} else |
|
fatal("bad kex alg %s", k->name); |
|
} |
} |
|
|
static void |
static void |