/*
- * SHA1 hash algorithm. Used in SSH2 as a MAC, and the transform is
+ * SHA1 hash algorithm. Used in SSH-2 as a MAC, and the transform is
* also used as a `stirring' function for the PuTTY random number
* pool. Implemented directly from the specification by Simon
* Tatham.
SHA_Final(&s, output);
}
+/*
+ * Thin abstraction for things where hashes are pluggable.
+ */
+
+static void *sha1_init(void)
+{
+ SHA_State *s;
+
+ s = snew(SHA_State);
+ SHA_Init(s);
+ return s;
+}
+
+static void sha1_bytes(void *handle, void *p, int len)
+{
+ SHA_State *s = handle;
+
+ SHA_Bytes(s, p, len);
+}
+
+static void sha1_final(void *handle, unsigned char *output)
+{
+ SHA_State *s = handle;
+
+ SHA_Final(s, output);
+ sfree(s);
+}
+
+const struct ssh_hash ssh_sha1 = {
+ sha1_init, sha1_bytes, sha1_final, 20, "SHA-1"
+};
+
/* ----------------------------------------------------------------------
* The above is the SHA-1 algorithm itself. Now we implement the
* HMAC wrapper on it.
static void *sha1_make_context(void)
{
- return snewn(2, SHA_State);
+ return snewn(3, SHA_State);
}
static void sha1_free_context(void *handle)
SHA_Init(&keys[1]);
SHA_Bytes(&keys[1], foo, 64);
- memset(foo, 0, 64); /* burn the evidence */
+ smemclr(foo, 64); /* burn the evidence */
}
static void sha1_key(void *handle, unsigned char *key)
sha1_key_internal(handle, key, 16);
}
-static void sha1_do_hmac(void *handle, unsigned char *blk, int len,
- unsigned long seq, unsigned char *hmac)
+static void hmacsha1_start(void *handle)
+{
+ SHA_State *keys = (SHA_State *)handle;
+
+ keys[2] = keys[0]; /* structure copy */
+}
+
+static void hmacsha1_bytes(void *handle, unsigned char const *blk, int len)
+{
+ SHA_State *keys = (SHA_State *)handle;
+ SHA_Bytes(&keys[2], (void *)blk, len);
+}
+
+static void hmacsha1_genresult(void *handle, unsigned char *hmac)
{
SHA_State *keys = (SHA_State *)handle;
SHA_State s;
unsigned char intermediate[20];
- intermediate[0] = (unsigned char) ((seq >> 24) & 0xFF);
- intermediate[1] = (unsigned char) ((seq >> 16) & 0xFF);
- intermediate[2] = (unsigned char) ((seq >> 8) & 0xFF);
- intermediate[3] = (unsigned char) ((seq) & 0xFF);
-
- s = keys[0]; /* structure copy */
- SHA_Bytes(&s, intermediate, 4);
- SHA_Bytes(&s, blk, len);
+ s = keys[2]; /* structure copy */
SHA_Final(&s, intermediate);
s = keys[1]; /* structure copy */
SHA_Bytes(&s, intermediate, 20);
SHA_Final(&s, hmac);
}
+static void sha1_do_hmac(void *handle, unsigned char *blk, int len,
+ unsigned long seq, unsigned char *hmac)
+{
+ unsigned char seqbuf[4];
+
+ seqbuf[0] = (unsigned char) ((seq >> 24) & 0xFF);
+ seqbuf[1] = (unsigned char) ((seq >> 16) & 0xFF);
+ seqbuf[2] = (unsigned char) ((seq >> 8) & 0xFF);
+ seqbuf[3] = (unsigned char) ((seq) & 0xFF);
+
+ hmacsha1_start(handle);
+ hmacsha1_bytes(handle, seqbuf, 4);
+ hmacsha1_bytes(handle, blk, len);
+ hmacsha1_genresult(handle, hmac);
+}
+
static void sha1_generate(void *handle, unsigned char *blk, int len,
unsigned long seq)
{
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 !memcmp(correct, hmac, 20);
+}
+
static int sha1_verify(void *handle, unsigned char *blk, int len,
unsigned long seq)
{
return !memcmp(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, unsigned char *blk, int len,
+ unsigned long seq)
+{
+ 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 !memcmp(correct, hmac, 12);
+}
+
+static int sha1_96_verify(void *handle, unsigned char *blk, int len,
+ unsigned long seq)
+{
+ unsigned char correct[20];
+ sha1_do_hmac(handle, blk, len, seq, correct);
+ return !memcmp(correct, blk + len, 12);
+}
+
void hmac_sha1_simple(void *key, int keylen, void *data, int datalen,
unsigned char *output) {
SHA_State states[2];
SHA_Final(&states[1], output);
}
-const struct ssh_mac ssh_sha1 = {
+const struct ssh_mac ssh_hmac_sha1 = {
sha1_make_context, sha1_free_context, sha1_key,
sha1_generate, sha1_verify,
+ hmacsha1_start, hmacsha1_bytes, hmacsha1_genresult, hmacsha1_verresult,
"hmac-sha1",
20,
"HMAC-SHA1"
};
-const struct ssh_mac ssh_sha1_buggy = {
+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_bytes,
+ hmacsha1_96_genresult, hmacsha1_96_verresult,
+ "hmac-sha1-96",
+ 12,
+ "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_bytes, hmacsha1_genresult, hmacsha1_verresult,
"hmac-sha1",
20,
"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_bytes,
+ hmacsha1_96_genresult, hmacsha1_96_verresult,
+ "hmac-sha1-96",
+ 12,
+ "bug-compatible HMAC-SHA1-96"
+};