Commit 6095ae3c authored by Geoff Simmons's avatar Geoff Simmons

add the hmac object interface

parent c2ee035a
......@@ -28,8 +28,42 @@ CONTENTS
========
* BLOB hash(ENUM, BLOB)
* Object hmac
* BLOB hmac.hmac(BLOB)
* STRING version()
.. _obj_hmac:
Object hmac
===========
Prototype
new OBJ = blobdigest.hmac(ENUM hash, BLOB key)
Description
Creates an object that generates HMACs based on the
digest algorithm ``hash`` and the given ``key``.
Example
``new key = blobcode.blob(BASE64, "a2V5");``
``new hmac = blobdigest.hmac(SHA256, key.get());``
.. _func_hmac.hmac:
BLOB hmac.hmac(BLOB)
--------------------
Prototype
BLOB hmac.hmac(BLOB msg)
Description
Returns the HMAC for ``msg`` based on the key and
hash algorithm provided in the constructor.
Example
``set req.http.hmac = hmac.hmac(blobcode.decode(BASE64, "Zm9v"));``
.. _func_hash:
BLOB hash(ENUM, BLOB)
......
......@@ -9,6 +9,32 @@ varnish v1 -vcl {
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
# RFC4231 test cases
new k1 = blobcode.blob(HEX,
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
new rfc4231t1 = blobdigest.hmac(SHA224, k1.get());
new k2 = blobcode.blob(IDENTITY, "Jefe");
new rfc4231t2 = blobdigest.hmac(SHA224, k2.get());
new k3 = blobcode.blob(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
new rfc4231t3 = blobdigest.hmac(SHA224, k3.get());
new k4 = blobcode.blob(HEX,
"0102030405060708090a0b0c0d0e0f10111213141516171819");
new rfc4231t4 = blobdigest.hmac(SHA224, k4.get());
new k5 = blobcode.blob(HEX,
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
new rfc4231t5 = blobdigest.hmac(SHA224, k5.get());
new k6 = blobcode.blob(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
new rfc4231t6 = blobdigest.hmac(SHA224, k6.get());
}
sub vcl_recv {
return(synth(200));
}
......@@ -61,6 +87,45 @@ varnish v1 -vcl {
= blobcode.encode(HEXLC, blobdigest.hash(SHA224,
blobcode.decode(BASE64,
"AQACAQMCBAMFBAYFBwYIBwkICgkLCgwLDQwODQ8OEA8REBIRExIUExUUFhUXFhgXGRgaGRsaHBsdHB4dHx4gHyEgIiEjIiQjJSQmJScmKCcpKCopKyosKy0sLi0vLjAvMTAyMTMyNDM1NDY1NzY4Nzk4Ojk7Ojw7PTw+PT8+QD9BQEJBQ0JEQ0VERkVHRkhHSUhKSUtKTEtNTE5NT05QT1FQUlFTUlRTVVRWVVdWWFdZWFpZW1pcW11cXl1fXmBfYWBiYWNiZGNlZGZlZ2ZoZ2loamlramxrbWxubW9ucG9xcHJxc3J0c3V0dnV3dnh3eXh6eXt6fHt9fH59f36Afw==")));
set resp.http.rfc4231t1 = blobcode.encode(HEXLC,
rfc4231t1.hmac(blobcode.decode(IDENTITY, "Hi There")));
set resp.http.rfc4231t2
= blobcode.encode(HEXLC,
rfc4231t2.hmac(blobcode.decode(IDENTITY,
"what do ya want for nothing?")));
set resp.http.rfc4231t3
= blobcode.encode(HEXLC,
rfc4231t3.hmac(blobcode.decode(HEX,
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd")));
set resp.http.rfc4231t4
= blobcode.encode(HEXLC,
rfc4231t4.hmac(blobcode.decode(HEX,
"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd")));
set resp.http.rfc4231t5
= blobcode.encode(HEXLC,
rfc4231t5.hmac(blobcode.decode(IDENTITY,
"Test With Truncation")));
set resp.http.rfc4231t6
= blobcode.encode(HEXLC,
rfc4231t6.hmac(blobcode.decode(IDENTITY,
"Test Using Larger Than Block-Size Key - Hash Key First")));
/*
* Test case 7 uses the same key as 6, so we'll re-use
* object rfc4231t6. This tests repeated use of the same
* internal hash contexts.
*/
set resp.http.rfc4231t7
= blobcode.encode(HEXLC,
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.")));
}
} -start
......@@ -82,4 +147,13 @@ client c1 {
# verified with: base64 -d | sha224sum
expect resp.http.allbytes == "54ca05b51f257184cd6c46c14c5aa73e28406891dde26313d4088089"
# RFC4231 test cases
expect resp.http.rfc4231t1 == "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22"
expect resp.http.rfc4231t2 == "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44"
expect resp.http.rfc4231t3 == "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea"
expect resp.http.rfc4231t4 == "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a"
expect resp.http.rfc4231t5 ~ "^0e2aea68a90c8d37c988bcdb9fca6fa8"
expect resp.http.rfc4231t6 == "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e"
expect resp.http.rfc4231t7 == "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1"
} -run
......@@ -9,6 +9,32 @@ varnish v1 -vcl {
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
# RFC4231 test cases
new k1 = blobcode.blob(HEX,
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
new rfc4231t1 = blobdigest.hmac(SHA256, k1.get());
new k2 = blobcode.blob(IDENTITY, "Jefe");
new rfc4231t2 = blobdigest.hmac(SHA256, k2.get());
new k3 = blobcode.blob(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
new rfc4231t3 = blobdigest.hmac(SHA256, k3.get());
new k4 = blobcode.blob(HEX,
"0102030405060708090a0b0c0d0e0f10111213141516171819");
new rfc4231t4 = blobdigest.hmac(SHA256, k4.get());
new k5 = blobcode.blob(HEX,
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
new rfc4231t5 = blobdigest.hmac(SHA256, k5.get());
new k6 = blobcode.blob(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
new rfc4231t6 = blobdigest.hmac(SHA256, k6.get());
}
sub vcl_recv {
return(synth(200));
}
......@@ -62,6 +88,44 @@ varnish v1 -vcl {
blobcode.decode(BASE64,
"AQACAQMCBAMFBAYFBwYIBwkICgkLCgwLDQwODQ8OEA8REBIRExIUExUUFhUXFhgXGRgaGRsaHBsdHB4dHx4gHyEgIiEjIiQjJSQmJScmKCcpKCopKyosKy0sLi0vLjAvMTAyMTMyNDM1NDY1NzY4Nzk4Ojk7Ojw7PTw+PT8+QD9BQEJBQ0JEQ0VERkVHRkhHSUhKSUtKTEtNTE5NT05QT1FQUlFTUlRTVVRWVVdWWFdZWFpZW1pcW11cXl1fXmBfYWBiYWNiZGNlZGZlZ2ZoZ2loamlramxrbWxubW9ucG9xcHJxc3J0c3V0dnV3dnh3eXh6eXt6fHt9fH59f36Afw==")));
set resp.http.rfc4231t1 = blobcode.encode(HEXLC,
rfc4231t1.hmac(blobcode.decode(IDENTITY, "Hi There")));
set resp.http.rfc4231t2
= blobcode.encode(HEXLC,
rfc4231t2.hmac(blobcode.decode(IDENTITY,
"what do ya want for nothing?")));
set resp.http.rfc4231t3
= blobcode.encode(HEXLC,
rfc4231t3.hmac(blobcode.decode(HEX,
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd")));
set resp.http.rfc4231t4
= blobcode.encode(HEXLC,
rfc4231t4.hmac(blobcode.decode(HEX,
"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd")));
set resp.http.rfc4231t5
= blobcode.encode(HEXLC,
rfc4231t5.hmac(blobcode.decode(IDENTITY,
"Test With Truncation")));
set resp.http.rfc4231t6
= blobcode.encode(HEXLC,
rfc4231t6.hmac(blobcode.decode(IDENTITY,
"Test Using Larger Than Block-Size Key - Hash Key First")));
/*
* Test case 7 uses the same key as 6, so we'll re-use
* object rfc4231t6. This tests repeated use of the same
* internal hash contexts.
*/
set resp.http.rfc4231t7
= blobcode.encode(HEXLC,
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.")));
}
} -start
......@@ -85,4 +149,13 @@ client c1 {
# verified with: base 64 -d | sha256sum
expect resp.http.allbytes == "f62191c9a2deb78660d34fdf7070f1943211d46d13d1c26d9d8a1dc5bcb3e997"
# RFC4231 test cases
expect resp.http.rfc4231t1 == "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
expect resp.http.rfc4231t2 == "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"
expect resp.http.rfc4231t3 == "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"
expect resp.http.rfc4231t4 == "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"
expect resp.http.rfc4231t5 ~ "^a3b6167473100ee06e0c796c2955552b"
expect resp.http.rfc4231t6 == "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"
expect resp.http.rfc4231t7 == "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"
} -run
......@@ -9,6 +9,32 @@ varnish v1 -vcl {
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
# RFC4231 test cases
new k1 = blobcode.blob(HEX,
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
new rfc4231t1 = blobdigest.hmac(SHA512, k1.get());
new k2 = blobcode.blob(IDENTITY, "Jefe");
new rfc4231t2 = blobdigest.hmac(SHA512, k2.get());
new k3 = blobcode.blob(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
new rfc4231t3 = blobdigest.hmac(SHA512, k3.get());
new k4 = blobcode.blob(HEX,
"0102030405060708090a0b0c0d0e0f10111213141516171819");
new rfc4231t4 = blobdigest.hmac(SHA512, k4.get());
new k5 = blobcode.blob(HEX,
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
new rfc4231t5 = blobdigest.hmac(SHA512, k5.get());
new k6 = blobcode.blob(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
new rfc4231t6 = blobdigest.hmac(SHA512, k6.get());
}
sub vcl_recv {
return(synth(200));
}
......@@ -56,6 +82,45 @@ varnish v1 -vcl {
= blobcode.encode(HEXLC, blobdigest.hash(SHA512,
blobcode.decode(BASE64,
"AQACAQMCBAMFBAYFBwYIBwkICgkLCgwLDQwODQ8OEA8REBIRExIUExUUFhUXFhgXGRgaGRsaHBsdHB4dHx4gHyEgIiEjIiQjJSQmJScmKCcpKCopKyosKy0sLi0vLjAvMTAyMTMyNDM1NDY1NzY4Nzk4Ojk7Ojw7PTw+PT8+QD9BQEJBQ0JEQ0VERkVHRkhHSUhKSUtKTEtNTE5NT05QT1FQUlFTUlRTVVRWVVdWWFdZWFpZW1pcW11cXl1fXmBfYWBiYWNiZGNlZGZlZ2ZoZ2loamlramxrbWxubW9ucG9xcHJxc3J0c3V0dnV3dnh3eXh6eXt6fHt9fH59f36Afw==")));
set resp.http.rfc4231t1 = blobcode.encode(HEXLC,
rfc4231t1.hmac(blobcode.decode(IDENTITY, "Hi There")));
set resp.http.rfc4231t2
= blobcode.encode(HEXLC,
rfc4231t2.hmac(blobcode.decode(IDENTITY,
"what do ya want for nothing?")));
set resp.http.rfc4231t3
= blobcode.encode(HEXLC,
rfc4231t3.hmac(blobcode.decode(HEX,
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd")));
set resp.http.rfc4231t4
= blobcode.encode(HEXLC,
rfc4231t4.hmac(blobcode.decode(HEX,
"cdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd")));
set resp.http.rfc4231t5
= blobcode.encode(HEXLC,
rfc4231t5.hmac(blobcode.decode(IDENTITY,
"Test With Truncation")));
set resp.http.rfc4231t6
= blobcode.encode(HEXLC,
rfc4231t6.hmac(blobcode.decode(IDENTITY,
"Test Using Larger Than Block-Size Key - Hash Key First")));
/*
* Test case 7 uses the same key as 6, so we'll re-use
* object rfc4231t6. This tests repeated use of the same
* internal hash contexts.
*/
set resp.http.rfc4231t7
= blobcode.encode(HEXLC,
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.")));
}
} -start
......@@ -76,4 +141,13 @@ client c1 {
# verified with: base64 -d | sha512sum
expect resp.http.allbytes == "339d24bfddd04c682a07912f1bd44e9056855f7a4fcb69487951c03d5c09bf962d16e7672aa4e2bd64e75cd2d9be8b185f94f3357ec46cce702ccf5e385326b0"
# RFC4231 test cases
expect resp.http.rfc4231t1 == "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854"
expect resp.http.rfc4231t2 == "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737"
expect resp.http.rfc4231t3 == "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb"
expect resp.http.rfc4231t4 == "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3dba91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd"
expect resp.http.rfc4231t5 ~ "^415fad6271580a531d4179bc891d87a6"
expect resp.http.rfc4231t6 == "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598"
expect resp.http.rfc4231t7 == "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"
} -run
......@@ -25,6 +25,8 @@
*
*/
#include <stdlib.h>
#include "config.h"
#include "vcl.h"
......@@ -48,6 +50,14 @@
#define ILLEGAL(ctx, m) \
ERR((ctx), m " is illegal in vcl_init() and vcl_fini().")
struct vmod_blobdigest_hmac {
unsigned magic;
#define VMOD_BLOBDIGEST_HMAC_MAGIC 0x85678153
hash_ctx inner_ctx;
hash_ctx outer_ctx;
enum algorithm hash;
};
static void
errmsg(VRT_CTX, const char *fmt, ...)
{
......@@ -87,7 +97,7 @@ init(const enum algorithm hash, hash_ctx * const hctx)
static void
update(const enum algorithm hash, hash_ctx *restrict const hctx,
const uint8_t *restrict msg, const size_t len)
const uint8_t *restrict const msg, const size_t len)
{
switch(hash) {
case SHA224:
......@@ -123,6 +133,110 @@ final(const enum algorithm hash, hash_ctx *restrict const hctx,
}
}
static inline void
digest(const enum algorithm hash, hash_ctx *restrict const hctx,
const VCL_BLOB restrict const b, uint8_t *restrict digest)
{
init(hash, hctx);
update(hash, hctx, b->priv, b->len);
final(hash, hctx, digest);
}
/* Objects */
VCL_VOID
vmod_hmac__init(VRT_CTX, struct vmod_blobdigest_hmac **hmacp,
const char *vcl_name, VCL_ENUM hashs, VCL_BLOB key)
{
struct vmod_blobdigest_hmac *hmac;
enum algorithm hash = parse_algorithm(hashs);
size_t blocksz = hashspec[hash].blocksz;
uint8_t k[blocksz], innerk[blocksz], outerk[blocksz];
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(hmacp);
AZ(*hmacp);
AN(vcl_name);
ALLOC_OBJ(hmac, VMOD_BLOBDIGEST_HMAC_MAGIC);
AN(hmac);
*hmacp = hmac;
hmac->hash = hash;
memset(k, 0, blocksz);
if (key->len <= blocksz)
memcpy(k, key->priv, key->len);
else {
hash_ctx hctx[1];
assert(blocksz >= hashspec[hash].digestsz);
digest(hash, hctx, key, k);
}
for (int i = 0; i < blocksz; i++) {
innerk[i] = k[i] ^ 0x36;
outerk[i] = k[i] ^ 0x5c;
}
init(hash, &hmac->inner_ctx);
init(hash, &hmac->outer_ctx);
update(hash, &hmac->inner_ctx, innerk, blocksz);
update(hash, &hmac->outer_ctx, outerk, blocksz);
}
VCL_BLOB
vmod_hmac_hmac(VRT_CTX, struct vmod_blobdigest_hmac *h, VCL_BLOB msg)
{
struct vmod_priv *b;
char *snap;
hash_ctx inner_ctx, outer_ctx;
enum algorithm hash;
size_t digestsz;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(h, VMOD_BLOBDIGEST_HMAC_MAGIC);
hash = h->hash;
digestsz = hashspec[hash].digestsz;
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 hmac.hmac()");
return NULL;
}
if ((b->priv = WS_Alloc(ctx->ws, digestsz)) == NULL) {
WS_Reset(ctx->ws, snap);
ERRNOMEM(ctx, "allocating hash result in hmac.hmac()");
return NULL;
}
b->len = digestsz;
b->free = NULL;
uint8_t inner_digest[digestsz];
memcpy(&inner_ctx, &h->inner_ctx, sizeof(hash_ctx));
memcpy(&outer_ctx, &h->outer_ctx, sizeof(hash_ctx));
/* Hash the message with the inner key */
update(hash, &inner_ctx, msg->priv, msg->len);
final(hash, &inner_ctx, inner_digest);
/* Hash the result with the outer key */
update(hash, &outer_ctx, inner_digest, digestsz);
final(hash, &outer_ctx, b->priv);
return b;
}
VCL_VOID
vmod_hmac__fini(struct vmod_blobdigest_hmac **hmacp)
{
struct vmod_blobdigest_hmac *hmac;
AN(*hmacp);
hmac = *hmacp;
*hmacp = NULL;
CHECK_OBJ_NOTNULL(hmac, VMOD_BLOBDIGEST_HMAC_MAGIC);
FREE_OBJ(hmac);
}
/* Functions */
VCL_BLOB
vmod_hash(VRT_CTX, VCL_ENUM hashs, VCL_BLOB msg)
{
......@@ -145,16 +259,14 @@ vmod_hash(VRT_CTX, VCL_ENUM hashs, VCL_BLOB msg)
ERRNOMEM(ctx, "allocating blob in hash()");
return NULL;
}
if ((b->priv = WS_Alloc(ctx->ws, hashspec[hash])) == NULL) {
if ((b->priv = WS_Alloc(ctx->ws, hashspec[hash].digestsz)) == NULL) {
WS_Reset(ctx->ws, snap);
ERRNOMEM(ctx, "allocating hash result in hash()");
return NULL;
}
b->len = hashspec[hash];
b->len = hashspec[hash].digestsz;
b->free = NULL;
init(hash, hctx);
update(hash, hctx, msg->priv, msg->len);
final(hash, hctx, b->priv);
digest(hash, hctx, msg, b->priv);
return b;
}
......
......@@ -38,8 +38,20 @@ typedef union hash_ctx {
sha512_ctx sha512;
} hash_ctx;
static const size_t hashspec[] = {
[SHA224] = sha224_hash_size,
[SHA256] = SHA256_LEN,
[SHA512] = sha512_hash_size,
static const struct hashspec {
const size_t digestsz;
const size_t blocksz;
} hashspec[] = {
[SHA224] = {
sha224_hash_size,
sha256_block_size,
},
[SHA256] = {
SHA256_LEN,
sha256_block_size,
},
[SHA512] = {
sha512_hash_size,
sha512_block_size,
},
};
......@@ -9,6 +9,28 @@
$Module blobdigest 3 digests and hmacs for the VCL blob type
$Object hmac(ENUM {SHA224, SHA256, SHA512} hash, BLOB key)
Prototype
new OBJ = blobdigest.hmac(ENUM hash, BLOB key)
Description
Creates an object that generates HMACs based on the
digest algorithm ``hash`` and the given ``key``.
Example
``new key = blobcode.blob(BASE64, "a2V5");``
``new hmac = blobdigest.hmac(SHA256, key.get());``
$Method BLOB .hmac(BLOB msg)
Description
Returns the HMAC for ``msg`` based on the key and
hash algorithm provided in the constructor.
Example
``set req.http.hmac = hmac.hmac(blobcode.decode(BASE64, "Zm9v"));``
$Function BLOB hash(ENUM {SHA224, SHA256, SHA512} hash, BLOB msg)
$Function STRING version()
......
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