diff options
Diffstat (limited to 'sshhmac.c')
-rw-r--r-- | sshhmac.c | 257 |
1 files changed, 0 insertions, 257 deletions
diff --git a/sshhmac.c b/sshhmac.c deleted file mode 100644 index 8f18eb28..00000000 --- a/sshhmac.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Implementation of HMAC (RFC 2104) for PuTTY, in a general form that - * can wrap any underlying hash function. - */ - -#include "ssh.h" - -struct hmac { - const ssh_hashalg *hashalg; - ssh_hash *h_outer, *h_inner, *h_live; - uint8_t *digest; - strbuf *text_name; - ssh2_mac mac; -}; - -struct hmac_extra { - const ssh_hashalg *hashalg_base; - const char *suffix, *annotation; -}; - -static ssh2_mac *hmac_new(const ssh2_macalg *alg, ssh_cipher *cipher) -{ - struct hmac *ctx = snew(struct hmac); - const struct hmac_extra *extra = (const struct hmac_extra *)alg->extra; - - ctx->h_outer = ssh_hash_new(extra->hashalg_base); - /* In case that hashalg was a selector vtable, we'll now switch to - * using whatever real one it selected, for all future purposes. */ - ctx->hashalg = ssh_hash_alg(ctx->h_outer); - ctx->h_inner = ssh_hash_new(ctx->hashalg); - ctx->h_live = ssh_hash_new(ctx->hashalg); - - /* - * HMAC is not well defined as a wrapper on an absolutely general - * hash function; it expects that the function it's wrapping will - * consume data in fixed-size blocks, and it's partially defined - * in terms of that block size. So we insist that the hash we're - * given must have defined a meaningful block size. - */ - assert(ctx->hashalg->blocklen); - - ctx->digest = snewn(ctx->hashalg->hlen, uint8_t); - - ctx->text_name = strbuf_new(); - strbuf_catf(ctx->text_name, "HMAC-%s%s", - ctx->hashalg->text_basename, extra->suffix); - if (extra->annotation || ctx->hashalg->annotation) { - strbuf_catf(ctx->text_name, " ("); - const char *sep = ""; - if (extra->annotation) { - strbuf_catf(ctx->text_name, "%s%s", sep, extra->annotation); - sep = ", "; - } - if (ctx->hashalg->annotation) { - strbuf_catf(ctx->text_name, "%s%s", sep, ctx->hashalg->annotation); - sep = ", "; - } - strbuf_catf(ctx->text_name, ")"); - } - - ctx->mac.vt = alg; - BinarySink_DELEGATE_INIT(&ctx->mac, ctx->h_live); - - return &ctx->mac; -} - -static void hmac_free(ssh2_mac *mac) -{ - struct hmac *ctx = container_of(mac, struct hmac, mac); - - ssh_hash_free(ctx->h_outer); - ssh_hash_free(ctx->h_inner); - ssh_hash_free(ctx->h_live); - smemclr(ctx->digest, ctx->hashalg->hlen); - sfree(ctx->digest); - strbuf_free(ctx->text_name); - - smemclr(ctx, sizeof(*ctx)); - sfree(ctx); -} - -#define PAD_OUTER 0x5C -#define PAD_INNER 0x36 - -static void hmac_key(ssh2_mac *mac, ptrlen key) -{ - struct hmac *ctx = container_of(mac, struct hmac, mac); - - const uint8_t *kp; - size_t klen; - strbuf *sb = NULL; - - if (key.len > ctx->hashalg->blocklen) { - /* - * RFC 2104 section 2: if the key exceeds the block length of - * the underlying hash, then we start by hashing the key, and - * use that hash as the 'true' key for the HMAC construction. - */ - sb = strbuf_new_nm(); - strbuf_append(sb, ctx->hashalg->hlen); - hash_simple(ctx->hashalg, key, sb->u); - kp = sb->u; - klen = sb->len; - } else { - /* - * A short enough key is used as is. - */ - kp = (const uint8_t *)key.ptr; - klen = key.len; - } - - ssh_hash_reset(ctx->h_outer); - for (size_t i = 0; i < klen; i++) - put_byte(ctx->h_outer, PAD_OUTER ^ kp[i]); - for (size_t i = klen; i < ctx->hashalg->blocklen; i++) - put_byte(ctx->h_outer, PAD_OUTER); - - ssh_hash_reset(ctx->h_inner); - for (size_t i = 0; i < klen; i++) - put_byte(ctx->h_inner, PAD_INNER ^ kp[i]); - for (size_t i = klen; i < ctx->hashalg->blocklen; i++) - put_byte(ctx->h_inner, PAD_INNER); - - if (sb) - strbuf_free(sb); -} - -static void hmac_start(ssh2_mac *mac) -{ - struct hmac *ctx = container_of(mac, struct hmac, mac); - ssh_hash_copyfrom(ctx->h_live, ctx->h_inner); -} - -static void hmac_genresult(ssh2_mac *mac, unsigned char *output) -{ - struct hmac *ctx = container_of(mac, struct hmac, mac); - ssh_hash *htmp; - - /* Leave h_live and h_outer in place, so that the SSH-2 BPP can - * continue regenerating test results from different-length - * prefixes of the packet */ - ssh_hash_digest_nondestructive(ctx->h_live, ctx->digest); - - htmp = ssh_hash_copy(ctx->h_outer); - put_data(htmp, ctx->digest, ctx->hashalg->hlen); - ssh_hash_final(htmp, ctx->digest); - - /* - * Some instances of HMAC truncate the output hash, so instead of - * writing it directly to 'output' we wrote it to our own - * full-length buffer, and now we copy the required amount. - */ - memcpy(output, ctx->digest, mac->vt->len); - smemclr(ctx->digest, ctx->hashalg->hlen); -} - -static const char *hmac_text_name(ssh2_mac *mac) -{ - struct hmac *ctx = container_of(mac, struct hmac, mac); - return ctx->text_name->s; -} - -static const struct hmac_extra ssh_hmac_sha256_extra = { &ssh_sha256, "" }; -const ssh2_macalg ssh_hmac_sha256 = { - .new = hmac_new, - .free = hmac_free, - .setkey = hmac_key, - .start = hmac_start, - .genresult = hmac_genresult, - .text_name = hmac_text_name, - .name = "hmac-sha2-256", - .etm_name = "hmac-sha2-256-etm@openssh.com", - .len = 32, - .keylen = 32, - .extra = &ssh_hmac_sha256_extra, -}; - -static const struct hmac_extra ssh_hmac_md5_extra = { &ssh_md5, "" }; -const ssh2_macalg ssh_hmac_md5 = { - .new = hmac_new, - .free = hmac_free, - .setkey = hmac_key, - .start = hmac_start, - .genresult = hmac_genresult, - .text_name = hmac_text_name, - .name = "hmac-md5", - .etm_name = "hmac-md5-etm@openssh.com", - .len = 16, - .keylen = 16, - .extra = &ssh_hmac_md5_extra, -}; - -static const struct hmac_extra ssh_hmac_sha1_extra = { &ssh_sha1, "" }; - -const ssh2_macalg ssh_hmac_sha1 = { - .new = hmac_new, - .free = hmac_free, - .setkey = hmac_key, - .start = hmac_start, - .genresult = hmac_genresult, - .text_name = hmac_text_name, - .name = "hmac-sha1", - .etm_name = "hmac-sha1-etm@openssh.com", - .len = 20, - .keylen = 20, - .extra = &ssh_hmac_sha1_extra, -}; - -static const struct hmac_extra ssh_hmac_sha1_96_extra = { &ssh_sha1, "-96" }; - -const ssh2_macalg ssh_hmac_sha1_96 = { - .new = hmac_new, - .free = hmac_free, - .setkey = hmac_key, - .start = hmac_start, - .genresult = hmac_genresult, - .text_name = hmac_text_name, - .name = "hmac-sha1-96", - .etm_name = "hmac-sha1-96-etm@openssh.com", - .len = 12, - .keylen = 20, - .extra = &ssh_hmac_sha1_96_extra, -}; - -static const struct hmac_extra ssh_hmac_sha1_buggy_extra = { - &ssh_sha1, "", "bug-compatible" -}; - -const ssh2_macalg ssh_hmac_sha1_buggy = { - .new = hmac_new, - .free = hmac_free, - .setkey = hmac_key, - .start = hmac_start, - .genresult = hmac_genresult, - .text_name = hmac_text_name, - .name = "hmac-sha1", - .len = 20, - .keylen = 16, - .extra = &ssh_hmac_sha1_buggy_extra, -}; - -static const struct hmac_extra ssh_hmac_sha1_96_buggy_extra = { - &ssh_sha1, "-96", "bug-compatible" -}; - -const ssh2_macalg ssh_hmac_sha1_96_buggy = { - .new = hmac_new, - .free = hmac_free, - .setkey = hmac_key, - .start = hmac_start, - .genresult = hmac_genresult, - .text_name = hmac_text_name, - .name = "hmac-sha1-96", - .len = 12, - .keylen = 16, - .extra = &ssh_hmac_sha1_96_buggy_extra, -}; |