diff --git a/ssh.c b/ssh.c index 814d28b7..ab6d6fbe 100644 --- a/ssh.c +++ b/ssh.c @@ -668,8 +668,7 @@ enum RekeyClass { struct ssh_tag { char *v_c, *v_s; - void *exhash; - BinarySink *exhash_bs; + ssh_hash *exhash; 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, char chr, int keylen) { - const struct ssh_hash *h = ssh->kex->hash; + const struct ssh_hashalg *h = ssh->kex->hash; int keylen_padded; unsigned char *key; - void *s, *s2; - BinarySink *bs; + ssh_hash *s, *s2; if (keylen == 0) return; @@ -4805,32 +4803,30 @@ static void ssh2_mkkey(Ssh ssh, strbuf *out, Bignum K, unsigned char *H, key = strbuf_append(out, keylen_padded); /* First hlen bytes. */ - s = h->init(); - bs = h->sink(s); + s = ssh_hash_new(h); if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY)) - put_mp_ssh2(bs, K); - put_data(bs, H, h->hlen); - put_byte(bs, chr); - put_data(bs, ssh->v2_session_id, ssh->v2_session_id_len); - h->final(s, key); + put_mp_ssh2(s, K); + put_data(s, H, h->hlen); + put_byte(s, chr); + put_data(s, ssh->v2_session_id, ssh->v2_session_id_len); + ssh_hash_final(s, key); /* Subsequent blocks of hlen bytes. */ if (keylen_padded > h->hlen) { int offset; - s = h->init(); - bs = h->sink(s); + s = ssh_hash_new(h); if (!(ssh->remote_bugs & BUG_SSH2_DERIVEKEY)) - put_mp_ssh2(bs, K); - put_data(bs, H, h->hlen); + put_mp_ssh2(s, K); + put_data(s, H, h->hlen); for (offset = h->hlen; offset < keylen_padded; offset += h->hlen) { - put_data(bs, key + offset - h->hlen, h->hlen); - s2 = h->copy(s); - h->final(s2, key + offset); + put_data(s, key + offset - h->hlen, h->hlen); + s2 = ssh_hash_copy(s); + 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 */ s->ignorepkt = get_bool(pktin) && !s->guessok; - ssh->exhash = ssh->kex->hash->init(); - ssh->exhash_bs = ssh->kex->hash->sink(ssh->exhash); - put_stringz(ssh->exhash_bs, ssh->v_c); - put_stringz(ssh->exhash_bs, ssh->v_s); - put_string(ssh->exhash_bs, s->our_kexinit, s->our_kexinitlen); + ssh->exhash = ssh_hash_new(ssh->kex->hash); + put_stringz(ssh->exhash, ssh->v_c); + put_stringz(ssh->exhash, ssh->v_s); + put_string(ssh->exhash, s->our_kexinit, s->our_kexinitlen); sfree(s->our_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, BinarySource_UPCAST(pktin)->len + 1); @@ -5844,18 +5839,18 @@ static void do_ssh2_transport(void *vctx) * involve user interaction. */ 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 (!(ssh->remote_bugs & BUG_SSH2_OLDGEX)) - put_uint32(ssh->exhash_bs, DH_MIN_SIZE); - put_uint32(ssh->exhash_bs, s->pbits); + put_uint32(ssh->exhash, DH_MIN_SIZE); + put_uint32(ssh->exhash, s->pbits); if (!(ssh->remote_bugs & BUG_SSH2_OLDGEX)) - put_uint32(ssh->exhash_bs, DH_MAX_SIZE); - put_mp_ssh2(ssh->exhash_bs, s->p); - put_mp_ssh2(ssh->exhash_bs, s->g); + put_uint32(ssh->exhash, DH_MAX_SIZE); + put_mp_ssh2(ssh->exhash, s->p); + put_mp_ssh2(ssh->exhash, s->g); } - put_mp_ssh2(ssh->exhash_bs, s->e); - put_mp_ssh2(ssh->exhash_bs, s->f); + put_mp_ssh2(ssh->exhash, s->e); + put_mp_ssh2(ssh->exhash, s->f); dh_cleanup(ssh->kex_ctx); freebn(s->f); @@ -5893,19 +5888,19 @@ static void do_ssh2_transport(void *vctx) } 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); { strbuf *pubpoint = strbuf_new(); 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); } { 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); if (!get_err(pktin) && !s->K) { ssh_ecdhkex_freekey(s->eckey); @@ -6100,7 +6095,7 @@ static void do_ssh2_transport(void *vctx) if (ssh->hostkey_alg) { s->hkey = ssh_key_new_pub(ssh->hostkey_alg, s->hostkeydata); - put_string(ssh->exhash_bs, + put_string(ssh->exhash, s->hostkeydata.ptr, s->hostkeydata.len); } /* @@ -6149,18 +6144,18 @@ static void do_ssh2_transport(void *vctx) set_busy_status(ssh->frontend, BUSY_NOT); if (!s->hkey) - put_stringz(ssh->exhash_bs, ""); + put_stringz(ssh->exhash, ""); if (dh_is_gex(ssh->kex)) { /* min, preferred, max */ - put_uint32(ssh->exhash_bs, s->pbits); - put_uint32(ssh->exhash_bs, s->pbits); - put_uint32(ssh->exhash_bs, s->pbits * 2); + put_uint32(ssh->exhash, s->pbits); + put_uint32(ssh->exhash, s->pbits); + put_uint32(ssh->exhash, s->pbits * 2); - put_mp_ssh2(ssh->exhash_bs, s->p); - put_mp_ssh2(ssh->exhash_bs, s->g); + put_mp_ssh2(ssh->exhash, s->p); + put_mp_ssh2(ssh->exhash, s->g); } - put_mp_ssh2(ssh->exhash_bs, s->e); - put_mp_ssh2(ssh->exhash_bs, s->f); + put_mp_ssh2(ssh->exhash, s->e); + put_mp_ssh2(ssh->exhash, s->f); /* * 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); - put_stringpl(ssh->exhash_bs, s->hostkeydata); + put_stringpl(ssh->exhash, s->hostkeydata); s->hkey = ssh_key_new_pub(ssh->hostkey_alg, s->hostkeydata); rsakeydata = get_string(pktin); @@ -6203,7 +6198,7 @@ static void do_ssh2_transport(void *vctx) crStopV; } - put_stringpl(ssh->exhash_bs, rsakeydata); + put_stringpl(ssh->exhash, rsakeydata); /* * 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); ssh_pkt_write(ssh, s->pktout); - put_string(ssh->exhash_bs, outstr, outstrlen); + put_string(ssh->exhash, outstr, outstrlen); strbuf_free(buf); sfree(outstr); @@ -6270,9 +6265,9 @@ static void do_ssh2_transport(void *vctx) } } - put_mp_ssh2(ssh->exhash_bs, s->K); - assert(ssh->kex->hash->hlen <= sizeof(s->exchange_hash)); - ssh->kex->hash->final(ssh->exhash, s->exchange_hash); + put_mp_ssh2(ssh->exhash, s->K); + assert(ssh_hash_alg(ssh->exhash)->hlen <= sizeof(s->exchange_hash)); + ssh_hash_final(ssh->exhash, s->exchange_hash); #ifndef NO_GSSAPI if (ssh->kex->main_type == KEXTYPE_GSS) { diff --git a/ssh.h b/ssh.h index 6b768a8a..ff4305b0 100644 --- a/ssh.h +++ b/ssh.h @@ -331,11 +331,12 @@ int detect_attack(struct crcda_ctx *ctx, unsigned char *buf, uint32 len, /* * SSH2 RSA key exchange functions */ -struct ssh_hash; +struct ssh_hashalg; struct RSAKey *ssh_rsakex_newkey(const void *data, int len); void ssh_rsakex_freekey(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); /* @@ -527,20 +528,30 @@ int ssh2_mac_verresult(ssh2_mac *, const void *); void ssh2_mac_generate(ssh2_mac *, void *, int, unsigned long seq); int ssh2_mac_verify(ssh2_mac *, const void *, int, unsigned long seq); -struct ssh_hash { - void *(*init)(void); /* also allocates context */ - void *(*copy)(const void *); - BinarySink *(*sink) (void *); - void (*final)(void *, unsigned char *); /* also frees context */ - void (*free)(void *); +typedef struct ssh_hash { + const struct ssh_hashalg *vt; + BinarySink_DELEGATE_IMPLEMENTATION; +} ssh_hash; + +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 */ 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 { const char *name, *groupname; 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 */ }; @@ -625,10 +636,10 @@ extern const struct ssh2_ciphers ssh2_aes; extern const struct ssh2_ciphers ssh2_blowfish; extern const struct ssh2_ciphers ssh2_arcfour; extern const struct ssh2_ciphers ssh2_ccp; -extern const struct ssh_hash ssh_sha1; -extern const struct ssh_hash ssh_sha256; -extern const struct ssh_hash ssh_sha384; -extern const struct ssh_hash ssh_sha512; +extern const struct ssh_hashalg ssh_sha1; +extern const struct ssh_hashalg ssh_sha256; +extern const struct ssh_hashalg ssh_sha384; +extern const struct ssh_hashalg ssh_sha512; extern const struct ssh_kexes ssh_diffiehellman_group1; extern const struct ssh_kexes ssh_diffiehellman_group14; extern const struct ssh_kexes ssh_diffiehellman_gex; diff --git a/sshecc.c b/sshecc.c index ce663bfb..34d0e948 100644 --- a/sshecc.c +++ b/sshecc.c @@ -1688,7 +1688,7 @@ static int BinarySource_get_point(BinarySource *src, struct ec_point *point) struct ecsign_extra { 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 */ const unsigned char *oid; @@ -2227,7 +2227,7 @@ static int ecdsa_verify(ssh_key *key, ptrlen sig, ptrlen data) Bignum r, s; unsigned char digest[512 / 8]; int digestLen; - void *hashctx; + ssh_hash *hashctx; 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; assert(digestLen <= sizeof(digest)); - hashctx = extra->hash->init(); - put_data(extra->hash->sink(hashctx), data.ptr, data.len); - extra->hash->final(hashctx, digest); + hashctx = ssh_hash_new(extra->hash); + put_data(hashctx, data.ptr, data.len); + ssh_hash_final(hashctx, digest); /* Verify the signature */ 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)); freebn(s); } else { - void *hashctx; + ssh_hash *hashctx; strbuf *substr; digestLen = extra->hash->hlen; assert(digestLen <= sizeof(digest)); - hashctx = extra->hash->init(); - put_data(extra->hash->sink(hashctx), data, datalen); - extra->hash->final(hashctx, digest); + hashctx = ssh_hash_new(extra->hash); + put_data(hashctx, data, datalen); + ssh_hash_final(hashctx, digest); /* Do the signature */ _ecdsa_sign(ec->privateKey, ec->publicKey.curve, digest, digestLen, &r, &s); diff --git a/sshrsa.c b/sshrsa.c index f66af550..c2bc4bfb 100644 --- a/sshrsa.c +++ b/sshrsa.c @@ -783,7 +783,7 @@ int ssh_rsakex_klen(struct RSAKey *rsa) 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) { 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) { int i, max = (datalen > h->hlen ? h->hlen : datalen); - void *s; - BinarySink *bs; + ssh_hash *s; unsigned char hash[SSH2_KEX_MAX_HASH_LEN]; assert(h->hlen <= SSH2_KEX_MAX_HASH_LEN); - s = h->init(); - bs = h->sink(s); - put_data(bs, seed, seedlen); - put_uint32(bs, count); - h->final(s, hash); + s = ssh_hash_new(h); + put_data(s, seed, seedlen); + put_uint32(s, count); + ssh_hash_final(s, hash); count++; 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) { 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(); /* At position 1+HLEN, the data block DB, consisting of: */ /* 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 */ memset(out + 2*HLEN + 1, 0, outlen - (2*HLEN + 1)); /* A single 1 octet, followed by the input message data. */ diff --git a/sshsh256.c b/sshsh256.c index e4b14fd7..75a04495 100644 --- a/sshsh256.c +++ b/sshsh256.c @@ -204,51 +204,51 @@ void SHA256_Simple(const void *p, int len, unsigned char *output) { * Thin abstraction for things where hashes are pluggable. */ -static void *sha256_init(void) -{ - SHA256_State *s; +struct sha256_hash { + SHA256_State state; + ssh_hash hash; +}; - s = snew(SHA256_State); - SHA256_Init(s); - return s; +static ssh_hash *sha256_new(const struct ssh_hashalg *alg) +{ + 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; - SHA256_State *s; + struct sha256_hash *hold, *hnew; + ssh_hash *hashnew = sha256_new(hashold->vt); - s = snew(SHA256_State); - *s = *old; - BinarySink_COPIED(s); - return s; + hold = FROMFIELD(hashold, struct sha256_hash, hash); + hnew = FROMFIELD(hashnew, struct sha256_hash, hash); + + 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)); - sfree(s); + smemclr(h, sizeof(*h)); + sfree(h); } -static BinarySink *sha256_sink(void *handle) +static void sha256_final(ssh_hash *hash, unsigned char *output) { - SHA256_State *s = handle; - return BinarySink_UPCAST(s); + struct sha256_hash *h = FROMFIELD(hash, struct sha256_hash, hash); + SHA256_Final(&h->state, output); + sha256_free(hash); } -static void sha256_final(void *handle, unsigned char *output) -{ - 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" +const struct ssh_hashalg ssh_sha256 = { + sha256_new, sha256_copy, sha256_final, sha256_free, 32, "SHA-256" }; /* ---------------------------------------------------------------------- diff --git a/sshsh512.c b/sshsh512.c index e16e8c9f..85df1f29 100644 --- a/sshsh512.c +++ b/sshsh512.c @@ -327,74 +327,71 @@ void SHA384_Simple(const void *p, int len, unsigned char *output) { * Thin abstraction for things where hashes are pluggable. */ -static void *sha512_init(void) -{ - SHA512_State *s; - - 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" +struct sha512_hash { + SHA512_State state; + ssh_hash hash; }; -static void *sha384_init(void) +static ssh_hash *sha512_new(const struct ssh_hashalg *alg) { - SHA512_State *s; - - s = snew(SHA512_State); - SHA384_Init(s); - return s; + struct sha512_hash *h = snew(struct sha512_hash); + SHA512_Init(&h->state); + h->hash.vt = alg; + BinarySink_DELEGATE_INIT(&h->hash, &h->state); + 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); - smemclr(s, sizeof(*s)); - sfree(s); + hold = FROMFIELD(hashold, struct sha512_hash, hash); + hnew = FROMFIELD(hashnew, struct sha512_hash, hash); + + hnew->state = hold->state; + BinarySink_COPIED(&hnew->state); + + return hashnew; } -const struct ssh_hash ssh_sha384 = { - sha384_init, sha512_copy, sha512_sink, sha384_final, sha512_free, - 48, "SHA-384" +static void sha512_free(ssh_hash *hash) +{ + 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 diff --git a/sshsha.c b/sshsha.c index 310241a4..f93c2a1f 100644 --- a/sshsha.c +++ b/sshsha.c @@ -232,50 +232,51 @@ void SHA_Simple(const void *p, int len, unsigned char *output) * Thin abstraction for things where hashes are pluggable. */ -static void *sha1_init(void) -{ - SHA_State *s; +struct sha1_hash { + SHA_State state; + ssh_hash hash; +}; - s = snew(SHA_State); - SHA_Init(s); - return s; +static ssh_hash *sha1_new(const struct ssh_hashalg *alg) +{ + 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; - SHA_State *s; + struct sha1_hash *hold, *hnew; + ssh_hash *hashnew = sha1_new(hashold->vt); - s = snew(SHA_State); - *s = *old; - BinarySink_COPIED(s); - return s; + hold = FROMFIELD(hashold, struct sha1_hash, hash); + hnew = FROMFIELD(hashnew, struct sha1_hash, hash); + + 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)); - sfree(s); + smemclr(h, sizeof(*h)); + sfree(h); } -static BinarySink *sha1_sink(void *handle) +static void sha1_final(ssh_hash *hash, unsigned char *output) { - SHA_State *s = handle; - return BinarySink_UPCAST(s); + struct sha1_hash *h = FROMFIELD(hash, struct sha1_hash, hash); + SHA_Final(&h->state, output); + sha1_free(hash); } -static void sha1_final(void *handle, unsigned char *output) -{ - 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" +const struct ssh_hashalg ssh_sha1 = { + sha1_new, sha1_copy, sha1_final, sha1_free, 20, "SHA-1" }; /* ----------------------------------------------------------------------