757793b396d0b4657cf9b579eddb3677637d1b3b
[openssl.git] / engines / ccgost / engine.c
1 /**********************************************************************
2  *                          engine.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/evp.h>
12 #include <openssl/engine.h>
13 #include <openssl/obj_mac.h>
14 #include "e_gost_err.h"
15 #include "md.h"
16 #include "crypt.h"
17 #include "meth.h"
18
19 static const char *engine_gost_id = "gost";
20 static const char *engine_gost_name = "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[] =
37     {NID_id_Gost28147_89, 0};
38
39 static int gost_digest_nids[] =
40         {NID_id_GostR3411_94, 0};
41
42 static int gost_pkey_meth_nids[] = 
43         {NID_id_GostR3410_94_cc, NID_id_GostR3410_94, NID_id_GostR3410_2001_cc,
44                 NID_id_GostR3410_2001, 0};
45
46 static EVP_PKEY_METHOD *pmeth_GostR3410_94_cc = NULL, *pmeth_GostR3410_94 = NULL,
47         *pmeth_GostR3410_2001_cc = NULL, *pmeth_GostR3410_2001 = NULL;
48
49 static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94_cc = NULL, *ameth_GostR3410_94 = NULL,
50         *ameth_GostR3410_2001_cc = NULL, *ameth_GostR3410_2001 = NULL;
51
52
53 static int gost_engine_init(ENGINE *e) { 
54         return 1;
55 }
56 static int gost_engine_finish(ENGINE *e) { 
57         return 1;
58 }
59
60 static int gost_engine_destroy(ENGINE *e) { 
61         return 1;
62 }
63
64 static int bind_gost (ENGINE *e,const char *id) {
65         int ret = 0;
66         if (id && strcmp(id, engine_gost_id)) return 0;
67
68         if (!ENGINE_set_id(e, engine_gost_id)) {
69                 printf("ENGINE_set_id failed\n"); 
70                 goto end;
71         }       
72         if (!ENGINE_set_name(e, engine_gost_name)) {
73                 printf("ENGINE_set_name failed\n");
74                 goto end;
75         }       
76         if (!ENGINE_set_digests(e, gost_digests)) {
77                 printf("ENGINE_set_digests failed\n");
78                 goto end;
79         }       
80         if (! ENGINE_set_ciphers(e, gost_ciphers)) {
81                 printf("ENGINE_set_ciphers failed\n");
82                 goto end;
83         }       
84         if (! ENGINE_set_pkey_meths(e, gost_pkey_meths)) {
85                 printf("ENGINE_set_pkey_meths failed\n");
86                 goto end;
87         }       
88         if (! ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) {
89                 printf("ENGINE_set_pkey_asn1_meths failed\n");
90                 goto end;
91         }       
92         if ( ! ENGINE_set_destroy_function(e, gost_engine_destroy)
93                 || ! ENGINE_set_init_function(e,gost_engine_init)
94                 || ! ENGINE_set_finish_function(e,gost_engine_finish)) goto end;
95
96
97
98         if (!register_ameth_gost(NID_id_GostR3410_94_cc, &ameth_GostR3410_94_cc, "GOST94CC", "GOST R 34.10-94, Cryptocom LTD implementation")) goto end;
99         if (!register_ameth_gost(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", "GOST R 34.10-94")) goto end;
100         if (!register_ameth_gost(NID_id_GostR3410_2001_cc, &ameth_GostR3410_2001_cc, "GOST2001CC", "GOST R 34.10-2001, Cryptocom LTD implementation")) goto end;
101         if (!register_ameth_gost(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", "GOST R 34.10-2001")) goto end;
102
103         if (!register_pmeth_gost(NID_id_GostR3410_94_cc, &pmeth_GostR3410_94_cc, 0)) goto end;
104         if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) goto end;
105         if (!register_pmeth_gost(NID_id_GostR3410_2001_cc, &pmeth_GostR3410_2001_cc, 0)) goto end;
106         if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) goto end;
107         if ( ! ENGINE_register_ciphers(e)
108                 || ! ENGINE_register_digests(e)
109                 || ! ENGINE_register_pkey_meths(e)
110                 /* These two actually should go in LIST_ADD command */
111                 || ! EVP_add_cipher(&cipher_gost)
112                 || ! EVP_add_digest(&digest_gost)
113            ) goto end;
114
115         ERR_load_GOST_strings();
116         ret = 1;
117 end:
118         return ret;
119 }       
120
121 #ifdef _WIN32
122 extern __declspec( dllexport ) 
123 #endif
124         
125 //#ifndef OPENSSL_NO_DYNAMIC_ENGINE
126 IMPLEMENT_DYNAMIC_BIND_FN(bind_gost);
127
128 #ifdef _WIN32
129 extern __declspec( dllexport ) 
130 #endif
131
132 IMPLEMENT_DYNAMIC_CHECK_FN();
133 //#else
134 static ENGINE *engine_gost(void)
135         {
136         ENGINE *ret = ENGINE_new();
137         if(!ret)
138                 return NULL;
139         if(!bind_gost(ret, engine_gost_id))
140                 {
141                 ENGINE_free(ret);
142                 return NULL;
143                 }
144         return ret;
145         }
146
147 void ENGINE_load_gost(void)
148         {
149         /* Copied from eng_[openssl|dyn].c */
150         ENGINE *toadd = engine_gost();
151         if(!toadd) return;
152         ENGINE_add(toadd);
153         ENGINE_free(toadd);
154         ERR_clear_error();
155         }
156 //#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
157
158 static int gost_digests(ENGINE *e, const EVP_MD **digest,
159          const int **nids, int nid)
160
161         int ok =1 ;
162         if (!digest) {
163                 *nids = gost_digest_nids;
164                 return 1; 
165         }
166                 //printf("Digest no %d requested\n",nid);
167                 if(nid == NID_id_GostR3411_94) {
168                         *digest = &digest_gost;
169                 } else {
170                         ok =0;
171                         *digest = NULL;
172                 }
173         return ok;
174 }       
175         
176 static int gost_ciphers (ENGINE *e,const EVP_CIPHER **cipher,
177                 const int **nids, int nid) {
178         int ok = 1;
179         if (!cipher) {
180                 *nids = gost_cipher_nids;
181                 return 1; /* Only one cipher supported */
182         }
183
184         if(nid == NID_id_Gost28147_89) {
185                         *cipher = &cipher_gost;
186         } else {
187                 ok = 0;
188                 *cipher = NULL;
189         }
190         return ok;
191 }       
192
193 static int gost_pkey_meths (ENGINE *e, EVP_PKEY_METHOD **pmeth,
194                 const int **nids, int nid)
195 {
196         if (!pmeth) {
197                 *nids = gost_pkey_meth_nids;
198                 return 4;
199         }
200
201         switch (nid) {
202         case NID_id_GostR3410_94_cc: *pmeth = pmeth_GostR3410_94_cc; return 1;
203         case NID_id_GostR3410_94: *pmeth = pmeth_GostR3410_94; return 1;
204         case NID_id_GostR3410_2001_cc: *pmeth = pmeth_GostR3410_2001_cc; return 1;
205         case NID_id_GostR3410_2001: *pmeth = pmeth_GostR3410_2001; return 1;
206         default:;
207         }
208         
209         *pmeth = NULL;
210         return 0;
211 }
212
213 static int gost_pkey_asn1_meths (ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth,
214                 const int **nids, int nid)
215 {
216         if (!ameth) {
217                 *nids = gost_pkey_meth_nids;
218                 return 4;
219         }
220         switch (nid) {
221         case NID_id_GostR3410_94_cc: *ameth = ameth_GostR3410_94_cc; return 1;
222         case NID_id_GostR3410_94: *ameth = ameth_GostR3410_94; return 1;
223         case NID_id_GostR3410_2001_cc: *ameth = ameth_GostR3410_2001_cc; return 1;
224         case NID_id_GostR3410_2001: *ameth = ameth_GostR3410_2001; return 1;
225         default:;
226         }
227         
228         *ameth = NULL;
229         return 0;
230 }