Tim, sorry for the troubles. My mail program added automatic line breaks. :-(
I attached the two files now. - Patrick
>From 8f6ce045c80e0f67a485233ee602b57b4c311bde Mon Sep 17 00:00:00 2001 From: Patrick Gansterer <[email protected]> Date: Sun, 17 Jun 2018 11:21:11 +0200 Subject: [PATCH 1/2] MINOR: crypto: Move aes_gcm_dec implementation into new file --- Makefile | 2 +- src/crypto.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++ src/ssl_sock.c | 142 ------------------------------------------ 3 files changed, 164 insertions(+), 143 deletions(-) create mode 100644 src/crypto.c diff --git a/Makefile b/Makefile index 1e4213989..2dea46368 100644 --- a/Makefile +++ b/Makefile @@ -542,7 +542,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/src/crypto.c b/src/crypto.c new file mode 100644 index 000000000..74b92eee5 --- /dev/null +++ b/src/crypto.c @@ -0,0 +1,163 @@ +/* + * Crypto converters + * + * Copyright 2020 Nenad Merdanovic <[email protected]> + * + * 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/base64.h> +#include <common/chunk.h> +#include <common/standard.h> + +#include <proto/arg.h> +#include <proto/sample.h> +#include <proto/vars.h> + +#include <openssl/evp.h> + +#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL) +static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp) +{ + switch (arg->type) { + case ARGT_STR: + smp->data.type = SMP_T_STR; + smp->data.u.str = arg->data.str; + return 1; + case ARGT_VAR: + if (!vars_get_by_desc(&arg->data.var, smp)) + return 0; + if (!sample_casts[smp->data.type][SMP_T_STR]) + return 0; + if (!sample_casts[smp->data.type][SMP_T_STR](smp)) + return 0; + return 1; + default: + return 0; + } +} + +static int check_aes_gcm(struct arg *args, struct sample_conv *conv, + const char *file, int line, char **err) +{ + switch(args[0].data.sint) { + case 128: + case 192: + case 256: + break; + default: + memprintf(err, "key size must be 128, 192 or 256 (bits)."); + return 0; + } + /* Try to decode a variable. */ + vars_check_arg(&args[1], NULL); + vars_check_arg(&args[2], NULL); + vars_check_arg(&args[3], NULL); + return 1; +} + +/* Arguments: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */ +static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private) +{ + struct sample nonce, key, aead_tag; + struct buffer *smp_trash, *smp_trash_alloc; + EVP_CIPHER_CTX *ctx; + int dec_size, ret; + + smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt); + if (!sample_conv_var2smp_str(&arg_p[1], &nonce)) + return 0; + + smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt); + if (!sample_conv_var2smp_str(&arg_p[2], &key)) + return 0; + + smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt); + if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag)) + return 0; + + smp_trash = get_trash_chunk(); + smp_trash_alloc = alloc_trash_chunk(); + if (!smp_trash_alloc) + return 0; + + ctx = EVP_CIPHER_CTX_new(); + + if (!ctx) + goto err; + + dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size); + if (dec_size < 0) + goto err; + smp_trash->data = dec_size; + + /* Set cipher type and mode */ + switch(arg_p[0].data.sint) { + case 128: + EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); + break; + case 192: + EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL); + break; + case 256: + EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); + break; + } + + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL); + + /* Initialise IV */ + if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area)) + goto err; + + dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size); + if (dec_size < 0) + goto err; + smp_trash->data = dec_size; + + /* Initialise key */ + if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL)) + goto err; + + if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data, + (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data)) + goto err; + + dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size); + if (dec_size < 0) + goto err; + smp_trash_alloc->data = dec_size; + dec_size = smp_trash->data; + + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area); + ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data); + + if (ret <= 0) + goto err; + + smp->data.u.str.data = dec_size + smp_trash->data; + smp->data.u.str.area = smp_trash->area; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + free_trash_chunk(smp_trash_alloc); + return 1; + +err: + free_trash_chunk(smp_trash_alloc); + return 0; +} +# endif + +/* Note: must not be declared <const> as its list will be overwritten */ +static struct sample_conv_kw_list conv_kws = {ILH, { +#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL) + { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN }, +#endif + { NULL, NULL, 0, 0, 0 }, +}}; + +INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws); diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 9077e9114..717f0d393 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -12588,138 +12588,6 @@ static int cli_parse_set_ocspresponse(char **args, char *payload, struct appctx } -#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL) -static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp) -{ - switch (arg->type) { - case ARGT_STR: - smp->data.type = SMP_T_STR; - smp->data.u.str = arg->data.str; - return 1; - case ARGT_VAR: - if (!vars_get_by_desc(&arg->data.var, smp)) - return 0; - if (!sample_casts[smp->data.type][SMP_T_STR]) - return 0; - if (!sample_casts[smp->data.type][SMP_T_STR](smp)) - return 0; - return 1; - default: - return 0; - } -} - -static int check_aes_gcm(struct arg *args, struct sample_conv *conv, - const char *file, int line, char **err) -{ - switch(args[0].data.sint) { - case 128: - case 192: - case 256: - break; - default: - memprintf(err, "key size must be 128, 192 or 256 (bits)."); - return 0; - } - /* Try to decode a variable. */ - vars_check_arg(&args[1], NULL); - vars_check_arg(&args[2], NULL); - vars_check_arg(&args[3], NULL); - return 1; -} - -/* Arguments: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */ -static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, void *private) -{ - struct sample nonce, key, aead_tag; - struct buffer *smp_trash, *smp_trash_alloc; - EVP_CIPHER_CTX *ctx; - int dec_size, ret; - - smp_set_owner(&nonce, smp->px, smp->sess, smp->strm, smp->opt); - if (!sample_conv_var2smp_str(&arg_p[1], &nonce)) - return 0; - - smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt); - if (!sample_conv_var2smp_str(&arg_p[2], &key)) - return 0; - - smp_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt); - if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag)) - return 0; - - smp_trash = get_trash_chunk(); - smp_trash_alloc = alloc_trash_chunk(); - if (!smp_trash_alloc) - return 0; - - ctx = EVP_CIPHER_CTX_new(); - - if (!ctx) - goto err; - - dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size); - if (dec_size < 0) - goto err; - smp_trash->data = dec_size; - - /* Set cipher type and mode */ - switch(arg_p[0].data.sint) { - case 128: - EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); - break; - case 192: - EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL); - break; - case 256: - EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); - break; - } - - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, smp_trash->data, NULL); - - /* Initialise IV */ - if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) smp_trash->area)) - goto err; - - dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size); - if (dec_size < 0) - goto err; - smp_trash->data = dec_size; - - /* Initialise key */ - if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) smp_trash->area, NULL)) - goto err; - - if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data, - (unsigned char *) smp->data.u.str.area, (int) smp->data.u.str.data)) - goto err; - - dec_size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, smp_trash_alloc->size); - if (dec_size < 0) - goto err; - smp_trash_alloc->data = dec_size; - dec_size = smp_trash->data; - - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, smp_trash_alloc->data, (void *) smp_trash_alloc->area); - ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data); - - if (ret <= 0) - goto err; - - smp->data.u.str.data = dec_size + smp_trash->data; - smp->data.u.str.area = smp_trash->area; - smp->data.type = SMP_T_BIN; - smp->flags &= ~SMP_F_CONST; - free_trash_chunk(smp_trash_alloc); - return 1; - -err: - free_trash_chunk(smp_trash_alloc); - return 0; -} -# endif - /* Argument validation functions */ /* This function is used to validate the arguments passed to any "x_dn" ssl @@ -13018,16 +12886,6 @@ static struct cfg_kw_list cfg_kws = {ILH, { INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); -/* Note: must not be declared <const> as its list will be overwritten */ -static struct sample_conv_kw_list conv_kws = {ILH, { -#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL) - { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN }, -#endif - { NULL, NULL, 0, 0, 0 }, -}}; - -INITCALL1(STG_REGISTER, sample_register_convs, &conv_kws); - /* transport-layer operations for SSL sockets */ static struct xprt_ops ssl_sock = { .snd_buf = ssl_sock_from_buf, -- 2.26.1
>From f1334295e07337e98d470a8ae5cb87ae42c607c3 Mon Sep 17 00:00:00 2001 From: Patrick Gansterer <[email protected]> Date: Wed, 22 Apr 2020 16:47:57 +0200 Subject: [PATCH 2/2] MINOR: crypto: Add digest and hmac converters Make the digest and HMAC function of OpenSSL accessible to the user via converters. They can be used to sign and validate content. --- doc/configuration.txt | 16 ++++++ reg-tests/converter/digest.vtc | 57 ++++++++++++++++++++ reg-tests/converter/hmac.vtc | 54 +++++++++++++++++++ src/crypto.c | 95 +++++++++++++++++++++++++++++++++- 4 files changed, 221 insertions(+), 1 deletion(-) create mode 100644 reg-tests/converter/digest.vtc create mode 100644 reg-tests/converter/hmac.vtc diff --git a/doc/configuration.txt b/doc/configuration.txt index 2e548b66c..6b5f5ecf9 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -13918,6 +13918,13 @@ debug([<prefix][,<destination>]) Example: tcp-request connection track-sc0 src,debug(track-sc) +digest(<algorithm>) + Converts a binary input sample to a message digest. The result is a binary + sample. The algorithm must be an OpenSSL message digest name (e.g sha256). + + Please note that this converter is only available when haproxy has been + compiled with USE_OPENSSL. + 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 @@ -13972,6 +13979,15 @@ hex2i Converts a hex string containing two hex digits per input byte to an integer. If the input value cannot 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 algorithm must be one of the registered + OpenSSL message digest names (e.g sha256). The key parameter must be base64 + encoded. + + Please note that this converter is only available when haproxy has been + compiled with USE_OPENSSL. + http_date([<offset],[<unit>]) 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/reg-tests/converter/digest.vtc b/reg-tests/converter/digest.vtc new file mode 100644 index 000000000..39525a82b --- /dev/null +++ b/reg-tests/converter/digest.vtc @@ -0,0 +1,57 @@ +varnishtest "digest converter Test" + +#REQUIRE_VERSION=2.1 +#REQUIRE_OPTION=OPENSSL + +feature ignore_unknown_macro + +server s1 { + rxreq + txresp +} -repeat 2 -start + +haproxy h1 -conf { + defaults + mode http + timeout connect 1s + timeout client 1s + timeout server 1s + + frontend fe + bind "fd@${fe}" + + #### requests + http-request set-var(txn.hash) req.hdr(hash) + + http-response set-header SHA1 "%[var(txn.hash),digest(sha1),hex,lower]" + http-response set-header SHA224 "%[var(txn.hash),digest(sha224),hex,lower]" + http-response set-header SHA256 "%[var(txn.hash),digest(sha256),hex,lower]" + http-response set-header SHA384 "%[var(txn.hash),digest(sha384),hex,lower]" + http-response set-header SHA512 "%[var(txn.hash),digest(sha512),hex,lower]" + + default_backend be + + backend be + server s1 ${s1_addr}:${s1_port} +} -start + +client c1 -connect ${h1_fe_sock} { + txreq -url "/" \ + -hdr "Hash: 1" + rxresp + expect resp.status == 200 + expect resp.http.sha1 == "356a192b7913b04c54574d18c28d46e6395428ab" + expect resp.http.sha224 == "e25388fde8290dc286a6164fa2d97e551b53498dcbf7bc378eb1f178" + expect resp.http.sha256 == "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b" + expect resp.http.sha384 == "47f05d367b0c32e438fb63e6cf4a5f35c2aa2f90dc7543f8a41a0f95ce8a40a313ab5cf36134a2068c4c969cb50db776" + expect resp.http.sha512 == "4dff4ea340f0a823f15d3f4f01ab62eae0e5da579ccb851f8db9dfe84c58b2b37b89903a740e1ee172da793a6e79d560e5f7f9bd058a12a280433ed6fa46510a" + txreq -url "/" \ + -hdr "Hash: 2" + rxresp + expect resp.status == 200 + expect resp.http.sha1 == "da4b9237bacccdf19c0760cab7aec4a8359010b0" + expect resp.http.sha224 == "58b2aaa0bfae7acc021b3260e941117b529b2e69de878fd7d45c61a9" + expect resp.http.sha256 == "d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35" + expect resp.http.sha384 == "d063457705d66d6f016e4cdd747db3af8d70ebfd36badd63de6c8ca4a9d8bfb5d874e7fbd750aa804dcaddae7eeef51e" + expect resp.http.sha512 == "40b244112641dd78dd4f93b6c9190dd46e0099194d5a44257b7efad6ef9ff4683da1eda0244448cb343aa688f5d3efd7314dafe580ac0bcbf115aeca9e8dc114" +} -run diff --git a/reg-tests/converter/hmac.vtc b/reg-tests/converter/hmac.vtc new file mode 100644 index 000000000..9ede304e4 --- /dev/null +++ b/reg-tests/converter/hmac.vtc @@ -0,0 +1,54 @@ +varnishtest "HMAC converter Test" + +#REQUIRE_VERSION=2.1 +#REQUIRE_OPTION=OPENSSL + +feature ignore_unknown_macro + +server s1 { + rxreq + txresp +} -repeat 2 -start + +haproxy h1 -conf { + defaults + mode http + timeout connect 1s + timeout client 1s + timeout server 1s + + frontend fe + bind "fd@${fe}" + + #### requests + http-request set-var(txn.hash) req.hdr(hash) + + http-response set-header SHA1-short "%[var(txn.hash),hmac(sha1,a2V5),hex,lower]" + http-response set-header SHA1-long "%[var(txn.hash),hmac(sha1,bXlfc3VwZXJfc2VjcmV0X2xvbmdfa2V5),hex,lower]" + http-response set-header SHA256-short "%[var(txn.hash),hmac(sha256,a2V5),hex,lower]" + http-response set-header SHA256-long "%[var(txn.hash),hmac(sha256,bXlfc3VwZXJfc2VjcmV0X2xvbmdfa2V5),hex,lower]" + + default_backend be + + backend be + server s1 ${s1_addr}:${s1_port} +} -start + +client c1 -connect ${h1_fe_sock} { + txreq -url "/" \ + -hdr "Hash: 1" + rxresp + expect resp.status == 200 + expect resp.http.sha1-short == "e23feb105f9622241bf23db1638cd2b4208b1f53" + expect resp.http.sha1-long == "87b10ddcf39e26f6bd7c3b0e38e0125997b255be" + expect resp.http.sha256-short == "6da91fb91517be1f5cdcf3af91d7d40c717dd638a306157606fb2e584f7ae926" + expect resp.http.sha256-long == "2fb3de6a462c54d1803f946b52202f3a8cd46548ffb3f789b4ac11a4361ffef2" + txreq -url "/" \ + -hdr "Hash: 2" + rxresp + expect resp.status == 200 + expect resp.http.sha1-short == "311219c4a80c5ef81b1cee5505236c1d0ab1922c" + expect resp.http.sha1-long == "c5758af565ba4b87b3db49c8b32d4a94d430cb78" + expect resp.http.sha256-short == "ae7b3ee87b8c9214f714df1c2042c7a985b9d711e9938a063937ad1636775a88" + expect resp.http.sha256-long == "c073191a2ebf29f510444b92c187d62199d84b58f58dceeadb91994c170a9a16" +} -run diff --git a/src/crypto.c b/src/crypto.c index 74b92eee5..7a7231333 100644 --- a/src/crypto.c +++ b/src/crypto.c @@ -2,6 +2,7 @@ * Crypto converters * * Copyright 2020 Nenad Merdanovic <[email protected]> + * Copyright 2020 Patrick Gansterer <[email protected]> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,8 +20,8 @@ #include <proto/vars.h> #include <openssl/evp.h> +#include <openssl/hmac.h> -#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL) static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample *smp) { switch (arg->type) { @@ -41,6 +42,7 @@ static inline int sample_conv_var2smp_str(const struct arg *arg, struct sample * } } +#if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL) static int check_aes_gcm(struct arg *args, struct sample_conv *conv, const char *file, int line, char **err) { @@ -152,11 +154,102 @@ err: } # endif +static int check_crypto_digest(struct arg *args, struct sample_conv *conv, + const char *file, int line, char **err) +{ + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.area); + + if (evp) + return 1; + + memprintf(err, "algorithm must be a valid OpenSSL message digest name."); + return 0; +} + +static int sample_conv_crypto_digest(const struct arg *args, struct sample *smp, void *private) +{ + struct buffer *trash = get_trash_chunk(); + unsigned char *md = (unsigned char*) trash->area; + unsigned int md_len = trash->size; + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.area); + + if (!ctx) + return 0; + + if (!EVP_DigestInit_ex(ctx, evp, NULL) || + !EVP_DigestUpdate(ctx, smp->data.u.str.area, smp->data.u.str.data) || + !EVP_DigestFinal_ex(ctx, md, &md_len)) { + EVP_MD_CTX_free(ctx); + return 0; + } + + EVP_MD_CTX_free(ctx); + + trash->data = md_len; + smp->data.u.str = *trash; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + return 1; +} + +static int check_crypto_hmac(struct arg *args, struct sample_conv *conv, + const char *file, int line, char **err) +{ + if (!check_crypto_digest(args, conv, file, line, err)) + return 0; + + vars_check_arg(&args[1], NULL); + return 1; +} + +static int sample_conv_crypto_hmac(const struct arg *args, struct sample *smp, void *private) +{ + struct sample key; + struct buffer *trash, *key_trash; + unsigned char *md; + unsigned int md_len; + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.area); + int dec_size; + + smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt); + if (!sample_conv_var2smp_str(&args[1], &key)) + return 0; + + trash = get_trash_chunk(); + key_trash = alloc_trash_chunk(); + if (!key_trash) + return 0; + + dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, key_trash->area, key_trash->size); + if (dec_size < 0) + goto err; + + md = (unsigned char*) trash->area; + md_len = trash->size; + if (!HMAC(evp, key_trash->area, dec_size, (const unsigned char*) smp->data.u.str.area, smp->data.u.str.data, md, &md_len)) + goto err; + + free_trash_chunk(key_trash); + + trash->data = md_len; + smp->data.u.str = *trash; + smp->data.type = SMP_T_BIN; + smp->flags &= ~SMP_F_CONST; + return 1; + +err: + free_trash_chunk(key_trash); + return 0; +} + /* Note: must not be declared <const> as its list will be overwritten */ static struct sample_conv_kw_list conv_kws = {ILH, { #if (HA_OPENSSL_VERSION_NUMBER >= 0x1000100fL) { "aes_gcm_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN }, #endif + { "digest", sample_conv_crypto_digest, ARG1(1,STR), check_crypto_digest, SMP_T_BIN, SMP_T_BIN }, + { "hmac", sample_conv_crypto_hmac, ARG2(2,STR,STR), check_crypto_hmac, SMP_T_BIN, SMP_T_BIN }, { NULL, NULL, 0, 0, 0 }, }}; -- 2.26.1

