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