51d.single(prop[,prop*]) string string
add(value) integer integer
add_item(delim[,var[,suff]]) string string
-aes_gcm_dec(bits,nonce,key,aead_tag) binary binary
-aes_gcm_enc(bits,nonce,key,aead_tag) binary binary
+aes_gcm_dec(bits,nonce,key,aead_tag[,aad]) binary binary
+aes_gcm_enc(bits,nonce,key,aead_tag[,aad]) binary binary
and(value) integer integer
b64dec string binary
base2 binary string
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",req.score1),add_item(",",req.score2)'
http-request set-var(req.tagged) 'var(req.tagged),add_item(",",,(site1))' if src,in_table(site1)
-aes_gcm_dec(<bits>,<nonce>,<key>,<aead_tag>)
- Decrypts the raw byte input using the AES128-GCM, AES192-GCM or
- AES256-GCM algorithm, depending on the <bits> parameter. All other parameters
- need to be base64 encoded and the returned result is in raw byte format.
- If the <aead_tag> validation fails, the converter doesn't return any data.
- The <nonce>, <key> and <aead_tag> can either be strings or variables. This
- converter requires at least OpenSSL 1.0.1.
+aes_gcm_dec(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])
+ Decrypts the raw byte input using the AES128-GCM, AES192-GCM or AES256-GCM
+ algorithm, depending on the <bits> parameter. All other parameters need to be
+ base64 encoded and the returned result is in raw byte format. If the
+ <aead_tag> or <aad> validation fails, the converter doesn't return any data.
+ The <aad> parameter is optional. The <nonce>, <key>, <aead_tag> and <aad> can
+ either be strings or variables. This converter requires at least OpenSSL
+ 1.0.1.
Example:
http-response set-header X-Decrypted-Text %[var(txn.enc),\
aes_gcm_dec(128,txn.nonce,Zm9vb2Zvb29mb29wZm9vbw==,txn.aead_tag)]
-aes_gcm_enc(<bits>,<nonce>,<key>,<aead_tag>)
+aes_gcm_enc(<bits>,<nonce>,<key>,<aead_tag>[,<aad>])
Encrypts the raw byte input using the AES128-GCM, AES192-GCM or
- AES256-GCM algorithm, depending on the <bits> parameter. <nonce> and <key>
- parameters must be base64 encoded. Last parameter, <aead_tag>, must be a
- variable. The AEAD tag will be stored base64 encoded into that variable.
- The returned result is in raw byte format. The <nonce> and <key> can either
- be strings or variables. This converter requires at least OpenSSL 1.0.1.
+ AES256-GCM algorithm, depending on the <bits> parameter. <nonce>, <key> and
+ <aad> parameters must be base64 encoded. Parameter <aead_tag> must be a
+ variable. The AEAD tag will be stored base64 encoded into that variable. The
+ <aad> parameter is optional. The returned result is in raw byte format. The
+ <nonce>, <key> and <aad> can either be strings or variables. This converter
+ requires at least OpenSSL 1.0.1.
Example:
http-response set-header X-Encrypted-Text %[var(txn.plain),\
--- /dev/null
+varnishtest "aes_gcm converter Test"
+
+feature ignore_unknown_macro
+
+server s1 {
+ rxreq
+ txresp -hdr "Connection: close"
+} -repeat 2 -start
+
+
+haproxy h1 -conf {
+ global
+ .if feature(THREAD)
+ thread-groups 1
+ .endif
+
+ # WT: limit false-positives causing "HTTP header incomplete" due to
+ # idle server connections being randomly used and randomly expiring
+ # under us.
+ tune.idle-pool.shared off
+
+ defaults
+ mode http
+ timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout client "${HAPROXY_TEST_TIMEOUT-5s}"
+ timeout server "${HAPROXY_TEST_TIMEOUT-5s}"
+
+ frontend fe
+ bind "fd@${fe}"
+
+ http-request set-var(txn.plain) str("Hello from HAProxy AES-GCM")
+ http-request set-var(txn.nonce) str("MTIzNDU2Nzg5MDEy")
+ http-request set-var(txn.key) str("Zm9vb2Zvb29mb29vb29vbw==")
+
+ # AES-GCM enc wth vars + dec with strings
+ http-request set-var(txn.encrypted1) var(txn.plain),aes_gcm_enc(128,txn.nonce,txn.key,txn.aead_tag1),base64
+ http-after-response set-header X-Encrypted1 %[var(txn.encrypted1)]
+ http-after-response set-header X-AEAD-Tag1 %[var(txn.aead_tag1)]
+ http-request set-var(txn.decrypted1) var(txn.encrypted1),b64dec,aes_gcm_dec(128,"MTIzNDU2Nzg5MDEy","Zm9vb2Zvb29mb29vb29vbw==",txn.aead_tag1)
+ http-after-response set-header X-Decrypted1 %[var(txn.decrypted1)]
+
+ # AES-GCM enc wth strings + dec with vars
+ http-request set-var(txn.encrypted2) var(txn.plain),aes_gcm_enc(128,"MTIzNDU2Nzg5MDEy","Zm9vb2Zvb29mb29vb29vbw==",txn.aead_tag2),base64
+ http-after-response set-header X-Encrypted2 %[var(txn.encrypted2)]
+ http-after-response set-header X-AEAD-Tag2 %[var(txn.aead_tag2)]
+ http-request set-var(txn.decrypted2) var(txn.encrypted2),b64dec,aes_gcm_dec(128,txn.nonce,txn.key,txn.aead_tag2)
+ http-after-response set-header X-Decrypted2 %[var(txn.decrypted2)]
+
+ # AES-GCM + AAD enc wth vars + dec with strings
+ http-request set-var(txn.aad) str("dGVzdAo=")
+ http-request set-var(txn.encrypted3) var(txn.plain),aes_gcm_enc(128,txn.nonce,txn.key,txn.aead_tag3,txn.aad),base64
+ http-after-response set-header X-Encrypted3 %[var(txn.encrypted3)]
+ http-after-response set-header X-AEAD-Tag3 %[var(txn.aead_tag3)]
+ http-request set-var(txn.decrypted3) var(txn.encrypted3),b64dec,aes_gcm_dec(128,"MTIzNDU2Nzg5MDEy","Zm9vb2Zvb29mb29vb29vbw==",txn.aead_tag3,"dGVzdAo=")
+ http-after-response set-header X-Decrypted3 %[var(txn.decrypted3)]
+
+ # AES-GCM + AAD enc wth strings + enc with strings
+ http-request set-var(txn.encrypted4) var(txn.plain),aes_gcm_enc(128,"MTIzNDU2Nzg5MDEy","Zm9vb2Zvb29mb29vb29vbw==",txn.aead_tag4,"dGVzdAo="),base64
+ http-after-response set-header X-Encrypted4 %[var(txn.encrypted4)]
+ http-after-response set-header X-AEAD-Tag4 %[var(txn.aead_tag4)]
+ http-request set-var(txn.decrypted4) var(txn.encrypted4),b64dec,aes_gcm_dec(128,txn.nonce,txn.key,txn.aead_tag3,txn.aad)
+ http-after-response set-header X-Decrypted4 %[var(txn.decrypted4)]
+
+ default_backend be
+
+ backend be
+ server s1 ${s1_addr}:${s1_port}
+
+} -start
+
+client c1 -connect ${h1_fe_sock} {
+ txreq
+ rxresp
+ expect resp.http.x-decrypted1 == "Hello from HAProxy AES-GCM"
+ expect resp.http.x-decrypted2 == "Hello from HAProxy AES-GCM"
+ expect resp.http.x-decrypted3 == "Hello from HAProxy AES-GCM"
+ expect resp.http.x-decrypted4 == "Hello from HAProxy AES-GCM"
+} -run
memprintf(err, "failed to parse aead_tag : %s", *err);
return 0;
}
-
+ if (args[4].type) {
+ if (!sample_check_arg_base64(&args[4], err)) {
+ memprintf(err, "failed to parse aad : %s", *err);
+ return 0;
+ }
+ }
return 1;
}
/* Arguments: AES size in bits, nonce, key, tag. The last three arguments are base64 encoded */
static int sample_conv_aes_gcm(const struct arg *arg_p, struct sample *smp, void *private)
{
- struct sample nonce, key, aead_tag;
- struct buffer *smp_trash = NULL, *smp_trash_alloc = NULL;
+ struct sample nonce, key, aead_tag, aad;
+ struct buffer *smp_trash = NULL, *smp_trash_alloc = NULL, *aad_trash = NULL;
EVP_CIPHER_CTX *ctx = NULL;
int size, ret, dec;
if (!sample_conv_aes_gcm_init(dec, ctx, NULL, NULL, (unsigned char *) key.data.u.str.area, NULL))
goto err;
+ /* if there's an AAD parameter */
+ if (arg_p[4].type) {
+ smp_set_owner(&aad, smp->px, smp->sess, smp->strm, smp->opt);
+
+ if (!sample_conv_var2smp_str(&arg_p[4], &aad))
+ goto err;
+ /* if stored in a variable, the base64 decode was not done in check_aes_gcm() */
+ if (arg_p[4].type == ARGT_VAR) {
+ int aad_len;
+
+
+ aad_trash = alloc_trash_chunk();
+ if (!aad_trash)
+ return 0;
+
+ aad_len = base64dec(aad.data.u.str.area, aad.data.u.str.data, aad_trash->area, aad_trash->size);
+ if (aad_len < 0)
+ goto err;
+ aad_trash->data = aad_len;
+ aad.data.u.str = *aad_trash;
+ }
+
+ if (!sample_conv_aes_gcm_update(dec, ctx, NULL, (int *)&smp_trash->data,
+ (unsigned char *)aad.data.u.str.area, (int)aad.data.u.str.data))
+ goto err;
+ }
+
if (!sample_conv_aes_gcm_update(dec, ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data,
(unsigned char *) smp_trash_alloc->area, (int) smp_trash_alloc->data))
goto err;
smp_dup(smp);
free_trash_chunk(smp_trash_alloc);
free_trash_chunk(smp_trash);
+ free_trash_chunk(aad_trash);
EVP_CIPHER_CTX_free(ctx);
return 1;
err:
free_trash_chunk(smp_trash_alloc);
free_trash_chunk(smp_trash);
+ free_trash_chunk(aad_trash);
EVP_CIPHER_CTX_free(ctx);
return 0;
}
static struct sample_conv_kw_list sample_conv_kws = {ILH, {
{ "sha2", sample_conv_sha2, ARG1(0, SINT), smp_check_sha2, SMP_T_BIN, SMP_T_BIN },
#ifdef EVP_CIPH_GCM_MODE
- { "aes_gcm_enc", sample_conv_aes_gcm, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
- { "aes_gcm_dec", sample_conv_aes_gcm, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
+ { "aes_gcm_enc", sample_conv_aes_gcm, ARG5(4,SINT,STR,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
+ { "aes_gcm_dec", sample_conv_aes_gcm, ARG5(4,SINT,STR,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN },
#endif
{ "x509_v_err_str", sample_conv_x509_v_err, 0, NULL, SMP_T_SINT, SMP_T_STR },
{ "digest", sample_conv_crypto_digest, ARG1(1,STR), check_crypto_digest, SMP_T_BIN, SMP_T_BIN },