1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
#include "gost_lcl.h"
#include "gost_gost2015.h"
#include "e_gost_err.h"
#include <string.h>
int gost2015_final_call(EVP_CIPHER_CTX *ctx, EVP_MD_CTX *omac_ctx, size_t mac_size,
unsigned char *encrypted_mac,
int (*do_cipher) (EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl))
{
unsigned char calculated_mac[KUZNYECHIK_MAC_MAX_SIZE];
memset(calculated_mac, 0, KUZNYECHIK_MAC_MAX_SIZE);
if (EVP_CIPHER_CTX_encrypting(ctx)) {
EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size);
if (do_cipher(ctx, encrypted_mac, calculated_mac, mac_size) <= 0) {
return -1;
}
} else {
unsigned char expected_mac[KUZNYECHIK_MAC_MAX_SIZE];
memset(expected_mac, 0, KUZNYECHIK_MAC_MAX_SIZE);
EVP_DigestSignFinal(omac_ctx, calculated_mac, &mac_size);
if (do_cipher(ctx, expected_mac, encrypted_mac, mac_size) <= 0) {
return -1;
}
if (CRYPTO_memcmp(expected_mac, calculated_mac, mac_size) != 0)
return -1;
}
return 0;
}
/*
* UKM = iv|kdf_seed
* */
#define MAX_GOST2015_UKM_SIZE 16
#define KDF_SEED_SIZE 8
int gost2015_get_asn1_params(const ASN1_TYPE *params, size_t ukm_size,
unsigned char *iv, size_t ukm_offset, unsigned char *kdf_seed)
{
int iv_len = 16;
GOST2015_CIPHER_PARAMS *gcp = NULL;
unsigned char *p = NULL;
memset(iv, 0, iv_len);
/* Проверяем тип params */
if (ASN1_TYPE_get(params) != V_ASN1_SEQUENCE) {
GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
return 0;
}
p = params->value.sequence->data;
/* Извлекаем структуру параметров */
gcp = d2i_GOST2015_CIPHER_PARAMS(NULL, (const unsigned char **)&p, params->value.sequence->length);
if (gcp == NULL) {
GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
return 0;
}
/* Проверяем длину синхропосылки */
if (gcp->ukm->length != (int)ukm_size) {
GOSTerr(GOST_F_GOST2015_GET_ASN1_PARAMS, GOST_R_INVALID_CIPHER_PARAMS);
GOST2015_CIPHER_PARAMS_free(gcp);
return 0;
}
memcpy(iv, gcp->ukm->data, ukm_offset);
memcpy(kdf_seed, gcp->ukm->data+ukm_offset, KDF_SEED_SIZE);
GOST2015_CIPHER_PARAMS_free(gcp);
return 1;
}
int gost2015_set_asn1_params(ASN1_TYPE *params,
const unsigned char *iv, size_t iv_size, const unsigned char *kdf_seed)
{
GOST2015_CIPHER_PARAMS *gcp = GOST2015_CIPHER_PARAMS_new();
int ret = 0, len = 0;
ASN1_OCTET_STRING *os = NULL;
unsigned char ukm_buf[MAX_GOST2015_UKM_SIZE];
unsigned char *buf = NULL;
if (gcp == NULL) {
GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(ukm_buf, iv, iv_size);
memcpy(ukm_buf+iv_size, kdf_seed, KDF_SEED_SIZE);
if (ASN1_STRING_set(gcp->ukm, ukm_buf, iv_size + KDF_SEED_SIZE) == 0) {
GOSTerr(GOST_F_GOST2015_SET_ASN1_PARAMS, ERR_R_MALLOC_FAILURE);
goto end;
}
len = i2d_GOST2015_CIPHER_PARAMS(gcp, &buf);
if (len <= 0
|| (os = ASN1_OCTET_STRING_new()) == NULL
|| ASN1_OCTET_STRING_set(os, buf, len) == 0) {
goto end;
}
ASN1_TYPE_set(params, V_ASN1_SEQUENCE, os);
ret = 1;
end:
OPENSSL_free(buf);
if (ret <= 0 && os)
ASN1_OCTET_STRING_free(os);
GOST2015_CIPHER_PARAMS_free(gcp);
return ret;
}
|