Make the digest and HMAC function of OpenSSL accesable to the user via converters. e.g. They can be used to sign and validate cookies. --- Makefile | 2 +- doc/configuration.txt | 9 +++++ src/crypto.c | 84 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 src/crypto.c
diff --git a/Makefile b/Makefile index 5d170041..9a3a5024 100644 --- a/Makefile +++ b/Makefile @@ -609,7 +609,7 @@ OPTIONS_LDFLAGS += $(if $(SSL_LIB),-L$(SSL_LIB)) -lssl -lcrypto ifneq ($(USE_DL),) OPTIONS_LDFLAGS += -ldl endif -OPTIONS_OBJS += src/ssl_sock.o +OPTIONS_OBJS += src/crypto.o src/ssl_sock.o endif # The private cache option affect the way the shctx is built diff --git a/doc/configuration.txt b/doc/configuration.txt index e901d7ee..7c9eb55c 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -12909,6 +12909,10 @@ debug type of the input sample. The sample is returned as is on its output. This converter only exists when haproxy was built with debugging enabled. +digest(<algorithm>) + Converts a binary input sample to a message digest. The result is a binary + sample. The alorithm must a OpenSSL message digest name (e.g sha256). + div(<value>) Divides the input value of type signed integer by <value>, and returns the result as an signed integer. If <value> is null, the largest unsigned @@ -12963,6 +12967,11 @@ hex2i Converts a hex string containing two hex digits per input byte to an integer. If the input value can not be converted, then zero is returned. +hmac(<algorithm>, <key>) + Converts a binary input sample to a message authentication code with the given + key. The result is a binary sample. The alorithm must be of the registered + OpenSSL message digest names (e.g sha256). + http_date([<offset>]) Converts an integer supposed to contain a date since epoch to a string representing this date in a format suitable for use in HTTP header fields. If diff --git a/src/crypto.c b/src/crypto.c new file mode 100644 index 00000000..e4a65557 --- /dev/null +++ b/src/crypto.c @@ -0,0 +1,84 @@ +/* + * Crypto converters + * + * Copyright 2018 Patrick Gansterer <par...@paroga.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include <common/chunk.h> + +#include <proto/arg.h> +#include <proto/sample.h> + +#include <openssl/evp.h> +#include <openssl/hmac.h> + +static int sample_conv_crypto_digest(const struct arg *args, struct sample *smp, void *private) +{ + struct chunk *trash = get_trash_chunk(); + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.str); + unsigned char *md = (unsigned char*) trash->str; + unsigned int md_len = trash->size; + + if (!ctx) + return 0; + if (!evp) + return 0; + + if (!EVP_DigestInit(ctx, evp) || + !EVP_DigestUpdate(ctx, smp->data.u.str.str, smp->data.u.str.len) || + !EVP_DigestFinal(ctx, md, &md_len)) { + EVP_MD_CTX_free(ctx); + return 0; + } + + EVP_MD_CTX_free(ctx); + + trash->len = md_len; + smp->data.u.str = *trash; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + return 1; +} + +static int sample_conv_crypto_hmac(const struct arg *args, struct sample *smp, void *private) +{ + struct chunk *trash = get_trash_chunk(); + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.str); + const char* key = args[1].data.str.str; + int key_len = args[1].data.str.len; + unsigned char *md = (unsigned char*) trash->str; + unsigned int md_len = trash->size; + + trash->len = 0; + + if (!evp) + return 0; + + if (!HMAC(evp, key, key_len, (const unsigned char*) smp->data.u.str.str, smp->data.u.str.len, md, &md_len)) + return 0; + + trash->len = md_len; + smp->data.u.str = *trash; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + return 1; +} + +static struct sample_conv_kw_list sample_conv_kws = {ILH, { + { "digest", sample_conv_crypto_digest, ARG1(1,STR), NULL, SMP_T_BIN, SMP_T_BIN }, + { "hmac", sample_conv_crypto_hmac, ARG2(2,STR,STR), NULL, SMP_T_BIN, SMP_T_BIN }, + { /* END */ }, +}}; + +__attribute__((constructor)) +static void __crypto_init(void) +{ + sample_register_convs(&sample_conv_kws); +} -- 2.17.1