diff --git a/gost_crypt.c b/gost_crypt.c index 58848de6..69ec336e 100644 --- a/gost_crypt.c +++ b/gost_crypt.c @@ -427,11 +427,18 @@ static int magma_cipher_init(GOST_cipher_ctx *ctx, const unsigned char *key, const unsigned char *iv, int enc) { struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); + int key_meshing = c->key_meshing; + int key_meshing_set = c->key_meshing_set; + /* FIXME this is just initializtion check */ if (GOST_cipher_ctx_get_app_data(ctx) == NULL) { if (!gost_cipher_set_param(c, NID_id_tc26_gost_28147_param_Z)) return 0; GOST_cipher_ctx_set_app_data(ctx, GOST_cipher_ctx_get_cipher_data(ctx)); + if (key_meshing_set) { + c->key_meshing = key_meshing; + c->key_meshing_set = key_meshing_set; + } if (enc) { if (init_zero_kdf_seed(c->kdf_seed) == 0) @@ -452,9 +459,11 @@ static int magma_cipher_init(GOST_cipher_ctx *ctx, const unsigned char *key, if (GOST_cipher_ctx_nid(ctx) == NID_magma_ctr_acpkm || GOST_cipher_ctx_nid(ctx) == NID_magma_ctr_acpkm_omac) { - c->key_meshing = 1024; + if (!c->key_meshing_set) + c->key_meshing = 1024; } else { c->key_meshing = 0; + c->key_meshing_set = 0; } c->count = 0; @@ -1155,6 +1164,7 @@ static int gost_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) GOST_cipher_ctx_get_cipher_data(ctx); int nid; int cur_meshing; + int cur_meshing_set; int ret; if (c == NULL) { @@ -1171,8 +1181,10 @@ static int gost_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) } cur_meshing = c->key_meshing; + cur_meshing_set = c->key_meshing_set; ret = gost_cipher_set_param(c, nid); c->key_meshing = cur_meshing; + c->key_meshing_set = cur_meshing_set; return ret; } else { return 0; @@ -1191,6 +1203,7 @@ static int gost_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) } c->key_meshing = arg; + c->key_meshing_set = 1; return 1; } default: @@ -1260,6 +1273,7 @@ static int magma_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, void *ptr) } c->key_meshing = arg; + c->key_meshing_set = 1; return 1; } case EVP_CTRL_TLSTREE: @@ -1472,6 +1486,7 @@ static int magma_set_asn1_parameters (GOST_cipher_ctx *ctx, ASN1_TYPE *params) { struct ossl_gost_cipher_ctx *c = GOST_cipher_ctx_get_cipher_data(ctx); c->key_meshing = 8192; + c->key_meshing_set = 1; /* * Same lazy kdf_seed init as in gost_grasshopper_set_asn1_parameters: @@ -1493,6 +1508,7 @@ static int magma_get_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params) unsigned char iv[16]; c->key_meshing = 8192; + c->key_meshing_set = 1; if (gost2015_get_asn1_params(params, MAGMA_UKM_LEN, iv, 4, c->kdf_seed) == 0) return -1; diff --git a/gost_grasshopper_cipher.c b/gost_grasshopper_cipher.c index 3414b1c9..244fb1da 100644 --- a/gost_grasshopper_cipher.c +++ b/gost_grasshopper_cipher.c @@ -334,7 +334,8 @@ gost_grasshopper_cipher_init_ctracpkm(GOST_cipher_ctx /* NB: setting type makes EVP do_cipher callback useless */ c->c.type = GRASSHOPPER_CIPHER_CTRACPKM; GOST_cipher_ctx_set_num(ctx, 0); - c->section_size = 4096; + if (!c->section_size_set) + c->section_size = 4096; return gost_grasshopper_cipher_init(ctx, key, iv, enc); } @@ -350,7 +351,8 @@ gost_grasshopper_cipher_init_ctracpkm_omac(GOST_cipher_ctx /* NB: setting type makes EVP do_cipher callback useless */ c->c.type = GRASSHOPPER_CIPHER_CTRACPKMOMAC; GOST_cipher_ctx_set_num(ctx, 0); - c->section_size = 4096; + if (!c->section_size_set) + c->section_size = 4096; if (key) { unsigned char cipher_key[32]; @@ -1005,6 +1007,7 @@ static int gost_grasshopper_set_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE /* CMS implies 256kb section_size */ ctr->section_size = 256*1024; + ctr->section_size_set = 1; return gost2015_set_asn1_params(params, GOST_cipher_ctx_original_iv(ctx), 8, ctr->kdf_seed); @@ -1030,6 +1033,7 @@ gost_grasshopper_get_asn1_parameters(GOST_cipher_ctx *ctx, ASN1_TYPE *params) /* CMS implies 256kb section_size */ ctr->section_size = 256*1024; + ctr->section_size_set = 1; return 1; } return 0; @@ -1171,6 +1175,7 @@ static int gost_grasshopper_cipher_ctl(GOST_cipher_ctx *ctx, int type, int arg, || (arg % GRASSHOPPER_BLOCK_SIZE)) return -1; c->section_size = arg; + c->section_size_set = 1; break; } case EVP_CTRL_TLSTREE: diff --git a/gost_grasshopper_cipher.h b/gost_grasshopper_cipher.h index 6c47a0b9..fc38caf4 100644 --- a/gost_grasshopper_cipher.h +++ b/gost_grasshopper_cipher.h @@ -34,6 +34,7 @@ typedef struct { grasshopper_w128_t partial_buffer; unsigned int section_size; /* After how much bytes mesh the key, if 0 never mesh and work like plain ctr. */ + unsigned int section_size_set; unsigned char kdf_seed[8]; unsigned char tag[16]; EVP_MD_CTX *omac_ctx; diff --git a/gost_lcl.h b/gost_lcl.h index c106a6a8..5f18e083 100644 --- a/gost_lcl.h +++ b/gost_lcl.h @@ -217,6 +217,7 @@ struct ossl_gost_cipher_ctx { int paramNID; unsigned int count; int key_meshing; + int key_meshing_set; unsigned char kdf_seed[8]; unsigned char tag[8]; gost_ctx cctx; @@ -387,4 +388,3 @@ extern GOST_NID_JOB kuznyechik_mgm_NID; #endif /* vim: set expandtab cinoptions=\:0,l1,t0,g0,(0 sw=4 : */ - diff --git a/test_ciphers.c b/test_ciphers.c index 5becf69e..3746f661 100644 --- a/test_ciphers.c +++ b/test_ciphers.c @@ -580,6 +580,59 @@ static int test_provider_alg_id_param(const EVP_CIPHER *type, const char *name, return ret | test; } +static int test_engine_asn1_acpkm_reinit(const EVP_CIPHER *type, const char *name, + const unsigned char *key, + const unsigned char *iv) +{ + EVP_CIPHER_CTX *enc; + EVP_CIPHER_CTX *dec; + ASN1_TYPE *params; + unsigned char pt[8192]; + unsigned char ct[8192]; + unsigned char out[8192]; + int outlen = 0, tmplen = 0, total = 0; + int ret = 0, test; + size_t i; + + if (EVP_CIPHER_get0_provider(type) != NULL + || (strcmp(name, SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm) != 0 + && strcmp(name, SN_magma_ctr_acpkm) != 0)) + return 0; + + enc = EVP_CIPHER_CTX_new(); + dec = EVP_CIPHER_CTX_new(); + params = ASN1_TYPE_new(); + T(enc != NULL && dec != NULL && params != NULL); + + for (i = 0; i < sizeof(pt); i++) + pt[i] = (unsigned char)(i & 0xff); + + printf("Engine ASN1 ACPKM reinit test [%s]: ", name); + T(EVP_CipherInit_ex(enc, type, NULL, key, iv, 1)); + T(EVP_CIPHER_param_to_asn1(enc, params) > 0); + T(EVP_CipherUpdate(enc, ct, &outlen, pt, (int)sizeof(pt))); + total = outlen; + T(EVP_CipherFinal_ex(enc, ct + total, &tmplen)); + total += tmplen; + T(total == (int)sizeof(pt)); + + T(EVP_CipherInit_ex(dec, type, NULL, NULL, NULL, 0)); + T(EVP_CIPHER_asn1_to_param(dec, params) > 0); + T(EVP_CipherInit_ex(dec, NULL, NULL, key, NULL, 0)); + T(EVP_CipherUpdate(dec, out, &outlen, ct, total)); + total = outlen; + T(EVP_CipherFinal_ex(dec, out + total, &tmplen)); + total += tmplen; + + TEST_ASSERT(total != (int)sizeof(pt) || memcmp(out, pt, sizeof(pt))); + ret |= test; + + EVP_CIPHER_CTX_free(enc); + EVP_CIPHER_CTX_free(dec); + ASN1_TYPE_free(params); + return ret; +} + static int test_provider_padded_decrypt_case(const EVP_CIPHER *type, const char *name, const unsigned char *key, @@ -784,9 +837,22 @@ int main(int argc, char **argv) ret |= test_provider_padded_decrypt(ciph, t->algname, t->block, t->key, t->iv); } + ret |= test_engine_asn1_acpkm_reinit(ciph, t->algname, t->key, t->iv); EVP_CIPHER_free(ciph); } + { + EVP_CIPHER *ciph; + + ERR_set_mark(); + T((ciph = (EVP_CIPHER *)EVP_get_cipherbyname(SN_magma_ctr_acpkm)) + || (ciph = EVP_CIPHER_fetch(NULL, SN_magma_ctr_acpkm, NULL))); + ERR_pop_to_mark(); + + ret |= test_engine_asn1_acpkm_reinit(ciph, SN_magma_ctr_acpkm, + Km, iv_ctr); + EVP_CIPHER_free(ciph); + } warn_all_untested();