2 #include "gost_gost2015.h"
3 #include "e_gost_err.h"
5 #include <openssl/rand.h>
7 int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size,
8 unsigned char *encrypted_mac,
9 int (*do_cipher) (EVP_CIPHER_CTX *ctx,
11 const unsigned char *in,
14 unsigned char calculated_mac[KUZNYECHIK_MAC_MAX_SIZE];
15 memset(calculated_mac, 0, KUZNYECHIK_MAC_MAX_SIZE);
17 if (EVP_CIPHER_CTX_encrypting(ctx)) {
18 EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size);
20 if (do_cipher(ctx, encrypted_mac, calculated_mac, mac_size) <= 0) {
24 unsigned char expected_mac[KUZNYECHIK_MAC_MAX_SIZE];
26 memset(expected_mac, 0, KUZNYECHIK_MAC_MAX_SIZE);
27 EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size);
29 if (do_cipher(ctx, expected_mac, encrypted_mac, mac_size) <= 0) {
33 if (CRYPTO_memcmp(expected_mac, calculated_mac, mac_size) != 0)
42 #define MAX_GOST2015_UKM_SIZE 16
43 #define KDF_SEED_SIZE 8
44 int gost2015_get_asn1_params(const ASN1_TYPE *params, size_t ukm_size,
45 unsigned char *iv, size_t ukm_offset, unsigned char *kdf_seed)
48 GOST2015_CIPHER_PARAMS *gcp = NULL;
50 unsigned char *p = NULL;
52 memset(iv, 0, iv_len);
54 /* Проверяем тип params */
55 if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
56 GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
60 p = params->value.sequence->data;
61 /* Извлекаем структуру параметров */
62 gcp = d2i_GOST2015_CIPHER_PARAMS(NULL, (const unsigned char **)&p, params->value.sequence->length);
64 GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
68 /* Проверяем длину синхропосылки */
69 if (gcp->ukm->length != (int)ukm_size) {
70 GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
71 GOST2015_CIPHER_PARAMS_free(gcp);
75 memcpy(iv, gcp->ukm->data, ukm_offset);
76 memcpy(kdf_seed, gcp->ukm->data+ukm_offset, KDF_SEED_SIZE);
78 GOST2015_CIPHER_PARAMS_free(gcp);
82 int gost2015_set_asn1_params(ASN1_TYPE *params,
83 const unsigned char *iv, size_t iv_size, const unsigned char *kdf_seed)
85 GOST2015_CIPHER_PARAMS *gcp = GOST2015_CIPHER_PARAMS_new();
88 ASN1_OCTET_STRING *os = NULL;
89 unsigned char ukm_buf[MAX_GOST2015_UKM_SIZE];
90 unsigned char *buf = NULL;
93 GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
97 memcpy(ukm_buf, iv, iv_size);
98 memcpy(ukm_buf+iv_size, kdf_seed, KDF_SEED_SIZE);
100 if (ASN1_STRING_set(gcp->ukm, ukm_buf, iv_size + KDF_SEED_SIZE) == 0) {
101 GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
105 len = i2d_GOST2015_CIPHER_PARAMS(gcp, &buf);
108 || (os = ASN1_OCTET_STRING_new()) == NULL
109 || ASN1_OCTET_STRING_set(os, buf, len) == 0) {
113 ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
119 ASN1_OCTET_STRING_free(os);
121 GOST2015_CIPHER_PARAMS_free(gcp);
125 int gost2015_process_unprotected_attributes(STACK_OF(X509_ATTRIBUTE) *attrs,
126 int encryption, size_t mac_len, unsigned char *final_tag)
128 if (encryption == 0) /*Decrypting*/ {
129 ASN1_OCTET_STRING *osExpectedMac = X509at_get0_data_by_OBJ(attrs,
130 OBJ_txt2obj(OID_GOST_CMS_MAC, 1), -3, V_ASN1_OCTET_STRING);
132 if (!osExpectedMac || osExpectedMac->length != (int)mac_len)
135 memcpy(final_tag, osExpectedMac->data, osExpectedMac->length);
139 return (X509at_add1_attr_by_OBJ(&attrs, OBJ_txt2obj(OID_GOST_CMS_MAC, 1),
140 V_ASN1_OCTET_STRING, final_tag, mac_len) == NULL) ? -1 : 1;
145 int gost2015_acpkm_omac_init(int nid, int enc, const unsigned char *inkey,
146 EVP_MD_CTX *omac_ctx,
147 unsigned char *outkey, unsigned char *kdf_seed)
150 unsigned char keys[64];
151 const EVP_MD *md = EVP_get_digestbynid(nid);
158 if (RAND_bytes(kdf_seed, 8) != 1)
162 if (gost_kdftree2012_256(keys, 64, inkey, 32, (const unsigned char *)"kdf tree", 8, kdf_seed, 8, 1) <= 0)
165 mac_key = EVP_PKEY_new_mac_key(nid, NULL, keys+32, 32);
170 if (EVP_DigestInit_ex(omac_ctx, md, NULL) <= 0 ||
171 EVP_DigestSignInit(omac_ctx, NULL, md, NULL, mac_key) <= 0)
174 memcpy(outkey, keys, 32);
178 EVP_PKEY_free(mac_key);
179 OPENSSL_cleanse(keys, sizeof(keys));
184 int init_zero_kdf_seed(unsigned char *kdf_seed)
186 int is_zero_kdfseed = 1, i;
187 for (i = 0; i < 8; i++) {
188 if (kdf_seed[i] != 0)
192 return is_zero_kdfseed ? RAND_bytes(kdf_seed, 8) : 1;