1  /*
2   * Copyright 2001-2021 The OpenSSL Project Authors. All Rights Reserved.
3   *
4   * Licensed under the Apache License 2.0 (the "License").  You may not use
5   * this file except in compliance with the License.  You can obtain a copy
6   * in the file LICENSE in the source distribution or at
7   * https://www.openssl.org/source/license.html
8   */
9  
10  #include "e_os.h"
11  #include "eng_local.h"
12  #include <openssl/rand.h>
13  #include "internal/refcount.h"
14  
15  CRYPTO_RWLOCK *global_engine_lock;
16  
17  CRYPTO_ONCE engine_lock_init = CRYPTO_ONCE_STATIC_INIT;
18  
19  /* The "new"/"free" stuff first */
20  
DEFINE_RUN_ONCE(do_engine_lock_init)21  DEFINE_RUN_ONCE(do_engine_lock_init)
22  {
23      global_engine_lock = CRYPTO_THREAD_lock_new();
24      return global_engine_lock != NULL;
25  }
26  
ENGINE_new(void)27  ENGINE *ENGINE_new(void)
28  {
29      ENGINE *ret;
30  
31      if (!RUN_ONCE(&engine_lock_init, do_engine_lock_init)
32          || (ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
33          ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
34          return NULL;
35      }
36      ret->struct_ref = 1;
37      ENGINE_REF_PRINT(ret, 0, 1);
38      if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ENGINE, ret, &ret->ex_data)) {
39          OPENSSL_free(ret);
40          return NULL;
41      }
42      return ret;
43  }
44  
45  /*
46   * Placed here (close proximity to ENGINE_new) so that modifications to the
47   * elements of the ENGINE structure are more likely to be caught and changed
48   * here.
49   */
engine_set_all_null(ENGINE * e)50  void engine_set_all_null(ENGINE *e)
51  {
52      e->id = NULL;
53      e->name = NULL;
54      e->rsa_meth = NULL;
55      e->dsa_meth = NULL;
56      e->dh_meth = NULL;
57      e->rand_meth = NULL;
58      e->ciphers = NULL;
59      e->digests = NULL;
60      e->destroy = NULL;
61      e->init = NULL;
62      e->finish = NULL;
63      e->ctrl = NULL;
64      e->load_privkey = NULL;
65      e->load_pubkey = NULL;
66      e->cmd_defns = NULL;
67      e->flags = 0;
68  }
69  
engine_free_util(ENGINE * e,int not_locked)70  int engine_free_util(ENGINE *e, int not_locked)
71  {
72      int i;
73  
74      if (e == NULL)
75          return 1;
76      if (not_locked)
77          CRYPTO_DOWN_REF(&e->struct_ref, &i, global_engine_lock);
78      else
79          i = --e->struct_ref;
80      ENGINE_REF_PRINT(e, 0, -1);
81      if (i > 0)
82          return 1;
83      REF_ASSERT_ISNT(i < 0);
84      /* Free up any dynamically allocated public key methods */
85      engine_pkey_meths_free(e);
86      engine_pkey_asn1_meths_free(e);
87      /*
88       * Give the ENGINE a chance to do any structural cleanup corresponding to
89       * allocation it did in its constructor (eg. unload error strings)
90       */
91      if (e->destroy)
92          e->destroy(e);
93      CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ENGINE, e, &e->ex_data);
94      OPENSSL_free(e);
95      return 1;
96  }
97  
ENGINE_free(ENGINE * e)98  int ENGINE_free(ENGINE *e)
99  {
100      return engine_free_util(e, 1);
101  }
102  
103  /* Cleanup stuff */
104  
105  /*
106   * engine_cleanup_int() is coded such that anything that does work that will
107   * need cleanup can register a "cleanup" callback here. That way we don't get
108   * linker bloat by referring to all *possible* cleanups, but any linker bloat
109   * into code "X" will cause X's cleanup function to end up here.
110   */
111  static STACK_OF(ENGINE_CLEANUP_ITEM) *cleanup_stack = NULL;
int_cleanup_check(int create)112  static int int_cleanup_check(int create)
113  {
114      if (cleanup_stack)
115          return 1;
116      if (!create)
117          return 0;
118      cleanup_stack = sk_ENGINE_CLEANUP_ITEM_new_null();
119      return (cleanup_stack ? 1 : 0);
120  }
121  
int_cleanup_item(ENGINE_CLEANUP_CB * cb)122  static ENGINE_CLEANUP_ITEM *int_cleanup_item(ENGINE_CLEANUP_CB *cb)
123  {
124      ENGINE_CLEANUP_ITEM *item;
125  
126      if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) {
127          ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
128          return NULL;
129      }
130      item->cb = cb;
131      return item;
132  }
133  
engine_cleanup_add_first(ENGINE_CLEANUP_CB * cb)134  void engine_cleanup_add_first(ENGINE_CLEANUP_CB *cb)
135  {
136      ENGINE_CLEANUP_ITEM *item;
137  
138      if (!int_cleanup_check(1))
139          return;
140      item = int_cleanup_item(cb);
141      if (item)
142          sk_ENGINE_CLEANUP_ITEM_insert(cleanup_stack, item, 0);
143  }
144  
engine_cleanup_add_last(ENGINE_CLEANUP_CB * cb)145  void engine_cleanup_add_last(ENGINE_CLEANUP_CB *cb)
146  {
147      ENGINE_CLEANUP_ITEM *item;
148      if (!int_cleanup_check(1))
149          return;
150      item = int_cleanup_item(cb);
151      if (item != NULL) {
152          if (sk_ENGINE_CLEANUP_ITEM_push(cleanup_stack, item) <= 0)
153              OPENSSL_free(item);
154      }
155  }
156  
157  /* The API function that performs all cleanup */
engine_cleanup_cb_free(ENGINE_CLEANUP_ITEM * item)158  static void engine_cleanup_cb_free(ENGINE_CLEANUP_ITEM *item)
159  {
160      (*(item->cb)) ();
161      OPENSSL_free(item);
162  }
163  
engine_cleanup_int(void)164  void engine_cleanup_int(void)
165  {
166      if (int_cleanup_check(0)) {
167          sk_ENGINE_CLEANUP_ITEM_pop_free(cleanup_stack,
168                                          engine_cleanup_cb_free);
169          cleanup_stack = NULL;
170      }
171      CRYPTO_THREAD_lock_free(global_engine_lock);
172      global_engine_lock = NULL;
173  }
174  
175  /* Now the "ex_data" support */
176  
ENGINE_set_ex_data(ENGINE * e,int idx,void * arg)177  int ENGINE_set_ex_data(ENGINE *e, int idx, void *arg)
178  {
179      return CRYPTO_set_ex_data(&e->ex_data, idx, arg);
180  }
181  
ENGINE_get_ex_data(const ENGINE * e,int idx)182  void *ENGINE_get_ex_data(const ENGINE *e, int idx)
183  {
184      return CRYPTO_get_ex_data(&e->ex_data, idx);
185  }
186  
187  /*
188   * Functions to get/set an ENGINE's elements - mainly to avoid exposing the
189   * ENGINE structure itself.
190   */
191  
ENGINE_set_id(ENGINE * e,const char * id)192  int ENGINE_set_id(ENGINE *e, const char *id)
193  {
194      if (id == NULL) {
195          ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
196          return 0;
197      }
198      e->id = id;
199      return 1;
200  }
201  
ENGINE_set_name(ENGINE * e,const char * name)202  int ENGINE_set_name(ENGINE *e, const char *name)
203  {
204      if (name == NULL) {
205          ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
206          return 0;
207      }
208      e->name = name;
209      return 1;
210  }
211  
ENGINE_set_destroy_function(ENGINE * e,ENGINE_GEN_INT_FUNC_PTR destroy_f)212  int ENGINE_set_destroy_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR destroy_f)
213  {
214      e->destroy = destroy_f;
215      return 1;
216  }
217  
ENGINE_set_init_function(ENGINE * e,ENGINE_GEN_INT_FUNC_PTR init_f)218  int ENGINE_set_init_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR init_f)
219  {
220      e->init = init_f;
221      return 1;
222  }
223  
ENGINE_set_finish_function(ENGINE * e,ENGINE_GEN_INT_FUNC_PTR finish_f)224  int ENGINE_set_finish_function(ENGINE *e, ENGINE_GEN_INT_FUNC_PTR finish_f)
225  {
226      e->finish = finish_f;
227      return 1;
228  }
229  
ENGINE_set_ctrl_function(ENGINE * e,ENGINE_CTRL_FUNC_PTR ctrl_f)230  int ENGINE_set_ctrl_function(ENGINE *e, ENGINE_CTRL_FUNC_PTR ctrl_f)
231  {
232      e->ctrl = ctrl_f;
233      return 1;
234  }
235  
ENGINE_set_flags(ENGINE * e,int flags)236  int ENGINE_set_flags(ENGINE *e, int flags)
237  {
238      e->flags = flags;
239      return 1;
240  }
241  
ENGINE_set_cmd_defns(ENGINE * e,const ENGINE_CMD_DEFN * defns)242  int ENGINE_set_cmd_defns(ENGINE *e, const ENGINE_CMD_DEFN *defns)
243  {
244      e->cmd_defns = defns;
245      return 1;
246  }
247  
ENGINE_get_id(const ENGINE * e)248  const char *ENGINE_get_id(const ENGINE *e)
249  {
250      return e->id;
251  }
252  
ENGINE_get_name(const ENGINE * e)253  const char *ENGINE_get_name(const ENGINE *e)
254  {
255      return e->name;
256  }
257  
ENGINE_get_destroy_function(const ENGINE * e)258  ENGINE_GEN_INT_FUNC_PTR ENGINE_get_destroy_function(const ENGINE *e)
259  {
260      return e->destroy;
261  }
262  
ENGINE_get_init_function(const ENGINE * e)263  ENGINE_GEN_INT_FUNC_PTR ENGINE_get_init_function(const ENGINE *e)
264  {
265      return e->init;
266  }
267  
ENGINE_get_finish_function(const ENGINE * e)268  ENGINE_GEN_INT_FUNC_PTR ENGINE_get_finish_function(const ENGINE *e)
269  {
270      return e->finish;
271  }
272  
ENGINE_get_ctrl_function(const ENGINE * e)273  ENGINE_CTRL_FUNC_PTR ENGINE_get_ctrl_function(const ENGINE *e)
274  {
275      return e->ctrl;
276  }
277  
ENGINE_get_flags(const ENGINE * e)278  int ENGINE_get_flags(const ENGINE *e)
279  {
280      return e->flags;
281  }
282  
ENGINE_get_cmd_defns(const ENGINE * e)283  const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e)
284  {
285      return e->cmd_defns;
286  }
287  
288  /*
289   * eng_lib.o is pretty much linked into anything that touches ENGINE already,
290   * so put the "static_state" hack here.
291   */
292  
293  static int internal_static_hack = 0;
294  
ENGINE_get_static_state(void)295  void *ENGINE_get_static_state(void)
296  {
297      return &internal_static_hack;
298  }
299