Beispiel #1
0
int
ENGINE_ctrl_cmd(ENGINE *e, const char *cmd_name, long i, void *p,
    void (*f)(void), int cmd_optional)
{
	int num;

	if ((e == NULL) || (cmd_name == NULL)) {
		ENGINEerror(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;
		}
		ENGINEerror(ENGINE_R_INVALID_CMD_NAME);
		return 0;
	}

	/* Force the result of the control command to 0 or 1, for the reasons
	 * mentioned before. */
	if (ENGINE_ctrl(e, num, i, p, f) > 0)
		return 1;

	return 0;
}
Beispiel #2
0
int
ENGINE_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
{
	int ctrl_exists, ref_exists;

	if (e == NULL) {
		ENGINEerror(ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}
	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
	ref_exists = ((e->struct_ref > 0) ? 1 : 0);
	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
	ctrl_exists = ((e->ctrl == NULL) ? 0 : 1);
	if (!ref_exists) {
		ENGINEerror(ENGINE_R_NO_REFERENCE);
		return 0;
	}
	/* Intercept any "root-level" commands before trying to hand them on to
	 * ctrl() handlers. */
	switch (cmd) {
	case ENGINE_CTRL_HAS_CTRL_FUNCTION:
		return ctrl_exists;
	case ENGINE_CTRL_GET_FIRST_CMD_TYPE:
	case ENGINE_CTRL_GET_NEXT_CMD_TYPE:
	case ENGINE_CTRL_GET_CMD_FROM_NAME:
	case ENGINE_CTRL_GET_NAME_LEN_FROM_CMD:
	case ENGINE_CTRL_GET_NAME_FROM_CMD:
	case ENGINE_CTRL_GET_DESC_LEN_FROM_CMD:
	case ENGINE_CTRL_GET_DESC_FROM_CMD:
	case ENGINE_CTRL_GET_CMD_FLAGS:
		if (ctrl_exists && !(e->flags & ENGINE_FLAGS_MANUAL_CMD_CTRL))
			return int_ctrl_helper(e, cmd, i, p, f);
		if (!ctrl_exists) {
			ENGINEerror(ENGINE_R_NO_CONTROL_FUNCTION);
			/* For these cmd-related functions, failure is indicated
			 * by a -1 return value (because 0 is used as a valid
			 * return in some places). */
			return -1;
		}
	default:
		break;
	}
	/* Anything else requires a ctrl() handler to exist. */
	if (!ctrl_exists) {
		ENGINEerror(ENGINE_R_NO_CONTROL_FUNCTION);
		return 0;
	}
	return e->ctrl(e, cmd, i, p, f);
}
Beispiel #3
0
int
engine_free_util(ENGINE *e, int locked)
{
	int i;

	if (e == NULL) {
		ENGINEerror(ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}
	if (locked)
		i = CRYPTO_add(&e->struct_ref, -1, CRYPTO_LOCK_ENGINE);
	else
		i = --e->struct_ref;
	engine_ref_debug(e, 0, -1)
	if (i > 0)
		return 1;

	/* Free up any dynamically allocated public key methods */
	engine_pkey_meths_free(e);
	engine_pkey_asn1_meths_free(e);
	/* Give the ENGINE a chance to do any structural cleanup corresponding
	 * to allocation it did in its constructor (eg. unload error strings) */
	if (e->destroy)
		e->destroy(e);
	CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data);
	free(e);
	return 1;
}
Beispiel #4
0
static int
int_engine_module_init(CONF_IMODULE *md, const CONF *cnf)
{
	STACK_OF(CONF_VALUE) *elist;
	CONF_VALUE *cval;
	int i;

#ifdef ENGINE_CONF_DEBUG
	fprintf(stderr, "Called engine module: name %s, value %s\n",
	    CONF_imodule_get_name(md), CONF_imodule_get_value(md));
#endif
	/* Value is a section containing ENGINEs to configure */
	elist = NCONF_get_section(cnf, CONF_imodule_get_value(md));

	if (!elist) {
		ENGINEerror(ENGINE_R_ENGINES_SECTION_ERROR);
		return 0;
	}

	for (i = 0; i < sk_CONF_VALUE_num(elist); i++) {
		cval = sk_CONF_VALUE_value(elist, i);
		if (!int_engine_configure(cval->name, cval->value, cnf))
			return 0;
	}

	return 1;
}
Beispiel #5
0
/* Privately exposed (via eng_int.h) functions for adding and/or removing
 * ENGINEs from the implementation table */
int
engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
    ENGINE *e, const int *nids, int num_nids, int setdefault)
{
	int ret = 0, added = 0;
	ENGINE_PILE tmplate, *fnd;

	CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
	if (!(*table))
		added = 1;
	if (!int_table_check(table, 1))
		goto end;
	if (added)
		/* The cleanup callback needs to be added */
		engine_cleanup_add_first(cleanup);
	while (num_nids--) {
		tmplate.nid = *nids;
		fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
		if (!fnd) {
			fnd = malloc(sizeof(ENGINE_PILE));
			if (!fnd)
				goto end;
			fnd->uptodate = 1;
			fnd->nid = *nids;
			fnd->sk = sk_ENGINE_new_null();
			if (!fnd->sk) {
				free(fnd);
				goto end;
			}
			fnd->funct = NULL;
			(void)lh_ENGINE_PILE_insert(&(*table)->piles, fnd);
		}
		/* A registration shouldn't add duplciate entries */
		(void)sk_ENGINE_delete_ptr(fnd->sk, e);
		/* if 'setdefault', this ENGINE goes to the head of the list */
		if (!sk_ENGINE_push(fnd->sk, e))
			goto end;
		/* "touch" this ENGINE_PILE */
		fnd->uptodate = 0;
		if (setdefault) {
			if (!engine_unlocked_init(e)) {
				ENGINEerror(ENGINE_R_INIT_FAILED);
				goto end;
			}
			if (fnd->funct)
				engine_unlocked_finish(fnd->funct, 0);
			fnd->funct = e;
			fnd->uptodate = 1;
		}
		nids++;
	}
	ret = 1;
end:
	CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
	return ret;
}
Beispiel #6
0
int
ENGINE_set_name(ENGINE *e, const char *name)
{
	if (name == NULL) {
		ENGINEerror(ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}
	e->name = name;
	return 1;
}
Beispiel #7
0
int
ENGINE_set_id(ENGINE *e, const char *id)
{
	if (id == NULL) {
		ENGINEerror(ERR_R_PASSED_NULL_PARAMETER);
		return 0;
	}
	e->id = id;
	return 1;
}
Beispiel #8
0
/* Obtains a pkey_asn1_meth implementation from an ENGINE functional reference */
const EVP_PKEY_ASN1_METHOD *
ENGINE_get_pkey_asn1_meth(ENGINE *e, int nid)
{
	EVP_PKEY_ASN1_METHOD *ret;
	ENGINE_PKEY_ASN1_METHS_PTR fn = ENGINE_get_pkey_asn1_meths(e);

	if (!fn || !fn(e, &ret, NULL, nid)) {
		ENGINEerror(ENGINE_R_UNIMPLEMENTED_PUBLIC_KEY_METHOD);
		return NULL;
	}
	return ret;
}
Beispiel #9
0
int
ENGINE_cmd_is_executable(ENGINE *e, int cmd)
{
	int flags;

	if ((flags = ENGINE_ctrl(e, ENGINE_CTRL_GET_CMD_FLAGS, cmd,
	    NULL, NULL)) < 0) {
		ENGINEerror(ENGINE_R_INVALID_CMD_NUMBER);
		return 0;
	}
	if (!(flags & ENGINE_CMD_FLAG_NO_INPUT) &&
	    !(flags & ENGINE_CMD_FLAG_NUMERIC) &&
	    !(flags & ENGINE_CMD_FLAG_STRING))
		return 0;
	return 1;
}
Beispiel #10
0
ENGINE *
ENGINE_new(void)
{
	ENGINE *ret;

	if (!OPENSSL_init_crypto(0, NULL))
		return NULL;

	ret = malloc(sizeof(ENGINE));
	if (ret == NULL) {
		ENGINEerror(ERR_R_MALLOC_FAILURE);
		return NULL;
	}
	memset(ret, 0, sizeof(ENGINE));
	ret->struct_ref = 1;
	engine_ref_debug(ret, 0, 1)
	CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data);
	return ret;
}
Beispiel #11
0
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)) {
		ENGINEerror(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;
		}
		ENGINEerror(ENGINE_R_INVALID_CMD_NAME);
		return 0;
	}
	if (!ENGINE_cmd_is_executable(e, num)) {
		ENGINEerror(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. */
		ENGINEerror(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) {
			ENGINEerror(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) > 0)
			return 1;
		return 0;
	}
	/* So, we require input */
	if (arg == NULL) {
		ENGINEerror(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) > 0)
			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)) {
		ENGINEerror(ENGINE_R_INTERNAL_LIST_ERROR);
		return 0;
	}
	l = strtol(arg, &ptr, 10);
	if ((arg == ptr) || (*ptr != '\0')) {
		ENGINEerror(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) > 0)
		return 1;
	return 0;
}
Beispiel #12
0
static int
int_ctrl_helper(ENGINE *e, int cmd, long i, void *p, void (*f)(void))
{
	int idx;
	int ret;
	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) {
			ENGINEerror(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)) {
			ENGINEerror(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)) {
		ENGINEerror(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:
		ret = snprintf(s, strlen(e->cmd_defns[idx].cmd_name) + 1,
		    "%s", e->cmd_defns[idx].cmd_name);
		if (ret >= (strlen(e->cmd_defns[idx].cmd_name) + 1))
			ret = -1;
		return ret;
	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) {
			ret = snprintf(s,
			    strlen(e->cmd_defns[idx].cmd_desc) + 1,
			    "%s", e->cmd_defns[idx].cmd_desc);
			if (ret >= strlen(e->cmd_defns[idx].cmd_desc) + 1)
				ret = -1;
			return ret;
		}
		ret = snprintf(s, strlen(int_no_description) + 1, "%s",
		    int_no_description);
		if (ret >= strlen(int_no_description) + 1)
			ret = -1;
		return ret;
	case ENGINE_CTRL_GET_CMD_FLAGS:
		return e->cmd_defns[idx].cmd_flags;
	}

	/* Shouldn't really be here ... */
	ENGINEerror(ENGINE_R_INTERNAL_LIST_ERROR);
	return -1;
}
Beispiel #13
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) {
		ENGINEerror(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 (!strcmp(ctrlname, "engine_id"))
			name = ctrlvalue;
		else if (!strcmp(ctrlname, "soft_load"))
			soft = 1;
		/* Load a dynamic ENGINE */
		else if (!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 (!strcmp(ctrlvalue, "EMPTY"))
				ctrlvalue = NULL;
			if (!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) {
					ENGINEerror(ENGINE_R_INVALID_INIT_VALUE);
					goto err;
				}
			}
			else if (!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) {
		ENGINEerror(ENGINE_R_ENGINE_CONFIGURATION_ERROR);
		if (ecmd)
			ERR_asprintf_error_data(
			    "section=%s, name=%s, value=%s",
			    ecmd->section, ecmd->name, ecmd->value);
	}
	if (e)
		ENGINE_free(e);
	return ret;
}