You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
281 lines
7.6 KiB
281 lines
7.6 KiB
/********************************************************************** |
|
* gost_eng.c * |
|
* Copyright (c) 2005-2006 Cryptocom LTD * |
|
* This file is distributed under the same license as OpenSSL * |
|
* * |
|
* Main file of GOST engine * |
|
* for OpenSSL * |
|
* Requires OpenSSL 0.9.9 for compilation * |
|
**********************************************************************/ |
|
#include <string.h> |
|
#include <openssl/crypto.h> |
|
#include <openssl/err.h> |
|
#include <openssl/evp.h> |
|
#include <openssl/engine.h> |
|
#include <openssl/obj_mac.h> |
|
#include "e_gost_err.h" |
|
#include "gost_lcl.h" |
|
static const char *engine_gost_id = "gost"; |
|
static const char *engine_gost_name = |
|
"Reference implementation of GOST engine"; |
|
|
|
/* Symmetric cipher and digest function registrar */ |
|
|
|
static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, |
|
const int **nids, int nid); |
|
|
|
static int gost_digests(ENGINE *e, const EVP_MD **digest, |
|
const int **nids, int ind); |
|
|
|
static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, |
|
const int **nids, int nid); |
|
|
|
static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, |
|
const int **nids, int nid); |
|
|
|
static int gost_cipher_nids[] = { NID_id_Gost28147_89, NID_gost89_cnt, 0 }; |
|
|
|
static int gost_digest_nids[] = |
|
{ NID_id_GostR3411_94, NID_id_Gost28147_89_MAC, 0 }; |
|
|
|
static int gost_pkey_meth_nids[] = { NID_id_GostR3410_94, |
|
NID_id_GostR3410_2001, NID_id_Gost28147_89_MAC, 0 |
|
}; |
|
|
|
static EVP_PKEY_METHOD *pmeth_GostR3410_94 = NULL, |
|
*pmeth_GostR3410_2001 = NULL, *pmeth_Gost28147_MAC = NULL; |
|
|
|
static EVP_PKEY_ASN1_METHOD *ameth_GostR3410_94 = NULL, |
|
*ameth_GostR3410_2001 = NULL, *ameth_Gost28147_MAC = NULL; |
|
|
|
static int gost_engine_init(ENGINE *e) |
|
{ |
|
return 1; |
|
} |
|
|
|
static int gost_engine_finish(ENGINE *e) |
|
{ |
|
return 1; |
|
} |
|
|
|
static int gost_engine_destroy(ENGINE *e) |
|
{ |
|
gost_param_free(); |
|
|
|
pmeth_GostR3410_94 = NULL; |
|
pmeth_GostR3410_2001 = NULL; |
|
pmeth_Gost28147_MAC = NULL; |
|
ameth_GostR3410_94 = NULL; |
|
ameth_GostR3410_2001 = NULL; |
|
ameth_Gost28147_MAC = NULL; |
|
return 1; |
|
} |
|
|
|
static int bind_gost(ENGINE *e, const char *id) |
|
{ |
|
int ret = 0; |
|
if (id && strcmp(id, engine_gost_id)) |
|
return 0; |
|
if (ameth_GostR3410_94) { |
|
printf("GOST engine already loaded\n"); |
|
goto end; |
|
} |
|
|
|
if (!ENGINE_set_id(e, engine_gost_id)) { |
|
printf("ENGINE_set_id failed\n"); |
|
goto end; |
|
} |
|
if (!ENGINE_set_name(e, engine_gost_name)) { |
|
printf("ENGINE_set_name failed\n"); |
|
goto end; |
|
} |
|
if (!ENGINE_set_digests(e, gost_digests)) { |
|
printf("ENGINE_set_digests failed\n"); |
|
goto end; |
|
} |
|
if (!ENGINE_set_ciphers(e, gost_ciphers)) { |
|
printf("ENGINE_set_ciphers failed\n"); |
|
goto end; |
|
} |
|
if (!ENGINE_set_pkey_meths(e, gost_pkey_meths)) { |
|
printf("ENGINE_set_pkey_meths failed\n"); |
|
goto end; |
|
} |
|
if (!ENGINE_set_pkey_asn1_meths(e, gost_pkey_asn1_meths)) { |
|
printf("ENGINE_set_pkey_asn1_meths failed\n"); |
|
goto end; |
|
} |
|
/* Control function and commands */ |
|
if (!ENGINE_set_cmd_defns(e, gost_cmds)) { |
|
fprintf(stderr, "ENGINE_set_cmd_defns failed\n"); |
|
goto end; |
|
} |
|
if (!ENGINE_set_ctrl_function(e, gost_control_func)) { |
|
fprintf(stderr, "ENGINE_set_ctrl_func failed\n"); |
|
goto end; |
|
} |
|
if (!ENGINE_set_destroy_function(e, gost_engine_destroy) |
|
|| !ENGINE_set_init_function(e, gost_engine_init) |
|
|| !ENGINE_set_finish_function(e, gost_engine_finish)) { |
|
goto end; |
|
} |
|
|
|
if (!register_ameth_gost |
|
(NID_id_GostR3410_94, &ameth_GostR3410_94, "GOST94", |
|
"GOST R 34.10-94")) |
|
goto end; |
|
if (!register_ameth_gost |
|
(NID_id_GostR3410_2001, &ameth_GostR3410_2001, "GOST2001", |
|
"GOST R 34.10-2001")) |
|
goto end; |
|
if (!register_ameth_gost(NID_id_Gost28147_89_MAC, &ameth_Gost28147_MAC, |
|
"GOST-MAC", "GOST 28147-89 MAC")) |
|
goto end; |
|
|
|
if (!register_pmeth_gost(NID_id_GostR3410_94, &pmeth_GostR3410_94, 0)) |
|
goto end; |
|
if (!register_pmeth_gost(NID_id_GostR3410_2001, &pmeth_GostR3410_2001, 0)) |
|
goto end; |
|
if (!register_pmeth_gost |
|
(NID_id_Gost28147_89_MAC, &pmeth_Gost28147_MAC, 0)) |
|
goto end; |
|
if (!ENGINE_register_ciphers(e) |
|
|| !ENGINE_register_digests(e) |
|
|| !ENGINE_register_pkey_meths(e) |
|
/* These two actually should go in LIST_ADD command */ |
|
|| !EVP_add_cipher(&cipher_gost) |
|
|| !EVP_add_cipher(&cipher_gost_cpacnt) |
|
|| !EVP_add_digest(&digest_gost) |
|
|| !EVP_add_digest(&imit_gost_cpa) |
|
) { |
|
goto end; |
|
} |
|
|
|
ERR_load_GOST_strings(); |
|
ret = 1; |
|
end: |
|
return ret; |
|
} |
|
|
|
#ifndef OPENSSL_NO_DYNAMIC_ENGINE |
|
IMPLEMENT_DYNAMIC_BIND_FN(bind_gost) |
|
IMPLEMENT_DYNAMIC_CHECK_FN() |
|
#endif /* ndef OPENSSL_NO_DYNAMIC_ENGINE */ |
|
static int gost_digests(ENGINE *e, const EVP_MD **digest, |
|
const int **nids, int nid) |
|
{ |
|
int ok = 1; |
|
if (!digest) { |
|
*nids = gost_digest_nids; |
|
return 2; |
|
} |
|
/* |
|
* printf("Digest no %d requested\n",nid); |
|
*/ |
|
if (nid == NID_id_GostR3411_94) { |
|
*digest = &digest_gost; |
|
} else if (nid == NID_id_Gost28147_89_MAC) { |
|
*digest = &imit_gost_cpa; |
|
} else { |
|
ok = 0; |
|
*digest = NULL; |
|
} |
|
return ok; |
|
} |
|
|
|
static int gost_ciphers(ENGINE *e, const EVP_CIPHER **cipher, |
|
const int **nids, int nid) |
|
{ |
|
int ok = 1; |
|
if (!cipher) { |
|
*nids = gost_cipher_nids; |
|
return 2; /* two ciphers are supported */ |
|
} |
|
|
|
if (nid == NID_id_Gost28147_89) { |
|
*cipher = &cipher_gost; |
|
} else if (nid == NID_gost89_cnt) { |
|
*cipher = &cipher_gost_cpacnt; |
|
} else { |
|
ok = 0; |
|
*cipher = NULL; |
|
} |
|
return ok; |
|
} |
|
|
|
static int gost_pkey_meths(ENGINE *e, EVP_PKEY_METHOD **pmeth, |
|
const int **nids, int nid) |
|
{ |
|
if (!pmeth) { |
|
*nids = gost_pkey_meth_nids; |
|
return 3; |
|
} |
|
|
|
switch (nid) { |
|
case NID_id_GostR3410_94: |
|
*pmeth = pmeth_GostR3410_94; |
|
return 1; |
|
case NID_id_GostR3410_2001: |
|
*pmeth = pmeth_GostR3410_2001; |
|
return 1; |
|
case NID_id_Gost28147_89_MAC: |
|
*pmeth = pmeth_Gost28147_MAC; |
|
return 1; |
|
default:; |
|
} |
|
|
|
*pmeth = NULL; |
|
return 0; |
|
} |
|
|
|
static int gost_pkey_asn1_meths(ENGINE *e, EVP_PKEY_ASN1_METHOD **ameth, |
|
const int **nids, int nid) |
|
{ |
|
if (!ameth) { |
|
*nids = gost_pkey_meth_nids; |
|
return 3; |
|
} |
|
switch (nid) { |
|
case NID_id_GostR3410_94: |
|
*ameth = ameth_GostR3410_94; |
|
return 1; |
|
case NID_id_GostR3410_2001: |
|
*ameth = ameth_GostR3410_2001; |
|
return 1; |
|
case NID_id_Gost28147_89_MAC: |
|
*ameth = ameth_Gost28147_MAC; |
|
return 1; |
|
|
|
default:; |
|
} |
|
|
|
*ameth = NULL; |
|
return 0; |
|
} |
|
|
|
#ifdef OPENSSL_NO_DYNAMIC_ENGINE |
|
static ENGINE *engine_gost(void) |
|
{ |
|
ENGINE *ret = ENGINE_new(); |
|
if (!ret) |
|
return NULL; |
|
if (!bind_gost(ret, engine_gost_id)) { |
|
ENGINE_free(ret); |
|
return NULL; |
|
} |
|
return ret; |
|
} |
|
|
|
void ENGINE_load_gost(void) |
|
{ |
|
ENGINE *toadd; |
|
if (pmeth_GostR3410_94) |
|
return; |
|
toadd = engine_gost(); |
|
if (!toadd) |
|
return; |
|
ENGINE_add(toadd); |
|
ENGINE_free(toadd); |
|
ERR_clear_error(); |
|
} |
|
#endif
|
|
|