gost_eng.c revision 280304
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"
18static const char *engine_gost_id = "gost";
19static const char *engine_gost_name =
20    "Reference implementation of GOST engine";
21
22/* Symmetric cipher and digest function registrar */
23
24static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
25                        const int **nids, int nid);
26
27static int gost_digests(ENGINE *e, const EVP_MD **digest,
28                        const int **nids, int ind);
29
30static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
31                           const int **nids, int nid);
32
33static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
34                                const int **nids, int nid);
35
36static int gost_cipher_nids[] = { NID_id_Gost28147_89, NID_gost89_cnt, 0 };
37
38static int gost_digest_nids[] =
39    { NID_id_GostR3411_94, NID_id_Gost28147_89_MAC, 0 };
40
41static int gost_pkey_meth_nids[] = { NID_id_GostR3410_94,
42    NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0
43};
44
45static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
46    *pmeth_GostR3410_2001 = NULL, *pmeth_Gost28147_MAC = NULL;
47
48static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
49    *ameth_GostR3410_2001 = NULL, *ameth_Gost28147_MAC = NULL;
50
51static int gost_engine_init(ENGINE *e)
52{
53    return 1;
54}
55
56static int gost_engine_finish(ENGINE *e)
57{
58    return 1;
59}
60
61static 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
74static 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    }
83
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    }
122
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;
134
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    }
153
154    ERR_load_GOST_strings();
155    ret = 1;
156 end:
157    return ret;
158}
159
160#ifndef OPENSSL_NO_DYNAMIC_ENGINE
161IMPLEMENT_DYNAMIC_BIND_FN(bind_gost)
162    IMPLEMENT_DYNAMIC_CHECK_FN()
163#endif                          /* ndef OPENSSL_NO_DYNAMIC_ENGINE */
164static int gost_digests(ENGINE *e, const EVP_MD **digest,
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
186static 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}
205
206static 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    }
213
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    }
226
227    *pmeth = NULL;
228    return 0;
229}
230
231static 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}
255
256#ifdef OPENSSL_NO_DYNAMIC_ENGINE
257static ENGINE *engine_gost(void)
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}
268
269void 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
282