mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-05-09 13:42:09 -05:00
Implement "curve448-sha512" kex, from draft-ietf-curdle-ssh-curves-00.
I've demonstrated by diagnostic printfs that this passes the single Curve448 test vector given in section 6.2 of RFC 7748, but it is otherwise NOT INTEROPERABILITY-TESTED AT ALL. Also, its protocol identifier is not domain-suffixed despite not being in a published RFC (yet). So this implementation is strictly preliminary, and intended only for other SSH implementors to interop-test against.
This commit is contained in:
parent
d47be8d91a
commit
649480fd19
88
sshecc.c
88
sshecc.c
@ -365,6 +365,63 @@ static struct ec_curve *ec_curve25519(void)
|
|||||||
return &curve;
|
return &curve;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct ec_curve *ec_curve448(void)
|
||||||
|
{
|
||||||
|
static struct ec_curve curve = { 0 };
|
||||||
|
static unsigned char initialised = 0;
|
||||||
|
|
||||||
|
if (!initialised)
|
||||||
|
{
|
||||||
|
static const unsigned char p[56] = {
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
};
|
||||||
|
static const unsigned char a[56] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x62, 0xa6,
|
||||||
|
};
|
||||||
|
static const unsigned char b[56] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||||
|
};
|
||||||
|
static const unsigned char gx[56] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05,
|
||||||
|
};
|
||||||
|
|
||||||
|
initialise_mcurve(&curve, 448, p, a, b, gx);
|
||||||
|
/* This curve doesn't need a name, because it's never used in
|
||||||
|
* any format that embeds the curve name */
|
||||||
|
curve.name = NULL;
|
||||||
|
curve.textname = "Curve448";
|
||||||
|
|
||||||
|
/* Now initialised, no need to do it again */
|
||||||
|
initialised = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return &curve;
|
||||||
|
}
|
||||||
|
|
||||||
static struct ec_curve *ec_ed25519(void)
|
static struct ec_curve *ec_ed25519(void)
|
||||||
{
|
{
|
||||||
static struct ec_curve curve = { 0 };
|
static struct ec_curve curve = { 0 };
|
||||||
@ -2684,6 +2741,7 @@ const struct ssh_signkey ssh_ecdsa_nistp521 = {
|
|||||||
|
|
||||||
struct eckex_extra {
|
struct eckex_extra {
|
||||||
struct ec_curve *(*curve)(void);
|
struct ec_curve *(*curve)(void);
|
||||||
|
int low_byte_mask, high_byte_top_bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
static Bignum ecdh_calculate(const Bignum private,
|
static Bignum ecdh_calculate(const Bignum private,
|
||||||
@ -2750,18 +2808,21 @@ void *ssh_ecdhkex_newkey(const struct ssh_kex *kex)
|
|||||||
key->publicKey.curve = curve;
|
key->publicKey.curve = curve;
|
||||||
|
|
||||||
if (curve->type == EC_MONTGOMERY) {
|
if (curve->type == EC_MONTGOMERY) {
|
||||||
unsigned char bytes[32] = {0};
|
int nbytes = (curve->fieldBits+7) / 8;
|
||||||
|
unsigned char bytes[56] = {0};
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < sizeof(bytes); ++i)
|
assert(nbytes <= lenof(bytes));
|
||||||
|
|
||||||
|
for (i = 0; i < nbytes; ++i)
|
||||||
{
|
{
|
||||||
bytes[i] = (unsigned char)random_byte();
|
bytes[i] = (unsigned char)random_byte();
|
||||||
}
|
}
|
||||||
bytes[0] &= 248;
|
bytes[0] &= extra->low_byte_mask;
|
||||||
bytes[31] &= 127;
|
bytes[nbytes-1] &= extra->high_byte_top_bit - 1;
|
||||||
bytes[31] |= 64;
|
bytes[nbytes-1] |= extra->high_byte_top_bit;
|
||||||
key->privateKey = bignum_from_bytes_le(bytes, sizeof(bytes));
|
key->privateKey = bignum_from_bytes_le(bytes, nbytes);
|
||||||
smemclr(bytes, sizeof(bytes));
|
smemclr(bytes, nbytes);
|
||||||
if (!key->privateKey) {
|
if (!key->privateKey) {
|
||||||
sfree(key);
|
sfree(key);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2866,12 +2927,22 @@ void ssh_ecdhkex_freekey(void *key)
|
|||||||
ecdsa_freekey(key);
|
ecdsa_freekey(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct eckex_extra kex_extra_curve25519 = { ec_curve25519 };
|
static const struct eckex_extra kex_extra_curve25519 = {
|
||||||
|
ec_curve25519, 0xF8, 0x40,
|
||||||
|
};
|
||||||
static const struct ssh_kex ssh_ec_kex_curve25519 = {
|
static const struct ssh_kex ssh_ec_kex_curve25519 = {
|
||||||
"curve25519-sha256@libssh.org", NULL, KEXTYPE_ECDH,
|
"curve25519-sha256@libssh.org", NULL, KEXTYPE_ECDH,
|
||||||
&ssh_sha256, &kex_extra_curve25519,
|
&ssh_sha256, &kex_extra_curve25519,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct eckex_extra kex_extra_curve448 = {
|
||||||
|
ec_curve448, 0xFC, 0x80,
|
||||||
|
};
|
||||||
|
static const struct ssh_kex ssh_ec_kex_curve448 = {
|
||||||
|
"curve448-sha512", NULL, KEXTYPE_ECDH,
|
||||||
|
&ssh_sha512, &kex_extra_curve448,
|
||||||
|
};
|
||||||
|
|
||||||
const struct eckex_extra kex_extra_nistp256 = { ec_p256 };
|
const struct eckex_extra kex_extra_nistp256 = { ec_p256 };
|
||||||
static const struct ssh_kex ssh_ec_kex_nistp256 = {
|
static const struct ssh_kex ssh_ec_kex_nistp256 = {
|
||||||
"ecdh-sha2-nistp256", NULL, KEXTYPE_ECDH,
|
"ecdh-sha2-nistp256", NULL, KEXTYPE_ECDH,
|
||||||
@ -2891,6 +2962,7 @@ static const struct ssh_kex ssh_ec_kex_nistp521 = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const struct ssh_kex *const ec_kex_list[] = {
|
static const struct ssh_kex *const ec_kex_list[] = {
|
||||||
|
&ssh_ec_kex_curve448,
|
||||||
&ssh_ec_kex_curve25519,
|
&ssh_ec_kex_curve25519,
|
||||||
&ssh_ec_kex_nistp256,
|
&ssh_ec_kex_nistp256,
|
||||||
&ssh_ec_kex_nistp384,
|
&ssh_ec_kex_nistp384,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user