/* * Free a functional reference to a engine type. This version is only used * internally. */ int engine_unlocked_finish(ENGINE *e, int unlock_for_handlers) { int to_return = 1; /* * Reduce the functional reference count here so if it's the terminating * case, we can release the lock safely and call the finish() handler * without risk of a race. We get a race if we leave the count until * after and something else is calling "finish" at the same time - * there's a chance that both threads will together take the count from 2 * to 0 without either calling finish(). */ e->funct_ref--; engine_ref_debug(e, 1, -1); if ((e->funct_ref == 0) && e->finish) { if (unlock_for_handlers) CRYPTO_THREAD_unlock(global_engine_lock); to_return = e->finish(e); if (unlock_for_handlers) CRYPTO_THREAD_write_lock(global_engine_lock); if (!to_return) return 0; } REF_ASSERT_ISNT(e->funct_ref < 0); /* Release the structural reference too */ if (!engine_free_util(e, 0)) { ENGINEerr(ENGINE_F_ENGINE_UNLOCKED_FINISH, ENGINE_R_FINISH_FAILED); return 0; } return to_return; }
/* These static functions starting with a lower case "engine_" always * take place when CRYPTO_LOCK_ENGINE has been locked up. */ static int engine_list_add(ENGINE *e) { int conflict = 0; ENGINE *iterator = NULL; if(e == NULL) { ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ERR_R_PASSED_NULL_PARAMETER); return 0; } iterator = engine_list_head; while(iterator && !conflict) { conflict = (strcmp(iterator->id, e->id) == 0); iterator = iterator->next; } if(conflict) { ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_CONFLICTING_ENGINE_ID); return 0; } if(engine_list_head == NULL) { /* We are adding to an empty list. */ if(engine_list_tail) { ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR); return 0; } engine_list_head = e; e->prev = NULL; /* The first time the list allocates, we should register the * cleanup. */ engine_cleanup_add_last(engine_list_cleanup); } else { /* We are adding to the tail of an existing list. */ if((engine_list_tail == NULL) || (engine_list_tail->next != NULL)) { ENGINEerr(ENGINE_F_ENGINE_LIST_ADD, ENGINE_R_INTERNAL_LIST_ERROR); return 0; } engine_list_tail->next = e; e->prev = engine_list_tail; } /* Having the engine in the list assumes a structural * reference. */ e->struct_ref++; engine_ref_debug(e, 0, 1) /* However it came to be, e is the last item in the list. */ engine_list_tail = e; e->next = NULL; return 1; }
ENGINE *ENGINE_get_last(void) { ENGINE *ret; CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); ret = engine_list_tail; if (ret) { ret->struct_ref++; engine_ref_debug(ret, 0, 1); } CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); return ret; }
/* * Initialise a engine type for use (or up its functional reference count if * it's already in use). This version is only used internally. */ int engine_unlocked_init(ENGINE *e) { int to_return = 1; if ((e->funct_ref == 0) && e->init) /* * This is the first functional reference and the engine requires * initialisation so we do it now. */ to_return = e->init(e); if (to_return) { /* * OK, we return a functional reference which is also a structural * reference. */ e->struct_ref++; e->funct_ref++; engine_ref_debug(e, 0, 1); engine_ref_debug(e, 1, 1); } return to_return; }
ENGINE *ENGINE_new(void) { ENGINE *ret; ret = OPENSSL_zalloc(sizeof(*ret)); if (ret == NULL) { ENGINEerr(ENGINE_F_ENGINE_NEW, ERR_R_MALLOC_FAILURE); return NULL; } ret->struct_ref = 1; engine_ref_debug(ret, 0, 1); CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data); return ret; }
ENGINE *ENGINE_new(void) { ENGINE *ret; if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init) || (ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) { ENGINEerr(ENGINE_F_ENGINE_NEW, ERR_R_MALLOC_FAILURE); return NULL; } ret->struct_ref = 1; engine_ref_debug(ret, 0, 1); if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data)) { OPENSSL_free(ret); return NULL; } return ret; }
ENGINE *ENGINE_get_prev(ENGINE *e) { ENGINE *ret = NULL; if (e == NULL) { ENGINEerr(ENGINE_F_ENGINE_GET_PREV, ERR_R_PASSED_NULL_PARAMETER); return 0; } CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); ret = e->prev; if (ret) { /* Return a valid structural reference to the next ENGINE */ ret->struct_ref++; engine_ref_debug(ret, 0, 1); } CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); /* Release the structural reference to the previous ENGINE */ ENGINE_free(e); return ret; }
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; }
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 recursion 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 */ }