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