示例#1
0
文件: eng_list.c 项目: GH-JY/openssl
ENGINE *ENGINE_by_id(const char *id)
{
    ENGINE *iterator;
    char *load_dir = NULL;
    if (id == NULL) {
        ENGINEerr(ENGINE_F_ENGINE_BY_ID, ERR_R_PASSED_NULL_PARAMETER);
        return NULL;
    }
    CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
    iterator = engine_list_head;
    while (iterator && (strcmp(id, iterator->id) != 0))
        iterator = iterator->next;
    if (iterator != NULL) {
        /*
         * We need to return a structural reference. If this is an ENGINE
         * type that returns copies, make a duplicate - otherwise increment
         * the existing ENGINE's reference count.
         */
        if (iterator->flags & ENGINE_FLAGS_BY_ID_COPY) {
            ENGINE *cp = ENGINE_new();
            if (cp == NULL)
                iterator = NULL;
            else {
                engine_cpy(cp, iterator);
                iterator = cp;
            }
        } else {
            iterator->struct_ref++;
            engine_ref_debug(iterator, 0, 1)
        }
    }
    CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
    if (iterator != NULL)
        return iterator;
    /*
     * Prevent infinite recusrion if we're looking for the dynamic engine.
     */
    if (strcmp(id, "dynamic")) {
# ifdef OPENSSL_SYS_VMS
        if ((load_dir = getenv("OPENSSL_ENGINES")) == 0)
            load_dir = "SSLROOT:[ENGINES]";
# else
        if ((load_dir = getenv("OPENSSL_ENGINES")) == 0)
            load_dir = ENGINESDIR;
# endif
        iterator = ENGINE_by_id("dynamic");
        if (!iterator || !ENGINE_ctrl_cmd_string(iterator, "ID", id, 0) ||
            !ENGINE_ctrl_cmd_string(iterator, "DIR_LOAD", "2", 0) ||
            !ENGINE_ctrl_cmd_string(iterator, "DIR_ADD",
                                    load_dir, 0) ||
            !ENGINE_ctrl_cmd_string(iterator, "LIST_ADD", "1", 0) ||
            !ENGINE_ctrl_cmd_string(iterator, "LOAD", NULL, 0))
            goto notfound;
        return iterator;
    }
 notfound:
    ENGINE_free(iterator);
    ENGINEerr(ENGINE_F_ENGINE_BY_ID, ENGINE_R_NO_SUCH_ENGINE);
    ERR_add_error_data(2, "id=", id);
    return NULL;
    /* EEK! Experimental code ends */
}
static int int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, void (*f)())
	{
	int idx;
	char *s = (char *)p;
	/* Take care of the easy one first (eg. it requires no searches) */
	if(cmd == ENGINE_CTRL_GET_FIRST_CMD_TYPE)
		{
		if((e->cmd_defns == NULL) || int_ctrl_cmd_is_null(e->cmd_defns))
			return 0;
		return e->cmd_defns->cmd_num;
		}
	/* One or two commands require that "p" be a valid string buffer */
	if((cmd == ENGINE_CTRL_GET_CMD_FROM_NAME) ||
			(cmd == ENGINE_CTRL_GET_NAME_FROM_CMD) ||
			(cmd == ENGINE_CTRL_GET_DESC_FROM_CMD))
		{
		if(s == NULL)
			{
			ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
				ERR_R_PASSED_NULL_PARAMETER);
			return -1;
			}
		}
	/* Now handle cmd_name -> cmd_num conversion */
	if(cmd == ENGINE_CTRL_GET_CMD_FROM_NAME)
		{
		if((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_name(
						e->cmd_defns, s)) < 0))
			{
			ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
				ENGINE_R_INVALID_CMD_NAME);
			return -1;
			}
		return e->cmd_defns[idx].cmd_num;
		}
	/* For the rest of the commands, the 'long' argument must specify a
	 * valie command number - so we need to conduct a search. */
	if((e->cmd_defns == NULL) || ((idx = int_ctrl_cmd_by_num(e->cmd_defns,
					(unsigned int)i)) < 0))
		{
		ENGINEerr(ENGINE_F_INT_CTRL_HELPER,
			ENGINE_R_INVALID_CMD_NUMBER);
		return -1;
		}
	/* Now the logic splits depending on command type */
	switch(cmd)
		{
	case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
		idx++;
		if(int_ctrl_cmd_is_null(e->cmd_defns + idx))
			/* end-of-list */
			return 0;
		else
			return e->cmd_defns[idx].cmd_num;
	case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
		return strlen(e->cmd_defns[idx].cmd_name);
	case ENGINE_CTRL_GET_NAME_FROM_CMD:
		return BIO_snprintf(s,strlen(e->cmd_defns[idx].cmd_name) + 1,
				    "%s", e->cmd_defns[idx].cmd_name);
	case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
		if(e->cmd_defns[idx].cmd_desc)
			return strlen(e->cmd_defns[idx].cmd_desc);
		return strlen(int_no_description);
	case ENGINE_CTRL_GET_DESC_FROM_CMD:
		if(e->cmd_defns[idx].cmd_desc)
			return BIO_snprintf(s,
					    strlen(e->cmd_defns[idx].cmd_desc) + 1,
					    "%s", e->cmd_defns[idx].cmd_desc);
		return BIO_snprintf(s, strlen(int_no_description) + 1,"%s",
				    int_no_description);
	case ENGINE_CTRL_GET_CMD_FLAGS:
		return e->cmd_defns[idx].cmd_flags;
		}
	/* Shouldn't really be here ... */
	ENGINEerr(ENGINE_F_INT_CTRL_HELPER,ENGINE_R_INTERNAL_LIST_ERROR);
	return -1;
	}
int ENGINE_ctrl_cmd_string(ENGINE *e, const char *cmd_name, const char *arg,
				int cmd_optional)
	{
	int num, flags;
	long l;
	char *ptr;
	if((e == NULL) || (cmd_name == NULL))
		{
		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
			ERR_R_PASSED_NULL_PARAMETER);
		return 0;
		}
	if((e->ctrl == NULL) || ((num = ENGINE_ctrl(e,
					ENGINE_CTRL_GET_CMD_FROM_NAME,
					0, (void *)cmd_name, NULL)) <= 0))
		{
		/* If the command didn't *have* to be supported, we fake
		 * success. This allows certain settings to be specified for
		 * multiple ENGINEs and only require a change of ENGINE id
		 * (without having to selectively apply settings). Eg. changing
		 * from a hardware device back to the regular software ENGINE
		 * without editing the config file, etc. */
		if(cmd_optional)
			{
			ERR_clear_error();
			return 1;
			}
		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
			ENGINE_R_INVALID_CMD_NAME);
		return 0;
		}
	if(!ENGINE_cmd_is_executable(e, num))
		{
		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
			ENGINE_R_CMD_NOT_EXECUTABLE);
		return 0;
		}
	if((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, num, NULL, NULL)) < 0)
		{
		/* Shouldn't happen, given that ENGINE_cmd_is_executable()
		 * returned success. */
		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
			ENGINE_R_INTERNAL_LIST_ERROR);
		return 0;
		}
	/* If the command takes no input, there must be no input. And vice
	 * versa. */
	if(flags & ENGINE_CMD_FLAG_NO_INPUT)
		{
		if(arg != NULL)
			{
			ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
				ENGINE_R_COMMAND_TAKES_NO_INPUT);
			return 0;
			}
		/* We deliberately force the result of ENGINE_ctrl() to 0 or 1
		 * rather than returning it as "return data". This is to ensure
		 * usage of these commands is consistent across applications and
		 * that certain applications don't understand it one way, and
		 * others another. */
		if(ENGINE_ctrl(e, num, 0, (void *)arg, NULL))
			return 1;
		return 0;
		}
	/* So, we require input */
	if(arg == NULL)
		{
		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
			ENGINE_R_COMMAND_TAKES_INPUT);
		return 0;
		}
	/* If it takes string input, that's easy */
	if(flags & ENGINE_CMD_FLAG_STRING)
		{
		/* Same explanation as above */
		if(ENGINE_ctrl(e, num, 0, (void *)arg, NULL))
			return 1;
		return 0;
		}
	/* If it doesn't take numeric either, then it is unsupported for use in
	 * a config-setting situation, which is what this function is for. This
	 * should never happen though, because ENGINE_cmd_is_executable() was
	 * used. */
	if(!(flags & ENGINE_CMD_FLAG_NUMERIC))
		{
		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
			ENGINE_R_INTERNAL_LIST_ERROR);
		return 0;
		}
	l = strtol(arg, &ptr, 10);
	if((arg == ptr) || (*ptr != '\0'))
		{
		ENGINEerr(ENGINE_F_ENGINE_CTRL_CMD_STRING,
			ENGINE_R_ARGUMENT_IS_NOT_A_NUMBER);
		return 0;
		}
	/* Force the result of the control command to 0 or 1, for the reasons
	 * mentioned before. */
	if(ENGINE_ctrl(e, num, l, NULL, NULL))
		return 1;
	return 0;
	}
示例#4
0
static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
{
    ENGINE cpy;
    dynamic_fns fns;

    if (ctx->dynamic_dso == NULL)
        ctx->dynamic_dso = DSO_new();
    if (ctx->dynamic_dso == NULL)
        return 0;
    if (!ctx->DYNAMIC_LIBNAME) {
        if (!ctx->engine_id)
            return 0;
        ctx->DYNAMIC_LIBNAME =
            DSO_convert_filename(ctx->dynamic_dso, ctx->engine_id);
    }
    if (!int_load(ctx)) {
        ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_NOT_FOUND);
        DSO_free(ctx->dynamic_dso);
        ctx->dynamic_dso = NULL;
        return 0;
    }
    /* We have to find a bind function otherwise it'll always end badly */
    if (!
        (ctx->bind_engine =
         (dynamic_bind_engine) DSO_bind_func(ctx->dynamic_dso,
                                             ctx->DYNAMIC_F2))) {
        ctx->bind_engine = NULL;
        DSO_free(ctx->dynamic_dso);
        ctx->dynamic_dso = NULL;
        ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_DSO_FAILURE);
        return 0;
    }
    /* Do we perform version checking? */
    if (!ctx->no_vcheck) {
        unsigned long vcheck_res = 0;
        /*
         * Now we try to find a version checking function and decide how to
         * cope with failure if/when it fails.
         */
        ctx->v_check =
            (dynamic_v_check_fn) DSO_bind_func(ctx->dynamic_dso,
                                               ctx->DYNAMIC_F1);
        if (ctx->v_check)
            vcheck_res = ctx->v_check(OSSL_DYNAMIC_VERSION);
        /*
         * We fail if the version checker veto'd the load *or* if it is
         * deferring to us (by returning its version) and we think it is too
         * old.
         */
        if (vcheck_res < OSSL_DYNAMIC_OLDEST) {
            /* Fail */
            ctx->bind_engine = NULL;
            ctx->v_check = NULL;
            DSO_free(ctx->dynamic_dso);
            ctx->dynamic_dso = NULL;
            ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
                      ENGINE_R_VERSION_INCOMPATIBILITY);
            return 0;
        }
    }
    /*
     * First binary copy the ENGINE structure so that we can roll back if the
     * hand-over fails
     */
    memcpy(&cpy, e, sizeof(ENGINE));
    /*
     * Provide the ERR, "ex_data", memory, and locking callbacks so the
     * loaded library uses our state rather than its own. FIXME: As noted in
     * engine.h, much of this would be simplified if each area of code
     * provided its own "summary" structure of all related callbacks. It
     * would also increase opaqueness.
     */
    fns.static_state = ENGINE_get_static_state();
    fns.lock_fns.lock_locking_cb = CRYPTO_get_locking_callback();
    fns.lock_fns.lock_add_lock_cb = CRYPTO_get_add_lock_callback();
    fns.lock_fns.dynlock_create_cb = CRYPTO_get_dynlock_create_callback();
    fns.lock_fns.dynlock_lock_cb = CRYPTO_get_dynlock_lock_callback();
    fns.lock_fns.dynlock_destroy_cb = CRYPTO_get_dynlock_destroy_callback();
    /*
     * Now that we've loaded the dynamic engine, make sure no "dynamic"
     * ENGINE elements will show through.
     */
    engine_set_all_null(e);

    /* Try to bind the ENGINE onto our own ENGINE structure */
    if (!ctx->bind_engine(e, ctx->engine_id, &fns)) {
        ctx->bind_engine = NULL;
        ctx->v_check = NULL;
        DSO_free(ctx->dynamic_dso);
        ctx->dynamic_dso = NULL;
        ENGINEerr(ENGINE_F_DYNAMIC_LOAD, ENGINE_R_INIT_FAILED);
        /* Copy the original ENGINE structure back */
        memcpy(e, &cpy, sizeof(ENGINE));
        return 0;
    }
    /* Do we try to add this ENGINE to the internal list too? */
    if (ctx->list_add_value > 0) {
        if (!ENGINE_add(e)) {
            /* Do we tolerate this or fail? */
            if (ctx->list_add_value > 1) {
                /*
                 * Fail - NB: By this time, it's too late to rollback, and
                 * trying to do so allows the bind_engine() code to have
                 * created leaks. We just have to fail where we are, after
                 * the ENGINE has changed.
                 */
                ENGINEerr(ENGINE_F_DYNAMIC_LOAD,
                          ENGINE_R_CONFLICTING_ENGINE_ID);
                return 0;
            }
            /* Tolerate */
            ERR_clear_error();
        }
    }
    return 1;
}
示例#5
0
static int dynamic_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void))
{
    dynamic_data_ctx *ctx = dynamic_get_data_ctx(e);
    int initialised;

    if (!ctx) {
        ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_NOT_LOADED);
        return 0;
    }
    initialised = ((ctx->dynamic_dso == NULL) ? 0 : 1);
    /* All our control commands require the ENGINE to be uninitialised */
    if (initialised) {
        ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_ALREADY_LOADED);
        return 0;
    }
    switch (cmd) {
    case DYNAMIC_CMD_SO_PATH:
        /* a NULL 'p' or a string of zero-length is the same thing */
        if (p && (strlen((const char *)p) < 1))
            p = NULL;
        OPENSSL_free(ctx->DYNAMIC_LIBNAME);
        if (p)
            ctx->DYNAMIC_LIBNAME = OPENSSL_strdup(p);
        else
            ctx->DYNAMIC_LIBNAME = NULL;
        return (ctx->DYNAMIC_LIBNAME ? 1 : 0);
    case DYNAMIC_CMD_NO_VCHECK:
        ctx->no_vcheck = ((i == 0) ? 0 : 1);
        return 1;
    case DYNAMIC_CMD_ID:
        /* a NULL 'p' or a string of zero-length is the same thing */
        if (p && (strlen((const char *)p) < 1))
            p = NULL;
        OPENSSL_free(ctx->engine_id);
        if (p)
            ctx->engine_id = OPENSSL_strdup(p);
        else
            ctx->engine_id = NULL;
        return (ctx->engine_id ? 1 : 0);
    case DYNAMIC_CMD_LIST_ADD:
        if ((i < 0) || (i > 2)) {
            ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
            return 0;
        }
        ctx->list_add_value = (int)i;
        return 1;
    case DYNAMIC_CMD_LOAD:
        return dynamic_load(e, ctx);
    case DYNAMIC_CMD_DIR_LOAD:
        if ((i < 0) || (i > 2)) {
            ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
            return 0;
        }
        ctx->dir_load = (int)i;
        return 1;
    case DYNAMIC_CMD_DIR_ADD:
        /* a NULL 'p' or a string of zero-length is the same thing */
        if (!p || (strlen((const char *)p) < 1)) {
            ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_INVALID_ARGUMENT);
            return 0;
        }
        {
            char *tmp_str = OPENSSL_strdup(p);
            if (!tmp_str) {
                ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ERR_R_MALLOC_FAILURE);
                return 0;
            }
            sk_OPENSSL_STRING_insert(ctx->dirs, tmp_str, -1);
        }
        return 1;
    default:
        break;
    }
    ENGINEerr(ENGINE_F_DYNAMIC_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED);
    return 0;
}
示例#6
0
static int int_engine_configure(char *name, char *value, const CONF *cnf)
	{
	int i;
	int ret = 0;
	long do_init = -1;
	STACK_OF(CONF_VALUE) *ecmds;
	CONF_VALUE *ecmd = NULL;
	char *ctrlname, *ctrlvalue;
	ENGINE *e = NULL;
	int soft = 0;

	name = skip_dot(name);
#ifdef ENGINE_CONF_DEBUG
	fprintf(stderr, "Configuring engine %s\n", name);
#endif
	/* Value is a section containing ENGINE commands */
	ecmds = NCONF_get_section(cnf, value);

	if (!ecmds)
		{
		ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_SECTION_ERROR);
		return 0;
		}

	for (i = 0; i < sk_CONF_VALUE_num(ecmds); i++)
		{
		ecmd = sk_CONF_VALUE_value(ecmds, i);
		ctrlname = skip_dot(ecmd->name);
		ctrlvalue = ecmd->value;
#ifdef ENGINE_CONF_DEBUG
	fprintf(stderr, "ENGINE conf: doing ctrl(%s,%s)\n", ctrlname, ctrlvalue);
#endif

		/* First handle some special pseudo ctrls */

		/* Override engine name to use */
		if (!op_strcmp(ctrlname, "engine_id"))
			name = ctrlvalue;
		else if (!strcmp(ctrlname, "soft_load"))
			soft = 1;
		/* Load a dynamic ENGINE */
		else if (!op_strcmp(ctrlname, "dynamic_path"))
			{
			e = ENGINE_by_id("dynamic");
			if (!e)
				goto err;
			if (!ENGINE_ctrl_cmd_string(e, "SO_PATH", ctrlvalue, 0))
				goto err;
			if (!ENGINE_ctrl_cmd_string(e, "LIST_ADD", "2", 0))
				goto err;
			if (!ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0))
				goto err;
			}
		/* ... add other pseudos here ... */
		else
			{
			/* At this point we need an ENGINE structural reference
			 * if we don't already have one.
			 */
			if (!e)
				{
				e = ENGINE_by_id(name);
				if (!e && soft)
					{
					ERR_clear_error();
					return 1;
					}
				if (!e)
					goto err;
				}
			/* Allow "EMPTY" to mean no value: this allows a valid
			 * "value" to be passed to ctrls of type NO_INPUT
		 	 */
			if (!op_strcmp(ctrlvalue, "EMPTY"))
				ctrlvalue = NULL;
			if (!op_strcmp(ctrlname, "init"))
				{
				if (!NCONF_get_number_e(cnf, value, "init", &do_init))
					goto err;
				if (do_init == 1)
					{
					if (!int_engine_init(e))
						goto err;
					}
				else if (do_init != 0)
					{
					ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_INVALID_INIT_VALUE);
					goto err;
					}
				}
			else if (!op_strcmp(ctrlname, "default_algorithms"))
				{
				if (!ENGINE_set_default_string(e, ctrlvalue))
					goto err;
				}
			else if (!ENGINE_ctrl_cmd_string(e,
					ctrlname, ctrlvalue, 0))
				goto err;
			}



		}
	if (e && (do_init == -1) && !int_engine_init(e))
		{
		ecmd = NULL;
		goto err;
		}
	ret = 1;
	err:
	if (ret != 1)
		{
		ENGINEerr(ENGINE_F_INT_ENGINE_CONFIGURE, ENGINE_R_ENGINE_CONFIGURATION_ERROR);
		if (ecmd)
			ERR_add_error_data(6, "section=", ecmd->section, 
						", name=", ecmd->name,
						", value=", ecmd->value);
		}
	if (e)
		ENGINE_free(e);
	return ret;
	}
/* DH stuff Functions
 */
static int DH_zencod_generate_key ( DH *dh )
{
	BIGNUM *bn_prv = NULL;
	BIGNUM *bn_pub = NULL;
	zen_nb_t y, x, g, p;
	int generate_x;

	CHEESE();

	if ( !zencod_dso ) {
		ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_NOT_LOADED);
		return 0;
	}

	/* Private key */
	if ( dh->priv_key ) {
		bn_prv = dh->priv_key;
		generate_x = 0;
	} else {
		if (!(bn_prv = BN_new())) {
			ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
			goto FAILED;
		}
		generate_x = 1;
	}

	/* Public key */
	if ( dh->pub_key )
		bn_pub = dh->pub_key;
	else
		if ( !( bn_pub = BN_new () ) ) {
			ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
			goto FAILED;
		}

	/* Expand */
	if ( !bn_wexpand ( bn_prv, dh->p->dmax ) ||
	    !bn_wexpand ( bn_pub, dh->p->dmax ) ) {
		ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_BN_EXPAND_FAIL);
		goto FAILED;
	}
	bn_prv->top = dh->p->top;
	bn_pub->top = dh->p->top;

	/* Convert all keys */
	BIGNUM2ZEN ( &p, dh->p ) ;
	BIGNUM2ZEN ( &g, dh->g ) ;
	BIGNUM2ZEN ( &y, bn_pub ) ;
	BIGNUM2ZEN ( &x, bn_prv ) ;
	x.len = DH_size(dh) * 8;

	/* Adjust the lengths of P and G */
	p.len = ptr_zencod_bytes2bits ( p.data, ZEN_BYTES ( p.len ) ) ;
	g.len = ptr_zencod_bytes2bits ( g.data, ZEN_BYTES ( g.len ) ) ;

	/* Send the request to the driver */
	if ( ptr_zencod_dh_generate_key ( &y, &x, &g, &p, generate_x ) < 0 ) {
		perror("zenbridge_dh_generate_key");
		ENGINEerr(ZENCOD_F_ZENCOD_DH_GENERATE, ZENCOD_R_REQUEST_FAILED);
		goto FAILED;
	}

	dh->priv_key = bn_prv;
	dh->pub_key  = bn_pub;

	return 1;

 FAILED:
	if (!dh->priv_key && bn_prv)
		BN_free(bn_prv);
	if (!dh->pub_key && bn_pub)
		BN_free(bn_pub);

	return 0;
}
/* DSA stuff Functions
 */
static DSA_SIG *DSA_zencod_do_sign ( const unsigned char *dgst, int dlen, DSA *dsa )
{
	zen_nb_t p, q, g, x, y, r, s, data;
	DSA_SIG *sig;
	BIGNUM *bn_r = NULL;
	BIGNUM *bn_s = NULL;
	char msg[20];

	CHEESE();

	if ( !zencod_dso ) {
		ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_NOT_LOADED);
		goto FAILED;
	}

	if ( dlen > 160 ) {
		ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
		goto FAILED;
	}

	/* Do in software if argument is too large for hardware */
	if ( BN_num_bits(dsa->p) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ||
		BN_num_bits(dsa->g) > ZENBRIDGE_MAX_KEYSIZE_DSA_SIGN ) {
		const DSA_METHOD *meth;
		ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BAD_KEY_COMPONENTS);
		meth = DSA_OpenSSL();
		return meth->dsa_do_sign(dgst, dlen, dsa);
	}

	if ( !(bn_s = BN_new()) || !(bn_r = BN_new()) ) {
		ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BAD_KEY_COMPONENTS);
		goto FAILED;
	}

	if ( !bn_expand(bn_r, 160) || !bn_expand(bn_s, 160) ) {
		ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_BN_EXPAND_FAIL);
		goto FAILED;
	}

	bn_r->top = bn_s->top = (160 + BN_BITS2 - 1) / BN_BITS2;
	BIGNUM2ZEN ( &p, dsa->p ) ;
	BIGNUM2ZEN ( &q, dsa->q ) ;
	BIGNUM2ZEN ( &g, dsa->g ) ;
	BIGNUM2ZEN ( &x, dsa->priv_key ) ;
	BIGNUM2ZEN ( &y, dsa->pub_key ) ;
	BIGNUM2ZEN ( &r, bn_r ) ;
	BIGNUM2ZEN ( &s, bn_s ) ;
	q.len = x.len = 160;

	ypcmem(msg, dgst, 20);
	ptr_zencod_init_number ( &data, 160, msg ) ;

	if ( ptr_zencod_dsa_do_sign ( 0, &data, &y, &p, &q, &g, &x, &r, &s ) < 0 ) {
		PERROR("zenbridge_dsa_do_sign");
		ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
		goto FAILED;
	}

	if ( !( sig = DSA_SIG_new () ) ) {
		ENGINEerr(ZENCOD_F_ZENCOD_DSA_DO_SIGN, ZENCOD_R_REQUEST_FAILED);
		goto FAILED;
	}
	sig->r = bn_r;
	sig->s = bn_s;
	return sig;

 FAILED:
	if (bn_r)
		BN_free(bn_r);
	if (bn_s)
		BN_free(bn_s);
	return NULL;
}