From: Patrick Gansterer Date: Sun, 17 Jun 2018 09:21:11 +0000 (+0200) Subject: MINOR: sample: Move aes_gcm_dec implementation into sample.c X-Git-Tag: v2.2-dev8~86 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b399bfb9e21d9076133e00511dc07026ac9301d6;p=thirdparty%2Fhaproxy.git MINOR: sample: Move aes_gcm_dec implementation into sample.c aes_gcm_dec is independent of the TLS implementation and fits better in sample.c file with others hash functions. [Cf: I slightly updated this patch to move aes_gcm_dec converter in sample.c instead the new file crypto.c] Reviewed-by: Tim Duesterhus --- diff --git a/src/sample.c b/src/sample.c index 12724f73d7..1be9459930 100644 --- a/src/sample.c +++ b/src/sample.c @@ -1653,7 +1653,140 @@ static int sample_conv_sha2(const struct arg *arg_p, struct sample *smp, void *p smp->flags &= ~SMP_F_CONST; return 1; } -#endif + +#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 /* HA_OPENSSL_VERSION_NUMBER */ + +#endif /* USE_OPENSSL */ static int sample_conv_bin2hex(const struct arg *arg_p, struct sample *smp, void *private) { @@ -3496,6 +3629,9 @@ static struct sample_conv_kw_list sample_conv_kws = {ILH, { { "sha1", sample_conv_sha1, 0, NULL, SMP_T_BIN, SMP_T_BIN }, #ifdef USE_OPENSSL { "sha2", sample_conv_sha2, ARG1(0, SINT), smp_check_sha2, SMP_T_BIN, SMP_T_BIN }, +#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 #endif { "concat", sample_conv_concat, ARG3(1,STR,STR,STR), smp_check_concat, SMP_T_STR, SMP_T_STR }, { "strcmp", sample_conv_strcmp, ARG1(1,STR), smp_check_strcmp, SMP_T_STR, SMP_T_SINT }, diff --git a/src/ssl_sock.c b/src/ssl_sock.c index 78d6da303a..16c7227a18 100644 --- a/src/ssl_sock.c +++ b/src/ssl_sock.c @@ -12656,138 +12656,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 @@ -13090,16 +12958,6 @@ static struct cfg_kw_list cfg_kws = {ILH, { INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); -/* Note: must not be declared 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,