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 160static 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 182static 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 202static 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 227static 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 253static 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 265void 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#else 278IMPLEMENT_DYNAMIC_BIND_FN(bind_gost) 279IMPLEMENT_DYNAMIC_CHECK_FN() 280#endif 281