]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_gost2015.c
GOST CMS encryption implementation.
[openssl-gost/engine.git] / gost_gost2015.c
1 #include "gost_lcl.h"
2 #include "gost_gost2015.h"
3 #include "e_gost_err.h"
4 #include <string.h>
5 #include <openssl/rand.h>
6
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,
10                                 unsigned char *out,
11                                 const unsigned char *in,
12                                 size_t inl))
13 {
14   unsigned char calculated_mac[KUZNYECHIK_MAC_MAX_SIZE];
15   memset(calculated_mac, 0, KUZNYECHIK_MAC_MAX_SIZE);
16
17   if (EVP_CIPHER_CTX_encrypting(ctx)) {
18     EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size);
19
20     if (do_cipher(ctx, encrypted_mac, calculated_mac, mac_size) <= 0) {
21         return -1;
22     }
23   } else {
24     unsigned char expected_mac[KUZNYECHIK_MAC_MAX_SIZE];
25
26     memset(expected_mac, 0, KUZNYECHIK_MAC_MAX_SIZE);
27     EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size);
28
29     if (do_cipher(ctx, expected_mac, encrypted_mac, mac_size) <= 0) {
30         return -1;
31     }
32
33     if (CRYPTO_memcmp(expected_mac, calculated_mac, mac_size) != 0)
34       return -1;
35   }
36   return 0;
37 }
38
39 /*
40  * UKM = iv|kdf_seed
41  * */
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)
46 {
47   int iv_len = 16;
48   GOST2015_CIPHER_PARAMS *gcp = NULL;
49
50   unsigned char *p = NULL;
51
52   memset(iv, 0, iv_len);
53
54   /* Проверяем тип params */
55   if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
56       GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
57       return 0;
58   }
59
60   p = params->value.sequence->data;
61   /* Извлекаем структуру параметров */
62   gcp = d2i_GOST2015_CIPHER_PARAMS(NULL, (const unsigned char **)&p, params->value.sequence->length);
63   if (gcp == NULL) {
64       GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
65       return 0;
66   }
67
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);
72       return 0;
73   }
74
75   memcpy(iv, gcp->ukm->data, ukm_offset);
76   memcpy(kdf_seed, gcp->ukm->data+ukm_offset, KDF_SEED_SIZE);
77
78   GOST2015_CIPHER_PARAMS_free(gcp);
79   return 1;
80 }
81
82 int gost2015_set_asn1_params(ASN1_TYPE *params,
83   const unsigned char *iv, size_t iv_size, const unsigned char *kdf_seed)
84 {
85   GOST2015_CIPHER_PARAMS *gcp = GOST2015_CIPHER_PARAMS_new();
86   int ret = 0, len = 0;
87
88   ASN1_OCTET_STRING *os = NULL;
89   unsigned char ukm_buf[MAX_GOST2015_UKM_SIZE];
90   unsigned char *buf = NULL;
91
92   if (gcp == NULL) {
93       GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
94       return 0;
95   }
96
97   memcpy(ukm_buf, iv, iv_size);
98   memcpy(ukm_buf+iv_size, kdf_seed, KDF_SEED_SIZE);
99
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);
102       goto end;
103   }
104
105   len = i2d_GOST2015_CIPHER_PARAMS(gcp, &buf);
106
107   if (len <= 0
108       || (os = ASN1_OCTET_STRING_new()) == NULL
109       || ASN1_OCTET_STRING_set(os, buf, len) == 0) {
110       goto end;
111   }
112
113   ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
114   ret = 1;
115
116 end:
117   OPENSSL_free(buf);
118   if (ret <= 0 && os)
119     ASN1_OCTET_STRING_free(os);
120
121   GOST2015_CIPHER_PARAMS_free(gcp);
122   return ret;
123 }
124
125 int gost2015_process_unprotected_attributes(STACK_OF(X509_ATTRIBUTE) *attrs,
126             int encryption, size_t mac_len, unsigned char *final_tag)
127 {
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);
131
132     if (!osExpectedMac || osExpectedMac->length != (int)mac_len)
133       return -1;
134
135     memcpy(final_tag, osExpectedMac->data, osExpectedMac->length);
136   } else {
137     if (attrs == NULL)
138       return -1;
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;
141   }
142   return 1;
143 }
144
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)
148 {
149   int ret = 0;
150   unsigned char keys[64];
151   const EVP_MD *md = EVP_get_digestbynid(nid);
152   EVP_PKEY *mac_key;
153
154   if (md == NULL)
155     return 0;
156
157   if (enc) {
158     if (RAND_bytes(kdf_seed, 8) != 1)
159       return 0;
160   }
161
162   if (gost_kdftree2012_256(keys, 64, inkey, 32, (const unsigned char *)"kdf tree", 8, kdf_seed, 8, 1) <= 0)
163     return 0;
164
165   mac_key = EVP_PKEY_new_mac_key(nid, NULL, keys+32, 32);
166
167   if (mac_key == NULL)
168     goto end;
169
170   if (EVP_DigestInit_ex(omac_ctx, md, NULL) <= 0 ||
171       EVP_DigestSignInit(omac_ctx, NULL, md, NULL, mac_key) <= 0)
172        goto end;
173
174   memcpy(outkey, keys, 32);
175
176   ret = 1;
177 end:
178   EVP_PKEY_free(mac_key);
179   OPENSSL_cleanse(keys, sizeof(keys));
180
181   return ret;
182 }
183
184 int init_zero_kdf_seed(unsigned char *kdf_seed)
185 {
186   int is_zero_kdfseed = 1, i;
187   for (i = 0; i < 8; i++) {
188     if (kdf_seed[i] != 0)
189       is_zero_kdfseed = 0;
190   }
191
192   return is_zero_kdfseed ? RAND_bytes(kdf_seed, 8) : 1;
193 }