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