gost_eng.c revision 272461
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"
18static const char *engine_gost_id = "gost";
19static const char *engine_gost_name = "Reference implementation of GOST engine";
20
21/* Symmetric cipher and digest function registrar */
22
23static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
24	const int **nids, int nid);
25
26static int gost_digests(ENGINE *e, const EVP_MD **digest,
27	const int **nids, int ind);
28
29static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
30	const int **nids, int nid);
31
32static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
33	const int **nids, int nid);
34
35static int gost_cipher_nids[] =
36    {NID_id_Gost28147_89, NID_gost89_cnt,0};
37
38static int gost_digest_nids[] =
39	{NID_id_GostR3411_94,NID_id_Gost28147_89_MAC, 0};
40
41static int gost_pkey_meth_nids[] =
42	{NID_id_GostR3410_94,
43	 NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0};
44
45static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
46	 *pmeth_GostR3410_2001 = NULL,
47	*pmeth_Gost28147_MAC = NULL;
48
49static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
50	*ameth_GostR3410_2001 = NULL,
51	*ameth_Gost28147_MAC = NULL;
52
53
54static int gost_engine_init(ENGINE *e)
55	{
56	return 1;
57	}
58
59static int gost_engine_finish(ENGINE *e)
60	{
61	return 1;
62	}
63
64static 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
77static 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
164IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
165IMPLEMENT_DYNAMIC_CHECK_FN()
166#endif  /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
167
168static 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
194static 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
220static 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
241static 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
263static 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
276void 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