]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_gost2015.c
Fix code formating.
[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(
126     STACK_OF(X509_ATTRIBUTE) *attrs,
127     int encryption, size_t mac_len, unsigned char *final_tag)
128 {
129     if (encryption == 0) /*Decrypting*/ {
130         ASN1_OCTET_STRING *osExpectedMac = X509at_get0_data_by_OBJ(attrs,
131             OBJ_txt2obj(OID_GOST_CMS_MAC, 1), -3, V_ASN1_OCTET_STRING);
132
133         if (!osExpectedMac || osExpectedMac->length != (int)mac_len)
134             return -1;
135
136         memcpy(final_tag, osExpectedMac->data, osExpectedMac->length);
137     } else {
138         if (attrs == NULL)
139             return -1;
140         return (X509at_add1_attr_by_OBJ(&attrs,
141                OBJ_txt2obj(OID_GOST_CMS_MAC, 1),
142                V_ASN1_OCTET_STRING, final_tag,
143                mac_len) == NULL) ? -1 : 1;
144     }
145     return 1;
146 }
147
148 int gost2015_acpkm_omac_init(int nid, int enc, const unsigned char *inkey,
149                              EVP_MD_CTX *omac_ctx,
150                              unsigned char *outkey, unsigned char *kdf_seed)
151 {
152     int ret = 0;
153     unsigned char keys[64];
154     const EVP_MD *md = EVP_get_digestbynid(nid);
155     EVP_PKEY *mac_key;
156
157     if (md == NULL)
158         return 0;
159
160     if (enc) {
161         if (RAND_bytes(kdf_seed, 8) != 1)
162             return 0;
163     }
164
165     if (gost_kdftree2012_256(keys, 64, inkey, 32,
166        (const unsigned char *)"kdf tree", 8, kdf_seed, 8, 1) <= 0)
167         return 0;
168
169     mac_key = EVP_PKEY_new_mac_key(nid, NULL, keys+32, 32);
170
171     if (mac_key == NULL)
172         goto end;
173
174     if (EVP_DigestInit_ex(omac_ctx, md, NULL) <= 0 ||
175        EVP_DigestSignInit(omac_ctx, NULL, md, NULL, mac_key) <= 0)
176         goto end;
177
178     memcpy(outkey, keys, 32);
179
180     ret = 1;
181 end:
182     EVP_PKEY_free(mac_key);
183     OPENSSL_cleanse(keys, sizeof(keys));
184
185     return ret;
186 }
187
188 int init_zero_kdf_seed(unsigned char *kdf_seed)
189 {
190     int is_zero_kdfseed = 1, i;
191     for (i = 0; i < 8; i++) {
192         if (kdf_seed[i] != 0)
193             is_zero_kdfseed = 0;
194     }
195
196     return is_zero_kdfseed ? RAND_bytes(kdf_seed, 8) : 1;
197 }