Hello!
On Mon, 17 Jan 2005, Richard Levitte - VMS Whacker wrote:
> In message <[EMAIL PROTECTED]> on Mon, 17 Jan 2005 11:06:49 +0300 (MSK),
> Dmitry Belyavsky <[EMAIL PROTECTED]> said:
>
> beldmit> We are implementing custom engine providing GOST algorithms.
> beldmit> We get a SEGFAULT on app_shutdown.
>
> That's because of the call to ENGINE_unregister_ciphers() in
> cce_destroy(). Can I suggest you take a look at, for example,
> demos/engines/rsaref/ for a working example to look at?
Unfortunately that's not only because of ENGINE_unregister_ciphers(). I
took a look a demos/engines/rsaref/. My engine doesn't use existing NIDs
but registers custom with OBJ_create. So when I comment out line 81,
nothing but memory leaks happens. When I don't comment it, I get a
SEGFAULT again. Should I call OBJ_cleanup() from engine destroy function
and how do I avoid memory leaks if not?
I use 20050117 snapshot. "Engine" code is attached, engine is used via
"openssl engine minimum" command line.
Thank you.
--
SY, Dmitry Belyavsky (ICQ UIN 11116575)
#include <string.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
#include <openssl/objects.h>
static int NID_minimum_cipher_GOST = NID_undef;
#define OID_gost89 "1.2.643.2.9.1.1.1"
#define SN_gost89 "gost89"
#define LN_gost89 "GOST 28147-89 symmetric cipher"
int register_minimum_NID (void)
{
NID_minimum_cipher_GOST = OBJ_create(OID_gost89, SN_gost89, LN_gost89);
if (NID_minimum_cipher_GOST == NID_undef) {goto err;}
return 1;
err:
NID_minimum_cipher_GOST = NID_undef;
return 0;
}
/* Fake crypt functions */
int cce_cipher_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc){return 1;}
int cce_cipher_do(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, unsigned int inl){return 1;}
int cce_cipher_cleanup(EVP_CIPHER_CTX *ctx){return 1;}
#define minimum_LIB_NAME "minimum GOST engine"
static const char *engine_minimum_id = "minimum";
static const char *engine_minimum_name = "minimum GOST engine";
static int cce_destroy(ENGINE *e);
static int cce_init(ENGINE *e);
static int cce_finish(ENGINE *e);
/* Engine commands */
static const ENGINE_CMD_DEFN cce_cmd_defns[] = {
{0, NULL, NULL, 0}
};
/* Symetric cipher and digest function registrar */
static int cce_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
static int cce_cipher_nids[]=
{NID_undef,0};
static EVP_CIPHER cipher_gost =
{
NID_undef,
1,/*block_size*/
32,/*key_size*/
8,
EVP_CIPH_CFB_MODE|EVP_CIPH_CUSTOM_IV|EVP_CIPH_NO_PADDING,
cce_cipher_init,
cce_cipher_do,
cce_cipher_cleanup,
0,/* ctx_size */
NULL,
NULL,
NULL,
NULL,
};
static int cce_init(ENGINE *e) {
return 1;
}
static int cce_finish(ENGINE *e) {
return 1;
}
static int cce_destroy(ENGINE *e) {
OBJ_cleanup();
return 1;
}
static int bind_cce (ENGINE *e,const char *id) {
if (id && strcmp(id, engine_minimum_id)) return 0;
if (!ENGINE_set_id(e, engine_minimum_id)) {
printf("ENGINE_set_id failed\n");
return 0;
}
if (!ENGINE_set_name(e, engine_minimum_name)) {
printf("ENGINE_set_name failed\n");
return 0;
}
if (!register_minimum_NID()) return 0;
/* -------- set up NIDs */
cipher_gost.nid = NID_minimum_cipher_GOST;
/* -------- end set up NIDs */
if (! ENGINE_set_ciphers(e, cce_ciphers)) {
printf("ENGINE_set_ciphers failed\n");
return 0;
}
if ( ! ENGINE_set_destroy_function(e, cce_destroy)
|| ! ENGINE_set_init_function(e,cce_init)
|| ! ENGINE_set_finish_function(e,cce_finish)) return 0;
if (!EVP_add_cipher(&cipher_gost)) return 0;
return 1;
}
#ifdef _WIN32
extern __declspec( dllexport )
#endif
#ifndef OPENSSL_NO_DYNAMIC_ENGINE
IMPLEMENT_DYNAMIC_BIND_FN(bind_cce);
IMPLEMENT_DYNAMIC_CHECK_FN();
#else
static ENGINE *engine_cce(void)
{
ENGINE *ret = ENGINE_new();
if(!ret)
return NULL;
if(!bind_cce(ret, engine_minimum_id))
{
ENGINE_free(ret);
return NULL;
}
return ret;
}
void ENGINE_load_cce(void)
{
/* Copied from eng_[openssl|dyn].c */
ENGINE *toadd = engine_cce();
if(!toadd) return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
}
#endif /* OPENSSL_NO_DYNAMIC_ENGINE */
static int cce_ciphers (ENGINE *e,const EVP_CIPHER **cipher,
const int **nids, int nid) {
int ok = 1;
if (!cipher) {
/* return list of supported nids */
if (cce_cipher_nids[0] == NID_undef) {
cce_cipher_nids[0] = NID_minimum_cipher_GOST;
}
*nids = cce_cipher_nids;
return 1; /* Only one cipher supported */
}
if(nid == NID_minimum_cipher_GOST) {
*cipher = &cipher_gost;
} else {
ok = 0;
}
return ok;
}