1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Support ECDH key exchange using the 'curve25519' curve.

This is the kex protocol id "curve25519-sha256@libssh.org", so called
because it's over the prime field of order 2^255 - 19.

Arithmetic in this curve is done using the Montgomery representation,
rather than the Weierstrass representation. So 'struct ec_curve' has
grown a discriminant field and a union of subtypes.
This commit is contained in:
Chris Staite 2015-05-09 15:02:52 +01:00 committed by Simon Tatham
parent 7d6bf4a6ca
commit 541abf9258
4 changed files with 934 additions and 258 deletions

9
ssh.c
View File

@ -6845,14 +6845,7 @@ static void do_ssh2_transport(Ssh ssh, void *vin, int inlen,
ssh->kex->hash->text_name); ssh->kex->hash->text_name);
ssh->pkt_kctx = SSH2_PKTCTX_ECDHKEX; ssh->pkt_kctx = SSH2_PKTCTX_ECDHKEX;
s->eckey = NULL; s->eckey = ssh_ecdhkex_newkey(ssh->kex->name);
if (!strcmp(ssh->kex->name, "ecdh-sha2-nistp256")) {
s->eckey = ssh_ecdhkex_newkey(ec_p256());
} else if (!strcmp(ssh->kex->name, "ecdh-sha2-nistp384")) {
s->eckey = ssh_ecdhkex_newkey(ec_p384());
} else if (!strcmp(ssh->kex->name, "ecdh-sha2-nistp521")) {
s->eckey = ssh_ecdhkex_newkey(ec_p521());
}
if (!s->eckey) { if (!s->eckey) {
bombout(("Unable to generate key for ECDH")); bombout(("Unable to generate key for ECDH"));
crStopV; crStopV;

32
ssh.h
View File

@ -110,27 +110,51 @@ struct ec_point {
void ec_point_free(struct ec_point *point); void ec_point_free(struct ec_point *point);
struct ec_curve { /* Weierstrass form curve */
unsigned int fieldBits; struct ec_wcurve
Bignum p, a, b, n; {
Bignum a, b, n;
struct ec_point G; struct ec_point G;
}; };
/* Montgomery form curve */
struct ec_mcurve
{
Bignum a, b;
struct ec_point G;
};
struct ec_curve {
enum { EC_WEIERSTRASS, EC_MONTGOMERY } type;
unsigned int fieldBits;
Bignum p;
union {
struct ec_wcurve w;
struct ec_mcurve m;
};
};
extern unsigned char nistp256_oid[]; extern unsigned char nistp256_oid[];
extern unsigned char nistp384_oid[]; extern unsigned char nistp384_oid[];
extern unsigned char nistp521_oid[]; extern unsigned char nistp521_oid[];
extern unsigned char curve25519_oid[];
extern int nistp256_oid_len; extern int nistp256_oid_len;
extern int nistp384_oid_len; extern int nistp384_oid_len;
extern int nistp521_oid_len; extern int nistp521_oid_len;
extern int curve25519_oid_len;
struct ec_curve *ec_p256(void); struct ec_curve *ec_p256(void);
struct ec_curve *ec_p384(void); struct ec_curve *ec_p384(void);
struct ec_curve *ec_p521(void); struct ec_curve *ec_p521(void);
struct ec_curve *ec_ed25519(void);
struct ec_curve *ec_curve25519(void);
struct ec_key { struct ec_key {
struct ec_point publicKey; struct ec_point publicKey;
Bignum privateKey; Bignum privateKey;
}; };
struct ec_point *ec_public(const Bignum privateKey, const struct ec_curve *curve);
int makekey(const unsigned char *data, int len, struct RSAKey *result, int makekey(const unsigned char *data, int len, struct RSAKey *result,
const unsigned char **keystr, int order); const unsigned char **keystr, int order);
int makeprivate(const unsigned char *data, int len, struct RSAKey *result); int makeprivate(const unsigned char *data, int len, struct RSAKey *result);
@ -176,7 +200,7 @@ void ssh_rsakex_encrypt(const struct ssh_hash *h, unsigned char *in, int inlen,
/* /*
* SSH2 ECDH key exchange functions * SSH2 ECDH key exchange functions
*/ */
void *ssh_ecdhkex_newkey(struct ec_curve *curve); void *ssh_ecdhkex_newkey(const char *name);
void ssh_ecdhkex_freekey(void *key); void ssh_ecdhkex_freekey(void *key);
char *ssh_ecdhkex_getpublic(void *key, int *len); char *ssh_ecdhkex_getpublic(void *key, int *len);
Bignum ssh_ecdhkex_getkey(void *key, char *remoteKey, int remoteKeyLen); Bignum ssh_ecdhkex_getkey(void *key, char *remoteKey, int remoteKeyLen);

1147
sshecc.c

File diff suppressed because it is too large Load Diff

View File

@ -22,10 +22,10 @@ int ec_generate(struct ec_key *key, int bits, progfn_t pfn,
return 0; return 0;
} }
key->privateKey = bignum_random_in_range(One, key->publicKey.curve->n); key->privateKey = bignum_random_in_range(One, key->publicKey.curve->w.n);
if (!key->privateKey) return 0; if (!key->privateKey) return 0;
publicKey = ecp_mul(&key->publicKey.curve->G, key->privateKey); publicKey = ec_public(key->privateKey, key->publicKey.curve);
if (!publicKey) { if (!publicKey) {
freebn(key->privateKey); freebn(key->privateKey);
key->privateKey = NULL; key->privateKey = NULL;