gost_eng.c revision 296341
125540Sdfr/**********************************************************************
225540Sdfr *                          gost_eng.c                                *
325540Sdfr *             Copyright (c) 2005-2006 Cryptocom LTD                  *
425540Sdfr *         This file is distributed under the same license as OpenSSL *
525540Sdfr *                                                                    *
625540Sdfr *              Main file of GOST engine                              *
725540Sdfr *       for OpenSSL                                                  *
825540Sdfr *          Requires OpenSSL 0.9.9 for compilation                    *
925540Sdfr **********************************************************************/
1025540Sdfr#include <string.h>
1125540Sdfr#include <openssl/crypto.h>
1225540Sdfr#include <openssl/err.h>
1325540Sdfr#include <openssl/evp.h>
1425540Sdfr#include <openssl/engine.h>
1525540Sdfr#include <openssl/obj_mac.h>
1625540Sdfr#include "e_gost_err.h"
1725540Sdfr#include "gost_lcl.h"
1825540Sdfrstatic const char *engine_gost_id = "gost";
1925540Sdfrstatic const char *engine_gost_name =
2025540Sdfr    "Reference implementation of GOST engine";
2125540Sdfr
2225540Sdfr/* Symmetric cipher and digest function registrar */
2325540Sdfr
2425540Sdfrstatic int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
2525540Sdfr                        const int **nids, int nid);
2650476Speter
2725540Sdfrstatic int gost_digests(ENGINE *e, const EVP_MD **digest,
28152568Sru                        const int **nids, int ind);
2925540Sdfr
3025540Sdfrstatic int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth,
3125540Sdfr                           const int **nids, int nid);
3225540Sdfr
3325540Sdfrstatic int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
3425540Sdfr                                const int **nids, int nid);
3568960Sru
3625540Sdfrstatic int gost_cipher_nids[] = { NID_id_Gost28147_89, NID_gost89_cnt, 0 };
3725540Sdfr
38145861Sfjoestatic int gost_digest_nids[] =
39145861Sfjoe    { NID_id_GostR3411_94, NID_id_Gost28147_89_MAC, 0 };
40150497Spjd
41145861Sfjoestatic int gost_pkey_meth_nids[] = { NID_id_GostR3410_94,
4225540Sdfr    NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0
4325540Sdfr};
4425540Sdfr
4562327Spsstatic EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL,
4662327Sps    *pmeth_GostR3410_2001 = NULL, *pmeth_Gost28147_MAC = NULL;
4725540Sdfr
4832270Scharnierstatic EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL,
4941108Sobrien    *ameth_GostR3410_2001 = NULL, *ameth_Gost28147_MAC = NULL;
5025540Sdfr
5162327Spsstatic int gost_engine_init(ENGINE *e)
5225540Sdfr{
5325540Sdfr    return 1;
54145861Sfjoe}
55145861Sfjoe
56150497Spjdstatic int gost_engine_finish(ENGINE *e)
57150497Spjd{
58145861Sfjoe    return 1;
59145861Sfjoe}
6025540Sdfr
61140368Srustatic int gost_engine_destroy(ENGINE *e)
62140368Sru{
6325540Sdfr    gost_param_free();
6450847Schris
6525540Sdfr    pmeth_GostR3410_94 = NULL;
6625540Sdfr    pmeth_GostR3410_2001 = NULL;
6730627Sjmg    pmeth_Gost28147_MAC = NULL;
6830627Sjmg    ameth_GostR3410_94 = NULL;
6930627Sjmg    ameth_GostR3410_2001 = NULL;
7099501Scharnier    ameth_Gost28147_MAC = NULL;
7141108Sobrien    return 1;
7241108Sobrien}
73166690Sbrueffer
7441108Sobrienstatic int bind_gost(ENGINE *e, const char *id)
7534673Scharnier{
7634673Scharnier    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