1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

New centralised binary-data marshalling system.

I've finally got tired of all the code throughout PuTTY that repeats
the same logic about how to format the SSH binary primitives like
uint32, string, mpint. We've got reasonably organised code in ssh.c
that appends things like that to 'struct Packet'; something similar in
sftp.c which repeats a lot of the work; utility functions in various
places to format an mpint to feed to one or another hash function; and
no end of totally ad-hoc stuff in functions like public key blob
formatters which actually have to _count up_ the size of data
painstakingly, then malloc exactly that much and mess about with
PUT_32BIT.

It's time to bring all of that into one place, and stop repeating
myself in error-prone ways everywhere. The new marshal.h defines a
system in which I centralise all the actual marshalling functions, and
then layer a touch of C macro trickery on top to allow me to (look as
if I) pass a wide range of different types to those functions, as long
as the target type has been set up in the right way to have a write()
function.

This commit adds the new header and source file, and sets up some
general centralised types (strbuf and the various hash-function
contexts like SHA_State), but doesn't use the new calls for anything
yet.

(I've also renamed some internal functions in import.c which were
using the same names that I've just defined macros over. That won't
last long - those functions are going to go away soon, so the changed
names are strictly temporary.)
This commit is contained in:
Simon Tatham 2018-05-24 09:17:13 +01:00
parent bff128fea9
commit 0e3082ee89
14 changed files with 341 additions and 33 deletions

23
Recipe
View File

@ -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

2
defs.h
View File

@ -27,6 +27,8 @@ struct RSAKey;
#include <stdint.h>
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

View File

@ -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 */

View File

@ -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

79
marshal.c Normal file
View File

@ -0,0 +1,79 @@
#include <assert.h>
#include <stddef.h>
#include <string.h>
#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;
}

138
marshal.h Normal file
View File

@ -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 */

8
misc.c
View File

@ -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));

2
misc.h
View File

@ -7,6 +7,7 @@
#include "defs.h"
#include "puttymem.h"
#include "marshal.h"
#include <stdio.h> /* for FILE * */
#include <stdarg.h> /* 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);

7
ssh.h
View File

@ -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

22
sshbn.c
View File

@ -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.
*/

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}