Commit fb281624 authored by Geoff Simmons's avatar Geoff Simmons

add the hmac function

parent f9027544
......@@ -30,6 +30,7 @@ CONTENTS
* Object blob
* BLOB blob.hash()
* BLOB hash(BLOB)
* BLOB hmac(BLOB, BLOB)
* Object hmac
* BLOB hmac.hmac(BLOB)
* STRING version()
......@@ -108,6 +109,17 @@ Prototype
Description
Returns the SHA256 digest for ``msg``.
.. _func_hmac:
BLOB hmac(BLOB, BLOB)
---------------------
Prototype
BLOB hmac(BLOB msg, BLOB key)
Description
Returns the SHA256 HMAC for ``msg`` based on ``key``.
.. _func_version:
STRING version()
......
......@@ -90,6 +90,7 @@ varnish v1 -vcl {
blobcode.decode(BASE64,
"AQACAQMCBAMFBAYFBwYIBwkICgkLCgwLDQwODQ8OEA8REBIRExIUExUUFhUXFhgXGRgaGRsaHBsdHB4dHx4gHyEgIiEjIiQjJSQmJScmKCcpKCopKyosKy0sLi0vLjAvMTAyMTMyNDM1NDY1NzY4Nzk4Ojk7Ojw7PTw+PT8+QD9BQEJBQ0JEQ0VERkVHRkhHSUhKSUtKTEtNTE5NT05QT1FQUlFTUlRTVVRWVVdWWFdZWFpZW1pcW11cXl1fXmBfYWBiYWNiZGNlZGZlZ2ZoZ2loamlramxrbWxubW9ucG9xcHJxc3J0c3V0dnV3dnh3eXh6eXt6fHt9fH59f36Afw==")));
# hmac object
set resp.http.rfc4231t1 = blobcode.encode(HEXLC,
rfc4231t1.hmac(blobcode.decode(IDENTITY, "Hi There")));
......@@ -128,6 +129,54 @@ varnish v1 -vcl {
rfc4231t6.hmac(blobcode.decode(IDENTITY,
"This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.")));
# hmac function
set resp.http.rfc4231t1f = blobcode.encode(HEXLC,
blobsha256.hmac(blobcode.decode(IDENTITY, "Hi There"),
blobcode.decode(HEX,
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"
)));
set resp.http.rfc4231t2f
= blobcode.encode(HEXLC,
blobsha256.hmac(blobcode.decode(IDENTITY,
"what do ya want for nothing?"),
blobcode.decode(IDENTITY, "Jefe")));
set resp.http.rfc4231t3f
= blobcode.encode(HEXLC,
blobsha256.hmac(blobcode.decode(HEX,
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"),
blobcode.decode(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")));
set resp.http.rfc4231t4f
= blobcode.encode(HEXLC,
blobsha256.hmac(blobcode.decode(HEX,
"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd"),
blobcode.decode(HEX,
"0102030405060708090a0b0c0d0e0f10111213141516171819")));
set resp.http.rfc4231t5f
= blobcode.encode(HEXLC,
blobsha256.hmac(blobcode.decode(IDENTITY,
"Test With Truncation"),
blobcode.decode(HEX,
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c")));
set resp.http.rfc4231t6f
= blobcode.encode(HEXLC,
blobsha256.hmac(blobcode.decode(IDENTITY,
"Test Using Larger Than Block-Size Key - Hash Key First"),
blobcode.decode(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")));
set resp.http.rfc4231t7f
= blobcode.encode(HEXLC,
blobsha256.hmac(blobcode.decode(IDENTITY,
"This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm."),
blobcode.decode(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")));
}
} -start
......@@ -153,6 +202,7 @@ client c1 {
expect resp.http.allbytes == "f62191c9a2deb78660d34fdf7070f1943211d46d13d1c26d9d8a1dc5bcb3e997"
# RFC4231 test cases
# hmac object
expect resp.http.rfc4231t1 == "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
expect resp.http.rfc4231t2 == "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
expect resp.http.rfc4231t3 == "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"
......@@ -160,4 +210,13 @@ client c1 {
expect resp.http.rfc4231t5 ~ "^a3b6167473100ee06e0c796c2955552b"
expect resp.http.rfc4231t6 == "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"
expect resp.http.rfc4231t7 == "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"
# hmac function
expect resp.http.rfc4231t1f == "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
expect resp.http.rfc4231t2f == "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
expect resp.http.rfc4231t3f == "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"
expect resp.http.rfc4231t4f == "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"
expect resp.http.rfc4231t5f ~ "^a3b6167473100ee06e0c796c2955552b"
expect resp.http.rfc4231t6f == "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"
expect resp.http.rfc4231t7f == "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"
} -run
......@@ -95,6 +95,43 @@ digest(VCL_BLOB restrict const b, uint8_t *restrict digest)
SHA256_Final(digest, ctx);
}
static void
hmac_init(VCL_BLOB restrict const key, SHA256_CTX * restrict const inner_ctx,
SHA256_CTX * restrict const outer_ctx)
{
uint8_t k[SHA256_BLOCKSZ] = { 0 }, innerk[SHA256_BLOCKSZ],
outerk[SHA256_BLOCKSZ];
if (key->len <= SHA256_BLOCKSZ)
memcpy(k, key->priv, key->len);
else
digest(key, k);
for (int i = 0; i < SHA256_BLOCKSZ; i++) {
innerk[i] = k[i] ^ 0x36;
outerk[i] = k[i] ^ 0x5c;
}
SHA256_Init(inner_ctx);
SHA256_Init(outer_ctx);
SHA256_Update(inner_ctx, innerk, SHA256_BLOCKSZ);
SHA256_Update(outer_ctx, outerk, SHA256_BLOCKSZ);
}
static void
hmac_fini(VCL_BLOB restrict const msg, SHA256_CTX * restrict const inner_ctx,
SHA256_CTX * restrict const outer_ctx, VCL_BLOB restrict const result)
{
uint8_t inner_digest[SHA256_LEN];
/* Hash the message with the inner key */
SHA256_Update(inner_ctx, msg->priv, msg->len);
SHA256_Final(inner_digest, inner_ctx);
/* Hash the result with the outer key */
SHA256_Update(outer_ctx, inner_digest, SHA256_LEN);
SHA256_Final(result->priv, outer_ctx);
}
/* Object hmac */
VCL_VOID
......@@ -102,8 +139,6 @@ vmod_hmac__init(VRT_CTX, struct vmod_blobsha256_hmac **hmacp,
const char *vcl_name, VCL_BLOB key)
{
struct vmod_blobsha256_hmac *hmac;
uint8_t k[SHA256_BLOCKSZ] = { 0 }, innerk[SHA256_BLOCKSZ],
outerk[SHA256_BLOCKSZ];
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(hmacp);
......@@ -113,19 +148,7 @@ vmod_hmac__init(VRT_CTX, struct vmod_blobsha256_hmac **hmacp,
AN(hmac);
*hmacp = hmac;
if (key->len <= SHA256_BLOCKSZ)
memcpy(k, key->priv, key->len);
else
digest(key, k);
for (int i = 0; i < SHA256_BLOCKSZ; i++) {
innerk[i] = k[i] ^ 0x36;
outerk[i] = k[i] ^ 0x5c;
}
SHA256_Init(&hmac->inner_ctx);
SHA256_Init(&hmac->outer_ctx);
SHA256_Update(&hmac->inner_ctx, innerk, SHA256_BLOCKSZ);
SHA256_Update(&hmac->outer_ctx, outerk, SHA256_BLOCKSZ);
hmac_init(key, &hmac->inner_ctx, &hmac->outer_ctx);
}
VCL_BLOB
......@@ -133,8 +156,7 @@ vmod_hmac_hmac(VRT_CTX, struct vmod_blobsha256_hmac *h, VCL_BLOB msg)
{
struct vmod_priv *b;
char *snap;
SHA256_CTX inner_ctx, outer_ctx;
uint8_t inner_digest[SHA256_LEN];
SHA256_CTX inner_ctx[1], outer_ctx[1];
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(h, VMOD_BLOBSHA256_HMAC_MAGIC);
......@@ -153,16 +175,10 @@ vmod_hmac_hmac(VRT_CTX, struct vmod_blobsha256_hmac *h, VCL_BLOB msg)
b->len = SHA256_LEN;
b->free = NULL;
memcpy(&inner_ctx, &h->inner_ctx, sizeof(SHA256_CTX));
memcpy(&outer_ctx, &h->outer_ctx, sizeof(SHA256_CTX));
memcpy(inner_ctx, &h->inner_ctx, sizeof(SHA256_CTX));
memcpy(outer_ctx, &h->outer_ctx, sizeof(SHA256_CTX));
/* Hash the message with the inner key */
SHA256_Update(&inner_ctx, msg->priv, msg->len);
SHA256_Final(inner_digest, &inner_ctx);
/* Hash the result with the outer key */
SHA256_Update(&outer_ctx, inner_digest, SHA256_LEN);
SHA256_Final(b->priv, &outer_ctx);
hmac_fini(msg, inner_ctx, outer_ctx, b);
return b;
}
......@@ -258,6 +274,40 @@ vmod_hash(VRT_CTX, VCL_BLOB msg)
return b;
}
VCL_BLOB
vmod_hmac(VRT_CTX, VCL_BLOB msg, VCL_BLOB key)
{
struct vmod_priv *b;
char *snap;
SHA256_CTX inner_ctx[1], outer_ctx[1];
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
if (INIT_FINI(ctx)) {
ILLEGAL(ctx, "blobsha256.hmac()");
return NULL;
}
if (msg == NULL || key == NULL)
return NULL;
CHECK_OBJ_NOTNULL(ctx->ws, WS_MAGIC);
snap = WS_Snapshot(ctx->ws);
if ((b = WS_Alloc(ctx->ws, sizeof(struct vmod_priv))) == NULL) {
ERRNOMEM(ctx, "allocating blob in blobsha256.hmac()");
return NULL;
}
if ((b->priv = WS_Alloc(ctx->ws, SHA256_LEN)) == NULL) {
WS_Reset(ctx->ws, snap);
ERRNOMEM(ctx, "allocating hash result in blobsha256.hmac()");
return NULL;
}
b->len = SHA256_LEN;
b->free = NULL;
hmac_init(key, inner_ctx, outer_ctx);
hmac_fini(msg, inner_ctx, outer_ctx, b);
return b;
}
VCL_STRING
vmod_version(VRT_CTX __attribute__((unused)))
{
......
......@@ -57,6 +57,11 @@ $Function BLOB hash(BLOB msg)
Description
Returns the SHA256 digest for ``msg``.
$Function BLOB hmac(BLOB msg, BLOB key)
Description
Returns the SHA256 HMAC for ``msg`` based on ``key``.
$Function STRING version()
Description
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment