+static int magma_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
+ const unsigned char *iv, int enc);
+static int magma_cipher_init_ctr_acpkm_omac(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);
+
+static int magma_cipher_do_ctr_acpkm_omac(EVP_CIPHER_CTX *ctx, unsigned char *out,
+ const unsigned char *in, size_t inl);
+
+/* set/get cipher parameters */
+static int magma_set_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params);
+static int magma_get_asn1_parameters(EVP_CIPHER_CTX *ctx, ASN1_TYPE *params);
+/* Control function */
+static int magma_cipher_ctl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+static int magma_cipher_ctl_acpkm_omac(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+
+EVP_CIPHER *GOST_init_cipher(GOST_cipher *c)
+{
+ if (c->cipher)
+ return c->cipher;
+
+ EVP_CIPHER *cipher;
+ if (!(cipher = EVP_CIPHER_meth_new(c->nid, c->block_size, c->key_len))
+ || !EVP_CIPHER_meth_set_iv_length(cipher, c->iv_len)
+ || !EVP_CIPHER_meth_set_flags(cipher, c->flags)
+ || !EVP_CIPHER_meth_set_init(cipher, c->init)
+ || !EVP_CIPHER_meth_set_do_cipher(cipher, c->do_cipher)
+ || !EVP_CIPHER_meth_set_cleanup(cipher, c->cleanup)
+ || !EVP_CIPHER_meth_set_impl_ctx_size(cipher, c->ctx_size)
+ || !EVP_CIPHER_meth_set_set_asn1_params(cipher, c->set_asn1_parameters)
+ || !EVP_CIPHER_meth_set_get_asn1_params(cipher, c->get_asn1_parameters)
+ || !EVP_CIPHER_meth_set_ctrl(cipher, c->ctrl)) {
+ EVP_CIPHER_meth_free(cipher);
+ cipher = NULL;
+ }
+ c->cipher = cipher;
+ return c->cipher;
+}
+
+void GOST_deinit_cipher(GOST_cipher *c)
+{
+ if (c->cipher) {
+ EVP_CIPHER_meth_free(c->cipher);
+ c->cipher = NULL;
+ }
+}
+
+GOST_cipher Gost28147_89_cipher = {
+ .nid = NID_id_Gost28147_89,
+ .block_size = 1,
+ .key_len = 32,
+ .iv_len = 8,
+ .flags = EVP_CIPH_CFB_MODE |
+ EVP_CIPH_NO_PADDING |
+ EVP_CIPH_CUSTOM_IV |
+ EVP_CIPH_RAND_KEY |
+ EVP_CIPH_ALWAYS_CALL_INIT,
+ .init = gost_cipher_init,
+ .do_cipher = gost_cipher_do_cfb,
+ .cleanup = gost_cipher_cleanup,
+ .ctx_size = sizeof(struct ossl_gost_cipher_ctx),
+ .set_asn1_parameters = gost89_set_asn1_parameters,
+ .get_asn1_parameters = gost89_get_asn1_parameters,
+ .ctrl = gost_cipher_ctl,
+};
+
+GOST_cipher Gost28147_89_cbc_cipher = {
+ .nid = NID_gost89_cbc,
+ .block_size = 8,
+ .key_len = 32,
+ .iv_len = 8,
+ .flags = EVP_CIPH_CBC_MODE |
+ EVP_CIPH_CUSTOM_IV |
+ EVP_CIPH_RAND_KEY |
+ EVP_CIPH_ALWAYS_CALL_INIT,
+ .init = gost_cipher_init_cbc,
+ .do_cipher = gost_cipher_do_cbc,
+ .cleanup = gost_cipher_cleanup,
+ .ctx_size = sizeof(struct ossl_gost_cipher_ctx),
+ .set_asn1_parameters = gost89_set_asn1_parameters,
+ .get_asn1_parameters = gost89_get_asn1_parameters,
+ .ctrl = gost_cipher_ctl,
+};
+
+GOST_cipher Gost28147_89_cnt_cipher = {
+ .nid = NID_gost89_cnt,
+ .block_size = 1,
+ .key_len = 32,
+ .iv_len = 8,
+ .flags = EVP_CIPH_OFB_MODE |
+ EVP_CIPH_NO_PADDING |
+ EVP_CIPH_CUSTOM_IV |
+ EVP_CIPH_RAND_KEY |
+ EVP_CIPH_ALWAYS_CALL_INIT,
+ .init = gost_cipher_init_cpa,
+ .do_cipher = gost_cipher_do_cnt,
+ .cleanup = gost_cipher_cleanup,
+ .ctx_size = sizeof(struct ossl_gost_cipher_ctx),
+ .set_asn1_parameters = gost89_set_asn1_parameters,
+ .get_asn1_parameters = gost89_get_asn1_parameters,
+ .ctrl = gost_cipher_ctl,