+ const unsigned char *iv, size_t iv_size, const unsigned char *kdf_seed)
+{
+ GOST2015_CIPHER_PARAMS *gcp = GOST2015_CIPHER_PARAMS_new();
+ int ret = 0, len = 0;
+
+ ASN1_OCTET_STRING *os = NULL;
+ unsigned char ukm_buf[MAX_GOST2015_UKM_SIZE];
+ unsigned char *buf = NULL;
+
+ if (gcp == NULL) {
+ GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ memcpy(ukm_buf, iv, iv_size);
+ memcpy(ukm_buf+iv_size, kdf_seed, KDF_SEED_SIZE);
+
+ if (ASN1_STRING_set(gcp->ukm, ukm_buf, iv_size + KDF_SEED_SIZE) == 0) {
+ GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
+ goto end;
+ }
+
+ len = i2d_GOST2015_CIPHER_PARAMS(gcp, &buf);
+
+ if (len <= 0
+ || (os = ASN1_OCTET_STRING_new()) == NULL
+ || ASN1_OCTET_STRING_set(os, buf, len) == 0) {
+ goto end;
+ }
+
+ ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
+ ret = 1;
+
+end:
+ OPENSSL_free(buf);
+ if (ret <= 0 && os)
+ ASN1_OCTET_STRING_free(os);
+
+ GOST2015_CIPHER_PARAMS_free(gcp);
+ return ret;
+}
+
+int gost2015_process_unprotected_attributes(STACK_OF(X509_ATTRIBUTE) *attrs,
+ int encryption, size_t mac_len, unsigned char *final_tag)
+{
+ if (encryption == 0) /*Decrypting*/ {
+ ASN1_OCTET_STRING *osExpectedMac = X509at_get0_data_by_OBJ(attrs,
+ OBJ_txt2obj(OID_GOST_CMS_MAC, 1), -3, V_ASN1_OCTET_STRING);
+
+ if (!osExpectedMac || osExpectedMac->length != (int)mac_len)
+ return -1;
+
+ memcpy(final_tag, osExpectedMac->data, osExpectedMac->length);
+ } else {
+ if (attrs == NULL)
+ return -1;
+ return (X509at_add1_attr_by_OBJ(&attrs, OBJ_txt2obj(OID_GOST_CMS_MAC, 1),
+ V_ASN1_OCTET_STRING, final_tag, mac_len) == NULL) ? -1 : 1;
+ }
+ return 1;
+}
+
+int gost2015_acpkm_omac_init(int nid, int enc, const unsigned char *inkey,
+ EVP_MD_CTX *omac_ctx,
+ unsigned char *outkey, unsigned char *kdf_seed)