- djm@cvs.openbsd.org 2013/04/19 01:06:50
[authfile.c cipher.c cipher.h kex.c kex.h kexecdh.c kexecdhc.c kexecdhs.c] [key.c key.h mac.c mac.h packet.c ssh.1 ssh.c] add the ability to query supported ciphers, MACs, key type and KEX algorithms to ssh. Includes some refactoring of KEX and key type handling to be table-driven; ok markus@
This commit is contained in:
parent
a56086b990
commit
ea11119eee
|
@ -69,6 +69,12 @@
|
||||||
reintroduce 1.262 without the connection-killing bug:
|
reintroduce 1.262 without the connection-killing bug:
|
||||||
fatal() when ChrootDirectory specified by running without root privileges;
|
fatal() when ChrootDirectory specified by running without root privileges;
|
||||||
ok markus@
|
ok markus@
|
||||||
|
- djm@cvs.openbsd.org 2013/04/19 01:06:50
|
||||||
|
[authfile.c cipher.c cipher.h kex.c kex.h kexecdh.c kexecdhc.c kexecdhs.c]
|
||||||
|
[key.c key.h mac.c mac.h packet.c ssh.1 ssh.c]
|
||||||
|
add the ability to query supported ciphers, MACs, key type and KEX
|
||||||
|
algorithms to ssh. Includes some refactoring of KEX and key type handling
|
||||||
|
to be table-driven; ok markus@
|
||||||
|
|
||||||
20130418
|
20130418
|
||||||
- (djm) [config.guess config.sub] Update to last versions before they switch
|
- (djm) [config.guess config.sub] Update to last versions before they switch
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: authfile.c,v 1.95 2013/01/08 18:49:04 markus Exp $ */
|
/* $OpenBSD: authfile.c,v 1.96 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -89,7 +89,7 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
|
||||||
u_char buf[100], *cp;
|
u_char buf[100], *cp;
|
||||||
int i, cipher_num;
|
int i, cipher_num;
|
||||||
CipherContext ciphercontext;
|
CipherContext ciphercontext;
|
||||||
Cipher *cipher;
|
const Cipher *cipher;
|
||||||
u_int32_t rnd;
|
u_int32_t rnd;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -421,7 +421,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
|
||||||
Buffer decrypted;
|
Buffer decrypted;
|
||||||
u_char *cp;
|
u_char *cp;
|
||||||
CipherContext ciphercontext;
|
CipherContext ciphercontext;
|
||||||
Cipher *cipher;
|
const Cipher *cipher;
|
||||||
Key *prv = NULL;
|
Key *prv = NULL;
|
||||||
Buffer copy;
|
Buffer copy;
|
||||||
|
|
||||||
|
|
55
cipher.c
55
cipher.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: cipher.c,v 1.87 2013/01/26 06:11:05 djm Exp $ */
|
/* $OpenBSD: cipher.c,v 1.88 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -65,7 +65,9 @@ struct Cipher {
|
||||||
u_int discard_len;
|
u_int discard_len;
|
||||||
u_int cbc_mode;
|
u_int cbc_mode;
|
||||||
const EVP_CIPHER *(*evptype)(void);
|
const EVP_CIPHER *(*evptype)(void);
|
||||||
} ciphers[] = {
|
};
|
||||||
|
|
||||||
|
static const struct Cipher ciphers[] = {
|
||||||
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
|
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
|
||||||
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
|
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
|
||||||
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
|
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
|
||||||
|
@ -98,6 +100,27 @@ struct Cipher {
|
||||||
|
|
||||||
/*--*/
|
/*--*/
|
||||||
|
|
||||||
|
/* Returns a comma-separated list of supported ciphers. */
|
||||||
|
char *
|
||||||
|
cipher_alg_list(void)
|
||||||
|
{
|
||||||
|
char *ret = NULL;
|
||||||
|
size_t nlen, rlen = 0;
|
||||||
|
const Cipher *c;
|
||||||
|
|
||||||
|
for (c = ciphers; c->name != NULL; c++) {
|
||||||
|
if (c->number != SSH_CIPHER_SSH2)
|
||||||
|
continue;
|
||||||
|
if (ret != NULL)
|
||||||
|
ret[rlen++] = '\n';
|
||||||
|
nlen = strlen(c->name);
|
||||||
|
ret = xrealloc(ret, 1, rlen + nlen + 2);
|
||||||
|
memcpy(ret + rlen, c->name, nlen + 1);
|
||||||
|
rlen += nlen;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
u_int
|
u_int
|
||||||
cipher_blocksize(const Cipher *c)
|
cipher_blocksize(const Cipher *c)
|
||||||
{
|
{
|
||||||
|
@ -146,20 +169,20 @@ cipher_mask_ssh1(int client)
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cipher *
|
const Cipher *
|
||||||
cipher_by_name(const char *name)
|
cipher_by_name(const char *name)
|
||||||
{
|
{
|
||||||
Cipher *c;
|
const Cipher *c;
|
||||||
for (c = ciphers; c->name != NULL; c++)
|
for (c = ciphers; c->name != NULL; c++)
|
||||||
if (strcmp(c->name, name) == 0)
|
if (strcmp(c->name, name) == 0)
|
||||||
return c;
|
return c;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cipher *
|
const Cipher *
|
||||||
cipher_by_number(int id)
|
cipher_by_number(int id)
|
||||||
{
|
{
|
||||||
Cipher *c;
|
const Cipher *c;
|
||||||
for (c = ciphers; c->name != NULL; c++)
|
for (c = ciphers; c->name != NULL; c++)
|
||||||
if (c->number == id)
|
if (c->number == id)
|
||||||
return c;
|
return c;
|
||||||
|
@ -170,7 +193,7 @@ cipher_by_number(int id)
|
||||||
int
|
int
|
||||||
ciphers_valid(const char *names)
|
ciphers_valid(const char *names)
|
||||||
{
|
{
|
||||||
Cipher *c;
|
const Cipher *c;
|
||||||
char *cipher_list, *cp;
|
char *cipher_list, *cp;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
@ -201,7 +224,7 @@ ciphers_valid(const char *names)
|
||||||
int
|
int
|
||||||
cipher_number(const char *name)
|
cipher_number(const char *name)
|
||||||
{
|
{
|
||||||
Cipher *c;
|
const Cipher *c;
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
for (c = ciphers; c->name != NULL; c++)
|
for (c = ciphers; c->name != NULL; c++)
|
||||||
|
@ -213,12 +236,12 @@ cipher_number(const char *name)
|
||||||
char *
|
char *
|
||||||
cipher_name(int id)
|
cipher_name(int id)
|
||||||
{
|
{
|
||||||
Cipher *c = cipher_by_number(id);
|
const Cipher *c = cipher_by_number(id);
|
||||||
return (c==NULL) ? "<unknown>" : c->name;
|
return (c==NULL) ? "<unknown>" : c->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
cipher_init(CipherContext *cc, Cipher *cipher,
|
cipher_init(CipherContext *cc, const Cipher *cipher,
|
||||||
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
|
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
|
||||||
int do_encrypt)
|
int do_encrypt)
|
||||||
{
|
{
|
||||||
|
@ -364,7 +387,7 @@ cipher_cleanup(CipherContext *cc)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
cipher_set_key_string(CipherContext *cc, Cipher *cipher,
|
cipher_set_key_string(CipherContext *cc, const Cipher *cipher,
|
||||||
const char *passphrase, int do_encrypt)
|
const char *passphrase, int do_encrypt)
|
||||||
{
|
{
|
||||||
MD5_CTX md;
|
MD5_CTX md;
|
||||||
|
@ -389,7 +412,7 @@ cipher_set_key_string(CipherContext *cc, Cipher *cipher,
|
||||||
int
|
int
|
||||||
cipher_get_keyiv_len(const CipherContext *cc)
|
cipher_get_keyiv_len(const CipherContext *cc)
|
||||||
{
|
{
|
||||||
Cipher *c = cc->cipher;
|
const Cipher *c = cc->cipher;
|
||||||
int ivlen;
|
int ivlen;
|
||||||
|
|
||||||
if (c->number == SSH_CIPHER_3DES)
|
if (c->number == SSH_CIPHER_3DES)
|
||||||
|
@ -402,7 +425,7 @@ cipher_get_keyiv_len(const CipherContext *cc)
|
||||||
void
|
void
|
||||||
cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
|
cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
|
||||||
{
|
{
|
||||||
Cipher *c = cc->cipher;
|
const Cipher *c = cc->cipher;
|
||||||
int evplen;
|
int evplen;
|
||||||
|
|
||||||
switch (c->number) {
|
switch (c->number) {
|
||||||
|
@ -438,7 +461,7 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
|
||||||
void
|
void
|
||||||
cipher_set_keyiv(CipherContext *cc, u_char *iv)
|
cipher_set_keyiv(CipherContext *cc, u_char *iv)
|
||||||
{
|
{
|
||||||
Cipher *c = cc->cipher;
|
const Cipher *c = cc->cipher;
|
||||||
int evplen = 0;
|
int evplen = 0;
|
||||||
|
|
||||||
switch (c->number) {
|
switch (c->number) {
|
||||||
|
@ -471,7 +494,7 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv)
|
||||||
int
|
int
|
||||||
cipher_get_keycontext(const CipherContext *cc, u_char *dat)
|
cipher_get_keycontext(const CipherContext *cc, u_char *dat)
|
||||||
{
|
{
|
||||||
Cipher *c = cc->cipher;
|
const Cipher *c = cc->cipher;
|
||||||
int plen = 0;
|
int plen = 0;
|
||||||
|
|
||||||
if (c->evptype == EVP_rc4) {
|
if (c->evptype == EVP_rc4) {
|
||||||
|
@ -486,7 +509,7 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat)
|
||||||
void
|
void
|
||||||
cipher_set_keycontext(CipherContext *cc, u_char *dat)
|
cipher_set_keycontext(CipherContext *cc, u_char *dat)
|
||||||
{
|
{
|
||||||
Cipher *c = cc->cipher;
|
const Cipher *c = cc->cipher;
|
||||||
int plen;
|
int plen;
|
||||||
|
|
||||||
if (c->evptype == EVP_rc4) {
|
if (c->evptype == EVP_rc4) {
|
||||||
|
|
13
cipher.h
13
cipher.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: cipher.h,v 1.39 2013/01/08 18:49:04 markus Exp $ */
|
/* $OpenBSD: cipher.h,v 1.40 2013/04/19 01:06:50 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -66,21 +66,22 @@ struct CipherContext {
|
||||||
int plaintext;
|
int plaintext;
|
||||||
int encrypt;
|
int encrypt;
|
||||||
EVP_CIPHER_CTX evp;
|
EVP_CIPHER_CTX evp;
|
||||||
Cipher *cipher;
|
const Cipher *cipher;
|
||||||
};
|
};
|
||||||
|
|
||||||
u_int cipher_mask_ssh1(int);
|
u_int cipher_mask_ssh1(int);
|
||||||
Cipher *cipher_by_name(const char *);
|
const Cipher *cipher_by_name(const char *);
|
||||||
Cipher *cipher_by_number(int);
|
const Cipher *cipher_by_number(int);
|
||||||
int cipher_number(const char *);
|
int cipher_number(const char *);
|
||||||
char *cipher_name(int);
|
char *cipher_name(int);
|
||||||
int ciphers_valid(const char *);
|
int ciphers_valid(const char *);
|
||||||
void cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
|
char *cipher_alg_list(void);
|
||||||
|
void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int,
|
||||||
const u_char *, u_int, int);
|
const u_char *, u_int, int);
|
||||||
void cipher_crypt(CipherContext *, u_char *, const u_char *,
|
void cipher_crypt(CipherContext *, u_char *, const u_char *,
|
||||||
u_int, u_int, u_int);
|
u_int, u_int, u_int);
|
||||||
void cipher_cleanup(CipherContext *);
|
void cipher_cleanup(CipherContext *);
|
||||||
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
|
void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int);
|
||||||
u_int cipher_blocksize(const Cipher *);
|
u_int cipher_blocksize(const Cipher *);
|
||||||
u_int cipher_keylen(const Cipher *);
|
u_int cipher_keylen(const Cipher *);
|
||||||
u_int cipher_authlen(const Cipher *);
|
u_int cipher_authlen(const Cipher *);
|
||||||
|
|
86
kex.c
86
kex.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kex.c,v 1.88 2013/01/08 18:49:04 markus Exp $ */
|
/* $OpenBSD: kex.c,v 1.89 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -62,6 +62,55 @@ extern const EVP_MD *evp_ssh_sha256(void);
|
||||||
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 },
|
||||||
|
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
||||||
|
{ KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, EVP_sha256 },
|
||||||
|
{ 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 },
|
||||||
|
#endif
|
||||||
|
{ 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)
|
||||||
|
@ -73,13 +122,7 @@ 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;
|
||||||
|
@ -348,29 +391,16 @@ choose_comp(Comp *comp, char *client, char *server)
|
||||||
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();
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x00907000L
|
|
||||||
} else if (strcmp(k->name, KEX_DHGEX_SHA256) == 0) {
|
|
||||||
k->kex_type = KEX_DH_GEX_SHA256;
|
|
||||||
k->evp_md = evp_ssh_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);
|
|
||||||
#endif
|
|
||||||
} else
|
|
||||||
fatal("bad kex alg %s", k->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
16
kex.h
16
kex.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kex.h,v 1.54 2013/01/08 18:49:04 markus Exp $ */
|
/* $OpenBSD: kex.h,v 1.55 2013/04/19 01:06:50 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
|
@ -40,8 +40,9 @@
|
||||||
#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1"
|
#define KEX_DHGEX_SHA1 "diffie-hellman-group-exchange-sha1"
|
||||||
#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256"
|
#define KEX_DHGEX_SHA256 "diffie-hellman-group-exchange-sha256"
|
||||||
#define KEX_RESUME "resume@appgate.com"
|
#define KEX_RESUME "resume@appgate.com"
|
||||||
/* The following represents the family of ECDH methods */
|
#define KEX_ECDH_SHA2_NISTP256 "ecdh-sha2-nistp256"
|
||||||
#define KEX_ECDH_SHA2_STEM "ecdh-sha2-"
|
#define KEX_ECDH_SHA2_NISTP384 "ecdh-sha2-nistp384"
|
||||||
|
#define KEX_ECDH_SHA2_NISTP521 "ecdh-sha2-nistp521"
|
||||||
|
|
||||||
#define COMP_NONE 0
|
#define COMP_NONE 0
|
||||||
#define COMP_ZLIB 1
|
#define COMP_ZLIB 1
|
||||||
|
@ -86,7 +87,7 @@ typedef struct Newkeys Newkeys;
|
||||||
|
|
||||||
struct Enc {
|
struct Enc {
|
||||||
char *name;
|
char *name;
|
||||||
Cipher *cipher;
|
const Cipher *cipher;
|
||||||
int enabled;
|
int enabled;
|
||||||
u_int key_len;
|
u_int key_len;
|
||||||
u_int iv_len;
|
u_int iv_len;
|
||||||
|
@ -131,6 +132,7 @@ struct Kex {
|
||||||
sig_atomic_t done;
|
sig_atomic_t done;
|
||||||
int flags;
|
int flags;
|
||||||
const EVP_MD *evp_md;
|
const EVP_MD *evp_md;
|
||||||
|
int ec_nid;
|
||||||
char *client_version_string;
|
char *client_version_string;
|
||||||
char *server_version_string;
|
char *server_version_string;
|
||||||
int (*verify_host_key)(Key *);
|
int (*verify_host_key)(Key *);
|
||||||
|
@ -141,6 +143,7 @@ struct Kex {
|
||||||
};
|
};
|
||||||
|
|
||||||
int kex_names_valid(const char *);
|
int kex_names_valid(const char *);
|
||||||
|
char *kex_alg_list(void);
|
||||||
|
|
||||||
Kex *kex_setup(char *[PROPOSAL_MAX]);
|
Kex *kex_setup(char *[PROPOSAL_MAX]);
|
||||||
void kex_finish(Kex *);
|
void kex_finish(Kex *);
|
||||||
|
@ -170,11 +173,6 @@ void
|
||||||
kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int,
|
kex_ecdh_hash(const EVP_MD *, const EC_GROUP *, char *, char *, char *, int,
|
||||||
char *, int, u_char *, int, const EC_POINT *, const EC_POINT *,
|
char *, int, u_char *, int, const EC_POINT *, const EC_POINT *,
|
||||||
const BIGNUM *, u_char **, u_int *);
|
const BIGNUM *, u_char **, u_int *);
|
||||||
int kex_ecdh_name_to_nid(const char *);
|
|
||||||
const EVP_MD *kex_ecdh_name_to_evpmd(const char *);
|
|
||||||
#else
|
|
||||||
# define kex_ecdh_name_to_nid(x) (-1)
|
|
||||||
# define kex_ecdh_name_to_evpmd(x) (NULL)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
20
kexecdh.c
20
kexecdh.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexecdh.c,v 1.3 2010/09/22 05:01:29 djm Exp $ */
|
/* $OpenBSD: kexecdh.c,v 1.4 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||||
|
@ -45,24 +45,6 @@
|
||||||
#include "kex.h"
|
#include "kex.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
int
|
|
||||||
kex_ecdh_name_to_nid(const char *kexname)
|
|
||||||
{
|
|
||||||
if (strlen(kexname) < sizeof(KEX_ECDH_SHA2_STEM) - 1)
|
|
||||||
fatal("%s: kexname too short \"%s\"", __func__, kexname);
|
|
||||||
return key_curve_name_to_nid(kexname + sizeof(KEX_ECDH_SHA2_STEM) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const EVP_MD *
|
|
||||||
kex_ecdh_name_to_evpmd(const char *kexname)
|
|
||||||
{
|
|
||||||
int nid = kex_ecdh_name_to_nid(kexname);
|
|
||||||
|
|
||||||
if (nid == -1)
|
|
||||||
fatal("%s: unsupported ECDH curve \"%s\"", __func__, kexname);
|
|
||||||
return key_ec_nid_to_evpmd(nid);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
kex_ecdh_hash(
|
kex_ecdh_hash(
|
||||||
const EVP_MD *evp_md,
|
const EVP_MD *evp_md,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexecdhc.c,v 1.2 2010/09/22 05:01:29 djm Exp $ */
|
/* $OpenBSD: kexecdhc.c,v 1.3 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||||
|
@ -57,11 +57,8 @@ kexecdh_client(Kex *kex)
|
||||||
u_char *server_host_key_blob = NULL, *signature = NULL;
|
u_char *server_host_key_blob = NULL, *signature = NULL;
|
||||||
u_char *kbuf, *hash;
|
u_char *kbuf, *hash;
|
||||||
u_int klen, slen, sbloblen, hashlen;
|
u_int klen, slen, sbloblen, hashlen;
|
||||||
int curve_nid;
|
|
||||||
|
|
||||||
if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1)
|
if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL)
|
||||||
fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name);
|
|
||||||
if ((client_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL)
|
|
||||||
fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
|
fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
|
||||||
if (EC_KEY_generate_key(client_key) != 1)
|
if (EC_KEY_generate_key(client_key) != 1)
|
||||||
fatal("%s: EC_KEY_generate_key failed", __func__);
|
fatal("%s: EC_KEY_generate_key failed", __func__);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexecdhs.c,v 1.2 2010/09/22 05:01:29 djm Exp $ */
|
/* $OpenBSD: kexecdhs.c,v 1.3 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||||
|
@ -59,11 +59,8 @@ kexecdh_server(Kex *kex)
|
||||||
u_char *server_host_key_blob = NULL, *signature = NULL;
|
u_char *server_host_key_blob = NULL, *signature = NULL;
|
||||||
u_char *kbuf, *hash;
|
u_char *kbuf, *hash;
|
||||||
u_int klen, slen, sbloblen, hashlen;
|
u_int klen, slen, sbloblen, hashlen;
|
||||||
int curve_nid;
|
|
||||||
|
|
||||||
if ((curve_nid = kex_ecdh_name_to_nid(kex->name)) == -1)
|
if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL)
|
||||||
fatal("%s: unsupported ECDH curve \"%s\"", __func__, kex->name);
|
|
||||||
if ((server_key = EC_KEY_new_by_curve_name(curve_nid)) == NULL)
|
|
||||||
fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
|
fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
|
||||||
if (EC_KEY_generate_key(server_key) != 1)
|
if (EC_KEY_generate_key(server_key) != 1)
|
||||||
fatal("%s: EC_KEY_generate_key failed", __func__);
|
fatal("%s: EC_KEY_generate_key failed", __func__);
|
||||||
|
|
230
key.c
230
key.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: key.c,v 1.100 2013/01/17 23:00:01 djm Exp $ */
|
/* $OpenBSD: key.c,v 1.101 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* read_bignum():
|
* read_bignum():
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -891,36 +891,6 @@ key_write(const Key *key, FILE *f)
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
|
||||||
key_type(const Key *k)
|
|
||||||
{
|
|
||||||
switch (k->type) {
|
|
||||||
case KEY_RSA1:
|
|
||||||
return "RSA1";
|
|
||||||
case KEY_RSA:
|
|
||||||
return "RSA";
|
|
||||||
case KEY_DSA:
|
|
||||||
return "DSA";
|
|
||||||
#ifdef OPENSSL_HAS_ECC
|
|
||||||
case KEY_ECDSA:
|
|
||||||
return "ECDSA";
|
|
||||||
#endif
|
|
||||||
case KEY_RSA_CERT_V00:
|
|
||||||
return "RSA-CERT-V00";
|
|
||||||
case KEY_DSA_CERT_V00:
|
|
||||||
return "DSA-CERT-V00";
|
|
||||||
case KEY_RSA_CERT:
|
|
||||||
return "RSA-CERT";
|
|
||||||
case KEY_DSA_CERT:
|
|
||||||
return "DSA-CERT";
|
|
||||||
#ifdef OPENSSL_HAS_ECC
|
|
||||||
case KEY_ECDSA_CERT:
|
|
||||||
return "ECDSA-CERT";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return "unknown";
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
key_cert_type(const Key *k)
|
key_cert_type(const Key *k)
|
||||||
{
|
{
|
||||||
|
@ -934,48 +904,59 @@ key_cert_type(const Key *k)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct keytype {
|
||||||
|
char *name;
|
||||||
|
char *shortname;
|
||||||
|
int type;
|
||||||
|
int nid;
|
||||||
|
int cert;
|
||||||
|
};
|
||||||
|
static const struct keytype keytypes[] = {
|
||||||
|
{ NULL, "RSA1", KEY_RSA1, 0, 0 },
|
||||||
|
{ "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
|
||||||
|
{ "ssh-dss", "DSA", KEY_DSA, 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-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
|
||||||
|
#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 },
|
||||||
|
#ifdef OPENSSL_HAS_ECC
|
||||||
|
{ "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
|
||||||
|
KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
|
||||||
|
{ "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
|
||||||
|
KEY_ECDSA_CERT, NID_secp384r1, 1 },
|
||||||
|
{ "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
|
||||||
|
KEY_ECDSA_CERT, NID_secp521r1, 1 },
|
||||||
|
#endif /* OPENSSL_HAS_ECC */
|
||||||
|
{ "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
|
||||||
|
KEY_RSA_CERT_V00, 0, 1 },
|
||||||
|
{ "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
|
||||||
|
KEY_DSA_CERT_V00, 0, 1 },
|
||||||
|
{ NULL, NULL, -1, -1, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *
|
||||||
|
key_type(const Key *k)
|
||||||
|
{
|
||||||
|
const struct keytype *kt;
|
||||||
|
|
||||||
|
for (kt = keytypes; kt->type != -1; kt++) {
|
||||||
|
if (kt->type == k->type)
|
||||||
|
return kt->shortname;
|
||||||
|
}
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
key_ssh_name_from_type_nid(int type, int nid)
|
key_ssh_name_from_type_nid(int type, int nid)
|
||||||
{
|
{
|
||||||
switch (type) {
|
const struct keytype *kt;
|
||||||
case KEY_RSA:
|
|
||||||
return "ssh-rsa";
|
for (kt = keytypes; kt->type != -1; kt++) {
|
||||||
case KEY_DSA:
|
if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
|
||||||
return "ssh-dss";
|
return kt->name;
|
||||||
case KEY_RSA_CERT_V00:
|
|
||||||
return "ssh-rsa-cert-v00@openssh.com";
|
|
||||||
case KEY_DSA_CERT_V00:
|
|
||||||
return "ssh-dss-cert-v00@openssh.com";
|
|
||||||
case KEY_RSA_CERT:
|
|
||||||
return "ssh-rsa-cert-v01@openssh.com";
|
|
||||||
case KEY_DSA_CERT:
|
|
||||||
return "ssh-dss-cert-v01@openssh.com";
|
|
||||||
#ifdef OPENSSL_HAS_ECC
|
|
||||||
case KEY_ECDSA:
|
|
||||||
switch (nid) {
|
|
||||||
case NID_X9_62_prime256v1:
|
|
||||||
return "ecdsa-sha2-nistp256";
|
|
||||||
case NID_secp384r1:
|
|
||||||
return "ecdsa-sha2-nistp384";
|
|
||||||
case NID_secp521r1:
|
|
||||||
return "ecdsa-sha2-nistp521";
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case KEY_ECDSA_CERT:
|
|
||||||
switch (nid) {
|
|
||||||
case NID_X9_62_prime256v1:
|
|
||||||
return "ecdsa-sha2-nistp256-cert-v01@openssh.com";
|
|
||||||
case NID_secp384r1:
|
|
||||||
return "ecdsa-sha2-nistp384-cert-v01@openssh.com";
|
|
||||||
case NID_secp521r1:
|
|
||||||
return "ecdsa-sha2-nistp521-cert-v01@openssh.com";
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#endif /* OPENSSL_HAS_ECC */
|
|
||||||
}
|
}
|
||||||
return "ssh-unknown";
|
return "ssh-unknown";
|
||||||
}
|
}
|
||||||
|
@ -993,6 +974,56 @@ key_ssh_name_plain(const Key *k)
|
||||||
k->ecdsa_nid);
|
k->ecdsa_nid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
key_type_from_name(char *name)
|
||||||
|
{
|
||||||
|
const struct keytype *kt;
|
||||||
|
|
||||||
|
for (kt = keytypes; kt->type != -1; kt++) {
|
||||||
|
/* Only allow shortname matches for plain key types */
|
||||||
|
if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
|
||||||
|
(!kt->cert && strcasecmp(kt->shortname, name) == 0))
|
||||||
|
return kt->type;
|
||||||
|
}
|
||||||
|
debug2("key_type_from_name: unknown key type '%s'", name);
|
||||||
|
return KEY_UNSPEC;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
key_ecdsa_nid_from_name(const char *name)
|
||||||
|
{
|
||||||
|
const struct keytype *kt;
|
||||||
|
|
||||||
|
for (kt = keytypes; kt->type != -1; kt++) {
|
||||||
|
if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
|
||||||
|
continue;
|
||||||
|
if (kt->name != NULL && strcmp(name, kt->name) == 0)
|
||||||
|
return kt->nid;
|
||||||
|
}
|
||||||
|
debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
key_alg_list(void)
|
||||||
|
{
|
||||||
|
char *ret = NULL;
|
||||||
|
size_t nlen, rlen = 0;
|
||||||
|
const struct keytype *kt;
|
||||||
|
|
||||||
|
for (kt = keytypes; kt->type != -1; kt++) {
|
||||||
|
if (kt->name == NULL)
|
||||||
|
continue;
|
||||||
|
if (ret != NULL)
|
||||||
|
ret[rlen++] = '\n';
|
||||||
|
nlen = strlen(kt->name);
|
||||||
|
ret = xrealloc(ret, 1, rlen + nlen + 2);
|
||||||
|
memcpy(ret + rlen, kt->name, nlen + 1);
|
||||||
|
rlen += nlen;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
u_int
|
u_int
|
||||||
key_size(const Key *k)
|
key_size(const Key *k)
|
||||||
{
|
{
|
||||||
|
@ -1247,65 +1278,6 @@ key_from_private(const Key *k)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
key_type_from_name(char *name)
|
|
||||||
{
|
|
||||||
if (strcmp(name, "rsa1") == 0) {
|
|
||||||
return KEY_RSA1;
|
|
||||||
} else if (strcmp(name, "rsa") == 0) {
|
|
||||||
return KEY_RSA;
|
|
||||||
} else if (strcmp(name, "dsa") == 0) {
|
|
||||||
return KEY_DSA;
|
|
||||||
} else if (strcmp(name, "ssh-rsa") == 0) {
|
|
||||||
return KEY_RSA;
|
|
||||||
} else if (strcmp(name, "ssh-dss") == 0) {
|
|
||||||
return KEY_DSA;
|
|
||||||
#ifdef OPENSSL_HAS_ECC
|
|
||||||
} else if (strcmp(name, "ecdsa") == 0 ||
|
|
||||||
strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
|
|
||||||
strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
|
|
||||||
strcmp(name, "ecdsa-sha2-nistp521") == 0) {
|
|
||||||
return KEY_ECDSA;
|
|
||||||
#endif
|
|
||||||
} else if (strcmp(name, "ssh-rsa-cert-v00@openssh.com") == 0) {
|
|
||||||
return KEY_RSA_CERT_V00;
|
|
||||||
} else if (strcmp(name, "ssh-dss-cert-v00@openssh.com") == 0) {
|
|
||||||
return KEY_DSA_CERT_V00;
|
|
||||||
} else if (strcmp(name, "ssh-rsa-cert-v01@openssh.com") == 0) {
|
|
||||||
return KEY_RSA_CERT;
|
|
||||||
} else if (strcmp(name, "ssh-dss-cert-v01@openssh.com") == 0) {
|
|
||||||
return KEY_DSA_CERT;
|
|
||||||
#ifdef OPENSSL_HAS_ECC
|
|
||||||
} else if (strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0 ||
|
|
||||||
strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0 ||
|
|
||||||
strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0) {
|
|
||||||
return KEY_ECDSA_CERT;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
debug2("key_type_from_name: unknown key type '%s'", name);
|
|
||||||
return KEY_UNSPEC;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
key_ecdsa_nid_from_name(const char *name)
|
|
||||||
{
|
|
||||||
#ifdef OPENSSL_HAS_ECC
|
|
||||||
if (strcmp(name, "ecdsa-sha2-nistp256") == 0 ||
|
|
||||||
strcmp(name, "ecdsa-sha2-nistp256-cert-v01@openssh.com") == 0)
|
|
||||||
return NID_X9_62_prime256v1;
|
|
||||||
if (strcmp(name, "ecdsa-sha2-nistp384") == 0 ||
|
|
||||||
strcmp(name, "ecdsa-sha2-nistp384-cert-v01@openssh.com") == 0)
|
|
||||||
return NID_secp384r1;
|
|
||||||
if (strcmp(name, "ecdsa-sha2-nistp521") == 0 ||
|
|
||||||
strcmp(name, "ecdsa-sha2-nistp521-cert-v01@openssh.com") == 0)
|
|
||||||
return NID_secp521r1;
|
|
||||||
#endif /* OPENSSL_HAS_ECC */
|
|
||||||
|
|
||||||
debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
key_names_valid2(const char *names)
|
key_names_valid2(const char *names)
|
||||||
{
|
{
|
||||||
|
|
7
key.h
7
key.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: key.h,v 1.35 2013/01/17 23:00:01 djm Exp $ */
|
/* $OpenBSD: key.h,v 1.36 2013/04/19 01:06:50 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
|
@ -118,15 +118,16 @@ int key_cert_is_legacy(const Key *);
|
||||||
|
|
||||||
int key_ecdsa_nid_from_name(const char *);
|
int key_ecdsa_nid_from_name(const char *);
|
||||||
int key_curve_name_to_nid(const char *);
|
int key_curve_name_to_nid(const char *);
|
||||||
const char * key_curve_nid_to_name(int);
|
const char *key_curve_nid_to_name(int);
|
||||||
u_int key_curve_nid_to_bits(int);
|
u_int key_curve_nid_to_bits(int);
|
||||||
int key_ecdsa_bits_to_nid(int);
|
int key_ecdsa_bits_to_nid(int);
|
||||||
#ifdef OPENSSL_HAS_ECC
|
#ifdef OPENSSL_HAS_ECC
|
||||||
int key_ecdsa_key_to_nid(EC_KEY *);
|
int key_ecdsa_key_to_nid(EC_KEY *);
|
||||||
const EVP_MD * key_ec_nid_to_evpmd(int nid);
|
const EVP_MD *key_ec_nid_to_evpmd(int nid);
|
||||||
int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
|
int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
|
||||||
int key_ec_validate_private(const EC_KEY *);
|
int key_ec_validate_private(const EC_KEY *);
|
||||||
#endif
|
#endif
|
||||||
|
char *key_alg_list(void);
|
||||||
|
|
||||||
Key *key_from_blob(const u_char *, u_int);
|
Key *key_from_blob(const u_char *, u_int);
|
||||||
int key_to_blob(const Key *, u_char **, u_int *);
|
int key_to_blob(const Key *, u_char **, u_int *);
|
||||||
|
|
60
mac.c
60
mac.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: mac.c,v 1.21 2012/12/11 22:51:45 sthen Exp $ */
|
/* $OpenBSD: mac.c,v 1.22 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
|
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */
|
||||||
#define SSH_UMAC128 3
|
#define SSH_UMAC128 3
|
||||||
|
|
||||||
struct {
|
struct macalg {
|
||||||
char *name;
|
char *name;
|
||||||
int type;
|
int type;
|
||||||
const EVP_MD * (*mdfunc)(void);
|
const EVP_MD * (*mdfunc)(void);
|
||||||
|
@ -58,7 +58,9 @@ struct {
|
||||||
int key_len; /* just for UMAC */
|
int key_len; /* just for UMAC */
|
||||||
int len; /* just for UMAC */
|
int len; /* just for UMAC */
|
||||||
int etm; /* Encrypt-then-MAC */
|
int etm; /* Encrypt-then-MAC */
|
||||||
} macs[] = {
|
};
|
||||||
|
|
||||||
|
static const struct macalg macs[] = {
|
||||||
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */
|
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */
|
||||||
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 },
|
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 },
|
||||||
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 },
|
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 },
|
||||||
|
@ -89,38 +91,58 @@ struct {
|
||||||
{ NULL, 0, NULL, 0, 0, 0, 0 }
|
{ NULL, 0, NULL, 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Returns a comma-separated list of supported MACs. */
|
||||||
|
char *
|
||||||
|
mac_alg_list(void)
|
||||||
|
{
|
||||||
|
char *ret = NULL;
|
||||||
|
size_t nlen, rlen = 0;
|
||||||
|
const struct macalg *m;
|
||||||
|
|
||||||
|
for (m = macs; m->name != NULL; m++) {
|
||||||
|
if (ret != NULL)
|
||||||
|
ret[rlen++] = '\n';
|
||||||
|
nlen = strlen(m->name);
|
||||||
|
ret = xrealloc(ret, 1, rlen + nlen + 2);
|
||||||
|
memcpy(ret + rlen, m->name, nlen + 1);
|
||||||
|
rlen += nlen;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mac_setup_by_id(Mac *mac, int which)
|
mac_setup_by_alg(Mac *mac, const struct macalg *macalg)
|
||||||
{
|
{
|
||||||
int evp_len;
|
int evp_len;
|
||||||
mac->type = macs[which].type;
|
|
||||||
|
mac->type = macalg->type;
|
||||||
if (mac->type == SSH_EVP) {
|
if (mac->type == SSH_EVP) {
|
||||||
mac->evp_md = (*macs[which].mdfunc)();
|
mac->evp_md = macalg->mdfunc();
|
||||||
if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0)
|
if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0)
|
||||||
fatal("mac %s len %d", mac->name, evp_len);
|
fatal("mac %s len %d", mac->name, evp_len);
|
||||||
mac->key_len = mac->mac_len = (u_int)evp_len;
|
mac->key_len = mac->mac_len = (u_int)evp_len;
|
||||||
} else {
|
} else {
|
||||||
mac->mac_len = macs[which].len / 8;
|
mac->mac_len = macalg->len / 8;
|
||||||
mac->key_len = macs[which].key_len / 8;
|
mac->key_len = macalg->key_len / 8;
|
||||||
mac->umac_ctx = NULL;
|
mac->umac_ctx = NULL;
|
||||||
}
|
}
|
||||||
if (macs[which].truncatebits != 0)
|
if (macalg->truncatebits != 0)
|
||||||
mac->mac_len = macs[which].truncatebits / 8;
|
mac->mac_len = macalg->truncatebits / 8;
|
||||||
mac->etm = macs[which].etm;
|
mac->etm = macalg->etm;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
mac_setup(Mac *mac, char *name)
|
mac_setup(Mac *mac, char *name)
|
||||||
{
|
{
|
||||||
int i;
|
const struct macalg *m;
|
||||||
|
|
||||||
for (i = 0; macs[i].name; i++) {
|
for (m = macs; m->name != NULL; m++) {
|
||||||
if (strcmp(name, macs[i].name) == 0) {
|
if (strcmp(name, m->name) != 0)
|
||||||
if (mac != NULL)
|
continue;
|
||||||
mac_setup_by_id(mac, i);
|
if (mac != NULL)
|
||||||
debug2("mac_setup: found %s", name);
|
mac_setup_by_alg(mac, m);
|
||||||
return (0);
|
debug2("mac_setup: found %s", name);
|
||||||
}
|
return (0);
|
||||||
}
|
}
|
||||||
debug2("mac_setup: unknown %s", name);
|
debug2("mac_setup: unknown %s", name);
|
||||||
return (-1);
|
return (-1);
|
||||||
|
|
3
mac.h
3
mac.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: mac.h,v 1.6 2007/06/07 19:37:34 pvalchev Exp $ */
|
/* $OpenBSD: mac.h,v 1.7 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -24,6 +24,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int mac_valid(const char *);
|
int mac_valid(const char *);
|
||||||
|
char *mac_alg_list(void);
|
||||||
int mac_setup(Mac *, char *);
|
int mac_setup(Mac *, char *);
|
||||||
int mac_init(Mac *);
|
int mac_init(Mac *);
|
||||||
u_char *mac_compute(Mac *, u_int32_t, u_char *, int);
|
u_char *mac_compute(Mac *, u_int32_t, u_char *, int);
|
||||||
|
|
6
packet.c
6
packet.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: packet.c,v 1.182 2013/04/11 02:27:50 djm Exp $ */
|
/* $OpenBSD: packet.c,v 1.183 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -215,7 +215,7 @@ alloc_session_state(void)
|
||||||
void
|
void
|
||||||
packet_set_connection(int fd_in, int fd_out)
|
packet_set_connection(int fd_in, int fd_out)
|
||||||
{
|
{
|
||||||
Cipher *none = cipher_by_name("none");
|
const Cipher *none = cipher_by_name("none");
|
||||||
|
|
||||||
if (none == NULL)
|
if (none == NULL)
|
||||||
fatal("packet_set_connection: cannot load cipher 'none'");
|
fatal("packet_set_connection: cannot load cipher 'none'");
|
||||||
|
@ -545,7 +545,7 @@ packet_start_compression(int level)
|
||||||
void
|
void
|
||||||
packet_set_encryption_key(const u_char *key, u_int keylen, int number)
|
packet_set_encryption_key(const u_char *key, u_int keylen, int number)
|
||||||
{
|
{
|
||||||
Cipher *cipher = cipher_by_number(number);
|
const Cipher *cipher = cipher_by_number(number);
|
||||||
|
|
||||||
if (cipher == NULL)
|
if (cipher == NULL)
|
||||||
fatal("packet_set_encryption_key: unknown cipher number %d", number);
|
fatal("packet_set_encryption_key: unknown cipher number %d", number);
|
||||||
|
|
21
ssh.1
21
ssh.1
|
@ -33,8 +33,8 @@
|
||||||
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.\" $OpenBSD: ssh.1,v 1.331 2013/04/07 02:10:33 dtucker Exp $
|
.\" $OpenBSD: ssh.1,v 1.332 2013/04/19 01:06:50 djm Exp $
|
||||||
.Dd $Mdocdate: April 7 2013 $
|
.Dd $Mdocdate: April 19 2013 $
|
||||||
.Dt SSH 1
|
.Dt SSH 1
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
|
@ -65,6 +65,8 @@
|
||||||
.Oo Ar user Ns @ Oc Ns Ar hostname
|
.Oo Ar user Ns @ Oc Ns Ar hostname
|
||||||
.Op Ar command
|
.Op Ar command
|
||||||
.Ek
|
.Ek
|
||||||
|
.Nm
|
||||||
|
.Fl Q Ar protocol_feature
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
(SSH client) is a program for logging into a remote machine and for
|
(SSH client) is a program for logging into a remote machine and for
|
||||||
|
@ -487,6 +489,21 @@ For full details of the options listed below, and their possible values, see
|
||||||
Port to connect to on the remote host.
|
Port to connect to on the remote host.
|
||||||
This can be specified on a
|
This can be specified on a
|
||||||
per-host basis in the configuration file.
|
per-host basis in the configuration file.
|
||||||
|
.It Fl Q Ar protocol_feature
|
||||||
|
Queries
|
||||||
|
.Nm
|
||||||
|
for the algorithms supported for the specified version 2
|
||||||
|
.Ar protocol_feature .
|
||||||
|
The queriable features are:
|
||||||
|
.Dq cipher
|
||||||
|
(supported symmetric ciphers),
|
||||||
|
.Dq MAC
|
||||||
|
(supported message integrity codes),
|
||||||
|
.Dq KEX
|
||||||
|
(key exchange algorithms),
|
||||||
|
.Dq key
|
||||||
|
(key types).
|
||||||
|
Protocol features are treated case-insensitively.
|
||||||
.It Fl q
|
.It Fl q
|
||||||
Quiet mode.
|
Quiet mode.
|
||||||
Causes most warning and diagnostic messages to be suppressed.
|
Causes most warning and diagnostic messages to be suppressed.
|
||||||
|
|
20
ssh.c
20
ssh.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh.c,v 1.375 2013/04/07 02:10:33 dtucker Exp $ */
|
/* $OpenBSD: ssh.c,v 1.376 2013/04/19 01:06:50 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -327,7 +327,7 @@ main(int ac, char **av)
|
||||||
|
|
||||||
again:
|
again:
|
||||||
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
|
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx"
|
||||||
"ACD:E:F:I:KL:MNO:PR:S:TVw:W:XYy")) != -1) {
|
"ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case '1':
|
case '1':
|
||||||
options.protocol = SSH_PROTO_1;
|
options.protocol = SSH_PROTO_1;
|
||||||
|
@ -389,6 +389,22 @@ main(int ac, char **av)
|
||||||
case 'P': /* deprecated */
|
case 'P': /* deprecated */
|
||||||
options.use_privileged_port = 0;
|
options.use_privileged_port = 0;
|
||||||
break;
|
break;
|
||||||
|
case 'Q': /* deprecated */
|
||||||
|
cp = NULL;
|
||||||
|
if (strcasecmp(optarg, "cipher") == 0)
|
||||||
|
cp = cipher_alg_list();
|
||||||
|
else if (strcasecmp(optarg, "mac") == 0)
|
||||||
|
cp = mac_alg_list();
|
||||||
|
else if (strcasecmp(optarg, "kex") == 0)
|
||||||
|
cp = kex_alg_list();
|
||||||
|
else if (strcasecmp(optarg, "key") == 0)
|
||||||
|
cp = key_alg_list();
|
||||||
|
if (cp == NULL)
|
||||||
|
fatal("Unsupported query \"%s\"", optarg);
|
||||||
|
printf("%s\n", cp);
|
||||||
|
free(cp);
|
||||||
|
exit(0);
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
options.forward_agent = 0;
|
options.forward_agent = 0;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in New Issue