diff --git a/Recipe b/Recipe index b3739b97..83c986fc 100644 --- a/Recipe +++ b/Recipe @@ -250,7 +250,7 @@ NONSSH = telnet raw rlogin ldisc pinger SSH = ssh sshcrc sshdes sshmd5 sshrsa sshrand sshsha sshblowf + sshdh sshcrcda sshpubk sshzlib sshdss x11fwd portfwd + sshaes sshccp sshsh256 sshsh512 sshbn wildcard pinger ssharcf - + sshgssc pgssapi sshshare sshecc aqsync + + sshgssc pgssapi sshshare sshecc aqsync marshal WINSSH = SSH winnoise wincapi winpgntc wingss winshare winnps winnpc + winhsock errsock UXSSH = SSH uxnoise uxagentc uxgss uxshare @@ -258,12 +258,13 @@ UXSSH = SSH uxnoise uxagentc uxgss uxshare # SFTP implementation (pscp, psftp). SFTP = sftp int64 logging cmdline -# Miscellaneous objects appearing in all the network utilities (not -# Pageant or PuTTYgen). -MISC = timing callback misc version settings tree234 proxy conf be_misc -WINMISC = MISC winstore winnet winhandl cmdline windefs winmisc winproxy +# Miscellaneous objects appearing in all the utilities, or all the +# network ones, or the Unix or Windows subsets of those in turn. +MISC = misc marshal +MISCNET = timing callback MISC version settings tree234 proxy conf be_misc +WINMISC = MISCNET winstore winnet winhandl cmdline windefs winmisc winproxy + wintime winhsock errsock winsecur winucs miscucs -UXMISC = MISC uxstore uxsel uxnet uxpeer uxmisc uxproxy time +UXMISC = MISCNET uxstore uxsel uxnet uxpeer uxmisc uxproxy time # import.c and dependencies, for PuTTYgen-like utilities that have to # load foreign key files. @@ -305,11 +306,11 @@ psftp : [C] psftp winsftp wincons WINSSH BE_SSH SFTP wildcard WINMISC + psftp.res winnojmp LIBS pageant : [G] winpgnt pageant sshrsa sshpubk sshdes sshbn sshmd5 version - + tree234 misc sshaes sshsha winsecur winpgntc aqsync sshdss sshsh256 + + tree234 MISC sshaes sshsha winsecur winpgntc aqsync sshdss sshsh256 + sshsh512 winutils sshecc winmisc winhelp conf pageant.res LIBS puttygen : [G] winpgen sshrsag sshdssg sshprime sshdes sshbn sshmd5 version - + sshrand winnoise sshsha winstore misc winctrls sshrsa sshdss winmisc + + sshrand winnoise sshsha winstore MISC winctrls sshrsa sshdss winmisc + sshpubk sshaes sshsh256 sshsh512 IMPORT winutils puttygen.res + tree234 notiming winhelp winnojmp conf LIBS wintime sshecc + sshecdsag winsecur @@ -328,7 +329,7 @@ plink : [U] uxplink uxcons NONSSH UXSSH U_BE_ALL logging UXMISC uxsignal + ux_x11 noterm uxnogtk sessprep cmdline PUTTYGEN_UNIX = sshrsag sshdssg sshprime sshdes sshbn sshmd5 version - + sshrand uxnoise sshsha misc sshrsa sshdss uxcons uxstore uxmisc + + sshrand uxnoise sshsha MISC sshrsa sshdss uxcons uxstore uxmisc + sshpubk sshaes sshsh256 sshsh512 IMPORT puttygen.res time tree234 + uxgen notiming conf sshecc sshecdsag uxnogtk puttygen : [U] cmdgen PUTTYGEN_UNIX @@ -352,8 +353,8 @@ osxlaunch : [UT] osxlaunch fuzzterm : [UT] UXTERM CHARSET misc version uxmisc uxucs fuzzterm time settings + uxstore be_none uxnogtk -testbn : [UT] testbn sshbn misc version conf tree234 uxmisc uxnogtk -testbn : [C] testbn sshbn misc version conf tree234 winmisc LIBS +testbn : [UT] testbn sshbn MISC version conf tree234 uxmisc uxnogtk +testbn : [C] testbn sshbn MISC version conf tree234 winmisc LIBS # ---------------------------------------------------------------------- # On Windows, provide a means of removing local test binaries that we diff --git a/defs.h b/defs.h index b2079572..4a8351fe 100644 --- a/defs.h +++ b/defs.h @@ -27,6 +27,8 @@ struct RSAKey; #include typedef uint32_t uint32; +typedef struct BinarySink BinarySink; + /* Do a compile-time type-check of 'to_check' (without evaluating it), * as a side effect of returning the value 'to_return'. Note that * although this macro double-*expands* to_return, it always diff --git a/import.c b/import.c index a071e80f..13243f2e 100644 --- a/import.c +++ b/import.c @@ -274,7 +274,7 @@ static int ber_write_id_len(void *dest, int id, int length, int flags) return len; } -static int put_uint32(void *target, unsigned val) +static int write_uint32(void *target, unsigned val) { unsigned char *d = (unsigned char *)target; @@ -282,7 +282,7 @@ static int put_uint32(void *target, unsigned val) return 4; } -static int put_string(void *target, const void *data, int len) +static int write_string(void *target, const void *data, int len) { unsigned char *d = (unsigned char *)target; @@ -291,9 +291,9 @@ static int put_string(void *target, const void *data, int len) return len+4; } -static int put_string_z(void *target, const char *string) +static int write_string_z(void *target, const char *string) { - return put_string(target, string, strlen(string)); + return write_string(target, string, strlen(string)); } static int put_mp(void *target, void *data, int len) @@ -1796,27 +1796,27 @@ int openssh_new_write(const Filename *filename, struct ssh2_userkey *key, /* Cipher and kdf names, and kdf options. */ if (!passphrase) { memset(bcrypt_salt, 0, sizeof(bcrypt_salt)); /* prevent warnings */ - p += put_string_z(p, "none"); - p += put_string_z(p, "none"); - p += put_string_z(p, ""); + p += write_string_z(p, "none"); + p += write_string_z(p, "none"); + p += write_string_z(p, ""); } else { unsigned char *q; for (i = 0; i < (int)sizeof(bcrypt_salt); i++) bcrypt_salt[i] = random_byte(); - p += put_string_z(p, "aes256-ctr"); - p += put_string_z(p, "bcrypt"); + p += write_string_z(p, "aes256-ctr"); + p += write_string_z(p, "bcrypt"); q = p; p += 4; - p += put_string(p, bcrypt_salt, sizeof(bcrypt_salt)); - p += put_uint32(p, bcrypt_rounds); + p += write_string(p, bcrypt_salt, sizeof(bcrypt_salt)); + p += write_uint32(p, bcrypt_rounds); PUT_32BIT_MSB_FIRST(q, (unsigned)(p - (q+4))); } /* Number of keys. */ - p += put_uint32(p, 1); + p += write_uint32(p, 1); /* Public blob. */ - p += put_string(p, pubblob, publen); + p += write_string(p, pubblob, publen); /* Begin private section. */ private_section_length_field = p; @@ -1827,17 +1827,17 @@ int openssh_new_write(const Filename *filename, struct ssh2_userkey *key, checkint = 0; for (i = 0; i < 4; i++) checkint = (checkint << 8) + random_byte(); - p += put_uint32(p, checkint); - p += put_uint32(p, checkint); + p += write_uint32(p, checkint); + p += write_uint32(p, checkint); /* Private key. The main private blob goes inline, with no string * wrapper. */ - p += put_string_z(p, key->alg->name); + p += write_string_z(p, key->alg->name); memcpy(p, privblob, privlen); p += privlen; /* Comment. */ - p += put_string_z(p, key->comment); + p += write_string_z(p, key->comment); /* Pad out the encrypted section. */ padvalue = 1; @@ -2425,11 +2425,11 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase, alg = &ssh_rsa; pos = 0; - pos += put_string(blob+pos, "ssh-rsa", 7); + pos += write_string(blob+pos, "ssh-rsa", 7); pos += put_mp(blob+pos, e.start, e.bytes); pos += put_mp(blob+pos, n.start, n.bytes); publen = pos; - pos += put_string(blob+pos, d.start, d.bytes); + pos += write_string(blob+pos, d.start, d.bytes); pos += put_mp(blob+pos, q.start, q.bytes); pos += put_mp(blob+pos, p.start, p.bytes); pos += put_mp(blob+pos, u.start, u.bytes); @@ -2456,7 +2456,7 @@ struct ssh2_userkey *sshcom_read(const Filename *filename, char *passphrase, alg = &ssh_dss; pos = 0; - pos += put_string(blob+pos, "ssh-dss", 7); + pos += write_string(blob+pos, "ssh-dss", 7); pos += put_mp(blob+pos, p.start, p.bytes); pos += put_mp(blob+pos, q.start, q.bytes); pos += put_mp(blob+pos, g.start, g.bytes); @@ -2597,10 +2597,10 @@ int sshcom_write(const Filename *filename, struct ssh2_userkey *key, pos = 0; PUT_32BIT(outblob+pos, SSHCOM_MAGIC_NUMBER); pos += 4; pos += 4; /* length field, fill in later */ - pos += put_string(outblob+pos, type, strlen(type)); + pos += write_string(outblob+pos, type, strlen(type)); { const char *ciphertype = passphrase ? "3des-cbc" : "none"; - pos += put_string(outblob+pos, ciphertype, strlen(ciphertype)); + pos += write_string(outblob+pos, ciphertype, strlen(ciphertype)); } lenpos = pos; /* remember this position */ pos += 4; /* encrypted-blob size */ diff --git a/int64.h b/int64.h index f62f8efc..6ac7f3fc 100644 --- a/int64.h +++ b/int64.h @@ -5,6 +5,8 @@ #ifndef PUTTY_INT64_H #define PUTTY_INT64_H +#include "defs.h" + typedef struct { unsigned long hi, lo; } uint64; @@ -21,4 +23,6 @@ uint64 uint64_shift_right(uint64 x, int shift); uint64 uint64_shift_left(uint64 x, int shift); uint64 uint64_from_decimal(char *str); +void BinarySink_put_uint64(BinarySink *, uint64); + #endif diff --git a/marshal.c b/marshal.c new file mode 100644 index 00000000..4c1f1bcc --- /dev/null +++ b/marshal.c @@ -0,0 +1,79 @@ +#include +#include +#include + +#include "marshal.h" +#include "misc.h" +#include "int64.h" + +void BinarySink_put_data(BinarySink *bs, const void *data, size_t len) +{ + bs->write(bs, data, len); +} + +void BinarySink_put_byte(BinarySink *bs, unsigned char val) +{ + bs->write(bs, &val, 1); +} + +void BinarySink_put_bool(BinarySink *bs, int val) +{ + unsigned char cval = val ? 1 : 0; + bs->write(bs, &cval, 1); +} + +void BinarySink_put_uint16(BinarySink *bs, unsigned long val) +{ + unsigned char data[2]; + PUT_16BIT_MSB_FIRST(data, val); + bs->write(bs, data, sizeof(data)); +} + +void BinarySink_put_uint32(BinarySink *bs, unsigned long val) +{ + unsigned char data[4]; + PUT_32BIT_MSB_FIRST(data, val); + bs->write(bs, data, sizeof(data)); +} + +void BinarySink_put_uint64(BinarySink *bs, uint64 val) +{ + BinarySink_put_uint32(bs, val.hi); + BinarySink_put_uint32(bs, val.lo); +} + +void BinarySink_put_string(BinarySink *bs, const void *data, size_t len) +{ + /* Check that the string length fits in a uint32, without doing a + * potentially implementation-defined shift of more than 31 bits */ + assert((len >> 31) < 2); + + BinarySink_put_uint32(bs, len); + bs->write(bs, data, len); +} + +void BinarySink_put_stringz(BinarySink *bs, const char *str) +{ + BinarySink_put_string(bs, str, strlen(str)); +} + +void BinarySink_put_stringsb(BinarySink *bs, struct strbuf *buf) +{ + BinarySink_put_string(bs, buf->s, buf->len); + strbuf_free(buf); +} + +void BinarySink_put_asciz(BinarySink *bs, const char *str) +{ + bs->write(bs, str, strlen(str) + 1); +} + +int BinarySink_put_pstring(BinarySink *bs, const char *str) +{ + size_t len = strlen(str); + if (len > 255) + return FALSE; /* can't write a Pascal-style string this long */ + BinarySink_put_byte(bs, len); + bs->write(bs, str, len); + return TRUE; +} diff --git a/marshal.h b/marshal.h new file mode 100644 index 00000000..95ec3769 --- /dev/null +++ b/marshal.h @@ -0,0 +1,138 @@ +#ifndef PUTTY_MARSHAL_H +#define PUTTY_MARSHAL_H + +#include "defs.h" + +/* + * A sort of 'abstract base class' or 'interface' or 'trait' which is + * the common feature of all types that want to accept data formatted + * using the SSH binary conventions of uint32, string, mpint etc. + */ +struct BinarySink { + void (*write)(BinarySink *sink, const void *data, size_t len); + BinarySink *binarysink_; +}; + +/* + * To define a structure type as a valid target for binary formatted + * data, put 'BinarySink_IMPLEMENTATION' in its declaration, and when + * an instance is set up, use 'BinarySink_INIT' to initialise the + * 'base class' state, providing a function pointer to be the + * implementation of the write() call above. + */ +#define BinarySink_IMPLEMENTATION BinarySink binarysink_[1] +#define BinarySink_INIT(obj, writefn) \ + ((obj)->binarysink_->write = (writefn), \ + (obj)->binarysink_->binarysink_ = (obj)->binarysink_) + +/* + * The implementing type's write function will want to downcast its + * 'BinarySink *' parameter back to the more specific type. Also, + * sometimes you'll want to upcast a pointer to a particular + * implementing type into an abstract 'BinarySink *' to pass to + * generic subroutines not defined in this file. These macros do that + * job. + * + * Importantly, BinarySink_UPCAST can also be applied to a BinarySink + * * itself (and leaves it unchanged). That's achieved by a small + * piece of C trickery: implementing structures and the BinarySink + * structure itself both contain a field called binarysink_, but in + * implementing objects it's a BinarySink[1] whereas in the abstract + * type it's a 'BinarySink *' pointing back to the same structure, + * meaning that you can say 'foo->binarysink_' in either case and get + * a pointer type by different methods. + */ +#define BinarySink_DOWNCAST(object, type) \ + TYPECHECK((object) == ((type *)0)->binarysink_, \ + ((type *)(((char *)(object)) - offsetof(type, binarysink_)))) +#define BinarySink_UPCAST(object) \ + TYPECHECK((object)->binarysink_ == (BinarySink *)0, \ + (object)->binarysink_) + +/* + * If you structure-copy an object that's implementing BinarySink, + * then that tricky self-pointer in its trait subobject will point to + * the wrong place. You could call BinarySink_INIT again, but this + * macro is terser and does all that's needed to fix up the copied + * object. + */ +#define BinarySink_COPIED(obj) \ + ((obj)->binarysink_->binarysink_ = (obj)->binarysink_) + +/* + * The put_* macros are the main client to this system. Any structure + * which implements the BinarySink 'trait' is valid for use as the + * first parameter of any of these put_* macros. + */ + +/* Basic big-endian integer types. uint64 is the structure type + * defined in int64.h, not the C99 built-in type. */ +#define put_byte(bs, val) \ + BinarySink_put_byte(BinarySink_UPCAST(bs), val) +#define put_uint16(bs, val) \ + BinarySink_put_uint16(BinarySink_UPCAST(bs), val) +#define put_uint32(bs, val) \ + BinarySink_put_uint32(BinarySink_UPCAST(bs), val) +#define put_uint64(bs, val) \ + BinarySink_put_uint64(BinarySink_UPCAST(bs), val) + +/* SSH booleans, encoded as a single byte storing either 0 or 1. */ +#define put_bool(bs, val) \ + BinarySink_put_bool(BinarySink_UPCAST(bs), val) + +/* SSH strings, with a leading uint32 length field. 'stringz' is a + * convenience function that takes an ordinary C zero-terminated + * string as input. 'stringsb' takes a strbuf * as input, and + * finalises it as a side effect (handy for multi-level marshalling in + * which you use these same functions to format an inner blob of data + * that then gets wrapped into a string container in an outer one). */ +#define put_string(bs, val, len) \ + BinarySink_put_string(BinarySink_UPCAST(bs),val,len) +#define put_stringz(bs, val) \ + BinarySink_put_stringz(BinarySink_UPCAST(bs), val) +#define put_stringsb(bs, val) \ + BinarySink_put_stringsb(BinarySink_UPCAST(bs), val) + +/* Other string outputs: 'asciz' emits the string data directly into + * the output including the terminating \0, and 'pstring' emits the + * string in Pascal style with a leading _one_-byte length field. + * pstring can fail if the string is too long. */ +#define put_asciz(bs, val) \ + BinarySink_put_asciz(BinarySink_UPCAST(bs), val) +#define put_pstring(bs, val) \ + BinarySink_put_pstring(BinarySink_UPCAST(bs), val) + +/* Multiprecision integers, in both the SSH-1 and SSH-2 formats. */ +#define put_mp_ssh1(bs, val) \ + BinarySink_put_mp_ssh1(BinarySink_UPCAST(bs), val) +#define put_mp_ssh2(bs, val) \ + BinarySink_put_mp_ssh2(BinarySink_UPCAST(bs), val) + +/* Fallback: just emit raw data bytes, using a syntax that matches the + * rest of these macros. */ +#define put_data(bs, val, len) \ + BinarySink_put_data(BinarySink_UPCAST(bs), val, len) + +/* + * The underlying real C functions that implement most of those + * macros. Generally you won't want to call these directly, because + * they have such cumbersome names; you call the wrapper macros above + * instead. + * + * A few functions whose wrapper macros are defined above are actually + * declared in other headers, so as to guarantee that the + * declaration(s) of their other parameter type(s) are in scope. + */ +void BinarySink_put_data(BinarySink *, const void *data, size_t len); +void BinarySink_put_byte(BinarySink *, unsigned char); +void BinarySink_put_bool(BinarySink *, int); +void BinarySink_put_uint16(BinarySink *, unsigned long); +void BinarySink_put_uint32(BinarySink *, unsigned long); +void BinarySink_put_string(BinarySink *, const void *data, size_t len); +void BinarySink_put_stringz(BinarySink *, const char *str); +struct strbuf; +void BinarySink_put_stringsb(BinarySink *, struct strbuf *); +void BinarySink_put_asciz(BinarySink *, const char *str); +int BinarySink_put_pstring(BinarySink *, const char *str); + +#endif /* PUTTY_MARSHAL_H */ diff --git a/misc.c b/misc.c index c85adfbd..d87a01ca 100644 --- a/misc.c +++ b/misc.c @@ -489,9 +489,17 @@ char *strbuf_append(strbuf *buf_o, size_t len) return toret; } +static void strbuf_BinarySink_write( + BinarySink *bs, const void *data, size_t len) +{ + strbuf *buf_o = BinarySink_DOWNCAST(bs, strbuf); + memcpy(strbuf_append(buf_o, len), data, len); +} + strbuf *strbuf_new(void) { struct strbuf_impl *buf = snew(struct strbuf_impl); + BinarySink_INIT(&buf->visible, strbuf_BinarySink_write); buf->visible.len = 0; buf->size = 512; STRBUF_SET_PTR(buf, snewn(buf->size, char)); diff --git a/misc.h b/misc.h index e6a5bf3b..299daa52 100644 --- a/misc.h +++ b/misc.h @@ -7,6 +7,7 @@ #include "defs.h" #include "puttymem.h" +#include "marshal.h" #include /* for FILE * */ #include /* for va_list */ @@ -41,6 +42,7 @@ struct strbuf { char *s; unsigned char *u; int len; + BinarySink_IMPLEMENTATION; /* (also there's a surrounding implementation struct in misc.c) */ }; strbuf *strbuf_new(void); diff --git a/ssh.h b/ssh.h index 80677b7c..3919a0c7 100644 --- a/ssh.h +++ b/ssh.h @@ -250,6 +250,7 @@ struct MD5Context { int blkused; uint32 lenhi, lenlo; #endif + BinarySink_IMPLEMENTATION; }; void MD5Init(struct MD5Context *context); @@ -272,6 +273,7 @@ typedef struct SHA_State { int blkused; uint32 lenhi, lenlo; void (*sha1)(struct SHA_State * s, const unsigned char *p, int len); + BinarySink_IMPLEMENTATION; } SHA_State; void SHA_Init(SHA_State * s); void SHA_Bytes(SHA_State * s, const void *p, int len); @@ -286,6 +288,7 @@ typedef struct SHA256_State { int blkused; uint32 lenhi, lenlo; void (*sha256)(struct SHA256_State * s, const unsigned char *p, int len); + BinarySink_IMPLEMENTATION; } SHA256_State; void SHA256_Init(SHA256_State * s); void SHA256_Bytes(SHA256_State * s, const void *p, int len); @@ -297,6 +300,7 @@ typedef struct { unsigned char block[128]; int blkused; uint32 len[4]; + BinarySink_IMPLEMENTATION; } SHA512_State; #define SHA384_State SHA512_State void SHA512_Init(SHA512_State * s); @@ -705,6 +709,9 @@ int bignum_cmp(Bignum a, Bignum b); char *bignum_decimal(Bignum x); Bignum bignum_from_decimal(const char *decimal); +void BinarySink_put_mp_ssh1(BinarySink *, Bignum); +void BinarySink_put_mp_ssh2(BinarySink *, Bignum); + #ifdef DEBUG void diagbn(char *prefix, Bignum md); #endif diff --git a/sshbn.c b/sshbn.c index 6768204b..5b918100 100644 --- a/sshbn.c +++ b/sshbn.c @@ -17,6 +17,7 @@ typedef BignumInt *Bignum; #include "ssh.h" +#include "marshal.h" BignumInt bnZero[1] = { 0 }; BignumInt bnOne[2] = { 1, 1 }; @@ -1619,6 +1620,27 @@ int ssh1_write_bignum(void *data, Bignum bn) return len; } +void BinarySink_put_mp_ssh1(BinarySink *bs, Bignum bn) +{ + int len = ssh1_bignum_length(bn); + int i; + int bitc = bignum_bitcount(bn); + + put_uint16(bs, bitc); + for (i = len - 2; i--;) + put_byte(bs, bignum_byte(bn, i)); +} + +void BinarySink_put_mp_ssh2(BinarySink *bs, Bignum bn) +{ + int bytes = (bignum_bitcount(bn) + 8) / 8; + int i; + + put_uint32(bs, bytes); + for (i = bytes; i--;) + put_byte(bs, bignum_byte(bn, i)); +} + /* * Compare two bignums. Returns like strcmp. */ diff --git a/sshmd5.c b/sshmd5.c index b39dfd3e..1fe14959 100644 --- a/sshmd5.c +++ b/sshmd5.c @@ -115,11 +115,19 @@ static void MD5_Block(MD5_Core_State * s, uint32 * block) #define BLKSIZE 64 +static void MD5_BinarySink_write(BinarySink *bs, + const void *data, size_t len) +{ + struct MD5Context *s = BinarySink_DOWNCAST(bs, struct MD5Context); + MD5Update(s, data, len); +} + void MD5Init(struct MD5Context *s) { MD5_Core_Init(&s->core); s->blkused = 0; s->lenhi = s->lenlo = 0; + BinarySink_INIT(s, MD5_BinarySink_write); } void MD5Update(struct MD5Context *s, unsigned char const *p, unsigned len) @@ -264,6 +272,7 @@ static void hmacmd5_start(void *handle) struct MD5Context *keys = (struct MD5Context *)handle; keys[2] = keys[0]; /* structure copy */ + BinarySink_COPIED(&keys[2]); } static void hmacmd5_bytes(void *handle, unsigned char const *blk, int len) @@ -279,8 +288,10 @@ static void hmacmd5_genresult(void *handle, unsigned char *hmac) unsigned char intermediate[16]; s = keys[2]; /* structure copy */ + BinarySink_COPIED(&s); MD5Final(intermediate, &s); s = keys[1]; /* structure copy */ + BinarySink_COPIED(&s); MD5Update(&s, intermediate, 16); MD5Final(hmac, &s); } diff --git a/sshsh256.c b/sshsh256.c index 9ffbc03b..cd9f8fe3 100644 --- a/sshsh256.c +++ b/sshsh256.c @@ -97,6 +97,13 @@ void SHA256_Block(SHA256_State *s, uint32 *block) { #define BLKSIZE 64 +static void SHA256_BinarySink_write(BinarySink *bs, + const void *data, size_t len) +{ + struct SHA256_State *s = BinarySink_DOWNCAST(bs, struct SHA256_State); + SHA256_Bytes(s, data, len); +} + void SHA256_Init(SHA256_State *s) { SHA256_Core_Init(s); s->blkused = 0; @@ -105,6 +112,7 @@ void SHA256_Init(SHA256_State *s) { s->sha256 = &SHA256_ni; else s->sha256 = &SHA256_sw; + BinarySink_INIT(s, SHA256_BinarySink_write); } void SHA256_Bytes(SHA256_State *s, const void *p, int len) { @@ -219,6 +227,7 @@ static void *sha256_copy(const void *vold) s = snew(SHA256_State); *s = *old; + BinarySink_COPIED(s); return s; } @@ -297,6 +306,7 @@ static void hmacsha256_start(void *handle) SHA256_State *keys = (SHA256_State *)handle; keys[2] = keys[0]; /* structure copy */ + BinarySink_COPIED(&keys[2]); } static void hmacsha256_bytes(void *handle, unsigned char const *blk, int len) @@ -312,8 +322,10 @@ static void hmacsha256_genresult(void *handle, unsigned char *hmac) unsigned char intermediate[32]; s = keys[2]; /* structure copy */ + BinarySink_COPIED(&s); SHA256_Final(&s, intermediate); s = keys[1]; /* structure copy */ + BinarySink_COPIED(&s); SHA256_Bytes(&s, intermediate, 32); SHA256_Final(&s, hmac); } diff --git a/sshsh512.c b/sshsh512.c index bdfc1e9d..975bb3c9 100644 --- a/sshsh512.c +++ b/sshsh512.c @@ -185,12 +185,20 @@ static void SHA512_Block(SHA512_State *s, uint64 *block) { * at the end, and pass those blocks to the core SHA512 algorithm. */ +static void SHA512_BinarySink_write(BinarySink *bs, + const void *data, size_t len) +{ + SHA512_State *s = BinarySink_DOWNCAST(bs, SHA512_State); + SHA512_Bytes(s, data, len); +} + void SHA512_Init(SHA512_State *s) { int i; SHA512_Core_Init(s); s->blkused = 0; for (i = 0; i < 4; i++) s->len[i] = 0; + BinarySink_INIT(s, SHA512_BinarySink_write); } void SHA384_Init(SHA512_State *s) { @@ -199,6 +207,7 @@ void SHA384_Init(SHA512_State *s) { s->blkused = 0; for (i = 0; i < 4; i++) s->len[i] = 0; + BinarySink_INIT(s, SHA512_BinarySink_write); } void SHA512_Bytes(SHA512_State *s, const void *p, int len) { @@ -338,6 +347,7 @@ static void *sha512_copy(const void *vold) s = snew(SHA512_State); *s = *old; + BinarySink_COPIED(s); return s; } diff --git a/sshsha.c b/sshsha.c index 011ad8c2..164202fd 100644 --- a/sshsha.c +++ b/sshsha.c @@ -124,6 +124,13 @@ void SHATransform(word32 * digest, word32 * block) * the end, and pass those blocks to the core SHA algorithm. */ +static void SHA_BinarySink_write(BinarySink *bs, + const void *data, size_t len) +{ + struct SHA_State *s = BinarySink_DOWNCAST(bs, struct SHA_State); + SHA_Bytes(s, data, len); +} + void SHA_Init(SHA_State * s) { SHA_Core_Init(s->h); @@ -133,6 +140,7 @@ void SHA_Init(SHA_State * s) s->sha1 = &sha1_ni; else s->sha1 = &sha1_sw; + BinarySink_INIT(s, SHA_BinarySink_write); } void SHA_Bytes(SHA_State * s, const void *p, int len) @@ -251,6 +259,7 @@ static void *sha1_copy(const void *vold) s = snew(SHA_State); *s = *old; + BinarySink_COPIED(s); return s; } @@ -333,6 +342,7 @@ static void hmacsha1_start(void *handle) SHA_State *keys = (SHA_State *)handle; keys[2] = keys[0]; /* structure copy */ + BinarySink_COPIED(&keys[2]); } static void hmacsha1_bytes(void *handle, unsigned char const *blk, int len) @@ -348,8 +358,10 @@ static void hmacsha1_genresult(void *handle, unsigned char *hmac) unsigned char intermediate[20]; s = keys[2]; /* structure copy */ + BinarySink_COPIED(&s); SHA_Final(&s, intermediate); s = keys[1]; /* structure copy */ + BinarySink_COPIED(&s); SHA_Bytes(&s, intermediate, 20); SHA_Final(&s, hmac); }