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