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