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