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