2 * Copyright (c) 2020 Dmitry Belyavskiy <beldmit@gmail.com>
4 * Contents licensed under the terms of the OpenSSL license
5 * See https://www.openssl.org/source/license.html for details
8 #include "gost_gost2015.h"
9 #include "e_gost_err.h"
11 #include <openssl/rand.h>
13 int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size,
14 unsigned char *encrypted_mac,
15 int (*do_cipher) (EVP_CIPHER_CTX *ctx,
17 const unsigned char *in,
20 unsigned char calculated_mac[KUZNYECHIK_MAC_MAX_SIZE];
21 memset(calculated_mac, 0, KUZNYECHIK_MAC_MAX_SIZE);
23 if (EVP_CIPHER_CTX_encrypting(ctx)) {
24 EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size);
26 if (do_cipher(ctx, encrypted_mac, calculated_mac, mac_size) <= 0) {
30 unsigned char expected_mac[KUZNYECHIK_MAC_MAX_SIZE];
32 memset(expected_mac, 0, KUZNYECHIK_MAC_MAX_SIZE);
33 EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size);
35 if (do_cipher(ctx, expected_mac, encrypted_mac, mac_size) <= 0) {
39 if (CRYPTO_memcmp(expected_mac, calculated_mac, mac_size) != 0)
48 #define MAX_GOST2015_UKM_SIZE 16
49 #define KDF_SEED_SIZE 8
50 int gost2015_get_asn1_params(const ASN1_TYPE *params, size_t ukm_size,
51 unsigned char *iv, size_t ukm_offset, unsigned char *kdf_seed)
54 GOST2015_CIPHER_PARAMS *gcp = NULL;
56 unsigned char *p = NULL;
58 memset(iv, 0, iv_len);
60 /* Проверяем тип params */
61 if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
62 GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
66 p = params->value.sequence->data;
67 /* Извлекаем структуру параметров */
68 gcp = d2i_GOST2015_CIPHER_PARAMS(NULL, (const unsigned char **)&p, params->value.sequence->length);
70 GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
74 /* Проверяем длину синхропосылки */
75 if (gcp->ukm->length != (int)ukm_size) {
76 GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
77 GOST2015_CIPHER_PARAMS_free(gcp);
81 memcpy(iv, gcp->ukm->data, ukm_offset);
82 memcpy(kdf_seed, gcp->ukm->data+ukm_offset, KDF_SEED_SIZE);
84 GOST2015_CIPHER_PARAMS_free(gcp);
88 int gost2015_set_asn1_params(ASN1_TYPE *params,
89 const unsigned char *iv, size_t iv_size, const unsigned char *kdf_seed)
91 GOST2015_CIPHER_PARAMS *gcp = GOST2015_CIPHER_PARAMS_new();
94 ASN1_OCTET_STRING *os = NULL;
95 unsigned char ukm_buf[MAX_GOST2015_UKM_SIZE];
96 unsigned char *buf = NULL;
99 GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
103 memcpy(ukm_buf, iv, iv_size);
104 memcpy(ukm_buf+iv_size, kdf_seed, KDF_SEED_SIZE);
106 if (ASN1_STRING_set(gcp->ukm, ukm_buf, iv_size + KDF_SEED_SIZE) == 0) {
107 GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
111 len = i2d_GOST2015_CIPHER_PARAMS(gcp, &buf);
114 || (os = ASN1_OCTET_STRING_new()) == NULL
115 || ASN1_OCTET_STRING_set(os, buf, len) == 0) {
119 ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
125 ASN1_OCTET_STRING_free(os);
127 GOST2015_CIPHER_PARAMS_free(gcp);
131 int gost2015_process_unprotected_attributes(
132 STACK_OF(X509_ATTRIBUTE) *attrs,
133 int encryption, size_t mac_len, unsigned char *final_tag)
135 if (encryption == 0) /*Decrypting*/ {
136 ASN1_OCTET_STRING *osExpectedMac = X509at_get0_data_by_OBJ(attrs,
137 OBJ_txt2obj(OID_GOST_CMS_MAC, 1), -3, V_ASN1_OCTET_STRING);
139 if (!osExpectedMac || osExpectedMac->length != (int)mac_len)
142 memcpy(final_tag, osExpectedMac->data, osExpectedMac->length);
146 return (X509at_add1_attr_by_OBJ(&attrs,
147 OBJ_txt2obj(OID_GOST_CMS_MAC, 1),
148 V_ASN1_OCTET_STRING, final_tag,
149 mac_len) == NULL) ? -1 : 1;
154 int gost2015_acpkm_omac_init(int nid, int enc, const unsigned char *inkey,
155 EVP_MD_CTX *omac_ctx,
156 unsigned char *outkey, unsigned char *kdf_seed)
159 unsigned char keys[64];
160 const EVP_MD *md = EVP_get_digestbynid(nid);
167 if (RAND_bytes(kdf_seed, 8) != 1)
171 if (gost_kdftree2012_256(keys, 64, inkey, 32,
172 (const unsigned char *)"kdf tree", 8, kdf_seed, 8, 1) <= 0)
175 mac_key = EVP_PKEY_new_mac_key(nid, NULL, keys+32, 32);
180 if (EVP_DigestInit_ex(omac_ctx, md, NULL) <= 0 ||
181 EVP_DigestSignInit(omac_ctx, NULL, md, NULL, mac_key) <= 0)
184 memcpy(outkey, keys, 32);
188 EVP_PKEY_free(mac_key);
189 OPENSSL_cleanse(keys, sizeof(keys));
194 int init_zero_kdf_seed(unsigned char *kdf_seed)
196 int is_zero_kdfseed = 1, i;
197 for (i = 0; i < 8; i++) {
198 if (kdf_seed[i] != 0)
202 return is_zero_kdfseed ? RAND_bytes(kdf_seed, 8) : 1;