gost_eng.c revision 280304
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"; 19280304Sjkimstatic const char *engine_gost_name = 20280304Sjkim "Reference implementation of GOST engine"; 21238384Sjkim 22238384Sjkim/* Symmetric cipher and digest function registrar */ 23238384Sjkim 24238384Sjkimstatic int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 25280304Sjkim const int **nids, int nid); 26238384Sjkim 27238384Sjkimstatic int gost_digests(ENGINE *e, const EVP_MD **digest, 28280304Sjkim const int **nids, int ind); 29238384Sjkim 30280304Sjkimstatic int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, 31280304Sjkim const int **nids, int nid); 32238384Sjkim 33280304Sjkimstatic int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, 34280304Sjkim const int **nids, int nid); 35238384Sjkim 36280304Sjkimstatic int gost_cipher_nids[] = { NID_id_Gost28147_89, NID_gost89_cnt, 0 }; 37238384Sjkim 38238384Sjkimstatic int gost_digest_nids[] = 39280304Sjkim { NID_id_GostR3411_94, NID_id_Gost28147_89_MAC, 0 }; 40238384Sjkim 41280304Sjkimstatic int gost_pkey_meth_nids[] = { NID_id_GostR3410_94, 42280304Sjkim NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0 43280304Sjkim}; 44238384Sjkim 45238384Sjkimstatic EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL, 46280304Sjkim *pmeth_GostR3410_2001 = NULL, *pmeth_Gost28147_MAC = NULL; 47238384Sjkim 48238384Sjkimstatic EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL, 49280304Sjkim *ameth_GostR3410_2001 = NULL, *ameth_Gost28147_MAC = NULL; 50238384Sjkim 51238384Sjkimstatic int gost_engine_init(ENGINE *e) 52280304Sjkim{ 53280304Sjkim return 1; 54280304Sjkim} 55238384Sjkim 56238384Sjkimstatic int gost_engine_finish(ENGINE *e) 57280304Sjkim{ 58280304Sjkim return 1; 59280304Sjkim} 60238384Sjkim 61238384Sjkimstatic int gost_engine_destroy(ENGINE *e) 62280304Sjkim{ 63280304Sjkim gost_param_free(); 64246772Sjkim 65280304Sjkim pmeth_GostR3410_94 = NULL; 66280304Sjkim pmeth_GostR3410_2001 = NULL; 67280304Sjkim pmeth_Gost28147_MAC = NULL; 68280304Sjkim ameth_GostR3410_94 = NULL; 69280304Sjkim ameth_GostR3410_2001 = NULL; 70280304Sjkim ameth_Gost28147_MAC = NULL; 71280304Sjkim return 1; 72280304Sjkim} 73238384Sjkim 74280304Sjkimstatic int bind_gost(ENGINE *e, const char *id) 75280304Sjkim{ 76280304Sjkim int ret = 0; 77280304Sjkim if (id && strcmp(id, engine_gost_id)) 78280304Sjkim return 0; 79280304Sjkim if (ameth_GostR3410_94) { 80280304Sjkim printf("GOST engine already loaded\n"); 81280304Sjkim goto end; 82280304Sjkim } 83238384Sjkim 84280304Sjkim if (!ENGINE_set_id(e, engine_gost_id)) { 85280304Sjkim printf("ENGINE_set_id failed\n"); 86280304Sjkim goto end; 87280304Sjkim } 88280304Sjkim if (!ENGINE_set_name(e, engine_gost_name)) { 89280304Sjkim printf("ENGINE_set_name failed\n"); 90280304Sjkim goto end; 91280304Sjkim } 92280304Sjkim if (!ENGINE_set_digests(e, gost_digests)) { 93280304Sjkim printf("ENGINE_set_digests failed\n"); 94280304Sjkim goto end; 95280304Sjkim } 96280304Sjkim if (!ENGINE_set_ciphers(e, gost_ciphers)) { 97280304Sjkim printf("ENGINE_set_ciphers failed\n"); 98280304Sjkim goto end; 99280304Sjkim } 100280304Sjkim if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) { 101280304Sjkim printf("ENGINE_set_pkey_meths failed\n"); 102280304Sjkim goto end; 103280304Sjkim } 104280304Sjkim if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) { 105280304Sjkim printf("ENGINE_set_pkey_asn1_meths failed\n"); 106280304Sjkim goto end; 107280304Sjkim } 108280304Sjkim /* Control function and commands */ 109280304Sjkim if (!ENGINE_set_cmd_defns(e, gost_cmds)) { 110280304Sjkim fprintf(stderr, "ENGINE_set_cmd_defns failed\n"); 111280304Sjkim goto end; 112280304Sjkim } 113280304Sjkim if (!ENGINE_set_ctrl_function(e, gost_control_func)) { 114280304Sjkim fprintf(stderr, "ENGINE_set_ctrl_func failed\n"); 115280304Sjkim goto end; 116280304Sjkim } 117280304Sjkim if (!ENGINE_set_destroy_function(e, gost_engine_destroy) 118280304Sjkim || !ENGINE_set_init_function(e, gost_engine_init) 119280304Sjkim || !ENGINE_set_finish_function(e, gost_engine_finish)) { 120280304Sjkim goto end; 121280304Sjkim } 122238384Sjkim 123280304Sjkim if (!register_ameth_gost 124280304Sjkim (NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", 125280304Sjkim "GOST R 34.10-94")) 126280304Sjkim goto end; 127280304Sjkim if (!register_ameth_gost 128280304Sjkim (NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", 129280304Sjkim "GOST R 34.10-2001")) 130280304Sjkim goto end; 131280304Sjkim if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC, 132280304Sjkim "GOST-MAC", "GOST 28147-89 MAC")) 133280304Sjkim goto end; 134238384Sjkim 135280304Sjkim if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) 136280304Sjkim goto end; 137280304Sjkim if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) 138280304Sjkim goto end; 139280304Sjkim if (!register_pmeth_gost 140280304Sjkim (NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0)) 141280304Sjkim goto end; 142280304Sjkim if (!ENGINE_register_ciphers(e) 143280304Sjkim || !ENGINE_register_digests(e) 144280304Sjkim || !ENGINE_register_pkey_meths(e) 145280304Sjkim /* These two actually should go in LIST_ADD command */ 146280304Sjkim || !EVP_add_cipher(&cipher_gost) 147280304Sjkim || !EVP_add_cipher(&cipher_gost_cpacnt) 148280304Sjkim || !EVP_add_digest(&digest_gost) 149280304Sjkim || !EVP_add_digest(&imit_gost_cpa) 150280304Sjkim ) { 151280304Sjkim goto end; 152280304Sjkim } 153238384Sjkim 154280304Sjkim ERR_load_GOST_strings(); 155280304Sjkim ret = 1; 156280304Sjkim end: 157280304Sjkim return ret; 158280304Sjkim} 159238384Sjkim 160238384Sjkim#ifndef OPENSSL_NO_DYNAMIC_ENGINE 161238384SjkimIMPLEMENT_DYNAMIC_BIND_FN(bind_gost) 162280304Sjkim IMPLEMENT_DYNAMIC_CHECK_FN() 163280304Sjkim#endif /* ndef OPENSSL_NO_DYNAMIC_ENGINE */ 164238384Sjkimstatic int gost_digests(ENGINE *e, const EVP_MD **digest, 165280304Sjkim const int **nids, int nid) 166280304Sjkim{ 167280304Sjkim int ok = 1; 168280304Sjkim if (!digest) { 169280304Sjkim *nids = gost_digest_nids; 170280304Sjkim return 2; 171280304Sjkim } 172280304Sjkim /* 173280304Sjkim * printf("Digest no %d requested\n",nid); 174280304Sjkim */ 175280304Sjkim if (nid == NID_id_GostR3411_94) { 176280304Sjkim *digest = &digest_gost; 177280304Sjkim } else if (nid == NID_id_Gost28147_89_MAC) { 178280304Sjkim *digest = &imit_gost_cpa; 179280304Sjkim } else { 180280304Sjkim ok = 0; 181280304Sjkim *digest = NULL; 182280304Sjkim } 183280304Sjkim return ok; 184280304Sjkim} 185238384Sjkim 186280304Sjkimstatic int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, 187280304Sjkim const int **nids, int nid) 188280304Sjkim{ 189280304Sjkim int ok = 1; 190280304Sjkim if (!cipher) { 191280304Sjkim *nids = gost_cipher_nids; 192280304Sjkim return 2; /* two ciphers are supported */ 193280304Sjkim } 194238384Sjkim 195280304Sjkim if (nid == NID_id_Gost28147_89) { 196280304Sjkim *cipher = &cipher_gost; 197280304Sjkim } else if (nid == NID_gost89_cnt) { 198280304Sjkim *cipher = &cipher_gost_cpacnt; 199280304Sjkim } else { 200280304Sjkim ok = 0; 201280304Sjkim *cipher = NULL; 202280304Sjkim } 203280304Sjkim return ok; 204280304Sjkim} 205238384Sjkim 206280304Sjkimstatic int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, 207280304Sjkim const int **nids, int nid) 208280304Sjkim{ 209280304Sjkim if (!pmeth) { 210280304Sjkim *nids = gost_pkey_meth_nids; 211280304Sjkim return 3; 212280304Sjkim } 213238384Sjkim 214280304Sjkim switch (nid) { 215280304Sjkim case NID_id_GostR3410_94: 216280304Sjkim *pmeth = pmeth_GostR3410_94; 217280304Sjkim return 1; 218280304Sjkim case NID_id_GostR3410_2001: 219280304Sjkim *pmeth = pmeth_GostR3410_2001; 220280304Sjkim return 1; 221280304Sjkim case NID_id_Gost28147_89_MAC: 222280304Sjkim *pmeth = pmeth_Gost28147_MAC; 223280304Sjkim return 1; 224280304Sjkim default:; 225280304Sjkim } 226238384Sjkim 227280304Sjkim *pmeth = NULL; 228280304Sjkim return 0; 229280304Sjkim} 230280304Sjkim 231280304Sjkimstatic int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, 232280304Sjkim const int **nids, int nid) 233280304Sjkim{ 234280304Sjkim if (!ameth) { 235280304Sjkim *nids = gost_pkey_meth_nids; 236280304Sjkim return 3; 237280304Sjkim } 238280304Sjkim switch (nid) { 239280304Sjkim case NID_id_GostR3410_94: 240280304Sjkim *ameth = ameth_GostR3410_94; 241280304Sjkim return 1; 242280304Sjkim case NID_id_GostR3410_2001: 243280304Sjkim *ameth = ameth_GostR3410_2001; 244280304Sjkim return 1; 245280304Sjkim case NID_id_Gost28147_89_MAC: 246280304Sjkim *ameth = ameth_Gost28147_MAC; 247280304Sjkim return 1; 248280304Sjkim 249280304Sjkim default:; 250280304Sjkim } 251280304Sjkim 252280304Sjkim *ameth = NULL; 253280304Sjkim return 0; 254280304Sjkim} 255280304Sjkim 256238384Sjkim#ifdef OPENSSL_NO_DYNAMIC_ENGINE 257238384Sjkimstatic ENGINE *engine_gost(void) 258280304Sjkim{ 259280304Sjkim ENGINE *ret = ENGINE_new(); 260280304Sjkim if (!ret) 261280304Sjkim return NULL; 262280304Sjkim if (!bind_gost(ret, engine_gost_id)) { 263280304Sjkim ENGINE_free(ret); 264280304Sjkim return NULL; 265280304Sjkim } 266280304Sjkim return ret; 267280304Sjkim} 268280304Sjkim 269238384Sjkimvoid ENGINE_load_gost(void) 270280304Sjkim{ 271280304Sjkim ENGINE *toadd; 272280304Sjkim if (pmeth_GostR3410_94) 273280304Sjkim return; 274280304Sjkim toadd = engine_gost(); 275280304Sjkim if (!toadd) 276280304Sjkim return; 277280304Sjkim ENGINE_add(toadd); 278280304Sjkim ENGINE_free(toadd); 279280304Sjkim ERR_clear_error(); 280280304Sjkim} 281280304Sjkim#endif 282