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 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 161 IMPLEMENT_DYNAMIC_BIND_FN(bind_gost) 162 IMPLEMENT_DYNAMIC_CHECK_FN() 163 #endif /* ndef OPENSSL_NO_DYNAMIC_ENGINE */ 164 static 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 186 static 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 206 static 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 231 static 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 257 static 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 269 void 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