X-Git-Url: http://wagner.pp.ru/gitweb/?a=blobdiff_plain;f=gost_crypt.c;h=930d40adc76941aedef3479efb841c44d7e55801;hb=419263293a3075c630d028b94378107714ab6fa6;hp=8587bd13bb0b4ba1550c28d6afb763c5c33678d0;hpb=c89b75723868791467e949c968988f8cab1c9cf9;p=openssl-gost%2Fengine.git diff --git a/gost_crypt.c b/gost_crypt.c index 8587bd1..930d40a 100644 --- a/gost_crypt.c +++ b/gost_crypt.c @@ -46,73 +46,234 @@ static int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params); /* Control function */ static int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); -EVP_CIPHER cipher_gost = { - NID_id_Gost28147_89, - 1, /* block_size */ - 32, /* key_size */ - 8, /* iv_len */ - EVP_CIPH_CFB_MODE | EVP_CIPH_NO_PADDING | - EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, - gost_cipher_init, - gost_cipher_do_cfb, - gost_cipher_cleanup, - sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ - gost89_set_asn1_parameters, - gost89_get_asn1_parameters, - gost_cipher_ctl, - NULL, -}; +static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc); +/* Handles block of data in CBC mode */ +static int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); +static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl); -EVP_CIPHER cipher_gost_cbc = { - NID_gost89_cbc, - 8, /*block_size */ - 32, /*key_size */ - 8, /*iv_len */ - EVP_CIPH_CBC_MODE | - EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, - gost_cipher_init_cbc, - gost_cipher_do_cbc, - gost_cipher_cleanup, - sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ - gost89_set_asn1_parameters, - gost89_get_asn1_parameters, - gost_cipher_ctl, - NULL, -}; +static EVP_CIPHER *_hidden_Gost28147_89_cipher = NULL; +const EVP_CIPHER *cipher_gost(void) +{ + if (_hidden_Gost28147_89_cipher == NULL + && ((_hidden_Gost28147_89_cipher = + EVP_CIPHER_meth_new(NID_id_Gost28147_89, 1 /* block_size */ , + 32 /* key_size */ )) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_Gost28147_89_cipher, 8) + || !EVP_CIPHER_meth_set_flags(_hidden_Gost28147_89_cipher, + EVP_CIPH_CFB_MODE | + EVP_CIPH_NO_PADDING | + EVP_CIPH_CUSTOM_IV | + EVP_CIPH_RAND_KEY | + EVP_CIPH_ALWAYS_CALL_INIT) + || !EVP_CIPHER_meth_set_init(_hidden_Gost28147_89_cipher, + gost_cipher_init) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_Gost28147_89_cipher, + gost_cipher_do_cfb) + || !EVP_CIPHER_meth_set_cleanup(_hidden_Gost28147_89_cipher, + gost_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_Gost28147_89_cipher, + sizeof(struct + ossl_gost_cipher_ctx)) + || + !EVP_CIPHER_meth_set_set_asn1_params(_hidden_Gost28147_89_cipher, + gost89_set_asn1_parameters) + || + !EVP_CIPHER_meth_set_get_asn1_params(_hidden_Gost28147_89_cipher, + gost89_get_asn1_parameters) + || !EVP_CIPHER_meth_set_ctrl(_hidden_Gost28147_89_cipher, + gost_cipher_ctl))) { + EVP_CIPHER_meth_free(_hidden_Gost28147_89_cipher); + _hidden_Gost28147_89_cipher = NULL; + } + return _hidden_Gost28147_89_cipher; +} -EVP_CIPHER cipher_gost_cpacnt = { - NID_gost89_cnt, - 1, /* block_size */ - 32, /* key_size */ - 8, /* iv_len */ - EVP_CIPH_OFB_MODE | EVP_CIPH_NO_PADDING | - EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, - gost_cipher_init_cpa, - gost_cipher_do_cnt, - gost_cipher_cleanup, - sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ - gost89_set_asn1_parameters, - gost89_get_asn1_parameters, - gost_cipher_ctl, - NULL, -}; +static EVP_CIPHER *_hidden_Gost28147_89_cbc = NULL; +const EVP_CIPHER *cipher_gost_cbc(void) +{ + if (_hidden_Gost28147_89_cbc == NULL + && ((_hidden_Gost28147_89_cbc = + EVP_CIPHER_meth_new(NID_gost89_cbc, 8 /* block_size */ , + 32 /* key_size */ )) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_Gost28147_89_cbc, 8) + || !EVP_CIPHER_meth_set_flags(_hidden_Gost28147_89_cbc, + EVP_CIPH_CBC_MODE | + EVP_CIPH_CUSTOM_IV | + EVP_CIPH_RAND_KEY | + EVP_CIPH_ALWAYS_CALL_INIT) + || !EVP_CIPHER_meth_set_init(_hidden_Gost28147_89_cbc, + gost_cipher_init_cbc) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_Gost28147_89_cbc, + gost_cipher_do_cbc) + || !EVP_CIPHER_meth_set_cleanup(_hidden_Gost28147_89_cbc, + gost_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_Gost28147_89_cbc, + sizeof(struct + ossl_gost_cipher_ctx)) + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_Gost28147_89_cbc, + gost89_set_asn1_parameters) + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_Gost28147_89_cbc, + gost89_get_asn1_parameters) + || !EVP_CIPHER_meth_set_ctrl(_hidden_Gost28147_89_cbc, + gost_cipher_ctl))) { + EVP_CIPHER_meth_free(_hidden_Gost28147_89_cbc); + _hidden_Gost28147_89_cbc = NULL; + } + return _hidden_Gost28147_89_cbc; +} -EVP_CIPHER cipher_gost_cpcnt_12 = { - NID_gost89_cnt_12, - 1, /* block_size */ - 32, /* key_size */ - 8, /* iv_len */ - EVP_CIPH_OFB_MODE | EVP_CIPH_NO_PADDING | - EVP_CIPH_CUSTOM_IV | EVP_CIPH_RAND_KEY | EVP_CIPH_ALWAYS_CALL_INIT, - gost_cipher_init_cp_12, - gost_cipher_do_cnt, - gost_cipher_cleanup, - sizeof(struct ossl_gost_cipher_ctx), /* ctx_size */ - gost89_set_asn1_parameters, - gost89_get_asn1_parameters, - gost_cipher_ctl, - NULL, -}; +static EVP_CIPHER *_hidden_gost89_cnt = NULL; +const EVP_CIPHER *cipher_gost_cpacnt(void) +{ + if (_hidden_gost89_cnt == NULL + && ((_hidden_gost89_cnt = + EVP_CIPHER_meth_new(NID_gost89_cnt, 1 /* block_size */ , + 32 /* key_size */ )) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_gost89_cnt, 8) + || !EVP_CIPHER_meth_set_flags(_hidden_gost89_cnt, + EVP_CIPH_OFB_MODE | + EVP_CIPH_NO_PADDING | + EVP_CIPH_CUSTOM_IV | + EVP_CIPH_RAND_KEY | + EVP_CIPH_ALWAYS_CALL_INIT) + || !EVP_CIPHER_meth_set_init(_hidden_gost89_cnt, + gost_cipher_init_cpa) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_gost89_cnt, + gost_cipher_do_cnt) + || !EVP_CIPHER_meth_set_cleanup(_hidden_gost89_cnt, + gost_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_gost89_cnt, + sizeof(struct + ossl_gost_cipher_ctx)) + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_gost89_cnt, + gost89_set_asn1_parameters) + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_gost89_cnt, + gost89_get_asn1_parameters) + || !EVP_CIPHER_meth_set_ctrl(_hidden_gost89_cnt, gost_cipher_ctl))) { + EVP_CIPHER_meth_free(_hidden_gost89_cnt); + _hidden_gost89_cnt = NULL; + } + return _hidden_gost89_cnt; +} + +static EVP_CIPHER *_hidden_gost89_cnt_12 = NULL; +const EVP_CIPHER *cipher_gost_cpcnt_12(void) +{ + if (_hidden_gost89_cnt_12 == NULL + && ((_hidden_gost89_cnt_12 = + EVP_CIPHER_meth_new(NID_gost89_cnt_12, 1 /* block_size */ , + 32 /* key_size */ )) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_gost89_cnt_12, 8) + || !EVP_CIPHER_meth_set_flags(_hidden_gost89_cnt_12, + EVP_CIPH_OFB_MODE | + EVP_CIPH_NO_PADDING | + EVP_CIPH_CUSTOM_IV | + EVP_CIPH_RAND_KEY | + EVP_CIPH_ALWAYS_CALL_INIT) + || !EVP_CIPHER_meth_set_init(_hidden_gost89_cnt_12, + gost_cipher_init_cp_12) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_gost89_cnt_12, + gost_cipher_do_cnt) + || !EVP_CIPHER_meth_set_cleanup(_hidden_gost89_cnt_12, + gost_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_gost89_cnt_12, + sizeof(struct + ossl_gost_cipher_ctx)) + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_gost89_cnt_12, + gost89_set_asn1_parameters) + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_gost89_cnt_12, + gost89_get_asn1_parameters) + || !EVP_CIPHER_meth_set_ctrl(_hidden_gost89_cnt_12, + gost_cipher_ctl))) { + EVP_CIPHER_meth_free(_hidden_gost89_cnt_12); + _hidden_gost89_cnt_12 = NULL; + } + return _hidden_gost89_cnt_12; +} + +static EVP_CIPHER *_hidden_magma_ctr = NULL; +const EVP_CIPHER *cipher_magma_ctr(void) +{ + if (_hidden_magma_ctr == NULL + && ((_hidden_magma_ctr = + EVP_CIPHER_meth_new(NID_magma_ctr, 1 /* block_size */ , + 32 /* key_size */ )) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_magma_ctr, 8) + || !EVP_CIPHER_meth_set_flags(_hidden_magma_ctr, + EVP_CIPH_CTR_MODE | + EVP_CIPH_NO_PADDING | + EVP_CIPH_CUSTOM_IV | + EVP_CIPH_RAND_KEY | + EVP_CIPH_ALWAYS_CALL_INIT) + || !EVP_CIPHER_meth_set_init(_hidden_magma_ctr, magma_cipher_init) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_magma_ctr, + magma_cipher_do_ctr) + || !EVP_CIPHER_meth_set_cleanup(_hidden_magma_ctr, + gost_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_magma_ctr, + sizeof(struct + ossl_gost_cipher_ctx)) + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_magma_ctr, + gost89_set_asn1_parameters) + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_magma_ctr, + gost89_get_asn1_parameters) + || !EVP_CIPHER_meth_set_ctrl(_hidden_magma_ctr, gost_cipher_ctl))) { + EVP_CIPHER_meth_free(_hidden_magma_ctr); + _hidden_magma_ctr = NULL; + } + return _hidden_magma_ctr; +} + +static EVP_CIPHER *_hidden_magma_cbc = NULL; +const EVP_CIPHER *cipher_magma_cbc(void) +{ + if (_hidden_magma_cbc == NULL + && ((_hidden_magma_cbc = + EVP_CIPHER_meth_new(NID_magma_cbc, 8 /* block_size */ , + 32 /* key_size */ )) == NULL + || !EVP_CIPHER_meth_set_iv_length(_hidden_magma_cbc, 8) + || !EVP_CIPHER_meth_set_flags(_hidden_magma_cbc, + EVP_CIPH_CBC_MODE | + EVP_CIPH_CUSTOM_IV | + EVP_CIPH_RAND_KEY | + EVP_CIPH_ALWAYS_CALL_INIT) + || !EVP_CIPHER_meth_set_init(_hidden_magma_cbc, magma_cipher_init) + || !EVP_CIPHER_meth_set_do_cipher(_hidden_magma_cbc, + magma_cipher_do_cbc) + || !EVP_CIPHER_meth_set_cleanup(_hidden_magma_cbc, + gost_cipher_cleanup) + || !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_magma_cbc, + sizeof(struct + ossl_gost_cipher_ctx)) + || !EVP_CIPHER_meth_set_set_asn1_params(_hidden_magma_cbc, + gost89_set_asn1_parameters) + || !EVP_CIPHER_meth_set_get_asn1_params(_hidden_magma_cbc, + gost89_get_asn1_parameters) + || !EVP_CIPHER_meth_set_ctrl(_hidden_magma_cbc, gost_cipher_ctl))) { + EVP_CIPHER_meth_free(_hidden_magma_cbc); + _hidden_magma_cbc = NULL; + } + return _hidden_magma_cbc; +} + +void cipher_gost_destroy(void) +{ + EVP_CIPHER_meth_free(_hidden_Gost28147_89_cipher); + _hidden_Gost28147_89_cipher = NULL; + EVP_CIPHER_meth_free(_hidden_gost89_cnt); + _hidden_gost89_cnt = NULL; + EVP_CIPHER_meth_free(_hidden_Gost28147_89_cbc); + _hidden_Gost28147_89_cbc = NULL; + EVP_CIPHER_meth_free(_hidden_gost89_cnt_12); + _hidden_gost89_cnt_12 = NULL; + EVP_CIPHER_meth_free(_hidden_magma_cbc); + _hidden_magma_cbc = NULL; + EVP_CIPHER_meth_free(_hidden_magma_ctr); + _hidden_magma_ctr = NULL; +} /* Implementation of GOST 28147-89 in MAC (imitovstavka) mode */ /* Init functions which set specific parameters */ @@ -128,41 +289,70 @@ static int gost_imit_cleanup(EVP_MD_CTX *ctx); /* Control function, knows how to set MAC key.*/ static int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr); -EVP_MD imit_gost_cpa = { - NID_id_Gost28147_89_MAC, - NID_undef, - 4, - 0, - gost_imit_init_cpa, - gost_imit_update, - gost_imit_final, - gost_imit_copy, - gost_imit_cleanup, - NULL, - NULL, - {0, 0, 0, 0, 0}, - 8, - sizeof(struct ossl_gost_imit_ctx), - gost_imit_ctrl -}; +static EVP_MD *_hidden_Gost28147_89_MAC_md = NULL; +static EVP_MD *_hidden_Gost28147_89_12_MAC_md = NULL; -EVP_MD imit_gost_cp_12 = { - NID_gost_mac_12, - NID_undef, - 4, - 0, - gost_imit_init_cp_12, - gost_imit_update, - gost_imit_final, - gost_imit_copy, - gost_imit_cleanup, - NULL, - NULL, - {0, 0, 0, 0, 0}, - 8, - sizeof(struct ossl_gost_imit_ctx), - gost_imit_ctrl -}; +EVP_MD *imit_gost_cpa(void) +{ + if (_hidden_Gost28147_89_MAC_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_id_Gost28147_89_MAC, NID_undef)) == NULL + || !EVP_MD_meth_set_result_size(md, 4) + || !EVP_MD_meth_set_input_blocksize(md, 8) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(struct ossl_gost_imit_ctx)) + || !EVP_MD_meth_set_flags(md, 0) + || !EVP_MD_meth_set_init(md, gost_imit_init_cpa) + || !EVP_MD_meth_set_update(md, gost_imit_update) + || !EVP_MD_meth_set_final(md, gost_imit_final) + || !EVP_MD_meth_set_copy(md, gost_imit_copy) + || !EVP_MD_meth_set_cleanup(md, gost_imit_cleanup) + || !EVP_MD_meth_set_ctrl(md, gost_imit_ctrl)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_Gost28147_89_MAC_md = md; + } + return _hidden_Gost28147_89_MAC_md; +} + +void imit_gost_cpa_destroy(void) +{ + EVP_MD_meth_free(_hidden_Gost28147_89_MAC_md); + _hidden_Gost28147_89_MAC_md = NULL; +} + +EVP_MD *imit_gost_cp_12(void) +{ + if (_hidden_Gost28147_89_12_MAC_md == NULL) { + EVP_MD *md; + + if ((md = EVP_MD_meth_new(NID_gost_mac_12, NID_undef)) == NULL + || !EVP_MD_meth_set_result_size(md, 4) + || !EVP_MD_meth_set_input_blocksize(md, 8) + || !EVP_MD_meth_set_app_datasize(md, + sizeof(struct ossl_gost_imit_ctx)) + || !EVP_MD_meth_set_flags(md, 0) + || !EVP_MD_meth_set_init(md, gost_imit_init_cp_12) + || !EVP_MD_meth_set_update(md, gost_imit_update) + || !EVP_MD_meth_set_final(md, gost_imit_final) + || !EVP_MD_meth_set_copy(md, gost_imit_copy) + || !EVP_MD_meth_set_cleanup(md, gost_imit_cleanup) + || !EVP_MD_meth_set_ctrl(md, gost_imit_ctrl)) { + EVP_MD_meth_free(md); + md = NULL; + } + _hidden_Gost28147_89_12_MAC_md = md; + } + return _hidden_Gost28147_89_12_MAC_md; +} + +void imit_gost_cp_12_destroy(void) +{ + EVP_MD_meth_free(_hidden_Gost28147_89_12_MAC_md); + _hidden_Gost28147_89_12_MAC_md = NULL; +} /* * Correspondence between gost parameter OIDs and substitution blocks @@ -234,8 +424,7 @@ const struct gost_cipher_info *get_encryption_params(ASN1_OBJECT *obj) static int gost_cipher_set_param(struct ossl_gost_cipher_ctx *c, int nid) { const struct gost_cipher_info *param; - param = - get_encryption_params((nid == NID_undef ? NULL : OBJ_nid2obj(nid))); + param = get_encryption_params((nid == NID_undef ? NULL : OBJ_nid2obj(nid))); if (!param) return 0; @@ -252,17 +441,42 @@ static int gost_cipher_init_param(EVP_CIPHER_CTX *ctx, const unsigned char *iv, int enc, int paramNID, int mode) { - struct ossl_gost_cipher_ctx *c = ctx->cipher_data; - if (ctx->app_data == NULL) { + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) { if (!gost_cipher_set_param(c, paramNID)) return 0; - ctx->app_data = ctx->cipher_data; + EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx)); } if (key) gost_key(&(c->cctx), key); - if (iv) - memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); - memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); + if (iv) { + memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, + EVP_CIPHER_CTX_iv_length(ctx)); + } + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx)); + return 1; +} + +static int magma_cipher_init_param(EVP_CIPHER_CTX *ctx, + const unsigned char *key, + const unsigned char *iv, int enc, + int paramNID, int mode) +{ + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + if (EVP_CIPHER_CTX_get_app_data(ctx) == NULL) { + if (!gost_cipher_set_param(c, NID_id_tc26_gost_28147_param_Z)) + return 0; + EVP_CIPHER_CTX_set_app_data(ctx, EVP_CIPHER_CTX_get_cipher_data(ctx)); + } + if (key) + magma_key(&(c->cctx), key); + if (iv) { + memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, + EVP_CIPHER_CTX_iv_length(ctx)); + } + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx)); return 1; } @@ -271,15 +485,18 @@ static int gost_cipher_init_cnt(EVP_CIPHER_CTX *ctx, const unsigned char *iv, gost_subst_block * block) { - struct ossl_gost_cipher_ctx *c = ctx->cipher_data; + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); gost_init(&(c->cctx), block); c->key_meshing = 1; c->count = 0; if (key) gost_key(&(c->cctx), key); - if (iv) - memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); - memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx)); + if (iv) { + memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), iv, + EVP_CIPHER_CTX_iv_length(ctx)); + } + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), + EVP_CIPHER_CTX_original_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx)); return 1; } @@ -312,6 +529,14 @@ int gost_cipher_init_cbc(EVP_CIPHER_CTX *ctx, const unsigned char *key, EVP_CIPH_CBC_MODE); } +/* Initializes EVP_CIPHER_CTX with default values */ +int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + return magma_cipher_init_param(ctx, key, iv, enc, NID_undef, + EVP_CIPH_CBC_MODE); +} + /* * Wrapper around gostcrypt function from gost89.c which perform key meshing * when nesseccary @@ -361,7 +586,7 @@ static void gost_cnt_next(void *ctx, unsigned char *iv, unsigned char *buf) c->count = c->count % 1024 + 8; } -/* GOST encryptoon in CBC mode */ +/* GOST encryption in CBC mode */ int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) { @@ -369,15 +594,16 @@ int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in_ptr = in; unsigned char *out_ptr = out; int i; - struct ossl_gost_cipher_ctx *c = ctx->cipher_data; - OPENSSL_assert(inl % 8 == 0); - if (ctx->encrypt) { + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); + if (EVP_CIPHER_CTX_encrypting(ctx)) { while (inl > 0) { + for (i = 0; i < 8; i++) { - b[i] = ctx->iv[i] ^ in_ptr[i]; + b[i] = iv[i] ^ in_ptr[i]; } gostcrypt(&(c->cctx), b, out_ptr); - memcpy(ctx->iv, out_ptr, 8); + memcpy(iv, out_ptr, 8); out_ptr += 8; in_ptr += 8; inl -= 8; @@ -386,9 +612,9 @@ int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, while (inl > 0) { gostdecrypt(&(c->cctx), in_ptr, b); for (i = 0; i < 8; i++) { - out_ptr[i] = ctx->iv[i] ^ b[i]; + out_ptr[i] = iv[i] ^ b[i]; } - memcpy(ctx->iv, in_ptr, 8); + memcpy(iv, in_ptr, 8); out_ptr += 8; in_ptr += 8; inl -= 8; @@ -397,6 +623,114 @@ int gost_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, return 1; } +/* MAGMA encryption in CBC mode */ +int magma_cipher_do_cbc(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + unsigned char b[8]; + unsigned char d[8]; + const unsigned char *in_ptr = in; + unsigned char *out_ptr = out; + int i; + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); + if (EVP_CIPHER_CTX_encrypting(ctx)) { + while (inl > 0) { + + for (i = 0; i < 8; i++) { + b[7 - i] = iv[i] ^ in_ptr[i]; + } + gostcrypt(&(c->cctx), b, d); + + for (i = 0; i < 8; i++) { + out_ptr[7 - i] = d[i]; + } + memcpy(iv, out_ptr, 8); + out_ptr += 8; + in_ptr += 8; + inl -= 8; + } + } else { + while (inl > 0) { + for (i = 0; i < 8; i++) { + d[7 - i] = in_ptr[i]; + } + gostdecrypt(&(c->cctx), d, b); + for (i = 0; i < 8; i++) { + out_ptr[i] = iv[i] ^ b[7 - i]; + } + memcpy(iv, in_ptr, 8); + out_ptr += 8; + in_ptr += 8; + inl -= 8; + } + } + return 1; +} + +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(unsigned char *counter) +{ + inc_counter(counter, 8); +} + +/* MAGMA encryption in CTR mode */ +static int magma_cipher_do_ctr(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inl) +{ + const unsigned char *in_ptr = in; + unsigned char *out_ptr = out; + size_t i = 0; + size_t j; + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); + unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); + unsigned char b[8]; +/* Process partial blocks */ + if (EVP_CIPHER_CTX_num(ctx)) { + for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl; + j++, i++, in_ptr++, out_ptr++) { + *out_ptr = buf[7 - j] ^ (*in_ptr); + } + if (j == 8) { + EVP_CIPHER_CTX_set_num(ctx, 0); + } else { + EVP_CIPHER_CTX_set_num(ctx, j); + return 1; + } + } + +/* Process full blocks */ + for (; i + 8 <= inl; i += 8, in_ptr += 8, out_ptr += 8) { + for (j = 0; j < 8; j++) { + b[7 - j] = iv[j]; + } + gostcrypt(&(c->cctx), b, buf); + for (j = 0; j < 8; j++) { + out_ptr[j] = buf[7 - j] ^ in_ptr[j]; + } + ctr64_inc(iv); + } + +/* Process the rest of plaintext */ + if (i < inl) { + for (j = 0; j < 8; j++) { + b[7 - j] = iv[j]; + } + gostcrypt(&(c->cctx), iv, buf); + ctr64_inc(iv); + for (j = 0; i < inl; j++, i++) { + out_ptr[j] = buf[7 - j] ^ in_ptr[j]; + } + + EVP_CIPHER_CTX_set_num(ctx, j); + } else { + EVP_CIPHER_CTX_set_num(ctx, 0); + } + + return 1; +} + /* GOST encryption in CFB mode */ int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, const unsigned char *in, size_t inl) @@ -405,21 +739,23 @@ int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, unsigned char *out_ptr = out; size_t i = 0; size_t j = 0; + unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); /* process partial block if any */ - if (ctx->num) { - for (j = ctx->num, i = 0; j < 8 && i < inl; + if (EVP_CIPHER_CTX_num(ctx)) { + for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl; j++, i++, in_ptr++, out_ptr++) { - if (!ctx->encrypt) - ctx->buf[j + 8] = *in_ptr; - *out_ptr = ctx->buf[j] ^ (*in_ptr); - if (ctx->encrypt) - ctx->buf[j + 8] = *out_ptr; + if (!EVP_CIPHER_CTX_encrypting(ctx)) + buf[j + 8] = *in_ptr; + *out_ptr = buf[j] ^ (*in_ptr); + if (EVP_CIPHER_CTX_encrypting(ctx)) + buf[j + 8] = *out_ptr; } if (j == 8) { - memcpy(ctx->iv, ctx->buf + 8, 8); - ctx->num = 0; + memcpy(iv, buf + 8, 8); + EVP_CIPHER_CTX_set_num(ctx, 0); } else { - ctx->num = j; + EVP_CIPHER_CTX_set_num(ctx, j); return 1; } } @@ -428,36 +764,36 @@ int gost_cipher_do_cfb(EVP_CIPHER_CTX *ctx, unsigned char *out, /* * block cipher current iv */ - gost_crypt_mesh(ctx->cipher_data, ctx->iv, ctx->buf); + gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf); /* * xor next block of input text with it and output it */ /* * output this block */ - if (!ctx->encrypt) - memcpy(ctx->iv, in_ptr, 8); + if (!EVP_CIPHER_CTX_encrypting(ctx)) + memcpy(iv, in_ptr, 8); for (j = 0; j < 8; j++) { - out_ptr[j] = ctx->buf[j] ^ in_ptr[j]; + out_ptr[j] = buf[j] ^ in_ptr[j]; } /* Encrypt */ /* Next iv is next block of cipher text */ - if (ctx->encrypt) - memcpy(ctx->iv, out_ptr, 8); + if (EVP_CIPHER_CTX_encrypting(ctx)) + memcpy(iv, out_ptr, 8); } /* Process rest of buffer */ if (i < inl) { - gost_crypt_mesh(ctx->cipher_data, ctx->iv, ctx->buf); - if (!ctx->encrypt) - memcpy(ctx->buf + 8, in_ptr, inl - i); + gost_crypt_mesh(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf); + if (!EVP_CIPHER_CTX_encrypting(ctx)) + memcpy(buf + 8, in_ptr, inl - i); for (j = 0; i < inl; j++, i++) { - out_ptr[j] = ctx->buf[j] ^ in_ptr[j]; + out_ptr[j] = buf[j] ^ in_ptr[j]; } - ctx->num = j; - if (ctx->encrypt) - memcpy(ctx->buf + 8, out_ptr, j); + EVP_CIPHER_CTX_set_num(ctx, j); + if (EVP_CIPHER_CTX_encrypting(ctx)) + memcpy(buf + 8, out_ptr, j); } else { - ctx->num = 0; + EVP_CIPHER_CTX_set_num(ctx, 0); } return 1; } @@ -469,16 +805,18 @@ static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, unsigned char *out_ptr = out; size_t i = 0; size_t j; + unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx); + unsigned char *iv = EVP_CIPHER_CTX_iv_noconst(ctx); /* process partial block if any */ - if (ctx->num) { - for (j = ctx->num, i = 0; j < 8 && i < inl; + if (EVP_CIPHER_CTX_num(ctx)) { + for (j = EVP_CIPHER_CTX_num(ctx), i = 0; j < 8 && i < inl; j++, i++, in_ptr++, out_ptr++) { - *out_ptr = ctx->buf[j] ^ (*in_ptr); + *out_ptr = buf[j] ^ (*in_ptr); } if (j == 8) { - ctx->num = 0; + EVP_CIPHER_CTX_set_num(ctx, 0); } else { - ctx->num = j; + EVP_CIPHER_CTX_set_num(ctx, j); return 1; } } @@ -488,7 +826,7 @@ static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, * block cipher current iv */ /* Encrypt */ - gost_cnt_next(ctx->cipher_data, ctx->iv, ctx->buf); + gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf); /* * xor next block of input text with it and output it */ @@ -496,18 +834,18 @@ static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, * output this block */ for (j = 0; j < 8; j++) { - out_ptr[j] = ctx->buf[j] ^ in_ptr[j]; + out_ptr[j] = buf[j] ^ in_ptr[j]; } } /* Process rest of buffer */ if (i < inl) { - gost_cnt_next(ctx->cipher_data, ctx->iv, ctx->buf); + gost_cnt_next(EVP_CIPHER_CTX_get_cipher_data(ctx), iv, buf); for (j = 0; i < inl; j++, i++) { - out_ptr[j] = ctx->buf[j] ^ in_ptr[j]; + out_ptr[j] = buf[j] ^ in_ptr[j]; } - ctx->num = j; + EVP_CIPHER_CTX_set_num(ctx, j); } else { - ctx->num = 0; + EVP_CIPHER_CTX_set_num(ctx, 0); } return 1; } @@ -515,8 +853,9 @@ static int gost_cipher_do_cnt(EVP_CIPHER_CTX *ctx, unsigned char *out, /* Cleaning up of EVP_CIPHER_CTX */ int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) { - gost_destroy(&((struct ossl_gost_cipher_ctx *)ctx->cipher_data)->cctx); - ctx->app_data = NULL; + gost_destroy(&((struct ossl_gost_cipher_ctx *) + EVP_CIPHER_CTX_get_cipher_data(ctx))->cctx); + EVP_CIPHER_CTX_set_app_data(ctx, NULL); return 1; } @@ -524,17 +863,21 @@ int gost_cipher_cleanup(EVP_CIPHER_CTX *ctx) int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) { switch (type) { +#if 0 case EVP_CTRL_INIT: { - struct ossl_gost_cipher_ctx *c = ctx->cipher_data; + struct ossl_gost_cipher_ctx *c = + EVP_CIPHER_CTX_get_cipher_data(ctx); if (c == NULL) { return -1; } return gost_cipher_set_param(c, arg); } +#endif case EVP_CTRL_RAND_KEY: { - if (RAND_bytes((unsigned char *)ptr, ctx->key_len) <= 0) { + if (RAND_bytes + ((unsigned char *)ptr, EVP_CIPHER_CTX_key_length(ctx)) <= 0) { GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_RNG_ERROR); return -1; } @@ -558,10 +901,11 @@ int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) } else { return 0; } -#ifdef EVP_CTRL_SET_SBOX + case EVP_CTRL_SET_SBOX: if (ptr) { - struct ossl_gost_cipher_ctx *c = ctx->cipher_data; + struct ossl_gost_cipher_ctx *c = + EVP_CIPHER_CTX_get_cipher_data(ctx); int nid; int cur_meshing; int ret; @@ -584,13 +928,12 @@ int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) c->key_meshing = cur_meshing; return ret; } else { - return 0; + return 0; } -#endif -#ifdef EVP_CTRL_KEY_MESH case EVP_CTRL_KEY_MESH: { - struct ossl_gost_cipher_ctx *c = ctx->cipher_data; + struct ossl_gost_cipher_ctx *c = + EVP_CIPHER_CTX_get_cipher_data(ctx); if (c == NULL) { return -1; @@ -602,11 +945,9 @@ int gost_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) c->key_meshing = arg; return 1; - } -#endif + } default: - GOSTerr(GOST_F_GOST_CIPHER_CTL, - GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND); + GOSTerr(GOST_F_GOST_CIPHER_CTL, GOST_R_UNSUPPORTED_CIPHER_CTL_COMMAND); return -1; } return 1; @@ -618,14 +959,15 @@ int gost89_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) int len = 0; unsigned char *buf = NULL; unsigned char *p = NULL; - struct ossl_gost_cipher_ctx *c = ctx->cipher_data; + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); GOST_CIPHER_PARAMS *gcp = GOST_CIPHER_PARAMS_new(); ASN1_OCTET_STRING *os = NULL; if (!gcp) { GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE); return 0; } - if (!ASN1_OCTET_STRING_set(gcp->iv, ctx->iv, ctx->cipher->iv_len)) { + if (!ASN1_OCTET_STRING_set + (gcp->iv, EVP_CIPHER_CTX_iv(ctx), EVP_CIPHER_CTX_iv_length(ctx))) { GOST_CIPHER_PARAMS_free(gcp); GOSTerr(GOST_F_GOST89_SET_ASN1_PARAMETERS, ERR_R_MALLOC_FAILURE); return 0; @@ -663,7 +1005,7 @@ int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) int len; GOST_CIPHER_PARAMS *gcp = NULL; unsigned char *p; - struct ossl_gost_cipher_ctx *c = ctx->cipher_data; + struct ossl_gost_cipher_ctx *c = EVP_CIPHER_CTX_get_cipher_data(ctx); int nid; if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) { @@ -676,7 +1018,7 @@ int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) params->value.sequence->length); len = gcp->iv->length; - if (len != ctx->cipher->iv_len) { + if (len != EVP_CIPHER_CTX_iv_length(ctx)) { GOST_CIPHER_PARAMS_free(gcp); GOSTerr(GOST_F_GOST89_GET_ASN1_PARAMETERS, GOST_R_INVALID_IV_LENGTH); return -1; @@ -694,12 +1036,9 @@ int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) GOST_CIPHER_PARAMS_free(gcp); return -1; } - - { - ASN1_TYPE tmp; - ASN1_TYPE_set(&tmp, V_ASN1_OCTET_STRING, gcp->iv); - EVP_CIPHER_get_asn1_iv(ctx, &tmp); - } + /*XXX missing non-const accessor */ + memcpy((unsigned char *)EVP_CIPHER_CTX_original_iv(ctx), gcp->iv->data, + EVP_CIPHER_CTX_iv_length(ctx)); GOST_CIPHER_PARAMS_free(gcp); @@ -708,7 +1047,7 @@ int gost89_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params) static int gost_imit_init(EVP_MD_CTX *ctx, gost_subst_block * block) { - struct ossl_gost_imit_ctx *c = ctx->md_data; + struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx); memset(c->buffer, 0, sizeof(c->buffer)); memset(c->partial_block, 0, sizeof(c->partial_block)); c->count = 0; @@ -748,7 +1087,7 @@ static void mac_block_mesh(struct ossl_gost_imit_ctx *c, int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) { - struct ossl_gost_imit_ctx *c = ctx->md_data; + struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx); const unsigned char *p = data; size_t bytes = count, i; if (!(c->key_set)) { @@ -780,7 +1119,7 @@ int gost_imit_update(EVP_MD_CTX *ctx, const void *data, size_t count) int gost_imit_final(EVP_MD_CTX *ctx, unsigned char *md) { - struct ossl_gost_imit_ctx *c = ctx->md_data; + struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx); if (!c->key_set) { GOSTerr(GOST_F_GOST_IMIT_FINAL, GOST_R_MAC_KEY_NOT_SET); return 0; @@ -809,20 +1148,19 @@ int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) return 1; case EVP_MD_CTRL_SET_KEY: { - struct ossl_gost_imit_ctx *gost_imit_ctx = ctx->md_data; + struct ossl_gost_imit_ctx *gost_imit_ctx = EVP_MD_CTX_md_data(ctx); - if (ctx->digest->init(ctx) <= 0) { + if (EVP_MD_meth_get_init(EVP_MD_CTX_md(ctx)) (ctx) <= 0) { GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_MAC_KEY_NOT_SET); return 0; } - ctx->flags |= EVP_MD_CTX_FLAG_NO_INIT; + EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NO_INIT); if (arg == 0) { struct gost_mac_key *key = (struct gost_mac_key *)ptr; if (key->mac_param_nid != NID_undef) { const struct gost_cipher_info *param = - get_encryption_params(OBJ_nid2obj - (key->mac_param_nid)); + get_encryption_params(OBJ_nid2obj(key->mac_param_nid)); if (param == NULL) { GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_PARAMS); @@ -844,7 +1182,7 @@ int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) } case EVP_MD_CTRL_MAC_LEN: { - struct ossl_gost_imit_ctx *c = ctx->md_data; + struct ossl_gost_imit_ctx *c = EVP_MD_CTX_md_data(ctx); if (arg < 1 || arg > 8) { GOSTerr(GOST_F_GOST_IMIT_CTRL, GOST_R_INVALID_MAC_SIZE); return 0; @@ -860,13 +1198,16 @@ int gost_imit_ctrl(EVP_MD_CTX *ctx, int type, int arg, void *ptr) int gost_imit_copy(EVP_MD_CTX *to, const EVP_MD_CTX *from) { - memcpy(to->md_data, from->md_data, sizeof(struct ossl_gost_imit_ctx)); + if (EVP_MD_CTX_md_data(to) && EVP_MD_CTX_md_data(from)) { + memcpy(EVP_MD_CTX_md_data(to), EVP_MD_CTX_md_data(from), + sizeof(struct ossl_gost_imit_ctx)); + } return 1; } /* Clean up imit ctx */ int gost_imit_cleanup(EVP_MD_CTX *ctx) { - memset(ctx->md_data, 0, sizeof(struct ossl_gost_imit_ctx)); + memset(EVP_MD_CTX_md_data(ctx), 0, sizeof(struct ossl_gost_imit_ctx)); return 1; }