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 curve = { 0 };
struct eckex_extra {
struct ec_curve *(*curve)(void);
+ int low_byte_mask, high_byte_top_bit;
};
static Bignum ecdh_calculate(const Bignum private,
key->publicKey.curve = curve;
if (curve->type == EC_MONTGOMERY) {
- unsigned char bytes[32] = {0};
+ int nbytes = (curve->fieldBits+7) / 8;
+ unsigned char bytes[56] = {0};
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[0] &= 248;
- bytes[31] &= 127;
- bytes[31] |= 64;
- key->privateKey = bignum_from_bytes_le(bytes, sizeof(bytes));
- smemclr(bytes, sizeof(bytes));
+ bytes[0] &= extra->low_byte_mask;
+ bytes[nbytes-1] &= extra->high_byte_top_bit - 1;
+ bytes[nbytes-1] |= extra->high_byte_top_bit;
+ key->privateKey = bignum_from_bytes_le(bytes, nbytes);
+ smemclr(bytes, nbytes);
if (!key->privateKey) {
sfree(key);
return NULL;
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 = {
"curve25519-sha256@libssh.org", NULL, KEXTYPE_ECDH,
&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 };
static const struct ssh_kex ssh_ec_kex_nistp256 = {
"ecdh-sha2-nistp256", NULL, KEXTYPE_ECDH,
};
static const struct ssh_kex *const ec_kex_list[] = {
+ &ssh_ec_kex_curve448,
&ssh_ec_kex_curve25519,
&ssh_ec_kex_nistp256,
&ssh_ec_kex_nistp384,