bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi#define VAR_EXPAND_CRYPT_DEFAULT_ALGO "AES-256-CBC"
5d2c15eaba4920cb6556be2c735fdb3f79655abaAki Tuomistatic bool var_expand_crypt_initialize(const char **error_r);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid auth_var_expand_crypt_init(struct module *module);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivar_expand_crypt_settings(struct var_expand_crypt_context *ctx,
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (var_expand_with_funcs(ctx->iv, value, ctx->ctx->table,
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* try to decode IV */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi ctx->enc_result_only = strcasecmp(value, "yes")==0;
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi const char *hexkey = t_strdup(str_c(ctx->enckey));
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi "Cannot parse hash arguments:"
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi "'%s' is not supported format",
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivar_expand_crypt(struct dcrypt_context_symmetric *dctx, buffer_t *key, buffer_t *iv,
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi const buffer_t *input, buffer_t *output, const char **error_r)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* make sure IV is correct */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* acquire IV */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi } else if (dcrypt_ctx_sym_get_iv_length(dctx) != iv->used) {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi *error_r = t_strdup_printf("crypt: IV length invalid (%"PRIuSIZE_T" != %u)",
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (dcrypt_ctx_sym_get_key_length(dctx) != key->used) {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi *error_r = t_strdup_printf("crypt: Key length invalid (%"PRIuSIZE_T" != %u)",
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi dcrypt_ctx_sym_set_key(dctx, key->data, key->used);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivar_expand_encrypt(struct var_expand_context *_ctx,
5d2c15eaba4920cb6556be2c735fdb3f79655abaAki Tuomi if (!has_been_init && !var_expand_crypt_initialize(error_r))
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if ((ret = var_expand_long(_ctx, field, strlen(field),
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (var_expand_crypt_settings(&ctx, args, error_r) < 0)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (!dcrypt_ctx_sym_create(ctx.algo, DCRYPT_MODE_ENCRYPT, &dctx, error_r))
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi ret = var_expand_crypt(dctx, ctx.enckey, ctx.iv, field_value, tmp, error_r);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (ret == 0) {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* makes compiler happy */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi enciv = binary_to_hex(ctx.iv->data, ctx.iv->used);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi *result_r = t_strdup_printf("%s$%s$", enciv, res);
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivar_expand_decrypt(struct var_expand_context *_ctx,
5d2c15eaba4920cb6556be2c735fdb3f79655abaAki Tuomi if (!has_been_init && !var_expand_crypt_initialize(error_r))
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if ((ret = var_expand_long(_ctx, field, strlen(field),
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (var_expand_crypt_settings(&ctx, args, error_r) < 0)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* make sure IV is correct */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (ctx.iv->used == 0 && (p = strchr(encdata, '$')) != NULL) {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* see if IV can be taken from data */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* try to decode iv and encdata */
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi str_append_str(ctx.iv, t_base64_decode_str(enciv));
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi str_append_str(field_value, t_base64_decode_str(encdata));
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi *error_r = t_strdup_printf("decrypt: IV missing");
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi if (!dcrypt_ctx_sym_create(ctx.algo, DCRYPT_MODE_DECRYPT, &dctx, error_r))
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi ret = var_expand_crypt(dctx, ctx.enckey, ctx.iv, field_value, tmp, error_r);
e8d8cff110f7a194c18abda75a07e9f15bc9fa44Aki Tuomi if (ret == 0) {
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomistatic const struct var_expand_extension_func_table funcs[] = {
5d2c15eaba4920cb6556be2c735fdb3f79655abaAki Tuomistatic bool var_expand_crypt_initialize(const char **error_r)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomivoid var_expand_crypt_init(struct module *module ATTR_UNUSED)
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi /* do not initialize dcrypt here - saves alot of memory
dbc351d8a8dad8cfbc0c1f5d957d23873ab5e26cAki Tuomi to not load openssl every time. Only load it if