]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_keyexpimp.c
GOST Kexp + test
[openssl-gost/engine.git] / gost_keyexpimp.c
1 #include <string.h>
2 #include <openssl/evp.h>
3
4 #include "gost_lcl.h"
5 #include "e_gost_err.h"
6
7 /*
8  * Function expects that out is a preallocated buffer of length
9  * defined as sum of shared_len and mac length defined by mac_nid
10  * */
11 int gost_kexp15(const unsigned char *shared_key, const int shared_len,
12                 int cipher_nid, const unsigned char *cipher_key,
13                 const size_t cipher_key_len, int mac_nid,
14                 unsigned char *mac_key, const size_t mac_key_len,
15                 const unsigned char *iv, const size_t ivlen, unsigned char *out,
16                 int *out_len)
17 {
18     /* out_len = key_len + mac_len */
19     unsigned char iv_full[16], mac_buf[16];
20     unsigned int mac_len;
21
22     EVP_CIPHER_CTX *ciph = NULL;
23     EVP_MD_CTX *mac = NULL;
24
25     int ret = 0;
26     int len;
27
28     mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
29         (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
30
31     if (mac_len == 0) {
32         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
33         goto err;
34     }
35
36     /* we expect IV of half length */
37     memset(iv_full, 0, 16);
38     memcpy(iv_full, iv, ivlen);
39
40     mac = EVP_MD_CTX_new();
41     if (mac == NULL) {
42         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
43         goto err;
44     }
45
46     if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
47         || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, mac_key_len, mac_key) <= 0
48         || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_MAC_LEN, mac_len, NULL) <= 0
49         || EVP_DigestUpdate(mac, iv, ivlen) <= 0
50         || EVP_DigestUpdate(mac, shared_key, shared_len) <= 0
51         /* As we set MAC length directly, we should not allow overwriting it */
52         || EVP_DigestFinal_ex(mac, mac_buf, NULL) <= 0) {
53         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
54         goto err;
55     }
56
57     ciph = EVP_CIPHER_CTX_new();
58     if (ciph == NULL) {
59         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
60         goto err;
61     }
62
63     if (EVP_CipherInit_ex
64         (ciph, EVP_get_cipherbynid(cipher_nid), NULL, NULL, NULL, 1) <= 0
65         || EVP_CipherInit_ex(ciph, NULL, NULL, cipher_key, iv_full, 1) <= 0
66         || EVP_CipherUpdate(ciph, out, &len, shared_key, shared_len) <= 0
67         || EVP_CipherUpdate(ciph, out + shared_len, &len, mac_buf, mac_len) <= 0
68         || EVP_CipherFinal_ex(ciph, out + shared_len + len, out_len) <= 0) {
69         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
70         goto err;
71     }
72
73     *out_len = shared_len + mac_len;
74
75     ret = 1;
76
77  err:
78     /* TODO clear mac_buf */
79     EVP_MD_CTX_free(mac);
80     EVP_CIPHER_CTX_free(ciph);
81
82     return ret;
83 }
84
85 int gost_kimp15(const char *expkey, const size_t expkeylen,
86                 int cipher_nid, const char *cipher_key,
87                 const size_t cipher_key_len, int mac_nid, const char *mac_key,
88                 const size_t mac_key_len, const char *iv, const size_t ivlen,
89                 char *shared_key, size_t *shared_len)
90 {
91     return 0;
92 }
93
94 /*
95  * keyout expected to be 64 bytes
96  * */
97 int gost_keg(const unsigned char *seckey, const size_t seckey_len,
98              const EC_POINT *pub, const unsigned char *h, unsigned char *keyout)
99 {
100     return 0;
101 }
102
103 #ifdef ENABLE_UNIT_TESTS
104 # include <stdio.h>
105 # include <string.h>
106 # include <openssl/obj_mac.h>
107
108 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
109 {
110     int n = 0;
111
112     fprintf(f, "%s", title);
113     for (; n < l; ++n) {
114         if ((n % 16) == 0)
115             fprintf(f, "\n%04x", n);
116         fprintf(f, " %02x", s[n]);
117     }
118     fprintf(f, "\n");
119 }
120
121 int main(void)
122 {
123     const unsigned char key[] = {
124         0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
125         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
126         0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
127         0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
128     };
129
130     const unsigned char magma_key[] = {
131         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
132         0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
133         0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
134         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
135     };
136
137     unsigned char mac_magma_key[] = {
138         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
139         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
140         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
141         0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
142     };
143
144     const unsigned char magma_iv[] = { 0x67, 0xBE, 0xD6, 0x54 };
145
146     const unsigned char magma_export[] =
147         { 0xCF, 0xD5, 0xA1, 0x2D, 0x5B, 0x81, 0xB6, 0xE1, 0xE9, 0x9C, 0x91,
148 0x6D, 0x07, 0x90, 0x0C, 0x6A,
149         0xC1, 0x27, 0x03, 0xFB, 0x3A, 0xBD, 0xED, 0x55, 0x56, 0x7B, 0xF3, 0x74,
150             0x2C, 0x89, 0x9C, 0x75,
151         0x5D, 0xAF, 0xE7, 0xB4, 0x2E, 0x3A, 0x8B, 0xD9
152     };
153
154     unsigned char buf[32 + 16];
155     int ret = 0;
156     int outlen = 40;
157
158     OpenSSL_add_all_algorithms();
159     memset(buf, 0, sizeof(buf));
160
161     ret = gost_kexp15(key, 32,
162                       NID_magma_ctr, magma_key, 32,
163                       NID_magma_mac, mac_magma_key, 32,
164                       magma_iv, 4, buf, &outlen);
165
166     if (ret <= 0)
167         ERR_print_errors_fp(stderr);
168     else {
169         hexdump(stdout, "Magma key export", buf, 40);
170         if (memcmp(buf, magma_export, 40) != 0) {
171             fprintf(stdout, "ERROR! test failed\n");
172         }
173     }
174
175     return 0;
176 }
177
178 #endif