gost_eng.c revision 238384
1238384Sjkim/**********************************************************************
2238384Sjkim *                          gost_eng.c                                *
3238384Sjkim *             Copyright (c) 2005-2006 Cryptocom LTD                  *
4238384Sjkim *         This file is distributed under the same license as OpenSSL *
5238384Sjkim *                                                                    *
6238384Sjkim *              Main file of GOST engine                              *
7238384Sjkim *       for OpenSSL                                                  *
8238384Sjkim *          Requires OpenSSL 0.9.9 for compilation                    *
9238384Sjkim **********************************************************************/
10238384Sjkim#include <string.h>
11238384Sjkim#include <openssl/crypto.h>
12238384Sjkim#include <openssl/err.h>
13238384Sjkim#include <openssl/evp.h>
14238384Sjkim#include <openssl/engine.h>
15238384Sjkim#include <openssl/obj_mac.h>
16238384Sjkim#include "e_gost_err.h"
17238384Sjkim#include "gost_lcl.h"
18238384Sjkimstatic const char *engine_gost_id = "gost";
19238384Sjkimstatic const char *engine_gost_name = "Reference implementation of GOST engine";
20238384Sjkim
21238384Sjkim/* Symmetric cipher and digest function registrar */
22238384Sjkim
23238384Sjkimstatic int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
24238384Sjkim	const int **nids, int nid);
25238384Sjkim
26238384Sjkimstatic int gost_digests(ENGINE *e, const EVP_MD **digest,
27238384Sjkim	const int **nids, int ind);
28238384Sjkim
29238384Sjkimstatic int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
30238384Sjkim	const int **nids, int nid);
31238384Sjkim
32238384Sjkimstatic int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
33238384Sjkim	const int **nids, int nid);
34238384Sjkim
35238384Sjkimstatic int gost_cipher_nids[] =
36238384Sjkim    {NID_id_Gost28147_89, NID_gost89_cnt,0};
37238384Sjkim
38238384Sjkimstatic int gost_digest_nids[] =
39238384Sjkim	{NID_id_GostR3411_94,NID_id_Gost28147_89_MAC, 0};
40238384Sjkim
41238384Sjkimstatic int gost_pkey_meth_nids[] =
42238384Sjkim	{NID_id_GostR3410_94,
43238384Sjkim	 NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0};
44238384Sjkim
45238384Sjkimstatic EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
46238384Sjkim	 *pmeth_GostR3410_2001 = NULL,
47238384Sjkim	*pmeth_Gost28147_MAC = NULL;
48238384Sjkim
49238384Sjkimstatic EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
50238384Sjkim	*ameth_GostR3410_2001 = NULL,
51238384Sjkim	*ameth_Gost28147_MAC = NULL;
52238384Sjkim
53238384Sjkim
54238384Sjkimstatic int gost_engine_init(ENGINE *e)
55238384Sjkim	{
56238384Sjkim	return 1;
57238384Sjkim	}
58238384Sjkim
59238384Sjkimstatic int gost_engine_finish(ENGINE *e)
60238384Sjkim	{
61238384Sjkim	return 1;
62238384Sjkim	}
63238384Sjkim
64238384Sjkimstatic int gost_engine_destroy(ENGINE *e)
65238384Sjkim	{
66238384Sjkim	gost_param_free();
67238384Sjkim	return 1;
68238384Sjkim	}
69238384Sjkim
70238384Sjkimstatic int bind_gost (ENGINE *e,const char *id)
71238384Sjkim	{
72238384Sjkim	int ret = 0;
73238384Sjkim	if (id && strcmp(id, engine_gost_id)) return 0;
74238384Sjkim
75238384Sjkim	if (!ENGINE_set_id(e, engine_gost_id))
76238384Sjkim		{
77238384Sjkim		printf("ENGINE_set_id failed\n");
78238384Sjkim		goto end;
79238384Sjkim		}
80238384Sjkim	if (!ENGINE_set_name(e, engine_gost_name))
81238384Sjkim		{
82238384Sjkim		printf("ENGINE_set_name failed\n");
83238384Sjkim		goto end;
84238384Sjkim		}
85238384Sjkim	if (!ENGINE_set_digests(e, gost_digests))
86238384Sjkim		{
87238384Sjkim		printf("ENGINE_set_digests failed\n");
88238384Sjkim		goto end;
89238384Sjkim		}
90238384Sjkim	if (! ENGINE_set_ciphers(e, gost_ciphers))
91238384Sjkim		{
92238384Sjkim		printf("ENGINE_set_ciphers failed\n");
93238384Sjkim		goto end;
94238384Sjkim		}
95238384Sjkim	if (! ENGINE_set_pkey_meths(e, gost_pkey_meths))
96238384Sjkim		{
97238384Sjkim		printf("ENGINE_set_pkey_meths failed\n");
98238384Sjkim		goto end;
99238384Sjkim		}
100238384Sjkim	if (! ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths))
101238384Sjkim		{
102238384Sjkim		printf("ENGINE_set_pkey_asn1_meths failed\n");
103238384Sjkim		goto end;
104238384Sjkim		}
105238384Sjkim	/* Control function and commands */
106238384Sjkim	if (!ENGINE_set_cmd_defns(e,gost_cmds))
107238384Sjkim		{
108238384Sjkim		fprintf(stderr,"ENGINE_set_cmd_defns failed\n");
109238384Sjkim		goto end;
110238384Sjkim		}
111238384Sjkim	if (!ENGINE_set_ctrl_function(e,gost_control_func))
112238384Sjkim		{
113238384Sjkim		fprintf(stderr,"ENGINE_set_ctrl_func failed\n");
114238384Sjkim		goto end;
115238384Sjkim		}
116238384Sjkim	if ( ! ENGINE_set_destroy_function(e, gost_engine_destroy)
117238384Sjkim		|| ! ENGINE_set_init_function(e,gost_engine_init)
118238384Sjkim		|| ! ENGINE_set_finish_function(e,gost_engine_finish))
119238384Sjkim		{
120238384Sjkim		goto end;
121238384Sjkim		}
122238384Sjkim
123238384Sjkim	if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end;
124238384Sjkim	if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end;
125238384Sjkim	if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC,
126238384Sjkim		"GOST-MAC", "GOST 28147-89 MAC")) goto end;
127238384Sjkim
128238384Sjkim	if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end;
129238384Sjkim	if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end;
130238384Sjkim	if (!register_pmeth_gost(NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0))
131238384Sjkim		goto end;
132238384Sjkim	if ( ! ENGINE_register_ciphers(e)
133238384Sjkim		|| ! ENGINE_register_digests(e)
134238384Sjkim		|| ! ENGINE_register_pkey_meths(e)
135238384Sjkim		/* These two actually should go in LIST_ADD command */
136238384Sjkim		|| ! EVP_add_cipher(&cipher_gost)
137238384Sjkim		|| ! EVP_add_cipher(&cipher_gost_cpacnt)
138238384Sjkim		|| ! EVP_add_digest(&digest_gost)
139238384Sjkim		|| ! EVP_add_digest(&imit_gost_cpa)
140238384Sjkim		)
141238384Sjkim		{
142238384Sjkim		goto end;
143238384Sjkim		}
144238384Sjkim
145238384Sjkim	ERR_load_GOST_strings();
146238384Sjkim	ret = 1;
147238384Sjkim	end:
148238384Sjkim	return ret;
149238384Sjkim	}
150238384Sjkim
151238384Sjkim#ifndef OPENSSL_NO_DYNAMIC_ENGINE
152238384SjkimIMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
153238384SjkimIMPLEMENT_DYNAMIC_CHECK_FN()
154238384Sjkim#endif  /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
155238384Sjkim
156238384Sjkimstatic int gost_digests(ENGINE *e, const EVP_MD **digest,
157238384Sjkim	const int **nids, int nid)
158238384Sjkim	{
159238384Sjkim	int ok =1 ;
160238384Sjkim	if (!digest)
161238384Sjkim		{
162238384Sjkim		*nids = gost_digest_nids;
163238384Sjkim		return 2;
164238384Sjkim		}
165238384Sjkim	/*printf("Digest no %d requested\n",nid);*/
166238384Sjkim	if(nid == NID_id_GostR3411_94)
167238384Sjkim		{
168238384Sjkim		*digest = &digest_gost;
169238384Sjkim		}
170238384Sjkim	else if (nid == NID_id_Gost28147_89_MAC)
171238384Sjkim		{
172238384Sjkim		*digest = &imit_gost_cpa;
173238384Sjkim		}
174238384Sjkim	else
175238384Sjkim		{
176238384Sjkim		ok =0;
177238384Sjkim		*digest = NULL;
178238384Sjkim		}
179238384Sjkim	return ok;
180238384Sjkim	}
181238384Sjkim
182238384Sjkimstatic int gost_ciphers (ENGINE *e,const EVP_CIPHER **cipher,
183238384Sjkim	const int **nids, int nid)
184238384Sjkim	{
185238384Sjkim	int ok = 1;
186238384Sjkim	if (!cipher)
187238384Sjkim		{
188238384Sjkim		*nids = gost_cipher_nids;
189238384Sjkim		return 2; /* two ciphers are supported */
190238384Sjkim		}
191238384Sjkim
192238384Sjkim	if(nid == NID_id_Gost28147_89)
193238384Sjkim		{
194238384Sjkim		*cipher = &cipher_gost;
195238384Sjkim		}
196238384Sjkim	else if  (nid == NID_gost89_cnt)
197238384Sjkim		{
198238384Sjkim		*cipher = &cipher_gost_cpacnt;
199238384Sjkim		}
200238384Sjkim	else
201238384Sjkim		{
202238384Sjkim		ok = 0;
203238384Sjkim		*cipher = NULL;
204238384Sjkim		}
205238384Sjkim	return ok;
206238384Sjkim	}
207238384Sjkim
208238384Sjkimstatic int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
209238384Sjkim	const int **nids, int nid)
210238384Sjkim	{
211238384Sjkim	if (!pmeth)
212238384Sjkim		{
213238384Sjkim		*nids = gost_pkey_meth_nids;
214238384Sjkim		return 3;
215238384Sjkim		}
216238384Sjkim
217238384Sjkim	switch (nid)
218238384Sjkim		{
219238384Sjkim		case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
220238384Sjkim		case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
221238384Sjkim		case NID_id_Gost28147_89_MAC: *pmeth = pmeth_Gost28147_MAC; return 1;
222238384Sjkim		default:;
223238384Sjkim		}
224238384Sjkim
225238384Sjkim	*pmeth = NULL;
226238384Sjkim	return 0;
227238384Sjkim	}
228238384Sjkim
229238384Sjkimstatic int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
230238384Sjkim	const int **nids, int nid)
231238384Sjkim	{
232238384Sjkim	if (!ameth)
233238384Sjkim		{
234238384Sjkim		*nids = gost_pkey_meth_nids;
235238384Sjkim		return 3;
236238384Sjkim		}
237238384Sjkim	switch (nid)
238238384Sjkim		{
239238384Sjkim		case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
240238384Sjkim		case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
241238384Sjkim		case NID_id_Gost28147_89_MAC: *ameth = ameth_Gost28147_MAC; return 1;
242238384Sjkim
243238384Sjkim		default:;
244238384Sjkim		}
245238384Sjkim
246238384Sjkim	*ameth = NULL;
247238384Sjkim	return 0;
248238384Sjkim	}
249238384Sjkim
250238384Sjkim#ifdef OPENSSL_NO_DYNAMIC_ENGINE
251238384Sjkimstatic ENGINE *engine_gost(void)
252238384Sjkim	{
253238384Sjkim	ENGINE *ret = ENGINE_new();
254238384Sjkim	if (!ret)
255238384Sjkim		return NULL;
256238384Sjkim	if (!bind_gost(ret,engine_gost_id))
257238384Sjkim		{
258238384Sjkim		ENGINE_free(ret);
259238384Sjkim		return NULL;
260238384Sjkim		}
261238384Sjkim	return ret;
262238384Sjkim	}
263238384Sjkim
264238384Sjkimvoid ENGINE_load_gost(void)
265238384Sjkim	{
266238384Sjkim	ENGINE *toadd =engine_gost();
267238384Sjkim	if (!toadd) return;
268238384Sjkim	ENGINE_add(toadd);
269238384Sjkim	ENGINE_free(toadd);
270238384Sjkim	ERR_clear_error();
271238384Sjkim	}
272238384Sjkim#endif
273238384Sjkim
274