gost_eng.c 6.6 KB
Newer Older
1
/**********************************************************************
2
 *                          gost_eng.c                                *
3 4 5 6 7 8 9 10 11 12 13 14
 *             Copyright (c) 2005-2006 Cryptocom LTD                  *
 *         This file is distributed under the same license as OpenSSL *
 *                                                                    *
 *              Main file of GOST engine                              *
 *       for OpenSSL                                                  *
 *          Requires OpenSSL 0.9.9 for compilation                    *
 **********************************************************************/
#include <string.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
#include <openssl/obj_mac.h>
#include "e_gost_err.h"
15
#include "gost_lcl.h"
16 17 18 19 20 21
static const char *engine_gost_id = "gost";
static const char *engine_gost_name = "Reference implementation of GOST engine";

/* Symmetric cipher and digest function registrar */

static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
22
	const int **nids, int nid);
23 24

static int gost_digests(ENGINE *e, const EVP_MD **digest,
25
	const int **nids, int ind);
26 27

static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
28
	const int **nids, int nid);
29 30

static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
31
	const int **nids, int nid);
32 33 34 35 36 37 38 39 40

static int gost_cipher_nids[] =
    {NID_id_Gost28147_89, 0};

static int gost_digest_nids[] =
	{NID_id_GostR3411_94, 0};

static int gost_pkey_meth_nids[] = 
	{NID_id_GostR3410_94_cc, NID_id_GostR3410_94, NID_id_GostR3410_2001_cc,
41
	 NID_id_GostR3410_2001, 0};
42 43 44 45 46 47 48 49

static EVP_PKEY_METHOD *pmeth_GostR3410_94_cc = NULL, *pmeth_GostR3410_94 = NULL,
	*pmeth_GostR3410_2001_cc = NULL, *pmeth_GostR3410_2001 = NULL;

static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94_cc = NULL, *ameth_GostR3410_94 = NULL,
	*ameth_GostR3410_2001_cc = NULL, *ameth_GostR3410_2001 = NULL;


50 51
static int gost_engine_init(ENGINE *e)
	{ 
52
	return 1;
53 54 55 56
	}

static int gost_engine_finish(ENGINE *e)
	{ 
57
	return 1;
58
	}
59

60 61
static int gost_engine_destroy(ENGINE *e)
	{ 
62
	return 1;
63
	}
64

65 66
static int bind_gost (ENGINE *e,const char *id) 
	{
67 68 69
	int ret = 0;
	if (id && strcmp(id, engine_gost_id)) return 0;

70 71
	if (!ENGINE_set_id(e, engine_gost_id)) 
		{
72 73
		printf("ENGINE_set_id failed\n"); 
		goto end;
74 75 76
		}	
	if (!ENGINE_set_name(e, engine_gost_name)) 
		{
77 78
		printf("ENGINE_set_name failed\n");
		goto end;
79 80 81
		}	
	if (!ENGINE_set_digests(e, gost_digests)) 
		{
82 83
		printf("ENGINE_set_digests failed\n");
		goto end;
84 85 86
		}	
	if (! ENGINE_set_ciphers(e, gost_ciphers)) 
		{
87 88
		printf("ENGINE_set_ciphers failed\n");
		goto end;
89 90 91
		}	
	if (! ENGINE_set_pkey_meths(e, gost_pkey_meths)) 
		{
92 93
		printf("ENGINE_set_pkey_meths failed\n");
		goto end;
94 95 96
		}	
	if (! ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) 
		{
97 98
		printf("ENGINE_set_pkey_asn1_meths failed\n");
		goto end;
99 100 101 102 103 104 105 106 107 108 109 110
		}	
	/* Control function and commands */
	if (!ENGINE_set_cmd_defns(e,gost_cmds)) 
		{
		fprintf(stderr,"ENGINE_set_cmd_defns failed\n");
		goto end;
		}	
	if (!ENGINE_set_ctrl_function(e,gost_control_func)) 
		{
		fprintf(stderr,"ENGINE_set_ctrl_func failed\n");
		goto end;
		}	
111 112
	if ( ! ENGINE_set_destroy_function(e, gost_engine_destroy)
		|| ! ENGINE_set_init_function(e,gost_engine_init)
113 114 115 116
		|| ! ENGINE_set_finish_function(e,gost_engine_finish))
		{
		goto end;
		}
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

	if (!register_ameth_gost(NID_id_GostR3410_94_cc, &ameth_GostR3410_94_cc, "GOST94CC", "GOST R 34.10-94, Cryptocom LTD implementation")) goto end;
	if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end;
	if (!register_ameth_gost(NID_id_GostR3410_2001_cc, &ameth_GostR3410_2001_cc, "GOST2001CC", "GOST R 34.10-2001, Cryptocom LTD implementation")) goto end;
	if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end;

	if (!register_pmeth_gost(NID_id_GostR3410_94_cc, &pmeth_GostR3410_94_cc, 0)) goto end;
	if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end;
	if (!register_pmeth_gost(NID_id_GostR3410_2001_cc, &pmeth_GostR3410_2001_cc, 0)) goto end;
	if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end;
	if ( ! ENGINE_register_ciphers(e)
		|| ! ENGINE_register_digests(e)
		|| ! ENGINE_register_pkey_meths(e)
		/* These two actually should go in LIST_ADD command */
		|| ! EVP_add_cipher(&cipher_gost)
		|| ! EVP_add_digest(&digest_gost)
133 134 135 136
		)
		{
		goto end;
		}
137 138 139

	ERR_load_GOST_strings();
	ret = 1;
140
	end:
141
	return ret;
142
	}	
143

144
#ifndef OPENSSL_NO_DYNAMIC_ENGINE
145 146
IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
IMPLEMENT_DYNAMIC_CHECK_FN()
147
#endif  /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
148 149

static int gost_digests(ENGINE *e, const EVP_MD **digest,
150 151
	const int **nids, int nid)
	{ 
152
	int ok =1 ;
153 154
	if (!digest) 
		{
155 156
		*nids = gost_digest_nids;
		return 1; 
157
		}
158
	/*printf("Digest no %d requested\n",nid);*/
159 160 161 162 163 164 165 166
	if(nid == NID_id_GostR3411_94) 
		{
		*digest = &digest_gost;
		}
	else 
		{
		ok =0;
		*digest = NULL;
167 168
		}
	return ok;
169
	}	
170 171
	
static int gost_ciphers (ENGINE *e,const EVP_CIPHER **cipher,
172 173
	const int **nids, int nid) 
	{
174
	int ok = 1;
175 176
	if (!cipher) 
		{
177 178
		*nids = gost_cipher_nids;
		return 1; /* Only one cipher supported */
179
		}
180

181 182 183 184 185 186
	if(nid == NID_id_Gost28147_89) 
		{
		*cipher = &cipher_gost;
		}
	else 
		{
187 188
		ok = 0;
		*cipher = NULL;
189
		}
190
	return ok;
191
	}	
192 193

static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
194 195 196 197
	const int **nids, int nid)
	{
	if (!pmeth) 
		{
198 199
		*nids = gost_pkey_meth_nids;
		return 4;
200
		}
201

202 203 204 205 206 207 208 209
	switch (nid) 
		{
		case NID_id_GostR3410_94_cc: *pmeth = pmeth_GostR3410_94_cc; return 1;
		case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
		case NID_id_GostR3410_2001_cc: *pmeth = pmeth_GostR3410_2001_cc; return 1;
		case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
		default:;
		}
210 211 212
	
	*pmeth = NULL;
	return 0;
213
	}
214 215

static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
216 217 218 219
	const int **nids, int nid)
	{
	if (!ameth) 
		{
220 221
		*nids = gost_pkey_meth_nids;
		return 4;
222 223 224 225 226 227 228 229 230
		}
	switch (nid) 
		{
		case NID_id_GostR3410_94_cc: *ameth = ameth_GostR3410_94_cc; return 1;
		case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
		case NID_id_GostR3410_2001_cc: *ameth = ameth_GostR3410_2001_cc; return 1;
		case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
		default:;
		}
231 232 233
	
	*ameth = NULL;
	return 0;
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
	}

#ifdef OPENSSL_NO_DYNAMIC_ENGINE
static ENGINE *engine_gost(void)
	{	
	ENGINE *ret = ENGINE_new();
	if (!ret)
		return NULL;
	if (!bind_gost(ret,engine_gost_id)) 
		{
		ENGINE_free(ret);
		return NULL;
		}
	return ret;
	}
	
void ENGINE_load_gost(void)
	{
	ENGINE *toadd =engine_gost();
	if (!toadd) return;
	ENGINE_add(toadd);
	ENGINE_free(toadd);
	ERR_clear_error();
	}
#endif