diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 05:11:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-03 05:11:10 +0000 |
commit | cff6d757e3ba609c08ef2aaa00f07e53551e5bf6 (patch) | |
tree | 08c4fc3255483ad397d712edb4214ded49149fd9 /src/ssl_sample.c | |
parent | Adding upstream version 2.9.7. (diff) | |
download | haproxy-upstream/3.0.0.tar.xz haproxy-upstream/3.0.0.zip |
Adding upstream version 3.0.0.upstream/3.0.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/ssl_sample.c')
-rw-r--r-- | src/ssl_sample.c | 236 |
1 files changed, 151 insertions, 85 deletions
diff --git a/src/ssl_sample.c b/src/ssl_sample.c index 22b4072..0757c12 100644 --- a/src/ssl_sample.c +++ b/src/ssl_sample.c @@ -219,6 +219,10 @@ static inline int sample_check_arg_base64(struct arg *arg, char **err) static int check_aes_gcm(struct arg *args, struct sample_conv *conv, const char *file, int line, char **err) { + if (conv->kw[8] == 'd') + /* flag it as "aes_gcm_dec" */ + args[0].type_flags = 1; + switch(args[0].data.sint) { case 128: case 192: @@ -238,7 +242,8 @@ static int check_aes_gcm(struct arg *args, struct sample_conv *conv, memprintf(err, "failed to parse key : %s", *err); return 0; } - if (!sample_check_arg_base64(&args[3], err)) { + if ((args[0].type_flags && !sample_check_arg_base64(&args[3], err)) || + (!args[0].type_flags && !vars_check_arg(&args[3], err))) { memprintf(err, "failed to parse aead_tag : %s", *err); return 0; } @@ -246,13 +251,37 @@ static int check_aes_gcm(struct arg *args, struct sample_conv *conv, return 1; } +#define sample_conv_aes_gcm_init(a, b, c, d, e, f) \ + ({ \ + int _ret = (a) ? \ + EVP_DecryptInit_ex(b, c, d, e, f) : \ + EVP_EncryptInit_ex(b, c, d, e, f); \ + _ret; \ + }) + +#define sample_conv_aes_gcm_update(a, b, c, d, e, f) \ + ({ \ + int _ret = (a) ? \ + EVP_DecryptUpdate(b, c, d, e, f) : \ + EVP_EncryptUpdate(b, c, d, e, f); \ + _ret; \ + }) + +#define sample_conv_aes_gcm_final(a, b, c, d) \ + ({ \ + int _ret = (a) ? \ + EVP_DecryptFinal_ex(b, c, d) : \ + EVP_EncryptFinal_ex(b, c, d); \ + _ret; \ + }) + /* 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) +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; EVP_CIPHER_CTX *ctx = NULL; - int dec_size, ret; + int size, ret, dec; smp_trash_alloc = alloc_trash_chunk(); if (!smp_trash_alloc) @@ -278,30 +307,33 @@ static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, goto err; if (arg_p[1].type == ARGT_VAR) { - dec_size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size); - if (dec_size < 0) + size = base64dec(nonce.data.u.str.area, nonce.data.u.str.data, smp_trash->area, smp_trash->size); + if (size < 0) goto err; - smp_trash->data = dec_size; + smp_trash->data = size; nonce.data.u.str = *smp_trash; } + /* encrypt (0) or decrypt (1) */ + dec = (arg_p[0].type_flags == 1); + /* Set cipher type and mode */ switch(arg_p[0].data.sint) { case 128: - EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); + sample_conv_aes_gcm_init(dec, ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); break; case 192: - EVP_DecryptInit_ex(ctx, EVP_aes_192_gcm(), NULL, NULL, NULL); + sample_conv_aes_gcm_init(dec, ctx, EVP_aes_192_gcm(), NULL, NULL, NULL); break; case 256: - EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); + sample_conv_aes_gcm_init(dec, ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); break; } EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, nonce.data.u.str.data, NULL); /* Initialise IV */ - if(!EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, (unsigned char *) nonce.data.u.str.area)) + if(!sample_conv_aes_gcm_init(dec, ctx, NULL, NULL, NULL, (unsigned char *) nonce.data.u.str.area)) goto err; smp_set_owner(&key, smp->px, smp->sess, smp->strm, smp->opt); @@ -309,42 +341,66 @@ static int sample_conv_aes_gcm_dec(const struct arg *arg_p, struct sample *smp, goto err; if (arg_p[2].type == ARGT_VAR) { - dec_size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size); - if (dec_size < 0) + size = base64dec(key.data.u.str.area, key.data.u.str.data, smp_trash->area, smp_trash->size); + if (size < 0) goto err; - smp_trash->data = dec_size; + smp_trash->data = size; key.data.u.str = *smp_trash; } /* Initialise key */ - if (!EVP_DecryptInit_ex(ctx, NULL, NULL, (unsigned char *) key.data.u.str.area, NULL)) + if (!sample_conv_aes_gcm_init(dec, ctx, NULL, NULL, (unsigned char *) key.data.u.str.area, NULL)) goto err; - if (!EVP_DecryptUpdate(ctx, (unsigned char *) smp_trash->area, (int *) &smp_trash->data, - (unsigned char *) smp_trash_alloc->area, (int) smp_trash_alloc->data)) + 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_set_owner(&aead_tag, smp->px, smp->sess, smp->strm, smp->opt); - if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag)) - goto err; - - if (arg_p[3].type == ARGT_VAR) { - 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) + if (dec) { + if (!sample_conv_var2smp_str(&arg_p[3], &aead_tag)) goto err; - smp_trash_alloc->data = dec_size; - aead_tag.data.u.str = *smp_trash_alloc; - } - dec_size = smp_trash->data; + if (arg_p[3].type == ARGT_VAR) { + size = base64dec(aead_tag.data.u.str.area, aead_tag.data.u.str.data, smp_trash_alloc->area, + smp_trash_alloc->size); + if (size < 0) + goto err; + smp_trash_alloc->data = size; + aead_tag.data.u.str = *smp_trash_alloc; + } - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, aead_tag.data.u.str.data, (void *) aead_tag.data.u.str.area); - ret = EVP_DecryptFinal_ex(ctx, (unsigned char *) smp_trash->area + smp_trash->data, (int *) &smp_trash->data); + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, aead_tag.data.u.str.data, + (void *) aead_tag.data.u.str.area); + } + + size = smp_trash->data; + ret = sample_conv_aes_gcm_final(dec, 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; + if (!dec) { + struct buffer *trash = get_trash_chunk(); + + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, 16, (void *) trash->area); + + aead_tag.data.u.str = *smp_trash_alloc; + ret = a2base64(trash->area, 16, aead_tag.data.u.str.area, aead_tag.data.u.str.size); + if (ret < 0) + goto err; + + aead_tag.data.u.str.data = ret; + aead_tag.data.type = SMP_T_STR; + + if (!var_set(arg_p[3].data.var.name_hash, arg_p[3].data.var.scope, &aead_tag, + (arg_p[3].data.var.scope == SCOPE_PROC) ? VF_COND_IFEXISTS : 0)) { + goto err; + } + } + + smp->data.u.str.data = size + smp_trash->data; smp->data.u.str.area = smp_trash->area; smp->data.type = SMP_T_BIN; smp_dup(smp); @@ -1317,61 +1373,61 @@ smp_fetch_ssl_fc_is_resumed(const struct arg *args, struct sample *smp, const ch static int smp_fetch_ssl_fc_ec(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct connection *conn; - SSL *ssl; - int __maybe_unused nid; - char *curve_name; - - if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) - conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL; - else - conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : - smp->strm ? sc_conn(smp->strm->scb) : NULL; - - ssl = ssl_sock_get_ssl_object(conn); - if (!ssl) - return 0; - - /* - * SSL_get0_group_name is a function to get the curve name and is available from - * OpenSSL v3.2 onwards. For OpenSSL >=3.0 and <3.2, we will continue to use - * SSL_get_negotiated_group to get the curve name. - */ - #if (HA_OPENSSL_VERSION_NUMBER >= 0x3020000fL) - curve_name = (char *)SSL_get0_group_name(ssl); - if (curve_name == NULL) - return 0; - else { - /** - * The curve name returned by SSL_get0_group_name is in lowercase whereas the curve - * name returned when we use `SSL_get_negotiated_group` and `OBJ_nid2sn` is the - * short name and is in upper case. To make the return value consistent across the - * different functional calls and to make it consistent while upgrading OpenSSL versions, - * will convert the curve name returned by SSL_get0_group_name to upper case. - */ - int i; - - for (i = 0; curve_name[i]; i++) - curve_name[i] = toupper(curve_name[i]); - } - #else - nid = SSL_get_negotiated_group(ssl); - if (!nid) - return 0; - curve_name = (char *)OBJ_nid2sn(nid); - if (curve_name == NULL) - return 0; - #endif - - smp->data.u.str.area = curve_name; - if (!smp->data.u.str.area) - return 0; - - smp->data.type = SMP_T_STR; - smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST; - smp->data.u.str.data = strlen(smp->data.u.str.area); - - return 1; + struct connection *conn; + SSL *ssl; + int __maybe_unused nid; + char *curve_name; + + if (obj_type(smp->sess->origin) == OBJ_TYPE_CHECK) + conn = (kw[4] == 'b') ? sc_conn(__objt_check(smp->sess->origin)->sc) : NULL; + else + conn = (kw[4] != 'b') ? objt_conn(smp->sess->origin) : + smp->strm ? sc_conn(smp->strm->scb) : NULL; + + ssl = ssl_sock_get_ssl_object(conn); + if (!ssl) + return 0; + + /* + * SSL_get0_group_name is a function to get the curve name and is available from + * OpenSSL v3.2 onwards. For OpenSSL >=3.0 and <3.2, we will continue to use + * SSL_get_negotiated_group to get the curve name. + */ +# if (HA_OPENSSL_VERSION_NUMBER >= 0x3020000fL) + curve_name = (char *)SSL_get0_group_name(ssl); + if (curve_name == NULL) { + return 0; + } else { + /* + * The curve name returned by SSL_get0_group_name is in lowercase whereas the curve + * name returned when we use `SSL_get_negotiated_group` and `OBJ_nid2sn` is the + * short name and is in upper case. To make the return value consistent across the + * different functional calls and to make it consistent while upgrading OpenSSL versions, + * will convert the curve name returned by SSL_get0_group_name to upper case. + */ + int i; + + for (i = 0; curve_name[i]; i++) + curve_name[i] = toupper(curve_name[i]); + } +# else + nid = SSL_get_negotiated_group(ssl); + if (!nid) + return 0; + curve_name = (char *)OBJ_nid2sn(nid); + if (curve_name == NULL) + return 0; +# endif + + smp->data.u.str.area = curve_name; + if (!smp->data.u.str.area) + return 0; + + smp->data.type = SMP_T_STR; + smp->flags |= SMP_F_VOL_SESS | SMP_F_CONST; + smp->data.u.str.data = strlen(smp->data.u.str.area); + + return 1; } #endif @@ -2263,6 +2319,15 @@ static struct sample_fetch_kw_list sample_fetch_keywords = {ILH, { { "ssl_bc_server_random", smp_fetch_ssl_fc_random, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV }, { "ssl_bc_session_key", smp_fetch_ssl_fc_session_key, 0, NULL, SMP_T_BIN, SMP_USE_L5SRV }, #endif +#ifdef HAVE_SSL_KEYLOG + { "ssl_bc_client_early_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, + { "ssl_bc_client_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, + { "ssl_bc_server_handshake_traffic_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, + { "ssl_bc_client_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, + { "ssl_bc_server_traffic_secret_0", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, + { "ssl_bc_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, + { "ssl_bc_early_exporter_secret", smp_fetch_ssl_x_keylog, 0, NULL, SMP_T_STR, SMP_USE_L5CLI }, +#endif { "ssl_bc_err", smp_fetch_ssl_fc_err, 0, NULL, SMP_T_SINT, SMP_USE_L5SRV }, { "ssl_bc_err_str", smp_fetch_ssl_fc_err_str, 0, NULL, SMP_T_STR, SMP_USE_L5SRV }, { "ssl_c_ca_err", smp_fetch_ssl_c_ca_err, 0, NULL, SMP_T_SINT, SMP_USE_L5CLI }, @@ -2367,7 +2432,8 @@ INITCALL1(STG_REGISTER, sample_register_fetches, &sample_fetch_keywords); 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_dec", sample_conv_aes_gcm_dec, ARG4(4,SINT,STR,STR,STR), check_aes_gcm, SMP_T_BIN, SMP_T_BIN }, + { "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 }, #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 }, |