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

Turn SSH hashes into a classoid.

The new version of ssh_hash has the same nice property as ssh2_mac,
that I can make the generic interface object type function directly as
a BinarySink so that clients don't have to call h->sink() and worry
about the separate sink object they get back from that.
This commit is contained in:
Simon Tatham 2018-09-13 16:41:46 +01:00
parent 853bd8b284
commit 4f9a90fc1a
7 changed files with 210 additions and 204 deletions

99
ssh.c
View File

@ -668,8 +668,7 @@ enum RekeyClass {
struct ssh_tag { struct ssh_tag {
char *v_c, *v_s; char *v_c, *v_s;
void *exhash; ssh_hash *exhash;
BinarySink *exhash_bs;
Socket s; Socket s;
@ -4780,11 +4779,10 @@ static void add_to_commasep(strbuf *buf, const char *data)
static void ssh2_mkkey(Ssh ssh, strbuf *out, Bignum K, unsigned char *H, static void ssh2_mkkey(Ssh ssh, strbuf *out, Bignum K, unsigned char *H,
char chr, int keylen) char chr, int keylen)
{ {
const struct ssh_hash *h = ssh->kex->hash; const struct ssh_hashalg *h = ssh->kex->hash;
int keylen_padded; int keylen_padded;
unsigned char *key; unsigned char *key;
void *s, *s2; ssh_hash *s, *s2;
BinarySink *bs;
if (keylen == 0) if (keylen == 0)
return; return;
@ -4805,32 +4803,30 @@ static void ssh2_mkkey(Ssh ssh, strbuf *out, Bignum K, unsigned char *H,
key = strbuf_append(out, keylen_padded); key = strbuf_append(out, keylen_padded);
/* First hlen bytes. */ /* First hlen bytes. */
s = h->init(); s = ssh_hash_new(h);
bs = h->sink(s);
if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY)) if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY))
put_mp_ssh2(bs, K); put_mp_ssh2(s, K);
put_data(bs, H, h->hlen); put_data(s, H, h->hlen);
put_byte(bs, chr); put_byte(s, chr);
put_data(bs, ssh->v2_session_id, ssh->v2_session_id_len); put_data(s, ssh->v2_session_id, ssh->v2_session_id_len);
h->final(s, key); ssh_hash_final(s, key);
/* Subsequent blocks of hlen bytes. */ /* Subsequent blocks of hlen bytes. */
if (keylen_padded > h->hlen) { if (keylen_padded > h->hlen) {
int offset; int offset;
s = h->init(); s = ssh_hash_new(h);
bs = h->sink(s);
if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY)) if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY))
put_mp_ssh2(bs, K); put_mp_ssh2(s, K);
put_data(bs, H, h->hlen); put_data(s, H, h->hlen);
for (offset = h->hlen; offset < keylen_padded; offset += h->hlen) { for (offset = h->hlen; offset < keylen_padded; offset += h->hlen) {
put_data(bs, key + offset - h->hlen, h->hlen); put_data(s, key + offset - h->hlen, h->hlen);
s2 = h->copy(s); s2 = ssh_hash_copy(s);
h->final(s2, key + offset); ssh_hash_final(s2, key + offset);
} }
h->free(s); ssh_hash_free(s);
} }
} }
@ -5600,14 +5596,13 @@ static void do_ssh2_transport(void *vctx)
get_string(pktin); /* server->client language */ get_string(pktin); /* server->client language */
s->ignorepkt = get_bool(pktin) && !s->guessok; s->ignorepkt = get_bool(pktin) && !s->guessok;
ssh->exhash = ssh->kex->hash->init(); ssh->exhash = ssh_hash_new(ssh->kex->hash);
ssh->exhash_bs = ssh->kex->hash->sink(ssh->exhash); put_stringz(ssh->exhash, ssh->v_c);
put_stringz(ssh->exhash_bs, ssh->v_c); put_stringz(ssh->exhash, ssh->v_s);
put_stringz(ssh->exhash_bs, ssh->v_s); put_string(ssh->exhash, s->our_kexinit, s->our_kexinitlen);
put_string(ssh->exhash_bs, s->our_kexinit, s->our_kexinitlen);
sfree(s->our_kexinit); sfree(s->our_kexinit);
/* Include the type byte in the hash of server's KEXINIT */ /* Include the type byte in the hash of server's KEXINIT */
put_string(ssh->exhash_bs, put_string(ssh->exhash,
(const char *)BinarySource_UPCAST(pktin)->data - 1, (const char *)BinarySource_UPCAST(pktin)->data - 1,
BinarySource_UPCAST(pktin)->len + 1); BinarySource_UPCAST(pktin)->len + 1);
@ -5844,18 +5839,18 @@ static void do_ssh2_transport(void *vctx)
* involve user interaction. */ * involve user interaction. */
set_busy_status(ssh->frontend, BUSY_NOT); set_busy_status(ssh->frontend, BUSY_NOT);
put_stringpl(ssh->exhash_bs, s->hostkeydata); put_stringpl(ssh->exhash, s->hostkeydata);
if (dh_is_gex(ssh->kex)) { if (dh_is_gex(ssh->kex)) {
if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX)) if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX))
put_uint32(ssh->exhash_bs, DH_MIN_SIZE); put_uint32(ssh->exhash, DH_MIN_SIZE);
put_uint32(ssh->exhash_bs, s->pbits); put_uint32(ssh->exhash, s->pbits);
if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX)) if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX))
put_uint32(ssh->exhash_bs, DH_MAX_SIZE); put_uint32(ssh->exhash, DH_MAX_SIZE);
put_mp_ssh2(ssh->exhash_bs, s->p); put_mp_ssh2(ssh->exhash, s->p);
put_mp_ssh2(ssh->exhash_bs, s->g); put_mp_ssh2(ssh->exhash, s->g);
} }
put_mp_ssh2(ssh->exhash_bs, s->e); put_mp_ssh2(ssh->exhash, s->e);
put_mp_ssh2(ssh->exhash_bs, s->f); put_mp_ssh2(ssh->exhash, s->f);
dh_cleanup(ssh->kex_ctx); dh_cleanup(ssh->kex_ctx);
freebn(s->f); freebn(s->f);
@ -5893,19 +5888,19 @@ static void do_ssh2_transport(void *vctx)
} }
s->hostkeydata = get_string(pktin); s->hostkeydata = get_string(pktin);
put_stringpl(ssh->exhash_bs, s->hostkeydata); put_stringpl(ssh->exhash, s->hostkeydata);
s->hkey = ssh_key_new_pub(ssh->hostkey_alg, s->hostkeydata); s->hkey = ssh_key_new_pub(ssh->hostkey_alg, s->hostkeydata);
{ {
strbuf *pubpoint = strbuf_new(); strbuf *pubpoint = strbuf_new();
ssh_ecdhkex_getpublic(s->eckey, BinarySink_UPCAST(pubpoint)); ssh_ecdhkex_getpublic(s->eckey, BinarySink_UPCAST(pubpoint));
put_string(ssh->exhash_bs, pubpoint->u, pubpoint->len); put_string(ssh->exhash, pubpoint->u, pubpoint->len);
strbuf_free(pubpoint); strbuf_free(pubpoint);
} }
{ {
ptrlen keydata = get_string(pktin); ptrlen keydata = get_string(pktin);
put_stringpl(ssh->exhash_bs, keydata); put_stringpl(ssh->exhash, keydata);
s->K = ssh_ecdhkex_getkey(s->eckey, keydata.ptr, keydata.len); s->K = ssh_ecdhkex_getkey(s->eckey, keydata.ptr, keydata.len);
if (!get_err(pktin) && !s->K) { if (!get_err(pktin) && !s->K) {
ssh_ecdhkex_freekey(s->eckey); ssh_ecdhkex_freekey(s->eckey);
@ -6100,7 +6095,7 @@ static void do_ssh2_transport(void *vctx)
if (ssh->hostkey_alg) { if (ssh->hostkey_alg) {
s->hkey = ssh_key_new_pub(ssh->hostkey_alg, s->hkey = ssh_key_new_pub(ssh->hostkey_alg,
s->hostkeydata); s->hostkeydata);
put_string(ssh->exhash_bs, put_string(ssh->exhash,
s->hostkeydata.ptr, s->hostkeydata.len); s->hostkeydata.ptr, s->hostkeydata.len);
} }
/* /*
@ -6149,18 +6144,18 @@ static void do_ssh2_transport(void *vctx)
set_busy_status(ssh->frontend, BUSY_NOT); set_busy_status(ssh->frontend, BUSY_NOT);
if (!s->hkey) if (!s->hkey)
put_stringz(ssh->exhash_bs, ""); put_stringz(ssh->exhash, "");
if (dh_is_gex(ssh->kex)) { if (dh_is_gex(ssh->kex)) {
/* min, preferred, max */ /* min, preferred, max */
put_uint32(ssh->exhash_bs, s->pbits); put_uint32(ssh->exhash, s->pbits);
put_uint32(ssh->exhash_bs, s->pbits); put_uint32(ssh->exhash, s->pbits);
put_uint32(ssh->exhash_bs, s->pbits * 2); put_uint32(ssh->exhash, s->pbits * 2);
put_mp_ssh2(ssh->exhash_bs, s->p); put_mp_ssh2(ssh->exhash, s->p);
put_mp_ssh2(ssh->exhash_bs, s->g); put_mp_ssh2(ssh->exhash, s->g);
} }
put_mp_ssh2(ssh->exhash_bs, s->e); put_mp_ssh2(ssh->exhash, s->e);
put_mp_ssh2(ssh->exhash_bs, s->f); put_mp_ssh2(ssh->exhash, s->f);
/* /*
* MIC verification is done below, after we compute the hash * MIC verification is done below, after we compute the hash
@ -6192,7 +6187,7 @@ static void do_ssh2_transport(void *vctx)
} }
s->hostkeydata = get_string(pktin); s->hostkeydata = get_string(pktin);
put_stringpl(ssh->exhash_bs, s->hostkeydata); put_stringpl(ssh->exhash, s->hostkeydata);
s->hkey = ssh_key_new_pub(ssh->hostkey_alg, s->hostkeydata); s->hkey = ssh_key_new_pub(ssh->hostkey_alg, s->hostkeydata);
rsakeydata = get_string(pktin); rsakeydata = get_string(pktin);
@ -6203,7 +6198,7 @@ static void do_ssh2_transport(void *vctx)
crStopV; crStopV;
} }
put_stringpl(ssh->exhash_bs, rsakeydata); put_stringpl(ssh->exhash, rsakeydata);
/* /*
* Next, set up a shared secret K, of precisely KLEN - * Next, set up a shared secret K, of precisely KLEN -
@ -6249,7 +6244,7 @@ static void do_ssh2_transport(void *vctx)
put_string(s->pktout, outstr, outstrlen); put_string(s->pktout, outstr, outstrlen);
ssh_pkt_write(ssh, s->pktout); ssh_pkt_write(ssh, s->pktout);
put_string(ssh->exhash_bs, outstr, outstrlen); put_string(ssh->exhash, outstr, outstrlen);
strbuf_free(buf); strbuf_free(buf);
sfree(outstr); sfree(outstr);
@ -6270,9 +6265,9 @@ static void do_ssh2_transport(void *vctx)
} }
} }
put_mp_ssh2(ssh->exhash_bs, s->K); put_mp_ssh2(ssh->exhash, s->K);
assert(ssh->kex->hash->hlen <= sizeof(s->exchange_hash)); assert(ssh_hash_alg(ssh->exhash)->hlen <= sizeof(s->exchange_hash));
ssh->kex->hash->final(ssh->exhash, s->exchange_hash); ssh_hash_final(ssh->exhash, s->exchange_hash);
#ifndef NO_GSSAPI #ifndef NO_GSSAPI
if (ssh->kex->main_type == KEXTYPE_GSS) { if (ssh->kex->main_type == KEXTYPE_GSS) {

37
ssh.h
View File

@ -331,11 +331,12 @@ int detect_attack(struct crcda_ctx *ctx, unsigned char *buf, uint32 len,
/* /*
* SSH2 RSA key exchange functions * SSH2 RSA key exchange functions
*/ */
struct ssh_hash; struct ssh_hashalg;
struct RSAKey *ssh_rsakex_newkey(const void *data, int len); struct RSAKey *ssh_rsakex_newkey(const void *data, int len);
void ssh_rsakex_freekey(struct RSAKey *key); void ssh_rsakex_freekey(struct RSAKey *key);
int ssh_rsakex_klen(struct RSAKey *key); int ssh_rsakex_klen(struct RSAKey *key);
void ssh_rsakex_encrypt(const struct ssh_hash *h, unsigned char *in, int inlen, void ssh_rsakex_encrypt(const struct ssh_hashalg *h,
unsigned char *in, int inlen,
unsigned char *out, int outlen, struct RSAKey *key); unsigned char *out, int outlen, struct RSAKey *key);
/* /*
@ -527,20 +528,30 @@ int ssh2_mac_verresult(ssh2_mac *, const void *);
void ssh2_mac_generate(ssh2_mac *, void *, int, unsigned long seq); void ssh2_mac_generate(ssh2_mac *, void *, int, unsigned long seq);
int ssh2_mac_verify(ssh2_mac *, const void *, int, unsigned long seq); int ssh2_mac_verify(ssh2_mac *, const void *, int, unsigned long seq);
struct ssh_hash { typedef struct ssh_hash {
void *(*init)(void); /* also allocates context */ const struct ssh_hashalg *vt;
void *(*copy)(const void *); BinarySink_DELEGATE_IMPLEMENTATION;
BinarySink *(*sink) (void *); } ssh_hash;
void (*final)(void *, unsigned char *); /* also frees context */
void (*free)(void *); struct ssh_hashalg {
ssh_hash *(*new)(const struct ssh_hashalg *alg);
ssh_hash *(*copy)(ssh_hash *);
void (*final)(ssh_hash *, unsigned char *); /* ALSO FREES THE ssh_hash! */
void (*free)(ssh_hash *);
int hlen; /* output length in bytes */ int hlen; /* output length in bytes */
const char *text_name; const char *text_name;
}; };
#define ssh_hash_new(alg) ((alg)->new(alg))
#define ssh_hash_copy(ctx) ((ctx)->vt->copy(ctx))
#define ssh_hash_final(ctx, out) ((ctx)->vt->final(ctx, out))
#define ssh_hash_free(ctx) ((ctx)->vt->free(ctx))
#define ssh_hash_alg(ctx) ((ctx)->vt)
struct ssh_kex { struct ssh_kex {
const char *name, *groupname; const char *name, *groupname;
enum { KEXTYPE_DH, KEXTYPE_RSA, KEXTYPE_ECDH, KEXTYPE_GSS } main_type; enum { KEXTYPE_DH, KEXTYPE_RSA, KEXTYPE_ECDH, KEXTYPE_GSS } main_type;
const struct ssh_hash *hash; const struct ssh_hashalg *hash;
const void *extra; /* private to the kex methods */ const void *extra; /* private to the kex methods */
}; };
@ -625,10 +636,10 @@ extern const struct ssh2_ciphers ssh2_aes;
extern const struct ssh2_ciphers ssh2_blowfish; extern const struct ssh2_ciphers ssh2_blowfish;
extern const struct ssh2_ciphers ssh2_arcfour; extern const struct ssh2_ciphers ssh2_arcfour;
extern const struct ssh2_ciphers ssh2_ccp; extern const struct ssh2_ciphers ssh2_ccp;
extern const struct ssh_hash ssh_sha1; extern const struct ssh_hashalg ssh_sha1;
extern const struct ssh_hash ssh_sha256; extern const struct ssh_hashalg ssh_sha256;
extern const struct ssh_hash ssh_sha384; extern const struct ssh_hashalg ssh_sha384;
extern const struct ssh_hash ssh_sha512; extern const struct ssh_hashalg ssh_sha512;
extern const struct ssh_kexes ssh_diffiehellman_group1; extern const struct ssh_kexes ssh_diffiehellman_group1;
extern const struct ssh_kexes ssh_diffiehellman_group14; extern const struct ssh_kexes ssh_diffiehellman_group14;
extern const struct ssh_kexes ssh_diffiehellman_gex; extern const struct ssh_kexes ssh_diffiehellman_gex;

View File

@ -1688,7 +1688,7 @@ static int BinarySource_get_point(BinarySource *src, 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; const struct ssh_hashalg *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;
@ -2227,7 +2227,7 @@ static int ecdsa_verify(ssh_key *key, ptrlen sig, ptrlen data)
Bignum r, s; Bignum r, s;
unsigned char digest[512 / 8]; unsigned char digest[512 / 8];
int digestLen; int digestLen;
void *hashctx; ssh_hash *hashctx;
BinarySource_BARE_INIT(src, sigstr.ptr, sigstr.len); BinarySource_BARE_INIT(src, sigstr.ptr, sigstr.len);
@ -2241,9 +2241,9 @@ static int ecdsa_verify(ssh_key *key, ptrlen sig, ptrlen data)
digestLen = extra->hash->hlen; digestLen = extra->hash->hlen;
assert(digestLen <= sizeof(digest)); assert(digestLen <= sizeof(digest));
hashctx = extra->hash->init(); hashctx = ssh_hash_new(extra->hash);
put_data(extra->hash->sink(hashctx), data.ptr, data.len); put_data(hashctx, data.ptr, data.len);
extra->hash->final(hashctx, digest); ssh_hash_final(hashctx, digest);
/* Verify the signature */ /* Verify the signature */
ret = _ecdsa_verify(&ec->publicKey, digest, digestLen, r, s); ret = _ecdsa_verify(&ec->publicKey, digest, digestLen, r, s);
@ -2363,14 +2363,14 @@ static void ecdsa_sign(ssh_key *key, const void *data, int datalen,
put_byte(bs, bignum_byte(s, i)); put_byte(bs, bignum_byte(s, i));
freebn(s); freebn(s);
} else { } else {
void *hashctx; ssh_hash *hashctx;
strbuf *substr; strbuf *substr;
digestLen = extra->hash->hlen; digestLen = extra->hash->hlen;
assert(digestLen <= sizeof(digest)); assert(digestLen <= sizeof(digest));
hashctx = extra->hash->init(); hashctx = ssh_hash_new(extra->hash);
put_data(extra->hash->sink(hashctx), data, datalen); put_data(hashctx, data, datalen);
extra->hash->final(hashctx, digest); ssh_hash_final(hashctx, digest);
/* 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);

View File

@ -783,7 +783,7 @@ int ssh_rsakex_klen(struct RSAKey *rsa)
return bignum_bitcount(rsa->modulus); return bignum_bitcount(rsa->modulus);
} }
static void oaep_mask(const struct ssh_hash *h, void *seed, int seedlen, static void oaep_mask(const struct ssh_hashalg *h, void *seed, int seedlen,
void *vdata, int datalen) void *vdata, int datalen)
{ {
unsigned char *data = (unsigned char *)vdata; unsigned char *data = (unsigned char *)vdata;
@ -791,16 +791,14 @@ static void oaep_mask(const struct ssh_hash *h, void *seed, int seedlen,
while (datalen > 0) { while (datalen > 0) {
int i, max = (datalen > h->hlen ? h->hlen : datalen); int i, max = (datalen > h->hlen ? h->hlen : datalen);
void *s; ssh_hash *s;
BinarySink *bs;
unsigned char hash[SSH2_KEX_MAX_HASH_LEN]; unsigned char hash[SSH2_KEX_MAX_HASH_LEN];
assert(h->hlen <= SSH2_KEX_MAX_HASH_LEN); assert(h->hlen <= SSH2_KEX_MAX_HASH_LEN);
s = h->init(); s = ssh_hash_new(h);
bs = h->sink(s); put_data(s, seed, seedlen);
put_data(bs, seed, seedlen); put_uint32(s, count);
put_uint32(bs, count); ssh_hash_final(s, hash);
h->final(s, hash);
count++; count++;
for (i = 0; i < max; i++) for (i = 0; i < max; i++)
@ -811,7 +809,8 @@ static void oaep_mask(const struct ssh_hash *h, void *seed, int seedlen,
} }
} }
void ssh_rsakex_encrypt(const struct ssh_hash *h, unsigned char *in, int inlen, void ssh_rsakex_encrypt(const struct ssh_hashalg *h,
unsigned char *in, int inlen,
unsigned char *out, int outlen, struct RSAKey *rsa) unsigned char *out, int outlen, struct RSAKey *rsa)
{ {
Bignum b1, b2; Bignum b1, b2;
@ -866,7 +865,10 @@ void ssh_rsakex_encrypt(const struct ssh_hash *h, unsigned char *in, int inlen,
out[i + 1] = random_byte(); out[i + 1] = random_byte();
/* At position 1+HLEN, the data block DB, consisting of: */ /* At position 1+HLEN, the data block DB, consisting of: */
/* The hash of the label (we only support an empty label here) */ /* The hash of the label (we only support an empty label here) */
h->final(h->init(), out + HLEN + 1); {
ssh_hash *s = ssh_hash_new(h);
ssh_hash_final(s, out + HLEN + 1);
}
/* A bunch of zero octets */ /* A bunch of zero octets */
memset(out + 2*HLEN + 1, 0, outlen - (2*HLEN + 1)); memset(out + 2*HLEN + 1, 0, outlen - (2*HLEN + 1));
/* A single 1 octet, followed by the input message data. */ /* A single 1 octet, followed by the input message data. */

View File

@ -204,51 +204,51 @@ void SHA256_Simple(const void *p, int len, unsigned char *output) {
* Thin abstraction for things where hashes are pluggable. * Thin abstraction for things where hashes are pluggable.
*/ */
static void *sha256_init(void) struct sha256_hash {
{ SHA256_State state;
SHA256_State *s; ssh_hash hash;
};
s = snew(SHA256_State); static ssh_hash *sha256_new(const struct ssh_hashalg *alg)
SHA256_Init(s); {
return s; struct sha256_hash *h = snew(struct sha256_hash);
SHA256_Init(&h->state);
h->hash.vt = alg;
BinarySink_DELEGATE_INIT(&h->hash, &h->state);
return &h->hash;
} }
static void *sha256_copy(const void *vold) static ssh_hash *sha256_copy(ssh_hash *hashold)
{ {
const SHA256_State *old = (const SHA256_State *)vold; struct sha256_hash *hold, *hnew;
SHA256_State *s; ssh_hash *hashnew = sha256_new(hashold->vt);
s = snew(SHA256_State); hold = FROMFIELD(hashold, struct sha256_hash, hash);
*s = *old; hnew = FROMFIELD(hashnew, struct sha256_hash, hash);
BinarySink_COPIED(s);
return s; hnew->state = hold->state;
BinarySink_COPIED(&hnew->state);
return hashnew;
} }
static void sha256_free(void *handle) static void sha256_free(ssh_hash *hash)
{ {
SHA256_State *s = handle; struct sha256_hash *h = FROMFIELD(hash, struct sha256_hash, hash);
smemclr(s, sizeof(*s)); smemclr(h, sizeof(*h));
sfree(s); sfree(h);
} }
static BinarySink *sha256_sink(void *handle) static void sha256_final(ssh_hash *hash, unsigned char *output)
{ {
SHA256_State *s = handle; struct sha256_hash *h = FROMFIELD(hash, struct sha256_hash, hash);
return BinarySink_UPCAST(s); SHA256_Final(&h->state, output);
sha256_free(hash);
} }
static void sha256_final(void *handle, unsigned char *output) const struct ssh_hashalg ssh_sha256 = {
{ sha256_new, sha256_copy, sha256_final, sha256_free, 32, "SHA-256"
SHA256_State *s = handle;
SHA256_Final(s, output);
sha256_free(s);
}
const struct ssh_hash ssh_sha256 = {
sha256_init, sha256_copy, sha256_sink, sha256_final, sha256_free,
32, "SHA-256"
}; };
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------

View File

@ -327,74 +327,71 @@ void SHA384_Simple(const void *p, int len, unsigned char *output) {
* Thin abstraction for things where hashes are pluggable. * Thin abstraction for things where hashes are pluggable.
*/ */
static void *sha512_init(void) struct sha512_hash {
{ SHA512_State state;
SHA512_State *s; ssh_hash hash;
s = snew(SHA512_State);
SHA512_Init(s);
return s;
}
static void *sha512_copy(const void *vold)
{
const SHA512_State *old = (const SHA512_State *)vold;
SHA512_State *s;
s = snew(SHA512_State);
*s = *old;
BinarySink_COPIED(s);
return s;
}
static void sha512_free(void *handle)
{
SHA512_State *s = handle;
smemclr(s, sizeof(*s));
sfree(s);
}
static BinarySink *sha512_sink(void *handle)
{
SHA512_State *s = handle;
return BinarySink_UPCAST(s);
}
static void sha512_final(void *handle, unsigned char *output)
{
SHA512_State *s = handle;
SHA512_Final(s, output);
sha512_free(s);
}
const struct ssh_hash ssh_sha512 = {
sha512_init, sha512_copy, sha512_sink, sha512_final, sha512_free,
64, "SHA-512"
}; };
static void *sha384_init(void) static ssh_hash *sha512_new(const struct ssh_hashalg *alg)
{ {
SHA512_State *s; struct sha512_hash *h = snew(struct sha512_hash);
SHA512_Init(&h->state);
s = snew(SHA512_State); h->hash.vt = alg;
SHA384_Init(s); BinarySink_DELEGATE_INIT(&h->hash, &h->state);
return s; return &h->hash;
} }
static void sha384_final(void *handle, unsigned char *output) static ssh_hash *sha512_copy(ssh_hash *hashold)
{ {
SHA512_State *s = handle; struct sha512_hash *hold, *hnew;
ssh_hash *hashnew = sha512_new(hashold->vt);
SHA384_Final(s, output); hold = FROMFIELD(hashold, struct sha512_hash, hash);
smemclr(s, sizeof(*s)); hnew = FROMFIELD(hashnew, struct sha512_hash, hash);
sfree(s);
hnew->state = hold->state;
BinarySink_COPIED(&hnew->state);
return hashnew;
} }
const struct ssh_hash ssh_sha384 = { static void sha512_free(ssh_hash *hash)
sha384_init, sha512_copy, sha512_sink, sha384_final, sha512_free, {
48, "SHA-384" struct sha512_hash *h = FROMFIELD(hash, struct sha512_hash, hash);
smemclr(h, sizeof(*h));
sfree(h);
}
static void sha512_final(ssh_hash *hash, unsigned char *output)
{
struct sha512_hash *h = FROMFIELD(hash, struct sha512_hash, hash);
SHA512_Final(&h->state, output);
sha512_free(hash);
}
const struct ssh_hashalg ssh_sha512 = {
sha512_new, sha512_copy, sha512_final, sha512_free, 64, "SHA-512"
};
static ssh_hash *sha384_new(const struct ssh_hashalg *alg)
{
struct sha512_hash *h = snew(struct sha512_hash);
SHA384_Init(&h->state);
h->hash.vt = alg;
BinarySink_DELEGATE_INIT(&h->hash, &h->state);
return &h->hash;
}
static void sha384_final(ssh_hash *hash, unsigned char *output)
{
struct sha512_hash *h = FROMFIELD(hash, struct sha512_hash, hash);
SHA384_Final(&h->state, output);
sha512_free(hash);
}
const struct ssh_hashalg ssh_sha384 = {
sha384_new, sha512_copy, sha384_final, sha512_free, 48, "SHA-384"
}; };
#ifdef TEST #ifdef TEST

View File

@ -232,50 +232,51 @@ void SHA_Simple(const void *p, int len, unsigned char *output)
* Thin abstraction for things where hashes are pluggable. * Thin abstraction for things where hashes are pluggable.
*/ */
static void *sha1_init(void) struct sha1_hash {
{ SHA_State state;
SHA_State *s; ssh_hash hash;
};
s = snew(SHA_State); static ssh_hash *sha1_new(const struct ssh_hashalg *alg)
SHA_Init(s); {
return s; struct sha1_hash *h = snew(struct sha1_hash);
SHA_Init(&h->state);
h->hash.vt = alg;
BinarySink_DELEGATE_INIT(&h->hash, &h->state);
return &h->hash;
} }
static void *sha1_copy(const void *vold) static ssh_hash *sha1_copy(ssh_hash *hashold)
{ {
const SHA_State *old = (const SHA_State *)vold; struct sha1_hash *hold, *hnew;
SHA_State *s; ssh_hash *hashnew = sha1_new(hashold->vt);
s = snew(SHA_State); hold = FROMFIELD(hashold, struct sha1_hash, hash);
*s = *old; hnew = FROMFIELD(hashnew, struct sha1_hash, hash);
BinarySink_COPIED(s);
return s; hnew->state = hold->state;
BinarySink_COPIED(&hnew->state);
return hashnew;
} }
static void sha1_free(void *handle) static void sha1_free(ssh_hash *hash)
{ {
SHA_State *s = handle; struct sha1_hash *h = FROMFIELD(hash, struct sha1_hash, hash);
smemclr(s, sizeof(*s)); smemclr(h, sizeof(*h));
sfree(s); sfree(h);
} }
static BinarySink *sha1_sink(void *handle) static void sha1_final(ssh_hash *hash, unsigned char *output)
{ {
SHA_State *s = handle; struct sha1_hash *h = FROMFIELD(hash, struct sha1_hash, hash);
return BinarySink_UPCAST(s); SHA_Final(&h->state, output);
sha1_free(hash);
} }
static void sha1_final(void *handle, unsigned char *output) const struct ssh_hashalg ssh_sha1 = {
{ sha1_new, sha1_copy, sha1_final, sha1_free, 20, "SHA-1"
SHA_State *s = handle;
SHA_Final(s, output);
sha1_free(s);
}
const struct ssh_hash ssh_sha1 = {
sha1_init, sha1_copy, sha1_sink, sha1_final, sha1_free, 20, "SHA-1"
}; };
/* ---------------------------------------------------------------------- /* ----------------------------------------------------------------------