1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-25 01:02:24 +00:00

Clean up hash selection in ECDSA.

Removed another set of ad-hoc tests of the key size to decide which
hash to use for the signature system, and replaced them with a
straightforward pointer to an ssh_hash structure in the 'extra' area.
This commit is contained in:
Simon Tatham 2015-05-15 10:13:06 +01:00
parent 7db526c730
commit a8c4e67ff9

View File

@ -2451,6 +2451,7 @@ static int getmppoint(const char **data, int *datalen, struct ec_point *point)
struct ecsign_extra { struct ecsign_extra {
struct ec_curve *(*curve)(void); struct ec_curve *(*curve)(void);
const struct ssh_hash *hash;
/* These fields are used by the OpenSSH PEM format importer/exporter */ /* These fields are used by the OpenSSH PEM format importer/exporter */
const unsigned char *oid; const unsigned char *oid;
@ -2979,6 +2980,8 @@ static int ecdsa_verifysig(void *key, const char *sig, int siglen,
const char *data, int datalen) const char *data, int datalen)
{ {
struct ec_key *ec = (struct ec_key *) key; struct ec_key *ec = (struct ec_key *) key;
const struct ecsign_extra *extra =
(const struct ecsign_extra *)ec->signalg->extra;
const char *p; const char *p;
int slen; int slen;
int digestLen; int digestLen;
@ -3107,6 +3110,7 @@ static int ecdsa_verifysig(void *key, const char *sig, int siglen,
} else { } else {
Bignum r, s; Bignum r, s;
unsigned char digest[512 / 8]; unsigned char digest[512 / 8];
void *hashctx;
r = getmp(&p, &slen); r = getmp(&p, &slen);
if (!r) return 0; if (!r) return 0;
@ -3116,17 +3120,11 @@ static int ecdsa_verifysig(void *key, const char *sig, int siglen,
return 0; return 0;
} }
/* Perform correct hash function depending on curve size */ digestLen = extra->hash->hlen;
if (ec->publicKey.curve->fieldBits <= 256) { assert(digestLen <= sizeof(digest));
SHA256_Simple(data, datalen, digest); hashctx = extra->hash->init();
digestLen = 256 / 8; extra->hash->bytes(hashctx, data, datalen);
} else if (ec->publicKey.curve->fieldBits <= 384) { extra->hash->final(hashctx, digest);
SHA384_Simple(data, datalen, digest);
digestLen = 384 / 8;
} else {
SHA512_Simple(data, datalen, digest);
digestLen = 512 / 8;
}
/* Verify the signature */ /* Verify the signature */
ret = _ecdsa_verify(&ec->publicKey, digest, digestLen, r, s); ret = _ecdsa_verify(&ec->publicKey, digest, digestLen, r, s);
@ -3142,6 +3140,8 @@ static unsigned char *ecdsa_sign(void *key, const char *data, int datalen,
int *siglen) int *siglen)
{ {
struct ec_key *ec = (struct ec_key *) key; struct ec_key *ec = (struct ec_key *) key;
const struct ecsign_extra *extra =
(const struct ecsign_extra *)ec->signalg->extra;
unsigned char digest[512 / 8]; unsigned char digest[512 / 8];
int digestLen; int digestLen;
Bignum r = NULL, s = NULL; Bignum r = NULL, s = NULL;
@ -3297,17 +3297,13 @@ static unsigned char *ecdsa_sign(void *key, const char *data, int datalen,
} }
freebn(s); freebn(s);
} else { } else {
/* Perform correct hash function depending on curve size */ void *hashctx;
if (ec->publicKey.curve->fieldBits <= 256) {
SHA256_Simple(data, datalen, digest); digestLen = extra->hash->hlen;
digestLen = 256 / 8; assert(digestLen <= sizeof(digest));
} else if (ec->publicKey.curve->fieldBits <= 384) { hashctx = extra->hash->init();
SHA384_Simple(data, datalen, digest); extra->hash->bytes(hashctx, data, datalen);
digestLen = 384 / 8; extra->hash->final(hashctx, digest);
} else {
SHA512_Simple(data, datalen, digest);
digestLen = 512 / 8;
}
/* Do the signature */ /* Do the signature */
_ecdsa_sign(ec->privateKey, ec->publicKey.curve, digest, digestLen, &r, &s); _ecdsa_sign(ec->privateKey, ec->publicKey.curve, digest, digestLen, &r, &s);
@ -3349,7 +3345,7 @@ static unsigned char *ecdsa_sign(void *key, const char *data, int datalen,
} }
const struct ecsign_extra sign_extra_ed25519 = { const struct ecsign_extra sign_extra_ed25519 = {
ec_ed25519, ec_ed25519, NULL,
NULL, 0, NULL, 0,
}; };
const struct ssh_signkey ssh_ecdsa_ed25519 = { const struct ssh_signkey ssh_ecdsa_ed25519 = {
@ -3375,7 +3371,7 @@ static const unsigned char nistp256_oid[] = {
0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07
}; };
const struct ecsign_extra sign_extra_nistp256 = { const struct ecsign_extra sign_extra_nistp256 = {
ec_p256, ec_p256, &ssh_sha256,
nistp256_oid, lenof(nistp256_oid), nistp256_oid, lenof(nistp256_oid),
}; };
const struct ssh_signkey ssh_ecdsa_nistp256 = { const struct ssh_signkey ssh_ecdsa_nistp256 = {
@ -3401,7 +3397,7 @@ static const unsigned char nistp384_oid[] = {
0x2b, 0x81, 0x04, 0x00, 0x22 0x2b, 0x81, 0x04, 0x00, 0x22
}; };
const struct ecsign_extra sign_extra_nistp384 = { const struct ecsign_extra sign_extra_nistp384 = {
ec_p384, ec_p384, &ssh_sha384,
nistp384_oid, lenof(nistp384_oid), nistp384_oid, lenof(nistp384_oid),
}; };
const struct ssh_signkey ssh_ecdsa_nistp384 = { const struct ssh_signkey ssh_ecdsa_nistp384 = {
@ -3427,7 +3423,7 @@ static const unsigned char nistp521_oid[] = {
0x2b, 0x81, 0x04, 0x00, 0x23 0x2b, 0x81, 0x04, 0x00, 0x23
}; };
const struct ecsign_extra sign_extra_nistp521 = { const struct ecsign_extra sign_extra_nistp521 = {
ec_p521, ec_p521, &ssh_sha512,
nistp521_oid, lenof(nistp521_oid), nistp521_oid, lenof(nistp521_oid),
}; };
const struct ssh_signkey ssh_ecdsa_nistp521 = { const struct ssh_signkey ssh_ecdsa_nistp521 = {