Commit 1d06f969 authored by Geoff Simmons's avatar Geoff Simmons

initial commit

parents
((nil . ((indent-tabs-mode . t)))
(c-mode . ((c-file-style . "BSD"))))
Makefile
Makefile.in
.deps/
.libs/
*.o
*.lo
*.la
*~
*.[1-9]
.dirstamp
/aclocal.m4
/autom4te.cache/
/compile
/config.guess
/config.h
/config.h.in
/config.log
/config.status
/config.sub
/configure
/depcomp
/install-sh
/libtool
/ltmain.sh
/missing
/stamp-h1
/m4/
/src/vcc_if.c
/src/vcc_if.h
/src/vmod_*rst
See LICENSE for details.
Copyright (c) 2016 UPLEX Nils Goroll Systemoptimierung
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
ACLOCAL_AMFLAGS = -I m4 -I ${LIBVARNISHAPI_DATAROOTDIR}/aclocal
SUBDIRS = src
DISTCHECK_CONFIGURE_FLAGS = \
VMOD_DIR='$${libdir}/varnish/vmods'
EXTRA_DIST = README.rst LICENSE COPYING
doc_DATA = README.rst LICENSE COPYING
dist_man_MANS = vmod_blobsha256.3
MAINTAINERCLEANFILES = $(dist_man_MANS)
vmod_blobsha256.3: README.rst
README.rst: src/vmod_blobsha256.man.rst
cp src/vmod_blobsha256.man.rst README.rst
src/vmod_blobsha256.man.rst:
make -C src vmod_blobsha256.man.rst
%.1 %.2 %.3 %.4 %.5 %.6 %.7 %.8 %.9:
if HAVE_RST2MAN
${RST2MAN} $< $@
else
@echo "========================================"
@echo "You need rst2man installed to make dist"
@echo "========================================"
@false
endif
..
.. NB: This file is machine generated, DO NOT EDIT!
..
.. Edit vmod.vcc and run make instead
..
.. role:: ref(emphasis)
.. _vmod_blobsha256(3):
===============
vmod_blobsha256
===============
----------------------------------------------
SHA256 digests and hmacs for the VCL blob type
----------------------------------------------
:Manual section: 3
SYNOPSIS
========
import blobsha256 [from "path"] ;
CONTENTS
========
* BLOB hash(BLOB)
* Object hmac
* BLOB hmac.hmac(BLOB)
* STRING version()
.. _obj_hmac:
Object hmac
===========
Prototype
new OBJ = blobsha256.hmac(BLOB key)
Description
Creates an object that generates HMACs based on SHA256 and the
given ``key``.
Example
``new key = blobcode.blob(BASE64, "a2V5");``
``new hmac = blobsha256.hmac(key.get());``
.. _func_hmac.hmac:
BLOB hmac.hmac(BLOB)
--------------------
Prototype
BLOB hmac.hmac(BLOB msg)
Description
Returns the HMAC-SHA256 message authentication code for
``msg`` based on the key provided in the constructor.
Example
``set req.http.hmac = hmac.hmac(blobcode.decode(BASE64, "Zm9v"));``
.. _func_hash:
BLOB hash(BLOB)
---------------
Prototype
BLOB hash(BLOB msg)
Description
Returns the SHA256 digest for ``msg``.
.. _func_version:
STRING version()
----------------
Prototype
STRING version()
Description
Returns the version string for this VMOD.
Example
``std.log("Using VMOD blobsha256 version " + blobsha256.version());``
#!/bin/sh
warn() {
echo "WARNING: $@" 1>&2
}
case `uname -s` in
Darwin)
LIBTOOLIZE=glibtoolize
;;
FreeBSD)
LIBTOOLIZE=libtoolize
;;
Linux)
LIBTOOLIZE=libtoolize
;;
SunOS)
LIBTOOLIZE=libtoolize
;;
*)
warn "unrecognized platform:" `uname -s`
LIBTOOLIZE=libtoolize
esac
automake_version=`automake --version | tr ' ' '\n' | egrep '^[0-9]\.[0-9a-z.-]+'`
if [ -z "$automake_version" ] ; then
warn "unable to determine automake version"
else
case $automake_version in
0.*|1.[0-8]|1.[0-8][.-]*)
warn "automake ($automake_version) detected; 1.9 or newer recommended"
;;
*)
;;
esac
fi
# check for varnishapi.m4 in custom paths
dataroot=$(pkg-config --variable=datarootdir varnishapi 2>/dev/null)
if [ -z "$dataroot" ] ; then
cat >&2 <<'EOF'
Package varnishapi was not found in the pkg-config search path.
Perhaps you should add the directory containing `varnishapi.pc'
to the PKG_CONFIG_PATH environment variable
EOF
exit 1
fi
set -ex
aclocal -I m4 -I ${dataroot}/aclocal
$LIBTOOLIZE --copy --force
autoheader
automake --add-missing --copy --foreign
autoconf
AC_PREREQ(2.59)
AC_COPYRIGHT([Copyright (c) 2016 UPLEX - Nils Goroll Systemoptimierung])
AC_INIT([libvmod-blobsha256], [trunk])
AC_CONFIG_MACRO_DIR([m4])
m4_ifndef([VARNISH_VMOD_INCLUDES], AC_MSG_ERROR([Need varnish.m4 -- see README.rst]))
AC_CONFIG_SRCDIR(src/vmod_blobsha256.vcc)
AM_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
AC_LANG(C)
AM_INIT_AUTOMAKE([foreign])
AC_GNU_SOURCE
AC_PROG_CC
AC_PROG_CC_STDC
if test "x$ac_cv_prog_cc_c99" = xno; then
AC_MSG_ERROR([Could not find a C99 compatible compiler])
fi
AC_PROG_CPP
AX_PTHREAD(,[AC_MSG_ERROR([Could not configure pthreads support])])
LIBS="$PTHREAD_LIBS $LIBS"
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
CC="$PTHREAD_CC"
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_PROG_MAKE_SET
# Check for rst utilities
AC_CHECK_PROGS(RST2MAN, [rst2man rst2man.py], "no")
if test "x$RST2MAN" = "xno"; then
AC_MSG_WARN([rst2man not found - not building man pages])
fi
AM_CONDITIONAL(HAVE_RST2MAN, [test "x$RST2MAN" != "xno"])
# Checks for C sources
AC_C_INLINE
AC_C_RESTRICT
AC_TYPE_UINT8_T
# backwards compat with older pkg-config
# - pull in AC_DEFUN from pkg.m4
m4_ifndef([PKG_CHECK_VAR], [
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
# -------------------------------------------
# Retrieves the value of the pkg-config variable for the given module.
AC_DEFUN([PKG_CHECK_VAR],
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
AS_VAR_COPY([$1], [pkg_cv_][$1])
AS_VAR_IF([$1], [""], [$5], [$4])dnl
])# PKG_CHECK_VAR
])
PKG_CHECK_MODULES([libvarnishapi], [varnishapi])
PKG_CHECK_VAR([LIBVARNISHAPI_DATAROOTDIR], [varnishapi], [datarootdir])
PKG_CHECK_VAR([LIBVARNISHAPI_BINDIR], [varnishapi], [bindir])
PKG_CHECK_VAR([LIBVARNISHAPI_SBINDIR], [varnishapi], [sbindir])
AC_SUBST([LIBVARNISHAPI_DATAROOTDIR])
# Varnish include files tree
VARNISH_VMOD_INCLUDES
VARNISH_VMOD_DIR
VARNISH_VMODTOOL
AC_PATH_PROG([VARNISHTEST], [varnishtest], [],
[$LIBVARNISHAPI_BINDIR:$LIBVARNISHAPI_SBINDIR:$PATH])
AC_PATH_PROG([VARNISHD], [varnishd], [],
[$LIBVARNISHAPI_SBINDIR:$LIBVARNISHAPI_BINDIR:$PATH])
# --enable-stack-protector
AC_ARG_ENABLE(stack-protector,
AS_HELP_STRING([--enable-stack-protector],[enable stack protector (default is YES)]),
[],
[enable_stack_protector=yes])
if test "x$enable_stack_protector" != "xno"; then
AX_CHECK_COMPILE_FLAG([-fstack-protector],
AX_CHECK_LINK_FLAG([-fstack-protector],
[CFLAGS="${CFLAGS} -fstack-protector"], [], []),
[], [])
fi
# --enable-debugging
AC_ARG_ENABLE(debugging,
AS_HELP_STRING([--enable-debugging],[enable debugging (default is NO)]),
[],
[enable_debugging=no])
# AC_PROG_CC sets CFLAGS to '-g -O2' unless already set, so there's no
# need to add -g. Disable or change by explicitly setting CFLAGS. If
# this option is enabled, then -Og or -O0 becomes the last
# optimization option, and hence takes precedence.
if test "x$enable_debugging" != "xno"; then
CFLAGS="${CFLAGS} -fno-inline"
AX_CHECK_COMPILE_FLAG([-Og],
[CFLAGS="${CFLAGS} -Og"],
[CFLAGS="${CFLAGS} -O0"],
[])
fi
AC_CONFIG_FILES([
Makefile
src/Makefile
])
AC_OUTPUT
AM_CPPFLAGS = @VMOD_INCLUDES@ -Wall -Werror
CFLAGS += -std=c99
vmoddir = @VMOD_DIR@
vmod_LTLIBRARIES = libvmod_blobsha256.la
libvmod_blobsha256_la_LDFLAGS = -module -export-dynamic -avoid-version -shared
libvmod_blobsha256_la_SOURCES = \
vmod_blobsha256.c
nodist_libvmod_blobsha256_la_SOURCES = \
vcc_if.c \
vcc_if.h
libvmod_blobsha256_la_LIBADD = \
${PTHREAD_LIBS}
vmod_blobsha256.lo: vcc_if.c vcc_if.h
vcc_if.c: vcc_if.h
vcc_if.h vmod_blobsha256.man.rst: @VMODTOOL@ $(top_srcdir)/src/vmod_blobsha256.vcc
@VMODTOOL@ $(top_srcdir)/src/vmod_blobsha256.vcc
VMOD_TESTS = $(top_srcdir)/src/tests/*.vtc
.PHONY: $(VMOD_TESTS)
$(top_srcdir)/src/tests/*.vtc: libvmod_blobsha256.la
@VARNISHTEST@ -Dvarnishd=@VARNISHD@ -Dvmod_topbuild=$(abs_top_builddir) $@
check: $(VMOD_TESTS)
EXTRA_DIST = \
vmod_blobsha256.vcc \
$(VMOD_TESTS)
CLEANFILES = \
$(builddir)/vcc_if.c \
$(builddir)/vcc_if.h \
$(builddir)/vmod_blobsha256.rst \
$(builddir)/vmod_blobsha256.man.rst
# looks like -*- vcl -*-
varnishtest "vcl.use and .discard, and version string"
server s1 {} -start
varnish v1 -vcl+backend {
import blobsha256 from "${vmod_topbuild}/src/.libs/libvmod_blobsha256.so";
} -start
varnish v1 -vcl+backend {}
varnish v1 -cli "vcl.list"
varnish v1 -cli "vcl.use vcl1"
varnish v1 -cli "vcl.use vcl2"
varnish v1 -cli "vcl.use vcl1"
varnish v1 -cli "vcl.show vcl1"
varnish v1 -cli "vcl.use vcl2"
varnish v1 -cli "vcl.discard vcl1"
varnish v1 -cli "vcl.list"
varnish v1 -vcl {
import blobsha256 from "${vmod_topbuild}/src/.libs/libvmod_blobsha256.so";
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.x-version = blobsha256.version();
if (!resp.http.x-version) {
set resp.status = 500;
}
return(deliver);
}
}
client c1 {
txreq -url "/"
rxresp
expect resp.status == 200
expect resp.http.x-version ~ "^.+$"
} -run
# looks like -*- vcl -*-
varnishtest "SHA256 hash"
# VMOD blobcode must be installed
varnish v1 -vcl {
import blobsha256 from
"${vmod_topbuild}/src/.libs/libvmod_blobsha256.so";
import blobcode;
backend b { .host = "${bad_ip}"; }
sub vcl_init {
# RFC4231 test cases
new k1 = blobcode.blob(HEX,
"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b");
new rfc4231t1 = blobsha256.hmac(k1.get());
new k2 = blobcode.blob(IDENTITY, "Jefe");
new rfc4231t2 = blobsha256.hmac(k2.get());
new k3 = blobcode.blob(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
new rfc4231t3 = blobsha256.hmac(k3.get());
new k4 = blobcode.blob(HEX,
"0102030405060708090a0b0c0d0e0f10111213141516171819");
new rfc4231t4 = blobsha256.hmac(k4.get());
new k5 = blobcode.blob(HEX,
"0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c");
new rfc4231t5 = blobsha256.hmac(k5.get());
new k6 = blobcode.blob(HEX,
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
new rfc4231t6 = blobsha256.hmac(k6.get());
}
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.empty
= blobcode.encode(HEXLC, blobsha256.hash(
blobcode.decode(IDENTITY, "")));
set resp.http.msgdigest
= blobcode.encode(HEXLC, blobsha256.hash(
blobcode.decode(IDENTITY,
"message digest")));
set resp.http.alphanum
= blobcode.encode(HEXLC, blobsha256.hash(
blobcode.decode(IDENTITY,
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")));
set resp.http.a
= blobcode.encode(HEXUC, blobsha256.hash(
blobcode.decode(IDENTITY, "a")));
set resp.http.abc
= blobcode.encode(HEXUC, blobsha256.hash(
blobcode.decode(IDENTITY, "abc")));
set resp.http.alphalc
= blobcode.encode(HEXUC, blobsha256.hash(
blobcode.decode(IDENTITY,
"abcdefghijklmnopqrstuvwxyz")));
set resp.http.pangram
= blobcode.encode(HEXUC, blobsha256.hash(
blobcode.decode(IDENTITY,
"The quick brown fox jumps over the lazy dog")));
set resp.http.alphasoup
= blobcode.encode(HEXUC, blobsha256.hash(
blobcode.decode(IDENTITY,
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")));
set resp.http.digits
= blobcode.encode(HEXUC, blobsha256.hash(
blobcode.decode(IDENTITY,
"12345678901234567890123456789012345678901234567890123456789012345678901234567890")));
# all 256 byte values in ascending, big-endian order
set resp.http.allbytes
= blobcode.encode(HEXLC, blobsha256.hash(
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
client c1 {
txreq
rxresp
expect resp.status == 200
# from libvarnish SHA256_Test
expect resp.http.empty == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
expect resp.http.msgdigest == "f7846f55cf23e14eebeab5b4e1550cad5b509e3348fbc4efa3a1413d393cb650"
expect resp.http.alphanum == "db4bfcbd4da0cd85a60c3c37d3fbd8805c77f15fc6b1fdfe614ee0a7c8fdb4c0"
# from librhash
expect resp.http.a == "CA978112CA1BBDCAFAC231B39A23DC4DA786EFF8147C4E72B9807785AFEE48BB"
expect resp.http.abc == "BA7816BF8F01CFEA414140DE5DAE2223B00361A396177A9CB410FF61F20015AD"
expect resp.http.alphalc == "71C480DF93D6AE2F1EFAD1447C66C9525E316218CF51FC8D9ED832F2DAF18B73"
expect resp.http.pangram == "D7A8FBB307D7809469CA9ABCB0082E4F8D5651E46D3CDB762D02D0BF37C9E592"
expect resp.http.alphasoup == "248D6A61D20638B8E5C026930C3E6039A33CE45964FF2167F6ECEDD419DB06C1"
expect resp.http.digits == "F371BC4A311F2B009EEF952DD83CA80E2B60026C8E935592D0F9C308453C813E"
# 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
/*-
* Copyright 2016 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <stdlib.h>
#include <stdint.h>
#include "config.h"
#include "vsha256.h"
#include "vcl.h"
#include "vrt.h"
#include "vas.h"
#include "vdef.h"
#include "cache/cache.h"
#include "vsb.h"
#include "vcc_if.h"
#define SHA256_BLOCKSZ 64
#define ERR(ctx, msg) \
errmsg((ctx), "vmod blobsha256 error: " msg)
#define ERRNOMEM(ctx, msg) \
ERR((ctx), msg ", out of space")
#define INIT_FINI(ctx) (((ctx)->method & (VCL_MET_INIT | VCL_MET_FINI)) != 0)
#define ILLEGAL(ctx, m) \
ERR((ctx), m " is illegal in vcl_init() and vcl_fini().")
struct vmod_blobsha256_hmac {
unsigned magic;
#define VMOD_BLOBSHA256_HMAC_MAGIC 0x96026563
SHA256_CTX inner_ctx;
SHA256_CTX outer_ctx;
};
static void
errmsg(VRT_CTX, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
if (ctx->method == VCL_MET_INIT) {
AN(ctx->msg);
VSB_vprintf(ctx->msg, fmt, args);
VRT_handling(ctx, VCL_RET_FAIL);
}
else if (ctx->vsl)
VSLbv(ctx->vsl, SLT_VCL_Error, fmt, args);
else
/* Should this ever happen in vcl_fini() ... */
VSL(SLT_VCL_Error, 0, fmt, args);
va_end(args);
}
static inline void
digest(SHA256_CTX *restrict const ctx, VCL_BLOB restrict const b,
uint8_t *restrict digest)
{
SHA256_Init(ctx);
SHA256_Update(ctx, b->priv, b->len);
SHA256_Final(digest, ctx);
}
/* Objects */
VCL_VOID
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);
AZ(*hmacp);
AN(vcl_name);
ALLOC_OBJ(hmac, VMOD_BLOBSHA256_HMAC_MAGIC);
AN(hmac);
*hmacp = hmac;
if (key->len <= SHA256_BLOCKSZ)
memcpy(k, key->priv, key->len);
else {
SHA256_CTX hctx[1];
digest(hctx, 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);
}
VCL_BLOB
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;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(h, VMOD_BLOBSHA256_HMAC_MAGIC);
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, SHA256_LEN)) == NULL) {
WS_Reset(ctx->ws, snap);
ERRNOMEM(ctx, "allocating hash result in hmac.hmac()");
return NULL;
}
b->len = SHA256_LEN;
b->free = NULL;
uint8_t inner_digest[SHA256_LEN];
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);
return b;
}
VCL_VOID
vmod_hmac__fini(struct vmod_blobsha256_hmac **hmacp)
{
struct vmod_blobsha256_hmac *hmac;
AN(*hmacp);
hmac = *hmacp;
*hmacp = NULL;
CHECK_OBJ_NOTNULL(hmac, VMOD_BLOBSHA256_HMAC_MAGIC);
FREE_OBJ(hmac);
}
/* Functions */
VCL_BLOB
vmod_hash(VRT_CTX, VCL_BLOB msg)
{
struct vmod_priv *b;
char *snap;
SHA256_CTX hctx[1];
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
if (INIT_FINI(ctx)) {
ILLEGAL(ctx, "hash()");
return NULL;
}
if (msg == 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 hash()");
return NULL;
}
if ((b->priv = WS_Alloc(ctx->ws, SHA256_LEN)) == NULL) {
WS_Reset(ctx->ws, snap);
ERRNOMEM(ctx, "allocating hash result in hash()");
return NULL;
}
b->len = SHA256_LEN;
b->free = NULL;
digest(hctx, msg, b->priv);
return b;
}
VCL_STRING
vmod_version(VRT_CTX __attribute__((unused)))
{
return VERSION;
}
#-
# Copyright (c) 2016 UPLEX Nils Goroll Systemoptimierung
# All rights reserved
#
# Author: Geoffrey Simmons <geoffrey.simmons@uplex.de>
#
# See LICENSE
#
$Module blobsha256 3 SHA256 digests and hmacs for the VCL blob type
$Object hmac(BLOB key)
Prototype
new OBJ = blobsha256.hmac(BLOB key)
Description
Creates an object that generates HMACs based on SHA256 and the
given ``key``.
Example
``new key = blobcode.blob(BASE64, "a2V5");``
``new hmac = blobsha256.hmac(key.get());``
$Method BLOB .hmac(BLOB msg)
Description
Returns the HMAC-SHA256 message authentication code for
``msg`` based on the key provided in the constructor.
Example
``set req.http.hmac = hmac.hmac(blobcode.decode(BASE64, "Zm9v"));``
$Function BLOB hash(BLOB msg)
Description
Returns the SHA256 digest for ``msg``.
$Function STRING version()
Description
Returns the version string for this VMOD.
Example
``std.log("Using VMOD blobsha256 version " + blobsha256.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