Patrick, Am 22.04.20 um 12:40 schrieb Patrick Gansterer: > diff --git a/doc/configuration.txt b/doc/configuration.txt > index 2e548b66c..17b2debe5 100644 > --- a/doc/configuration.txt > +++ b/doc/configuration.txt > @@ -13918,6 +13918,10 @@ 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).
Add a note that the converter is only available with USE_OPENSSL similar to the sha2() converted. > @@ -13972,6 +13976,11 @@ 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). Add a note that the converter is only available with USE_OPENSSL similar to the sha2() converted. > diff --git a/src/crypto.c b/src/crypto.c > new file mode 100644 > index 000000000..b4f2bfe32 > --- /dev/null > +++ b/src/crypto.c > @@ -0,0 +1,84 @@ > +static int sample_conv_crypto_digest(const struct arg *args, struct sample > *smp, void *private) > +{ > + struct buffer *trash = get_trash_chunk(); > + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); > + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.area); > + unsigned char *md = (unsigned char*) trash->area; > + unsigned int md_len = trash->size; > + > + if (!ctx) > + return 0; > + if (!evp) Will this leak ctx? > + return 0; > + > + if (!EVP_DigestInit(ctx, evp) || > + !EVP_DigestUpdate(ctx, smp->data.u.str.area, smp->data.u.str.data) > || > + !EVP_DigestFinal(ctx, md, &md_len)) { The OpenSSL manpage says: > The functions EVP_DigestInit(), EVP_DigestFinal() and EVP_MD_CTX_copy() are > obsolete but are retained to maintain compatibility with existing code. New > applications should use EVP_DigestInit_ex(), EVP_DigestFinal_ex() and > EVP_MD_CTX_copy_ex() because they can efficiently reuse a digest context > instead of initializing and cleaning it up on each call and allow non default > implementations of digests to be specified. . > + 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 sample_conv_crypto_hmac(const struct arg *args, struct sample > *smp, void *private) > +{ > + struct buffer *trash = get_trash_chunk(); > + const EVP_MD *evp = EVP_get_digestbyname(args[0].data.str.area); > + const char* key = args[1].data.str.area; > + int key_len = args[1].data.str.data; I'd say that the key should have support for taking the key from a variable similar to aes_gcm_dec(). I'd also say that the parameter should be base64 encoded to allow for arbitrary bytes. > + unsigned char *md = (unsigned char*) trash->area; > + unsigned int md_len = trash->size; > + > + trash->data = 0; > + > + if (!evp) > + return 0; > + > + if (!HMAC(evp, key, key_len, (const unsigned char*) > smp->data.u.str.area, smp->data.u.str.data, md, &md_len)) > + return 0; > + > + trash->data = 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 }, Add a validation function that checks whether the given hash algorithm is valid at configuration checking time. Best regards Tim Düsterhus