mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 17:38:00 +00:00
Turn SSH-2 MACs into a classoid.
This piece of tidying-up has come out particularly well in terms of saving tedious repetition and boilerplate. I've managed to remove three pointless methods from every MAC implementation by means of writing them once centrally in terms of the implementation-specific methods; another method (hmacmd5_sink) vanished because I was able to make the interface type 'ssh2_mac' be directly usable as a BinarySink by way of a new delegation system; and because all the method implementations can now find their own vtable, I was even able to merge a lot of keying and output functions that had previously differed only in length parameters by having them look up the lengths in whatever vtable they were passed.
This commit is contained in:
parent
229af2b5bf
commit
853bd8b284
1
Recipe
1
Recipe
@ -255,6 +255,7 @@ SSH = ssh ssh1bpp ssh2bpp ssh2bpp-bare ssh1censor ssh2censor
|
||||
+ sshdh sshcrcda sshpubk sshzlib sshdss x11fwd portfwd
|
||||
+ sshaes sshccp sshsh256 sshsh512 sshbn wildcard pinger ssharcf
|
||||
+ sshgssc pgssapi sshshare sshecc aqsync marshal nullplug agentf
|
||||
+ sshmac
|
||||
WINSSH = SSH winnoise wincapi winpgntc wingss winshare winnps winnpc
|
||||
+ winhsock errsock
|
||||
UXSSH = SSH uxnoise uxagentc uxgss uxshare
|
||||
|
4
cproxy.c
4
cproxy.c
@ -19,10 +19,10 @@
|
||||
static void hmacmd5_chap(const unsigned char *challenge, int challen,
|
||||
const char *passwd, unsigned char *response)
|
||||
{
|
||||
void *hmacmd5_ctx;
|
||||
struct hmacmd5_context *hmacmd5_ctx;
|
||||
int pwlen;
|
||||
|
||||
hmacmd5_ctx = hmacmd5_make_context(NULL);
|
||||
hmacmd5_ctx = hmacmd5_make_context();
|
||||
|
||||
pwlen = strlen(passwd);
|
||||
if (pwlen>64) {
|
||||
|
11
marshal.h
11
marshal.h
@ -25,6 +25,17 @@ struct BinarySink {
|
||||
((obj)->binarysink_->write = (writefn), \
|
||||
(obj)->binarysink_->binarysink_ = (obj)->binarysink_)
|
||||
|
||||
/*
|
||||
* To define a larger structure type as a valid BinarySink in such a
|
||||
* way that it will delegate the write method to some other object,
|
||||
* put 'BinarySink_DELEGATE_IMPLEMENTATION' in its declaration, and
|
||||
* when an instance is set up, use 'BinarySink_DELEGATE_INIT' to point
|
||||
* at the object it wants to delegate to.
|
||||
*/
|
||||
#define BinarySink_DELEGATE_IMPLEMENTATION BinarySink *binarysink_
|
||||
#define BinarySink_DELEGATE_INIT(obj, othersink) \
|
||||
((obj)->binarysink_ = BinarySink_UPCAST(othersink))
|
||||
|
||||
/*
|
||||
* The implementing type's write function will want to downcast its
|
||||
* 'BinarySink *' parameter back to the more specific type. Also,
|
||||
|
10
ssh.c
10
ssh.c
@ -328,10 +328,10 @@ const static struct ssh_signkey_with_user_pref_id hostkey_algs[] = {
|
||||
{ &ssh_rsa, HK_RSA },
|
||||
};
|
||||
|
||||
const static struct ssh_mac *const macs[] = {
|
||||
const static struct ssh2_macalg *const macs[] = {
|
||||
&ssh_hmac_sha256, &ssh_hmac_sha1, &ssh_hmac_sha1_96, &ssh_hmac_md5
|
||||
};
|
||||
const static struct ssh_mac *const buggymacs[] = {
|
||||
const static struct ssh2_macalg *const buggymacs[] = {
|
||||
&ssh_hmac_sha1_buggy, &ssh_hmac_sha1_96_buggy, &ssh_hmac_md5
|
||||
};
|
||||
|
||||
@ -4854,7 +4854,7 @@ struct kexinit_algorithm {
|
||||
int warn;
|
||||
} cipher;
|
||||
struct {
|
||||
const struct ssh_mac *mac;
|
||||
const struct ssh2_macalg *mac;
|
||||
int etm;
|
||||
} mac;
|
||||
const struct ssh_compress *comp;
|
||||
@ -5023,11 +5023,11 @@ static void do_ssh2_transport(void *vctx)
|
||||
void *our_kexinit;
|
||||
int our_kexinitlen;
|
||||
int kex_init_value, kex_reply_value;
|
||||
const struct ssh_mac *const *maclist;
|
||||
const struct ssh2_macalg *const *maclist;
|
||||
int nmacs;
|
||||
struct {
|
||||
const struct ssh2_cipheralg *cipher;
|
||||
const struct ssh_mac *mac;
|
||||
const struct ssh2_macalg *mac;
|
||||
int etm_mode;
|
||||
const struct ssh_compress *comp;
|
||||
} in, out;
|
||||
|
61
ssh.h
61
ssh.h
@ -374,11 +374,12 @@ void MD5Init(struct MD5Context *context);
|
||||
void MD5Final(unsigned char digest[16], struct MD5Context *context);
|
||||
void MD5Simple(void const *p, unsigned len, unsigned char output[16]);
|
||||
|
||||
void *hmacmd5_make_context(ssh2_cipher *);
|
||||
void hmacmd5_free_context(void *handle);
|
||||
void hmacmd5_key(void *handle, void const *key, int len);
|
||||
void hmacmd5_do_hmac(void *handle, unsigned char const *blk, int len,
|
||||
unsigned char *hmac);
|
||||
struct hmacmd5_context;
|
||||
struct hmacmd5_context *hmacmd5_make_context(void);
|
||||
void hmacmd5_free_context(struct hmacmd5_context *ctx);
|
||||
void hmacmd5_key(struct hmacmd5_context *ctx, void const *key, int len);
|
||||
void hmacmd5_do_hmac(struct hmacmd5_context *ctx,
|
||||
unsigned char const *blk, int len, unsigned char *hmac);
|
||||
|
||||
int supports_sha_ni(void);
|
||||
|
||||
@ -476,7 +477,7 @@ struct ssh2_cipheralg {
|
||||
#define SSH_CIPHER_SEPARATE_LENGTH 2
|
||||
const char *text_name;
|
||||
/* If set, this takes priority over other MAC. */
|
||||
const struct ssh_mac *required_mac;
|
||||
const struct ssh2_macalg *required_mac;
|
||||
};
|
||||
|
||||
#define ssh2_cipher_new(alg) ((alg)->new(alg))
|
||||
@ -496,24 +497,36 @@ struct ssh2_ciphers {
|
||||
const struct ssh2_cipheralg *const *list;
|
||||
};
|
||||
|
||||
struct ssh_mac {
|
||||
struct ssh2_macalg;
|
||||
typedef struct ssh2_mac {
|
||||
const struct ssh2_macalg *vt;
|
||||
BinarySink_DELEGATE_IMPLEMENTATION;
|
||||
} ssh2_mac;
|
||||
|
||||
struct ssh2_macalg {
|
||||
/* Passes in the cipher context */
|
||||
void *(*make_context)(ssh2_cipher *);
|
||||
void (*free_context)(void *);
|
||||
void (*setkey) (void *, const void *key);
|
||||
/* whole-packet operations */
|
||||
void (*generate) (void *, void *blk, int len, unsigned long seq);
|
||||
int (*verify) (void *, const void *blk, int len, unsigned long seq);
|
||||
/* partial-packet operations */
|
||||
void (*start) (void *);
|
||||
BinarySink *(*sink) (void *);
|
||||
void (*genresult) (void *, unsigned char *);
|
||||
int (*verresult) (void *, unsigned char const *);
|
||||
ssh2_mac *(*new)(const struct ssh2_macalg *alg, ssh2_cipher *cipher);
|
||||
void (*free)(ssh2_mac *);
|
||||
void (*setkey)(ssh2_mac *, const void *key);
|
||||
void (*start)(ssh2_mac *);
|
||||
void (*genresult)(ssh2_mac *, unsigned char *);
|
||||
const char *name, *etm_name;
|
||||
int len, keylen;
|
||||
const char *text_name;
|
||||
};
|
||||
|
||||
#define ssh2_mac_new(alg, cipher) ((alg)->new(alg, cipher))
|
||||
#define ssh2_mac_free(ctx) ((ctx)->vt->free(ctx))
|
||||
#define ssh2_mac_setkey(ctx, key) ((ctx)->vt->free(ctx, key))
|
||||
#define ssh2_mac_start(ctx) ((ctx)->vt->start(ctx))
|
||||
#define ssh2_mac_genresult(ctx, out) ((ctx)->vt->genresult(ctx, out))
|
||||
#define ssh2_mac_alg(ctx) ((ctx)->vt)
|
||||
|
||||
/* Centralised 'methods' for ssh2_mac, defined in sshmac.c */
|
||||
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 *);
|
||||
@ -628,12 +641,12 @@ extern const ssh_keyalg ssh_ecdsa_ed25519;
|
||||
extern const ssh_keyalg ssh_ecdsa_nistp256;
|
||||
extern const ssh_keyalg ssh_ecdsa_nistp384;
|
||||
extern const ssh_keyalg ssh_ecdsa_nistp521;
|
||||
extern const struct ssh_mac ssh_hmac_md5;
|
||||
extern const struct ssh_mac ssh_hmac_sha1;
|
||||
extern const struct ssh_mac ssh_hmac_sha1_buggy;
|
||||
extern const struct ssh_mac ssh_hmac_sha1_96;
|
||||
extern const struct ssh_mac ssh_hmac_sha1_96_buggy;
|
||||
extern const struct ssh_mac ssh_hmac_sha256;
|
||||
extern const struct ssh2_macalg ssh_hmac_md5;
|
||||
extern const struct ssh2_macalg ssh_hmac_sha1;
|
||||
extern const struct ssh2_macalg ssh_hmac_sha1_buggy;
|
||||
extern const struct ssh2_macalg ssh_hmac_sha1_96;
|
||||
extern const struct ssh2_macalg ssh_hmac_sha1_96_buggy;
|
||||
extern const struct ssh2_macalg ssh_hmac_sha256;
|
||||
|
||||
typedef struct AESContext AESContext;
|
||||
AESContext *aes_make_context(void);
|
||||
|
75
ssh2bpp.c
75
ssh2bpp.c
@ -12,9 +12,8 @@
|
||||
struct ssh2_bpp_direction {
|
||||
unsigned long sequence;
|
||||
ssh2_cipher *cipher;
|
||||
const struct ssh_mac *mac;
|
||||
ssh2_mac *mac;
|
||||
int etm_mode;
|
||||
void *mac_ctx;
|
||||
const struct ssh_compress *comp;
|
||||
void *comp_ctx;
|
||||
};
|
||||
@ -27,7 +26,6 @@ struct ssh2_bpp_state {
|
||||
unsigned char *data;
|
||||
unsigned cipherblk;
|
||||
PktIn *pktin;
|
||||
BinarySink *sc_mac_bs;
|
||||
|
||||
struct ssh2_bpp_direction in, out;
|
||||
int pending_newkeys;
|
||||
@ -61,14 +59,14 @@ static void ssh2_bpp_free(BinaryPacketProtocol *bpp)
|
||||
sfree(s->buf);
|
||||
if (s->out.cipher)
|
||||
ssh2_cipher_free(s->out.cipher);
|
||||
if (s->out.mac_ctx)
|
||||
s->out.mac->free_context(s->out.mac_ctx);
|
||||
if (s->out.mac)
|
||||
ssh2_mac_free(s->out.mac);
|
||||
if (s->out.comp_ctx)
|
||||
s->out.comp->compress_cleanup(s->out.comp_ctx);
|
||||
if (s->in.cipher)
|
||||
ssh2_cipher_free(s->in.cipher);
|
||||
if (s->in.mac_ctx)
|
||||
s->in.mac->free_context(s->in.mac_ctx);
|
||||
if (s->in.mac)
|
||||
ssh2_mac_free(s->in.mac);
|
||||
if (s->in.comp_ctx)
|
||||
s->in.comp->decompress_cleanup(s->in.comp_ctx);
|
||||
if (s->pktin)
|
||||
@ -79,7 +77,7 @@ static void ssh2_bpp_free(BinaryPacketProtocol *bpp)
|
||||
void ssh2_bpp_new_outgoing_crypto(
|
||||
BinaryPacketProtocol *bpp,
|
||||
const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
|
||||
const struct ssh_mac *mac, int etm_mode, const void *mac_key,
|
||||
const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
|
||||
const struct ssh_compress *compression)
|
||||
{
|
||||
struct ssh2_bpp_state *s;
|
||||
@ -88,8 +86,8 @@ void ssh2_bpp_new_outgoing_crypto(
|
||||
|
||||
if (s->out.cipher)
|
||||
ssh2_cipher_free(s->out.cipher);
|
||||
if (s->out.mac_ctx)
|
||||
s->out.mac->free_context(s->out.mac_ctx);
|
||||
if (s->out.mac)
|
||||
ssh2_mac_free(s->out.mac);
|
||||
if (s->out.comp_ctx)
|
||||
s->out.comp->compress_cleanup(s->out.comp_ctx);
|
||||
|
||||
@ -100,11 +98,12 @@ void ssh2_bpp_new_outgoing_crypto(
|
||||
} else {
|
||||
s->out.cipher = NULL;
|
||||
}
|
||||
s->out.mac = mac;
|
||||
s->out.etm_mode = etm_mode;
|
||||
if (mac) {
|
||||
s->out.mac_ctx = mac->make_context(s->out.cipher);
|
||||
mac->setkey(s->out.mac_ctx, mac_key);
|
||||
s->out.mac = ssh2_mac_new(mac, s->out.cipher);
|
||||
mac->setkey(s->out.mac, mac_key);
|
||||
} else {
|
||||
s->out.mac = NULL;
|
||||
}
|
||||
|
||||
s->out.comp = compression;
|
||||
@ -117,7 +116,7 @@ void ssh2_bpp_new_outgoing_crypto(
|
||||
void ssh2_bpp_new_incoming_crypto(
|
||||
BinaryPacketProtocol *bpp,
|
||||
const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
|
||||
const struct ssh_mac *mac, int etm_mode, const void *mac_key,
|
||||
const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
|
||||
const struct ssh_compress *compression)
|
||||
{
|
||||
struct ssh2_bpp_state *s;
|
||||
@ -126,8 +125,8 @@ void ssh2_bpp_new_incoming_crypto(
|
||||
|
||||
if (s->in.cipher)
|
||||
ssh2_cipher_free(s->in.cipher);
|
||||
if (s->in.mac_ctx)
|
||||
s->in.mac->free_context(s->in.mac_ctx);
|
||||
if (s->in.mac)
|
||||
ssh2_mac_free(s->in.mac);
|
||||
if (s->in.comp_ctx)
|
||||
s->in.comp->decompress_cleanup(s->in.comp_ctx);
|
||||
|
||||
@ -138,11 +137,12 @@ void ssh2_bpp_new_incoming_crypto(
|
||||
} else {
|
||||
s->in.cipher = NULL;
|
||||
}
|
||||
s->in.mac = mac;
|
||||
s->in.etm_mode = etm_mode;
|
||||
if (mac) {
|
||||
s->in.mac_ctx = mac->make_context(s->in.cipher);
|
||||
mac->setkey(s->in.mac_ctx, mac_key);
|
||||
s->in.mac = ssh2_mac_new(mac, s->in.cipher);
|
||||
mac->setkey(s->in.mac, mac_key);
|
||||
} else {
|
||||
s->in.mac = NULL;
|
||||
}
|
||||
|
||||
s->in.comp = compression;
|
||||
@ -171,7 +171,7 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
s->cipherblk = 8;
|
||||
if (s->cipherblk < 8)
|
||||
s->cipherblk = 8;
|
||||
s->maclen = s->in.mac ? s->in.mac->len : 0;
|
||||
s->maclen = s->in.mac ? ssh2_mac_alg(s->in.mac)->len : 0;
|
||||
|
||||
if (s->in.cipher &&
|
||||
(ssh2_cipher_alg(s->in.cipher)->flags & SSH_CIPHER_IS_CBC) &&
|
||||
@ -208,9 +208,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
s->bpp.in_raw, s->buf, s->maclen));
|
||||
|
||||
s->packetlen = 0;
|
||||
s->in.mac->start(s->in.mac_ctx);
|
||||
s->sc_mac_bs = s->in.mac->sink(s->in.mac_ctx);
|
||||
put_uint32(s->sc_mac_bs, s->in.sequence);
|
||||
ssh2_mac_start(s->in.mac);
|
||||
put_uint32(s->in.mac, s->in.sequence);
|
||||
|
||||
for (;;) { /* Once around this loop per cipher block. */
|
||||
/* Read another cipher-block's worth, and tack it on to
|
||||
@ -225,13 +224,12 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
s->buf + s->packetlen, s->cipherblk);
|
||||
|
||||
/* Feed that block to the MAC. */
|
||||
put_data(s->sc_mac_bs,
|
||||
put_data(s->in.mac,
|
||||
s->buf + s->packetlen, s->cipherblk);
|
||||
s->packetlen += s->cipherblk;
|
||||
|
||||
/* See if that gives us a valid packet. */
|
||||
if (s->in.mac->verresult(
|
||||
s->in.mac_ctx, s->buf + s->packetlen) &&
|
||||
if (ssh2_mac_verresult(s->in.mac, s->buf + s->packetlen) &&
|
||||
((s->len = toint(GET_32BIT(s->buf))) ==
|
||||
s->packetlen-4))
|
||||
break;
|
||||
@ -314,8 +312,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
/*
|
||||
* Check the MAC.
|
||||
*/
|
||||
if (s->in.mac && !s->in.mac->verify(
|
||||
s->in.mac_ctx, s->data, s->len + 4, s->in.sequence)) {
|
||||
if (s->in.mac && !ssh2_mac_verify(
|
||||
s->in.mac, s->data, s->len + 4, s->in.sequence)) {
|
||||
s->bpp.error = dupprintf("Incorrect MAC received on packet");
|
||||
crStopV;
|
||||
}
|
||||
@ -389,8 +387,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp)
|
||||
/*
|
||||
* Check the MAC.
|
||||
*/
|
||||
if (s->in.mac && !s->in.mac->verify(
|
||||
s->in.mac_ctx, s->data, s->len + 4, s->in.sequence)) {
|
||||
if (s->in.mac && !ssh2_mac_verify(
|
||||
s->in.mac, s->data, s->len + 4, s->in.sequence)) {
|
||||
s->bpp.error = dupprintf("Incorrect MAC received on packet");
|
||||
crStopV;
|
||||
}
|
||||
@ -542,7 +540,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
* make the overall packet length come to pkt->minlen.
|
||||
*/
|
||||
if (s->out.mac)
|
||||
minlen -= s->out.mac->len;
|
||||
minlen -= ssh2_mac_alg(s->out.mac)->len;
|
||||
minlen -= 8; /* length field + min padding */
|
||||
}
|
||||
|
||||
@ -565,7 +563,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
(cipherblk - (pkt->length - unencrypted_prefix + padding) % cipherblk)
|
||||
% cipherblk;
|
||||
assert(padding <= 255);
|
||||
maclen = s->out.mac ? s->out.mac->len : 0;
|
||||
maclen = s->out.mac ? ssh2_mac_alg(s->out.mac)->len : 0;
|
||||
origlen = pkt->length;
|
||||
for (i = 0; i < padding; i++)
|
||||
put_byte(pkt, random_byte());
|
||||
@ -588,16 +586,15 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt)
|
||||
if (s->out.cipher)
|
||||
ssh2_cipher_encrypt(s->out.cipher,
|
||||
pkt->data + 4, origlen + padding - 4);
|
||||
s->out.mac->generate(s->out.mac_ctx, pkt->data, origlen + padding,
|
||||
s->out.sequence);
|
||||
ssh2_mac_generate(s->out.mac, pkt->data, origlen + padding,
|
||||
s->out.sequence);
|
||||
} else {
|
||||
/*
|
||||
* SSH-2 standard protocol.
|
||||
*/
|
||||
if (s->out.mac)
|
||||
s->out.mac->generate(
|
||||
s->out.mac_ctx, pkt->data, origlen + padding,
|
||||
s->out.sequence);
|
||||
ssh2_mac_generate(s->out.mac, pkt->data, origlen + padding,
|
||||
s->out.sequence);
|
||||
if (s->out.cipher)
|
||||
ssh2_cipher_encrypt(s->out.cipher, pkt->data, origlen + padding);
|
||||
}
|
||||
@ -642,7 +639,7 @@ static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
|
||||
length += block-1;
|
||||
length -= (length % block);
|
||||
if (s->out.mac)
|
||||
length += s->out.mac->len;
|
||||
length += ssh2_mac_alg(s->out.mac)->len;
|
||||
|
||||
if (length < pkt->minlen) {
|
||||
/*
|
||||
@ -655,7 +652,7 @@ static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt)
|
||||
* contained string.
|
||||
*/
|
||||
if (s->out.mac)
|
||||
length -= s->out.mac->len;
|
||||
length -= ssh2_mac_alg(s->out.mac)->len;
|
||||
length -= 8; /* length field + min padding */
|
||||
length -= 5; /* type code + string length prefix */
|
||||
|
||||
|
4
sshbpp.h
4
sshbpp.h
@ -40,12 +40,12 @@ BinaryPacketProtocol *ssh2_bpp_new(void);
|
||||
void ssh2_bpp_new_outgoing_crypto(
|
||||
BinaryPacketProtocol *bpp,
|
||||
const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
|
||||
const struct ssh_mac *mac, int etm_mode, const void *mac_key,
|
||||
const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
|
||||
const struct ssh_compress *compression);
|
||||
void ssh2_bpp_new_incoming_crypto(
|
||||
BinaryPacketProtocol *bpp,
|
||||
const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv,
|
||||
const struct ssh_mac *mac, int etm_mode, const void *mac_key,
|
||||
const struct ssh2_macalg *mac, int etm_mode, const void *mac_key,
|
||||
const struct ssh_compress *compression);
|
||||
|
||||
BinaryPacketProtocol *ssh2_bare_bpp_new(void);
|
||||
|
95
sshccp.c
95
sshccp.c
@ -866,27 +866,32 @@ struct ccp_context {
|
||||
struct poly1305 mac;
|
||||
|
||||
BinarySink_IMPLEMENTATION;
|
||||
ssh2_cipher vt;
|
||||
ssh2_cipher cvt;
|
||||
ssh2_mac mac_if;
|
||||
};
|
||||
|
||||
static void *poly_make_context(ssh2_cipher *cipher)
|
||||
static ssh2_mac *poly_ssh2_new(
|
||||
const struct ssh2_macalg *alg, ssh2_cipher *cipher)
|
||||
{
|
||||
return FROMFIELD(cipher, struct ccp_context, vt);
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, cvt);
|
||||
ctx->mac_if.vt = alg;
|
||||
BinarySink_DELEGATE_INIT(&ctx->mac_if, ctx);
|
||||
return &ctx->mac_if;
|
||||
}
|
||||
|
||||
static void poly_free_context(void *ctx)
|
||||
static void poly_ssh2_free(ssh2_mac *mac)
|
||||
{
|
||||
/* Not allocated, just forwarded, no need to free */
|
||||
}
|
||||
|
||||
static void poly_setkey(void *ctx, const void *key)
|
||||
static void poly_setkey(ssh2_mac *mac, const void *key)
|
||||
{
|
||||
/* Uses the same context as ChaCha20, so ignore */
|
||||
}
|
||||
|
||||
static void poly_start(void *handle)
|
||||
static void poly_start(ssh2_mac *mac)
|
||||
{
|
||||
struct ccp_context *ctx = (struct ccp_context *)handle;
|
||||
struct ccp_context *ctx = FROMFIELD(mac, struct ccp_context, mac_if);
|
||||
|
||||
ctx->mac_initialised = 0;
|
||||
memset(ctx->mac_iv, 0, 8);
|
||||
@ -926,63 +931,15 @@ static void poly_BinarySink_write(BinarySink *bs, const void *blkv, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
static BinarySink *poly_sink(void *handle)
|
||||
static void poly_genresult(ssh2_mac *mac, unsigned char *blk)
|
||||
{
|
||||
struct ccp_context *ctx = (struct ccp_context *)handle;
|
||||
return BinarySink_UPCAST(ctx);
|
||||
}
|
||||
|
||||
static void poly_genresult(void *handle, unsigned char *blk)
|
||||
{
|
||||
struct ccp_context *ctx = (struct ccp_context *)handle;
|
||||
struct ccp_context *ctx = FROMFIELD(mac, struct ccp_context, mac_if);
|
||||
poly1305_finalise(&ctx->mac, blk);
|
||||
}
|
||||
|
||||
static int poly_verresult(void *handle, unsigned char const *blk)
|
||||
{
|
||||
struct ccp_context *ctx = (struct ccp_context *)handle;
|
||||
int res;
|
||||
unsigned char mac[16];
|
||||
poly1305_finalise(&ctx->mac, mac);
|
||||
res = smemeq(blk, mac, 16);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* The generic poly operation used before generate and verify */
|
||||
static void poly_op(void *handle, const unsigned char *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
struct ccp_context *ctx = (struct ccp_context *)handle;
|
||||
poly_start(ctx);
|
||||
/* the data receiver expects the first 4 bytes to be the IV */
|
||||
put_uint32(ctx, seq);
|
||||
put_data(ctx, blk, len);
|
||||
}
|
||||
|
||||
static void poly_generate(void *handle, void *vblk, int len, unsigned long seq)
|
||||
{
|
||||
unsigned char *blk = (unsigned char *)vblk;
|
||||
poly_op(handle, blk, len, seq);
|
||||
poly_genresult(handle, blk+len);
|
||||
}
|
||||
|
||||
static int poly_verify(void *handle, const void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
const unsigned char *blk = (const unsigned char *)vblk;
|
||||
poly_op(handle, blk, len, seq);
|
||||
return poly_verresult(handle, blk+len);
|
||||
}
|
||||
|
||||
static const struct ssh_mac ssh2_poly1305 = {
|
||||
poly_make_context, poly_free_context,
|
||||
poly_setkey,
|
||||
|
||||
/* whole-packet operations */
|
||||
poly_generate, poly_verify,
|
||||
|
||||
/* partial-packet operations */
|
||||
poly_start, poly_sink, poly_genresult, poly_verresult,
|
||||
static const struct ssh2_macalg ssh2_poly1305 = {
|
||||
poly_ssh2_new, poly_ssh2_free, poly_setkey,
|
||||
poly_start, poly_genresult,
|
||||
|
||||
"", "", /* Not selectable individually, just part of ChaCha20-Poly1305 */
|
||||
16, 0, "Poly1305"
|
||||
@ -993,13 +950,13 @@ static ssh2_cipher *ccp_new(const struct ssh2_cipheralg *alg)
|
||||
struct ccp_context *ctx = snew(struct ccp_context);
|
||||
BinarySink_INIT(ctx, poly_BinarySink_write);
|
||||
poly1305_init(&ctx->mac);
|
||||
ctx->vt = alg;
|
||||
return &ctx->vt;
|
||||
ctx->cvt = alg;
|
||||
return &ctx->cvt;
|
||||
}
|
||||
|
||||
static void ccp_free(ssh2_cipher *cipher)
|
||||
{
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt);
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, cvt);
|
||||
smemclr(&ctx->a_cipher, sizeof(ctx->a_cipher));
|
||||
smemclr(&ctx->b_cipher, sizeof(ctx->b_cipher));
|
||||
smemclr(&ctx->mac, sizeof(ctx->mac));
|
||||
@ -1008,14 +965,14 @@ static void ccp_free(ssh2_cipher *cipher)
|
||||
|
||||
static void ccp_iv(ssh2_cipher *cipher, const void *iv)
|
||||
{
|
||||
/* struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt); */
|
||||
/* struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, cvt); */
|
||||
/* IV is set based on the sequence number */
|
||||
}
|
||||
|
||||
static void ccp_key(ssh2_cipher *cipher, const void *vkey)
|
||||
{
|
||||
const unsigned char *key = (const unsigned char *)vkey;
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt);
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, cvt);
|
||||
/* Initialise the a_cipher (for decrypting lengths) with the first 256 bits */
|
||||
chacha20_key(&ctx->a_cipher, key + 32);
|
||||
/* Initialise the b_cipher (for content and MAC) with the second 256 bits */
|
||||
@ -1024,13 +981,13 @@ static void ccp_key(ssh2_cipher *cipher, const void *vkey)
|
||||
|
||||
static void ccp_encrypt(ssh2_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt);
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, cvt);
|
||||
chacha20_encrypt(&ctx->b_cipher, blk, len);
|
||||
}
|
||||
|
||||
static void ccp_decrypt(ssh2_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt);
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, cvt);
|
||||
chacha20_decrypt(&ctx->b_cipher, blk, len);
|
||||
}
|
||||
|
||||
@ -1054,7 +1011,7 @@ static void ccp_length_op(struct ccp_context *ctx, void *blk, int len,
|
||||
static void ccp_encrypt_length(ssh2_cipher *cipher, void *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt);
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, cvt);
|
||||
ccp_length_op(ctx, blk, len, seq);
|
||||
chacha20_encrypt(&ctx->a_cipher, blk, len);
|
||||
}
|
||||
@ -1062,7 +1019,7 @@ static void ccp_encrypt_length(ssh2_cipher *cipher, void *blk, int len,
|
||||
static void ccp_decrypt_length(ssh2_cipher *cipher, void *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt);
|
||||
struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, cvt);
|
||||
ccp_length_op(ctx, blk, len, seq);
|
||||
chacha20_decrypt(&ctx->a_cipher, blk, len);
|
||||
}
|
||||
|
42
sshmac.c
Normal file
42
sshmac.c
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Centralised parts of the SSH-2 MAC API, which don't need to vary
|
||||
* with the MAC implementation.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "ssh.h"
|
||||
|
||||
int ssh2_mac_verresult(ssh2_mac *mac, const void *candidate)
|
||||
{
|
||||
unsigned char correct[64]; /* at least as big as all known MACs */
|
||||
int toret;
|
||||
|
||||
assert(mac->vt->len <= sizeof(correct));
|
||||
ssh2_mac_genresult(mac, correct);
|
||||
toret = smemeq(correct, candidate, mac->vt->len);
|
||||
|
||||
smemclr(correct, sizeof(correct));
|
||||
|
||||
return toret;
|
||||
}
|
||||
|
||||
static void ssh2_mac_prepare(ssh2_mac *mac, const void *blk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
ssh2_mac_start(mac);
|
||||
put_uint32(mac, seq);
|
||||
put_data(mac, blk, len);
|
||||
}
|
||||
|
||||
void ssh2_mac_generate(ssh2_mac *mac, void *blk, int len, unsigned long seq)
|
||||
{
|
||||
ssh2_mac_prepare(mac, blk, len, seq);
|
||||
return ssh2_mac_genresult(mac, (unsigned char *)blk + len);
|
||||
}
|
||||
|
||||
int ssh2_mac_verify(ssh2_mac *mac, const void *blk, int len, unsigned long seq)
|
||||
{
|
||||
ssh2_mac_prepare(mac, blk, len, seq);
|
||||
return ssh2_mac_verresult(mac, (const unsigned char *)blk + len);
|
||||
}
|
129
sshmd5.c
129
sshmd5.c
@ -228,20 +228,40 @@ void MD5Simple(void const *p, unsigned len, unsigned char output[16])
|
||||
* useful elsewhere (SOCKS5 CHAP authentication uses HMAC-MD5).
|
||||
*/
|
||||
|
||||
void *hmacmd5_make_context(ssh2_cipher *cipher)
|
||||
struct hmacmd5_context {
|
||||
struct MD5Context md5[3];
|
||||
ssh2_mac mac;
|
||||
};
|
||||
|
||||
struct hmacmd5_context *hmacmd5_make_context(void)
|
||||
{
|
||||
return snewn(3, struct MD5Context);
|
||||
struct hmacmd5_context *ctx = snew(struct hmacmd5_context);
|
||||
BinarySink_DELEGATE_INIT(&ctx->mac, &ctx->md5[2]);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void hmacmd5_free_context(void *handle)
|
||||
static ssh2_mac *hmacmd5_ssh2_new(const struct ssh2_macalg *alg,
|
||||
ssh2_cipher *cipher)
|
||||
{
|
||||
smemclr(handle, 3*sizeof(struct MD5Context));
|
||||
sfree(handle);
|
||||
struct hmacmd5_context *ctx = hmacmd5_make_context();
|
||||
ctx->mac.vt = alg;
|
||||
return &ctx->mac;
|
||||
}
|
||||
|
||||
void hmacmd5_key(void *handle, void const *keyv, int len)
|
||||
void hmacmd5_free_context(struct hmacmd5_context *ctx)
|
||||
{
|
||||
smemclr(ctx, sizeof(*ctx));
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
static void hmacmd5_ssh2_free(ssh2_mac *mac)
|
||||
{
|
||||
struct hmacmd5_context *ctx = FROMFIELD(mac, struct hmacmd5_context, mac);
|
||||
hmacmd5_free_context(ctx);
|
||||
}
|
||||
|
||||
void hmacmd5_key(struct hmacmd5_context *ctx, void const *keyv, int len)
|
||||
{
|
||||
struct MD5Context *keys = (struct MD5Context *)handle;
|
||||
unsigned char foo[64];
|
||||
unsigned char const *key = (unsigned char const *)keyv;
|
||||
int i;
|
||||
@ -249,106 +269,59 @@ void hmacmd5_key(void *handle, void const *keyv, int len)
|
||||
memset(foo, 0x36, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
MD5Init(&keys[0]);
|
||||
put_data(&keys[0], foo, 64);
|
||||
MD5Init(&ctx->md5[0]);
|
||||
put_data(&ctx->md5[0], foo, 64);
|
||||
|
||||
memset(foo, 0x5C, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
MD5Init(&keys[1]);
|
||||
put_data(&keys[1], foo, 64);
|
||||
MD5Init(&ctx->md5[1]);
|
||||
put_data(&ctx->md5[1], foo, 64);
|
||||
|
||||
smemclr(foo, 64); /* burn the evidence */
|
||||
}
|
||||
|
||||
static void hmacmd5_key_16(void *handle, const void *key)
|
||||
static void hmacmd5_ssh2_setkey(ssh2_mac *mac, const void *key)
|
||||
{
|
||||
hmacmd5_key(handle, key, 16);
|
||||
struct hmacmd5_context *ctx = FROMFIELD(mac, struct hmacmd5_context, mac);
|
||||
hmacmd5_key(ctx, key, ctx->mac.vt->keylen);
|
||||
}
|
||||
|
||||
static void hmacmd5_start(void *handle)
|
||||
static void hmacmd5_start(ssh2_mac *mac)
|
||||
{
|
||||
struct MD5Context *keys = (struct MD5Context *)handle;
|
||||
struct hmacmd5_context *ctx = FROMFIELD(mac, struct hmacmd5_context, mac);
|
||||
|
||||
keys[2] = keys[0]; /* structure copy */
|
||||
BinarySink_COPIED(&keys[2]);
|
||||
ctx->md5[2] = ctx->md5[0]; /* structure copy */
|
||||
BinarySink_COPIED(&ctx->md5[2]);
|
||||
}
|
||||
|
||||
static BinarySink *hmacmd5_sink(void *handle)
|
||||
static void hmacmd5_genresult(ssh2_mac *mac, unsigned char *hmac)
|
||||
{
|
||||
struct MD5Context *keys = (struct MD5Context *)handle;
|
||||
return BinarySink_UPCAST(&keys[2]);
|
||||
}
|
||||
|
||||
static void hmacmd5_genresult(void *handle, unsigned char *hmac)
|
||||
{
|
||||
struct MD5Context *keys = (struct MD5Context *)handle;
|
||||
struct hmacmd5_context *ctx = FROMFIELD(mac, struct hmacmd5_context, mac);
|
||||
struct MD5Context s;
|
||||
unsigned char intermediate[16];
|
||||
|
||||
s = keys[2]; /* structure copy */
|
||||
s = ctx->md5[2]; /* structure copy */
|
||||
BinarySink_COPIED(&s);
|
||||
MD5Final(intermediate, &s);
|
||||
s = keys[1]; /* structure copy */
|
||||
s = ctx->md5[1]; /* structure copy */
|
||||
BinarySink_COPIED(&s);
|
||||
put_data(&s, intermediate, 16);
|
||||
MD5Final(hmac, &s);
|
||||
smemclr(intermediate, sizeof(intermediate));
|
||||
}
|
||||
|
||||
static int hmacmd5_verresult(void *handle, unsigned char const *hmac)
|
||||
void hmacmd5_do_hmac(struct hmacmd5_context *ctx,
|
||||
unsigned char const *blk, int len, unsigned char *hmac)
|
||||
{
|
||||
unsigned char correct[16];
|
||||
hmacmd5_genresult(handle, correct);
|
||||
return smemeq(correct, hmac, 16);
|
||||
ssh2_mac_start(&ctx->mac);
|
||||
put_data(&ctx->mac, blk, len);
|
||||
return ssh2_mac_genresult(&ctx->mac, hmac);
|
||||
}
|
||||
|
||||
static void hmacmd5_do_hmac_internal(void *handle,
|
||||
unsigned char const *blk, int len,
|
||||
unsigned char const *blk2, int len2,
|
||||
unsigned char *hmac)
|
||||
{
|
||||
BinarySink *bs = hmacmd5_sink(handle);
|
||||
hmacmd5_start(handle);
|
||||
put_data(bs, blk, len);
|
||||
if (blk2) put_data(bs, blk2, len2);
|
||||
hmacmd5_genresult(handle, hmac);
|
||||
}
|
||||
|
||||
void hmacmd5_do_hmac(void *handle, unsigned char const *blk, int len,
|
||||
unsigned char *hmac)
|
||||
{
|
||||
hmacmd5_do_hmac_internal(handle, blk, len, NULL, 0, hmac);
|
||||
}
|
||||
|
||||
static void hmacmd5_do_hmac_ssh(void *handle, unsigned char const *blk, int len,
|
||||
unsigned long seq, unsigned char *hmac)
|
||||
{
|
||||
unsigned char seqbuf[16];
|
||||
|
||||
PUT_32BIT_MSB_FIRST(seqbuf, seq);
|
||||
hmacmd5_do_hmac_internal(handle, seqbuf, 4, blk, len, hmac);
|
||||
}
|
||||
|
||||
static void hmacmd5_generate(void *handle, void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
unsigned char *blk = (unsigned char *)vblk;
|
||||
hmacmd5_do_hmac_ssh(handle, blk, len, seq, blk + len);
|
||||
}
|
||||
|
||||
static int hmacmd5_verify(void *handle, const void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
const unsigned char *blk = (const unsigned char *)vblk;
|
||||
unsigned char correct[16];
|
||||
hmacmd5_do_hmac_ssh(handle, blk, len, seq, correct);
|
||||
return smemeq(correct, blk + len, 16);
|
||||
}
|
||||
|
||||
const struct ssh_mac ssh_hmac_md5 = {
|
||||
hmacmd5_make_context, hmacmd5_free_context, hmacmd5_key_16,
|
||||
hmacmd5_generate, hmacmd5_verify,
|
||||
hmacmd5_start, hmacmd5_sink, hmacmd5_genresult, hmacmd5_verresult,
|
||||
const struct ssh2_macalg ssh_hmac_md5 = {
|
||||
hmacmd5_ssh2_new, hmacmd5_ssh2_free, hmacmd5_ssh2_setkey,
|
||||
hmacmd5_start, hmacmd5_genresult,
|
||||
"hmac-md5", "hmac-md5-etm@openssh.com",
|
||||
16, 16,
|
||||
"HMAC-MD5"
|
||||
|
99
sshsh256.c
99
sshsh256.c
@ -256,111 +256,80 @@ const struct ssh_hash ssh_sha256 = {
|
||||
* HMAC wrapper on it.
|
||||
*/
|
||||
|
||||
static void *sha256_make_context(ssh2_cipher *cipher)
|
||||
struct hmacsha256 {
|
||||
SHA256_State sha[3];
|
||||
ssh2_mac mac;
|
||||
};
|
||||
|
||||
static ssh2_mac *hmacsha256_new(
|
||||
const struct ssh2_macalg *alg, ssh2_cipher *cipher)
|
||||
{
|
||||
return snewn(3, SHA256_State);
|
||||
struct hmacsha256 *ctx = snew(struct hmacsha256);
|
||||
ctx->mac.vt = alg;
|
||||
BinarySink_DELEGATE_INIT(&ctx->mac, &ctx->sha[2]);
|
||||
return &ctx->mac;
|
||||
}
|
||||
|
||||
static void sha256_free_context(void *handle)
|
||||
static void hmacsha256_free(ssh2_mac *mac)
|
||||
{
|
||||
smemclr(handle, 3 * sizeof(SHA256_State));
|
||||
sfree(handle);
|
||||
struct hmacsha256 *ctx = FROMFIELD(mac, struct hmacsha256, mac);
|
||||
smemclr(ctx, sizeof(*ctx));
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
static void sha256_key_internal(void *handle,
|
||||
static void sha256_key_internal(struct hmacsha256 *ctx,
|
||||
const unsigned char *key, int len)
|
||||
{
|
||||
SHA256_State *keys = (SHA256_State *)handle;
|
||||
unsigned char foo[64];
|
||||
int i;
|
||||
|
||||
memset(foo, 0x36, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
SHA256_Init(&keys[0]);
|
||||
put_data(&keys[0], foo, 64);
|
||||
SHA256_Init(&ctx->sha[0]);
|
||||
put_data(&ctx->sha[0], foo, 64);
|
||||
|
||||
memset(foo, 0x5C, 64);
|
||||
for (i = 0; i < len && i < 64; i++)
|
||||
foo[i] ^= key[i];
|
||||
SHA256_Init(&keys[1]);
|
||||
put_data(&keys[1], foo, 64);
|
||||
SHA256_Init(&ctx->sha[1]);
|
||||
put_data(&ctx->sha[1], foo, 64);
|
||||
|
||||
smemclr(foo, 64); /* burn the evidence */
|
||||
}
|
||||
|
||||
static void sha256_key(void *handle, const void *key)
|
||||
static void hmacsha256_key(ssh2_mac *mac, const void *key)
|
||||
{
|
||||
sha256_key_internal(handle, key, 32);
|
||||
struct hmacsha256 *ctx = FROMFIELD(mac, struct hmacsha256, mac);
|
||||
sha256_key_internal(ctx, key, ctx->mac.vt->keylen);
|
||||
}
|
||||
|
||||
static void hmacsha256_start(void *handle)
|
||||
static void hmacsha256_start(ssh2_mac *mac)
|
||||
{
|
||||
SHA256_State *keys = (SHA256_State *)handle;
|
||||
struct hmacsha256 *ctx = FROMFIELD(mac, struct hmacsha256, mac);
|
||||
|
||||
keys[2] = keys[0]; /* structure copy */
|
||||
BinarySink_COPIED(&keys[2]);
|
||||
ctx->sha[2] = ctx->sha[0]; /* structure copy */
|
||||
BinarySink_COPIED(&ctx->sha[2]);
|
||||
}
|
||||
|
||||
static BinarySink *hmacsha256_sink(void *handle)
|
||||
static void hmacsha256_genresult(ssh2_mac *mac, unsigned char *hmac)
|
||||
{
|
||||
SHA256_State *keys = (SHA256_State *)handle;
|
||||
return BinarySink_UPCAST(&keys[2]);
|
||||
}
|
||||
|
||||
static void hmacsha256_genresult(void *handle, unsigned char *hmac)
|
||||
{
|
||||
SHA256_State *keys = (SHA256_State *)handle;
|
||||
struct hmacsha256 *ctx = FROMFIELD(mac, struct hmacsha256, mac);
|
||||
SHA256_State s;
|
||||
unsigned char intermediate[32];
|
||||
|
||||
s = keys[2]; /* structure copy */
|
||||
s = ctx->sha[2]; /* structure copy */
|
||||
BinarySink_COPIED(&s);
|
||||
SHA256_Final(&s, intermediate);
|
||||
s = keys[1]; /* structure copy */
|
||||
s = ctx->sha[1]; /* structure copy */
|
||||
BinarySink_COPIED(&s);
|
||||
put_data(&s, intermediate, 32);
|
||||
SHA256_Final(&s, hmac);
|
||||
}
|
||||
|
||||
static void sha256_do_hmac(void *handle, const unsigned char *blk, int len,
|
||||
unsigned long seq, unsigned char *hmac)
|
||||
{
|
||||
BinarySink *bs = hmacsha256_sink(handle);
|
||||
hmacsha256_start(handle);
|
||||
put_uint32(bs, seq);
|
||||
put_data(bs, blk, len);
|
||||
hmacsha256_genresult(handle, hmac);
|
||||
}
|
||||
|
||||
static void sha256_generate(void *handle, void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
unsigned char *blk = (unsigned char *)vblk;
|
||||
sha256_do_hmac(handle, blk, len, seq, blk + len);
|
||||
}
|
||||
|
||||
static int hmacsha256_verresult(void *handle, unsigned char const *hmac)
|
||||
{
|
||||
unsigned char correct[32];
|
||||
hmacsha256_genresult(handle, correct);
|
||||
return smemeq(correct, hmac, 32);
|
||||
}
|
||||
|
||||
static int sha256_verify(void *handle, const void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
const unsigned char *blk = (const unsigned char *)vblk;
|
||||
unsigned char correct[32];
|
||||
sha256_do_hmac(handle, blk, len, seq, correct);
|
||||
return smemeq(correct, blk + len, 32);
|
||||
}
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha256 = {
|
||||
sha256_make_context, sha256_free_context, sha256_key,
|
||||
sha256_generate, sha256_verify,
|
||||
hmacsha256_start, hmacsha256_sink,
|
||||
hmacsha256_genresult, hmacsha256_verresult,
|
||||
const struct ssh2_macalg ssh_hmac_sha256 = {
|
||||
hmacsha256_new, hmacsha256_free, hmacsha256_key,
|
||||
hmacsha256_start, hmacsha256_genresult,
|
||||
"hmac-sha2-256", "hmac-sha2-256-etm@openssh.com",
|
||||
32, 32,
|
||||
"HMAC-SHA-256"
|
||||
|
160
sshsha.c
160
sshsha.c
@ -283,20 +283,30 @@ const struct ssh_hash ssh_sha1 = {
|
||||
* HMAC wrapper on it.
|
||||
*/
|
||||
|
||||
static void *sha1_make_context(ssh2_cipher *cipher)
|
||||
struct hmacsha1 {
|
||||
SHA_State sha[3];
|
||||
ssh2_mac mac;
|
||||
};
|
||||
|
||||
static ssh2_mac *hmacsha1_new(
|
||||
const struct ssh2_macalg *alg, ssh2_cipher *cipher)
|
||||
{
|
||||
return snewn(3, SHA_State);
|
||||
struct hmacsha1 *ctx = snew(struct hmacsha1);
|
||||
ctx->mac.vt = alg;
|
||||
BinarySink_DELEGATE_INIT(&ctx->mac, &ctx->sha[2]);
|
||||
return &ctx->mac;
|
||||
}
|
||||
|
||||
static void sha1_free_context(void *handle)
|
||||
static void hmacsha1_free(ssh2_mac *mac)
|
||||
{
|
||||
smemclr(handle, 3 * sizeof(SHA_State));
|
||||
sfree(handle);
|
||||
struct hmacsha1 *ctx = FROMFIELD(mac, struct hmacsha1, mac);
|
||||
smemclr(ctx, sizeof(*ctx));
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
static void sha1_key_internal(void *handle, const unsigned char *key, int len)
|
||||
static void sha1_key_internal(SHA_State *keys,
|
||||
const unsigned char *key, int len)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
unsigned char foo[64];
|
||||
int i;
|
||||
|
||||
@ -315,108 +325,38 @@ static void sha1_key_internal(void *handle, const unsigned char *key, int len)
|
||||
smemclr(foo, 64); /* burn the evidence */
|
||||
}
|
||||
|
||||
static void sha1_key(void *handle, const void *key)
|
||||
static void hmacsha1_key(ssh2_mac *mac, const void *key)
|
||||
{
|
||||
sha1_key_internal(handle, key, 20);
|
||||
struct hmacsha1 *ctx = FROMFIELD(mac, struct hmacsha1, mac);
|
||||
/* Reading the key length out of the ssh2_macalg structure means
|
||||
* this same method can be used for the _buggy variants which use
|
||||
* a shorter key */
|
||||
sha1_key_internal(ctx->sha, key, ctx->mac.vt->keylen);
|
||||
}
|
||||
|
||||
static void sha1_key_buggy(void *handle, const void *key)
|
||||
static void hmacsha1_start(ssh2_mac *mac)
|
||||
{
|
||||
sha1_key_internal(handle, key, 16);
|
||||
struct hmacsha1 *ctx = FROMFIELD(mac, struct hmacsha1, mac);
|
||||
|
||||
ctx->sha[2] = ctx->sha[0]; /* structure copy */
|
||||
BinarySink_COPIED(&ctx->sha[2]);
|
||||
}
|
||||
|
||||
static void hmacsha1_start(void *handle)
|
||||
static void hmacsha1_genresult(ssh2_mac *mac, unsigned char *hmac)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
|
||||
keys[2] = keys[0]; /* structure copy */
|
||||
BinarySink_COPIED(&keys[2]);
|
||||
}
|
||||
|
||||
static BinarySink *hmacsha1_sink(void *handle)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
return BinarySink_UPCAST(&keys[2]);
|
||||
}
|
||||
|
||||
static void hmacsha1_genresult(void *handle, unsigned char *hmac)
|
||||
{
|
||||
SHA_State *keys = (SHA_State *)handle;
|
||||
struct hmacsha1 *ctx = FROMFIELD(mac, struct hmacsha1, mac);
|
||||
SHA_State s;
|
||||
unsigned char intermediate[20];
|
||||
|
||||
s = keys[2]; /* structure copy */
|
||||
s = ctx->sha[2]; /* structure copy */
|
||||
BinarySink_COPIED(&s);
|
||||
SHA_Final(&s, intermediate);
|
||||
s = keys[1]; /* structure copy */
|
||||
s = ctx->sha[1]; /* structure copy */
|
||||
BinarySink_COPIED(&s);
|
||||
put_data(&s, intermediate, 20);
|
||||
SHA_Final(&s, hmac);
|
||||
}
|
||||
|
||||
static void sha1_do_hmac(void *handle, const unsigned char *blk, int len,
|
||||
unsigned long seq, unsigned char *hmac)
|
||||
{
|
||||
BinarySink *bs = hmacsha1_sink(handle);
|
||||
hmacsha1_start(handle);
|
||||
put_uint32(bs, seq);
|
||||
put_data(bs, blk, len);
|
||||
hmacsha1_genresult(handle, hmac);
|
||||
}
|
||||
|
||||
static void sha1_generate(void *handle, void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
unsigned char *blk = (unsigned char *)vblk;
|
||||
sha1_do_hmac(handle, blk, len, seq, blk + len);
|
||||
}
|
||||
|
||||
static int hmacsha1_verresult(void *handle, unsigned char const *hmac)
|
||||
{
|
||||
unsigned char correct[20];
|
||||
hmacsha1_genresult(handle, correct);
|
||||
return smemeq(correct, hmac, 20);
|
||||
}
|
||||
|
||||
static int sha1_verify(void *handle, const void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
const unsigned char *blk = (const unsigned char *)vblk;
|
||||
unsigned char correct[20];
|
||||
sha1_do_hmac(handle, blk, len, seq, correct);
|
||||
return smemeq(correct, blk + len, 20);
|
||||
}
|
||||
|
||||
static void hmacsha1_96_genresult(void *handle, unsigned char *hmac)
|
||||
{
|
||||
unsigned char full[20];
|
||||
hmacsha1_genresult(handle, full);
|
||||
memcpy(hmac, full, 12);
|
||||
}
|
||||
|
||||
static void sha1_96_generate(void *handle, void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
unsigned char *blk = (unsigned char *)vblk;
|
||||
unsigned char full[20];
|
||||
sha1_do_hmac(handle, blk, len, seq, full);
|
||||
memcpy(blk + len, full, 12);
|
||||
}
|
||||
|
||||
static int hmacsha1_96_verresult(void *handle, unsigned char const *hmac)
|
||||
{
|
||||
unsigned char correct[20];
|
||||
hmacsha1_genresult(handle, correct);
|
||||
return smemeq(correct, hmac, 12);
|
||||
}
|
||||
|
||||
static int sha1_96_verify(void *handle, const void *vblk, int len,
|
||||
unsigned long seq)
|
||||
{
|
||||
const unsigned char *blk = (const unsigned char *)vblk;
|
||||
unsigned char correct[20];
|
||||
sha1_do_hmac(handle, blk, len, seq, correct);
|
||||
return smemeq(correct, blk + len, 12);
|
||||
SHA_Final(&s, intermediate);
|
||||
memcpy(hmac, intermediate, ctx->mac.vt->len);
|
||||
smemclr(intermediate, sizeof(intermediate));
|
||||
}
|
||||
|
||||
void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,
|
||||
@ -432,39 +372,33 @@ void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,
|
||||
SHA_Final(&states[1], output);
|
||||
}
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha1 = {
|
||||
sha1_make_context, sha1_free_context, sha1_key,
|
||||
sha1_generate, sha1_verify,
|
||||
hmacsha1_start, hmacsha1_sink, hmacsha1_genresult, hmacsha1_verresult,
|
||||
const struct ssh2_macalg ssh_hmac_sha1 = {
|
||||
hmacsha1_new, hmacsha1_free, hmacsha1_key,
|
||||
hmacsha1_start, hmacsha1_genresult,
|
||||
"hmac-sha1", "hmac-sha1-etm@openssh.com",
|
||||
20, 20,
|
||||
"HMAC-SHA1"
|
||||
};
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha1_96 = {
|
||||
sha1_make_context, sha1_free_context, sha1_key,
|
||||
sha1_96_generate, sha1_96_verify,
|
||||
hmacsha1_start, hmacsha1_sink,
|
||||
hmacsha1_96_genresult, hmacsha1_96_verresult,
|
||||
const struct ssh2_macalg ssh_hmac_sha1_96 = {
|
||||
hmacsha1_new, hmacsha1_free, hmacsha1_key,
|
||||
hmacsha1_start, hmacsha1_genresult,
|
||||
"hmac-sha1-96", "hmac-sha1-96-etm@openssh.com",
|
||||
12, 20,
|
||||
"HMAC-SHA1-96"
|
||||
};
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha1_buggy = {
|
||||
sha1_make_context, sha1_free_context, sha1_key_buggy,
|
||||
sha1_generate, sha1_verify,
|
||||
hmacsha1_start, hmacsha1_sink, hmacsha1_genresult, hmacsha1_verresult,
|
||||
const struct ssh2_macalg ssh_hmac_sha1_buggy = {
|
||||
hmacsha1_new, hmacsha1_free, hmacsha1_key,
|
||||
hmacsha1_start, hmacsha1_genresult,
|
||||
"hmac-sha1", NULL,
|
||||
20, 16,
|
||||
"bug-compatible HMAC-SHA1"
|
||||
};
|
||||
|
||||
const struct ssh_mac ssh_hmac_sha1_96_buggy = {
|
||||
sha1_make_context, sha1_free_context, sha1_key_buggy,
|
||||
sha1_96_generate, sha1_96_verify,
|
||||
hmacsha1_start, hmacsha1_sink,
|
||||
hmacsha1_96_genresult, hmacsha1_96_verresult,
|
||||
const struct ssh2_macalg ssh_hmac_sha1_96_buggy = {
|
||||
hmacsha1_new, hmacsha1_free, hmacsha1_key,
|
||||
hmacsha1_start, hmacsha1_genresult,
|
||||
"hmac-sha1-96", NULL,
|
||||
12, 16,
|
||||
"bug-compatible HMAC-SHA1-96"
|
||||
|
Loading…
Reference in New Issue
Block a user