1 /**********************************************************************
2 * gost_eng.c *
3 * Copyright (c) 2005-2006 Cryptocom LTD *
4 * This file is distributed under the same license as OpenSSL *
5 * *
6 * Main file of GOST engine *
7 * for OpenSSL *
8 * Requires OpenSSL 0.9.9 for compilation *
9 **********************************************************************/
10 #include <string.h>
11 #include <openssl/crypto.h>
12 #include <openssl/err.h>
13 #include <openssl/evp.h>
14 #include <openssl/engine.h>
15 #include <openssl/obj_mac.h>
16 #include "e_gost_err.h"
17 #include "gost_lcl.h"
18 static const char *engine_gost_id = "gost";
19 static const char *engine_gost_name =
20 "Reference implementation of GOST engine";
21
22 /* Symmetric cipher and digest function registrar */
23
24 static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
25 const int **nids, int nid);
26
27 static int gost_digests(ENGINE *e, const EVP_MD **digest,
28 const int **nids, int ind);
29
30 static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
31 const int **nids, int nid);
32
33 static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
34 const int **nids, int nid);
35
36 static int gost_cipher_nids[] = { NID_id_Gost28147_89, NID_gost89_cnt, 0 };
37
38 static int gost_digest_nids[] =
39 { NID_id_GostR3411_94, NID_id_Gost28147_89_MAC, 0 };
40
41 static int gost_pkey_meth_nids[] = { NID_id_GostR3410_94,
42 NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0
43 };
44
45 static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
46 *pmeth_GostR3410_2001 = NULL, *pmeth_Gost28147_MAC = NULL;
47
48 static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
49 *ameth_GostR3410_2001 = NULL, *ameth_Gost28147_MAC = NULL;
50
gost_engine_init(ENGINE * e)51 static int gost_engine_init(ENGINE *e)
52 {
53 return 1;
54 }
55
gost_engine_finish(ENGINE * e)56 static int gost_engine_finish(ENGINE *e)
57 {
58 return 1;
59 }
60
gost_engine_destroy(ENGINE * e)61 static int gost_engine_destroy(ENGINE *e)
62 {
63 gost_param_free();
64
65 pmeth_GostR3410_94 = NULL;
66 pmeth_GostR3410_2001 = NULL;
67 pmeth_Gost28147_MAC = NULL;
68 ameth_GostR3410_94 = NULL;
69 ameth_GostR3410_2001 = NULL;
70 ameth_Gost28147_MAC = NULL;
71 return 1;
72 }
73
bind_gost(ENGINE * e,const char * id)74 static int bind_gost(ENGINE *e, const char *id)
75 {
76 int ret = 0;
77 if (id && strcmp(id, engine_gost_id))
78 return 0;
79 if (ameth_GostR3410_94) {
80 printf("GOST engine already loaded\n");
81 goto end;
82 }
83
84 if (!ENGINE_set_id(e, engine_gost_id)) {
85 printf("ENGINE_set_id failed\n");
86 goto end;
87 }
88 if (!ENGINE_set_name(e, engine_gost_name)) {
89 printf("ENGINE_set_name failed\n");
90 goto end;
91 }
92 if (!ENGINE_set_digests(e, gost_digests)) {
93 printf("ENGINE_set_digests failed\n");
94 goto end;
95 }
96 if (!ENGINE_set_ciphers(e, gost_ciphers)) {
97 printf("ENGINE_set_ciphers failed\n");
98 goto end;
99 }
100 if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) {
101 printf("ENGINE_set_pkey_meths failed\n");
102 goto end;
103 }
104 if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) {
105 printf("ENGINE_set_pkey_asn1_meths failed\n");
106 goto end;
107 }
108 /* Control function and commands */
109 if (!ENGINE_set_cmd_defns(e, gost_cmds)) {
110 fprintf(stderr, "ENGINE_set_cmd_defns failed\n");
111 goto end;
112 }
113 if (!ENGINE_set_ctrl_function(e, gost_control_func)) {
114 fprintf(stderr, "ENGINE_set_ctrl_func failed\n");
115 goto end;
116 }
117 if (!ENGINE_set_destroy_function(e, gost_engine_destroy)
118 || !ENGINE_set_init_function(e, gost_engine_init)
119 || !ENGINE_set_finish_function(e, gost_engine_finish)) {
120 goto end;
121 }
122
123 if (!register_ameth_gost
124 (NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94",
125 "GOST R 34.10-94"))
126 goto end;
127 if (!register_ameth_gost
128 (NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001",
129 "GOST R 34.10-2001"))
130 goto end;
131 if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC,
132 "GOST-MAC", "GOST 28147-89 MAC"))
133 goto end;
134
135 if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0))
136 goto end;
137 if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0))
138 goto end;
139 if (!register_pmeth_gost
140 (NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0))
141 goto end;
142 if (!ENGINE_register_ciphers(e)
143 || !ENGINE_register_digests(e)
144 || !ENGINE_register_pkey_meths(e)
145 /* These two actually should go in LIST_ADD command */
146 || !EVP_add_cipher(&cipher_gost)
147 || !EVP_add_cipher(&cipher_gost_cpacnt)
148 || !EVP_add_digest(&digest_gost)
149 || !EVP_add_digest(&imit_gost_cpa)
150 ) {
151 goto end;
152 }
153
154 ERR_load_GOST_strings();
155 ret = 1;
156 end:
157 return ret;
158 }
159
160 #ifndef OPENSSL_NO_DYNAMIC_ENGINE
161 IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
IMPLEMENT_DYNAMIC_CHECK_FN()162 IMPLEMENT_DYNAMIC_CHECK_FN()
163 #endif /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
164 static int gost_digests(ENGINE *e, const EVP_MD **digest,
165 const int **nids, int nid)
166 {
167 int ok = 1;
168 if (!digest) {
169 *nids = gost_digest_nids;
170 return 2;
171 }
172 /*
173 * printf("Digest no %d requested\n",nid);
174 */
175 if (nid == NID_id_GostR3411_94) {
176 *digest = &digest_gost;
177 } else if (nid == NID_id_Gost28147_89_MAC) {
178 *digest = &imit_gost_cpa;
179 } else {
180 ok = 0;
181 *digest = NULL;
182 }
183 return ok;
184 }
185
gost_ciphers(ENGINE * e,const EVP_CIPHER ** cipher,const int ** nids,int nid)186 static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
187 const int **nids, int nid)
188 {
189 int ok = 1;
190 if (!cipher) {
191 *nids = gost_cipher_nids;
192 return 2; /* two ciphers are supported */
193 }
194
195 if (nid == NID_id_Gost28147_89) {
196 *cipher = &cipher_gost;
197 } else if (nid == NID_gost89_cnt) {
198 *cipher = &cipher_gost_cpacnt;
199 } else {
200 ok = 0;
201 *cipher = NULL;
202 }
203 return ok;
204 }
205
gost_pkey_meths(ENGINE * e,EVP_PKEY_METHOD ** pmeth,const int ** nids,int nid)206 static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
207 const int **nids, int nid)
208 {
209 if (!pmeth) {
210 *nids = gost_pkey_meth_nids;
211 return 3;
212 }
213
214 switch (nid) {
215 case NID_id_GostR3410_94:
216 *pmeth = pmeth_GostR3410_94;
217 return 1;
218 case NID_id_GostR3410_2001:
219 *pmeth = pmeth_GostR3410_2001;
220 return 1;
221 case NID_id_Gost28147_89_MAC:
222 *pmeth = pmeth_Gost28147_MAC;
223 return 1;
224 default:;
225 }
226
227 *pmeth = NULL;
228 return 0;
229 }
230
gost_pkey_asn1_meths(ENGINE * e,EVP_PKEY_ASN1_METHOD ** ameth,const int ** nids,int nid)231 static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
232 const int **nids, int nid)
233 {
234 if (!ameth) {
235 *nids = gost_pkey_meth_nids;
236 return 3;
237 }
238 switch (nid) {
239 case NID_id_GostR3410_94:
240 *ameth = ameth_GostR3410_94;
241 return 1;
242 case NID_id_GostR3410_2001:
243 *ameth = ameth_GostR3410_2001;
244 return 1;
245 case NID_id_Gost28147_89_MAC:
246 *ameth = ameth_Gost28147_MAC;
247 return 1;
248
249 default:;
250 }
251
252 *ameth = NULL;
253 return 0;
254 }
255
256 #ifdef OPENSSL_NO_DYNAMIC_ENGINE
engine_gost(void)257 static ENGINE *engine_gost(void)
258 {
259 ENGINE *ret = ENGINE_new();
260 if (!ret)
261 return NULL;
262 if (!bind_gost(ret, engine_gost_id)) {
263 ENGINE_free(ret);
264 return NULL;
265 }
266 return ret;
267 }
268
ENGINE_load_gost(void)269 void ENGINE_load_gost(void)
270 {
271 ENGINE *toadd;
272 if (pmeth_GostR3410_94)
273 return;
274 toadd = engine_gost();
275 if (!toadd)
276 return;
277 ENGINE_add(toadd);
278 ENGINE_free(toadd);
279 ERR_clear_error();
280 }
281 #endif
282