1238384Sjkim/********************************************************************** 2238384Sjkim * gost_eng.c * 3238384Sjkim * Copyright (c) 2005-2006 Cryptocom LTD * 4238384Sjkim * This file is distributed under the same license as OpenSSL * 5238384Sjkim * * 6238384Sjkim * Main file of GOST engine * 7238384Sjkim * for OpenSSL * 8238384Sjkim * Requires OpenSSL 0.9.9 for compilation * 9238384Sjkim **********************************************************************/ 10238384Sjkim#include <string.h> 11238384Sjkim#include <openssl/crypto.h> 12238384Sjkim#include <openssl/err.h> 13238384Sjkim#include <openssl/evp.h> 14238384Sjkim#include <openssl/engine.h> 15238384Sjkim#include <openssl/obj_mac.h> 16238384Sjkim#include "e_gost_err.h" 17238384Sjkim#include "gost_lcl.h" 18238384Sjkimstatic const char *engine_gost_id = "gost"; 19280297Sjkimstatic const char *engine_gost_name = 20280297Sjkim "Reference implementation of GOST engine"; 21238384Sjkim 22238384Sjkim/* Symmetric cipher and digest function registrar */ 23238384Sjkim 24238384Sjkimstatic int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 25280297Sjkim const int **nids, int nid); 26238384Sjkim 27238384Sjkimstatic int gost_digests(ENGINE *e, const EVP_MD **digest, 28280297Sjkim const int **nids, int ind); 29238384Sjkim 30280297Sjkimstatic int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, 31280297Sjkim const int **nids, int nid); 32238384Sjkim 33280297Sjkimstatic int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, 34280297Sjkim const int **nids, int nid); 35238384Sjkim 36280297Sjkimstatic int gost_cipher_nids[] = { NID_id_Gost28147_89, NID_gost89_cnt, 0 }; 37238384Sjkim 38238384Sjkimstatic int gost_digest_nids[] = 39280297Sjkim { NID_id_GostR3411_94, NID_id_Gost28147_89_MAC, 0 }; 40238384Sjkim 41280297Sjkimstatic int gost_pkey_meth_nids[] = { NID_id_GostR3410_94, 42280297Sjkim NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0 43280297Sjkim}; 44238384Sjkim 45238384Sjkimstatic EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL, 46280297Sjkim *pmeth_GostR3410_2001 = NULL, *pmeth_Gost28147_MAC = NULL; 47238384Sjkim 48238384Sjkimstatic EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL, 49280297Sjkim *ameth_GostR3410_2001 = NULL, *ameth_Gost28147_MAC = NULL; 50238384Sjkim 51238384Sjkimstatic int gost_engine_init(ENGINE *e) 52280297Sjkim{ 53280297Sjkim return 1; 54280297Sjkim} 55238384Sjkim 56238384Sjkimstatic int gost_engine_finish(ENGINE *e) 57280297Sjkim{ 58280297Sjkim return 1; 59280297Sjkim} 60238384Sjkim 61238384Sjkimstatic int gost_engine_destroy(ENGINE *e) 62280297Sjkim{ 63280297Sjkim gost_param_free(); 64246772Sjkim 65280297Sjkim pmeth_GostR3410_94 = NULL; 66280297Sjkim pmeth_GostR3410_2001 = NULL; 67280297Sjkim pmeth_Gost28147_MAC = NULL; 68280297Sjkim ameth_GostR3410_94 = NULL; 69280297Sjkim ameth_GostR3410_2001 = NULL; 70280297Sjkim ameth_Gost28147_MAC = NULL; 71280297Sjkim return 1; 72280297Sjkim} 73238384Sjkim 74280297Sjkimstatic int bind_gost(ENGINE *e, const char *id) 75280297Sjkim{ 76280297Sjkim int ret = 0; 77280297Sjkim if (id && strcmp(id, engine_gost_id)) 78280297Sjkim return 0; 79280297Sjkim if (ameth_GostR3410_94) { 80280297Sjkim printf("GOST engine already loaded\n"); 81280297Sjkim goto end; 82280297Sjkim } 83238384Sjkim 84280297Sjkim if (!ENGINE_set_id(e, engine_gost_id)) { 85280297Sjkim printf("ENGINE_set_id failed\n"); 86280297Sjkim goto end; 87280297Sjkim } 88280297Sjkim if (!ENGINE_set_name(e, engine_gost_name)) { 89280297Sjkim printf("ENGINE_set_name failed\n"); 90280297Sjkim goto end; 91280297Sjkim } 92280297Sjkim if (!ENGINE_set_digests(e, gost_digests)) { 93280297Sjkim printf("ENGINE_set_digests failed\n"); 94280297Sjkim goto end; 95280297Sjkim } 96280297Sjkim if (!ENGINE_set_ciphers(e, gost_ciphers)) { 97280297Sjkim printf("ENGINE_set_ciphers failed\n"); 98280297Sjkim goto end; 99280297Sjkim } 100280297Sjkim if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) { 101280297Sjkim printf("ENGINE_set_pkey_meths failed\n"); 102280297Sjkim goto end; 103280297Sjkim } 104280297Sjkim if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) { 105280297Sjkim printf("ENGINE_set_pkey_asn1_meths failed\n"); 106280297Sjkim goto end; 107280297Sjkim } 108280297Sjkim /* Control function and commands */ 109280297Sjkim if (!ENGINE_set_cmd_defns(e, gost_cmds)) { 110280297Sjkim fprintf(stderr, "ENGINE_set_cmd_defns failed\n"); 111280297Sjkim goto end; 112280297Sjkim } 113280297Sjkim if (!ENGINE_set_ctrl_function(e, gost_control_func)) { 114280297Sjkim fprintf(stderr, "ENGINE_set_ctrl_func failed\n"); 115280297Sjkim goto end; 116280297Sjkim } 117280297Sjkim if (!ENGINE_set_destroy_function(e, gost_engine_destroy) 118280297Sjkim || !ENGINE_set_init_function(e, gost_engine_init) 119280297Sjkim || !ENGINE_set_finish_function(e, gost_engine_finish)) { 120280297Sjkim goto end; 121280297Sjkim } 122238384Sjkim 123280297Sjkim if (!register_ameth_gost 124280297Sjkim (NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", 125280297Sjkim "GOST R 34.10-94")) 126280297Sjkim goto end; 127280297Sjkim if (!register_ameth_gost 128280297Sjkim (NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", 129280297Sjkim "GOST R 34.10-2001")) 130280297Sjkim goto end; 131280297Sjkim if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC, 132280297Sjkim "GOST-MAC", "GOST 28147-89 MAC")) 133280297Sjkim goto end; 134238384Sjkim 135280297Sjkim if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) 136280297Sjkim goto end; 137280297Sjkim if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) 138280297Sjkim goto end; 139280297Sjkim if (!register_pmeth_gost 140280297Sjkim (NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0)) 141280297Sjkim goto end; 142280297Sjkim if (!ENGINE_register_ciphers(e) 143280297Sjkim || !ENGINE_register_digests(e) 144280297Sjkim || !ENGINE_register_pkey_meths(e) 145280297Sjkim /* These two actually should go in LIST_ADD command */ 146280297Sjkim || !EVP_add_cipher(&cipher_gost) 147280297Sjkim || !EVP_add_cipher(&cipher_gost_cpacnt) 148280297Sjkim || !EVP_add_digest(&digest_gost) 149280297Sjkim || !EVP_add_digest(&imit_gost_cpa) 150280297Sjkim ) { 151280297Sjkim goto end; 152280297Sjkim } 153238384Sjkim 154280297Sjkim ERR_load_GOST_strings(); 155280297Sjkim ret = 1; 156280297Sjkim end: 157280297Sjkim return ret; 158280297Sjkim} 159238384Sjkim 160238384Sjkimstatic int gost_digests(ENGINE *e, const EVP_MD **digest, 161280297Sjkim const int **nids, int nid) 162280297Sjkim{ 163280297Sjkim int ok = 1; 164280297Sjkim if (!digest) { 165280297Sjkim *nids = gost_digest_nids; 166280297Sjkim return 2; 167280297Sjkim } 168280297Sjkim /* 169280297Sjkim * printf("Digest no %d requested\n",nid); 170280297Sjkim */ 171280297Sjkim if (nid == NID_id_GostR3411_94) { 172280297Sjkim *digest = &digest_gost; 173280297Sjkim } else if (nid == NID_id_Gost28147_89_MAC) { 174280297Sjkim *digest = &imit_gost_cpa; 175280297Sjkim } else { 176280297Sjkim ok = 0; 177280297Sjkim *digest = NULL; 178280297Sjkim } 179280297Sjkim return ok; 180280297Sjkim} 181238384Sjkim 182280297Sjkimstatic int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 183280297Sjkim const int **nids, int nid) 184280297Sjkim{ 185280297Sjkim int ok = 1; 186280297Sjkim if (!cipher) { 187280297Sjkim *nids = gost_cipher_nids; 188280297Sjkim return 2; /* two ciphers are supported */ 189280297Sjkim } 190238384Sjkim 191280297Sjkim if (nid == NID_id_Gost28147_89) { 192280297Sjkim *cipher = &cipher_gost; 193280297Sjkim } else if (nid == NID_gost89_cnt) { 194280297Sjkim *cipher = &cipher_gost_cpacnt; 195280297Sjkim } else { 196280297Sjkim ok = 0; 197280297Sjkim *cipher = NULL; 198280297Sjkim } 199280297Sjkim return ok; 200280297Sjkim} 201238384Sjkim 202280297Sjkimstatic int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, 203280297Sjkim const int **nids, int nid) 204280297Sjkim{ 205280297Sjkim if (!pmeth) { 206280297Sjkim *nids = gost_pkey_meth_nids; 207280297Sjkim return 3; 208280297Sjkim } 209238384Sjkim 210280297Sjkim switch (nid) { 211280297Sjkim case NID_id_GostR3410_94: 212280297Sjkim *pmeth = pmeth_GostR3410_94; 213280297Sjkim return 1; 214280297Sjkim case NID_id_GostR3410_2001: 215280297Sjkim *pmeth = pmeth_GostR3410_2001; 216280297Sjkim return 1; 217280297Sjkim case NID_id_Gost28147_89_MAC: 218280297Sjkim *pmeth = pmeth_Gost28147_MAC; 219280297Sjkim return 1; 220280297Sjkim default:; 221280297Sjkim } 222238384Sjkim 223280297Sjkim *pmeth = NULL; 224280297Sjkim return 0; 225280297Sjkim} 226280297Sjkim 227280297Sjkimstatic int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, 228280297Sjkim const int **nids, int nid) 229280297Sjkim{ 230280297Sjkim if (!ameth) { 231280297Sjkim *nids = gost_pkey_meth_nids; 232280297Sjkim return 3; 233280297Sjkim } 234280297Sjkim switch (nid) { 235280297Sjkim case NID_id_GostR3410_94: 236280297Sjkim *ameth = ameth_GostR3410_94; 237280297Sjkim return 1; 238280297Sjkim case NID_id_GostR3410_2001: 239280297Sjkim *ameth = ameth_GostR3410_2001; 240280297Sjkim return 1; 241280297Sjkim case NID_id_Gost28147_89_MAC: 242280297Sjkim *ameth = ameth_Gost28147_MAC; 243280297Sjkim return 1; 244280297Sjkim 245280297Sjkim default:; 246280297Sjkim } 247280297Sjkim 248280297Sjkim *ameth = NULL; 249280297Sjkim return 0; 250280297Sjkim} 251280297Sjkim 252238384Sjkim#ifdef OPENSSL_NO_DYNAMIC_ENGINE 253238384Sjkimstatic ENGINE *engine_gost(void) 254280297Sjkim{ 255280297Sjkim ENGINE *ret = ENGINE_new(); 256280297Sjkim if (!ret) 257280297Sjkim return NULL; 258280297Sjkim if (!bind_gost(ret, engine_gost_id)) { 259280297Sjkim ENGINE_free(ret); 260280297Sjkim return NULL; 261280297Sjkim } 262280297Sjkim return ret; 263280297Sjkim} 264280297Sjkim 265238384Sjkimvoid ENGINE_load_gost(void) 266280297Sjkim{ 267280297Sjkim ENGINE *toadd; 268280297Sjkim if (pmeth_GostR3410_94) 269280297Sjkim return; 270280297Sjkim toadd = engine_gost(); 271280297Sjkim if (!toadd) 272280297Sjkim return; 273280297Sjkim ENGINE_add(toadd); 274280297Sjkim ENGINE_free(toadd); 275280297Sjkim ERR_clear_error(); 276280297Sjkim} 277331638Sjkim#else 278331638SjkimIMPLEMENT_DYNAMIC_BIND_FN(bind_gost) 279331638SjkimIMPLEMENT_DYNAMIC_CHECK_FN() 280280297Sjkim#endif 281