summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/engine/eng_table.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/engine/eng_table.c')
-rw-r--r--src/lib/libcrypto/engine/eng_table.c258
1 files changed, 130 insertions, 128 deletions
diff --git a/src/lib/libcrypto/engine/eng_table.c b/src/lib/libcrypto/engine/eng_table.c
index 5781af1eb9..44f3e892b8 100644
--- a/src/lib/libcrypto/engine/eng_table.c
+++ b/src/lib/libcrypto/engine/eng_table.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: eng_table.c,v 1.5 2014/06/12 15:49:29 deraadt Exp $ */ 1/* $OpenBSD: eng_table.c,v 1.6 2014/06/22 12:05:09 jsing Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 2001 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 2001 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -7,7 +7,7 @@
7 * are met: 7 * are met:
8 * 8 *
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 11 *
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in 13 * notice, this list of conditions and the following disclaimer in
@@ -59,8 +59,7 @@
59#include "eng_int.h" 59#include "eng_int.h"
60 60
61/* The type of the items in the table */ 61/* The type of the items in the table */
62typedef struct st_engine_pile 62typedef struct st_engine_pile {
63 {
64 /* The 'nid' of this algorithm/mode */ 63 /* The 'nid' of this algorithm/mode */
65 int nid; 64 int nid;
66 /* ENGINEs that implement this algorithm/mode. */ 65 /* ENGINEs that implement this algorithm/mode. */
@@ -69,284 +68,287 @@ typedef struct st_engine_pile
69 ENGINE *funct; 68 ENGINE *funct;
70 /* Zero if 'sk' is newer than the cached 'funct', non-zero otherwise */ 69 /* Zero if 'sk' is newer than the cached 'funct', non-zero otherwise */
71 int uptodate; 70 int uptodate;
72 } ENGINE_PILE; 71} ENGINE_PILE;
73 72
74DECLARE_LHASH_OF(ENGINE_PILE); 73DECLARE_LHASH_OF(ENGINE_PILE);
75 74
76/* The type exposed in eng_int.h */ 75/* The type exposed in eng_int.h */
77struct st_engine_table 76struct st_engine_table {
78 {
79 LHASH_OF(ENGINE_PILE) piles; 77 LHASH_OF(ENGINE_PILE) piles;
80 }; /* ENGINE_TABLE */ 78}; /* ENGINE_TABLE */
81 79
82 80typedef struct st_engine_pile_doall {
83typedef struct st_engine_pile_doall
84 {
85 engine_table_doall_cb *cb; 81 engine_table_doall_cb *cb;
86 void *arg; 82 void *arg;
87 } ENGINE_PILE_DOALL; 83} ENGINE_PILE_DOALL;
88
89 84
90/* Global flags (ENGINE_TABLE_FLAG_***). */ 85/* Global flags (ENGINE_TABLE_FLAG_***). */
91static unsigned int table_flags = 0; 86static unsigned int table_flags = 0;
92 87
93/* API function manipulating 'table_flags' */ 88/* API function manipulating 'table_flags' */
94unsigned int ENGINE_get_table_flags(void) 89unsigned int
95 { 90ENGINE_get_table_flags(void)
91{
96 return table_flags; 92 return table_flags;
97 } 93}
98 94
99void ENGINE_set_table_flags(unsigned int flags) 95void
100 { 96ENGINE_set_table_flags(unsigned int flags)
97{
101 table_flags = flags; 98 table_flags = flags;
102 } 99}
103 100
104/* Internal functions for the "piles" hash table */ 101/* Internal functions for the "piles" hash table */
105static unsigned long engine_pile_hash(const ENGINE_PILE *c) 102static unsigned long
106 { 103engine_pile_hash(const ENGINE_PILE *c)
104{
107 return c->nid; 105 return c->nid;
108 } 106}
109 107
110static int engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b) 108static int
111 { 109engine_pile_cmp(const ENGINE_PILE *a, const ENGINE_PILE *b)
110{
112 return a->nid - b->nid; 111 return a->nid - b->nid;
113 } 112}
114static IMPLEMENT_LHASH_HASH_FN(engine_pile, ENGINE_PILE) 113static IMPLEMENT_LHASH_HASH_FN(engine_pile, ENGINE_PILE)
115static IMPLEMENT_LHASH_COMP_FN(engine_pile, ENGINE_PILE) 114static IMPLEMENT_LHASH_COMP_FN(engine_pile, ENGINE_PILE)
116 115
117static int int_table_check(ENGINE_TABLE **t, int create) 116static int
118 { 117int_table_check(ENGINE_TABLE **t, int create)
118{
119 LHASH_OF(ENGINE_PILE) *lh; 119 LHASH_OF(ENGINE_PILE) *lh;
120 120
121 if(*t) return 1; 121 if (*t)
122 if(!create) return 0; 122 return 1;
123 if((lh = lh_ENGINE_PILE_new()) == NULL) 123 if (!create)
124 return 0;
125 if ((lh = lh_ENGINE_PILE_new()) == NULL)
124 return 0; 126 return 0;
125 *t = (ENGINE_TABLE *)lh; 127 *t = (ENGINE_TABLE *)lh;
126 return 1; 128 return 1;
127 } 129}
128 130
129/* Privately exposed (via eng_int.h) functions for adding and/or removing 131/* Privately exposed (via eng_int.h) functions for adding and/or removing
130 * ENGINEs from the implementation table */ 132 * ENGINEs from the implementation table */
131int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, 133int
132 ENGINE *e, const int *nids, int num_nids, int setdefault) 134engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup,
133 { 135 ENGINE *e, const int *nids, int num_nids, int setdefault)
136{
134 int ret = 0, added = 0; 137 int ret = 0, added = 0;
135 ENGINE_PILE tmplate, *fnd; 138 ENGINE_PILE tmplate, *fnd;
139
136 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 140 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
137 if(!(*table)) 141 if (!(*table))
138 added = 1; 142 added = 1;
139 if(!int_table_check(table, 1)) 143 if (!int_table_check(table, 1))
140 goto end; 144 goto end;
141 if(added) 145 if (added)
142 /* The cleanup callback needs to be added */ 146 /* The cleanup callback needs to be added */
143 engine_cleanup_add_first(cleanup); 147 engine_cleanup_add_first(cleanup);
144 while(num_nids--) 148 while (num_nids--) {
145 {
146 tmplate.nid = *nids; 149 tmplate.nid = *nids;
147 fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate); 150 fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
148 if(!fnd) 151 if (!fnd) {
149 {
150 fnd = malloc(sizeof(ENGINE_PILE)); 152 fnd = malloc(sizeof(ENGINE_PILE));
151 if(!fnd) goto end; 153 if (!fnd)
154 goto end;
152 fnd->uptodate = 1; 155 fnd->uptodate = 1;
153 fnd->nid = *nids; 156 fnd->nid = *nids;
154 fnd->sk = sk_ENGINE_new_null(); 157 fnd->sk = sk_ENGINE_new_null();
155 if(!fnd->sk) 158 if (!fnd->sk) {
156 {
157 free(fnd); 159 free(fnd);
158 goto end; 160 goto end;
159 } 161 }
160 fnd->funct = NULL; 162 fnd->funct = NULL;
161 (void)lh_ENGINE_PILE_insert(&(*table)->piles, fnd); 163 (void)lh_ENGINE_PILE_insert(&(*table)->piles, fnd);
162 } 164 }
163 /* A registration shouldn't add duplciate entries */ 165 /* A registration shouldn't add duplciate entries */
164 (void)sk_ENGINE_delete_ptr(fnd->sk, e); 166 (void)sk_ENGINE_delete_ptr(fnd->sk, e);
165 /* if 'setdefault', this ENGINE goes to the head of the list */ 167 /* if 'setdefault', this ENGINE goes to the head of the list */
166 if(!sk_ENGINE_push(fnd->sk, e)) 168 if (!sk_ENGINE_push(fnd->sk, e))
167 goto end; 169 goto end;
168 /* "touch" this ENGINE_PILE */ 170 /* "touch" this ENGINE_PILE */
169 fnd->uptodate = 0; 171 fnd->uptodate = 0;
170 if(setdefault) 172 if (setdefault) {
171 { 173 if (!engine_unlocked_init(e)) {
172 if(!engine_unlocked_init(e))
173 {
174 ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER, 174 ENGINEerr(ENGINE_F_ENGINE_TABLE_REGISTER,
175 ENGINE_R_INIT_FAILED); 175 ENGINE_R_INIT_FAILED);
176 goto end; 176 goto end;
177 } 177 }
178 if(fnd->funct) 178 if (fnd->funct)
179 engine_unlocked_finish(fnd->funct, 0); 179 engine_unlocked_finish(fnd->funct, 0);
180 fnd->funct = e; 180 fnd->funct = e;
181 fnd->uptodate = 1; 181 fnd->uptodate = 1;
182 }
183 nids++;
184 } 182 }
183 nids++;
184 }
185 ret = 1; 185 ret = 1;
186end: 186end:
187 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 187 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
188 return ret; 188 return ret;
189 } 189}
190static void int_unregister_cb_doall_arg(ENGINE_PILE *pile, ENGINE *e) 190
191 { 191static void
192int_unregister_cb_doall_arg(ENGINE_PILE *pile, ENGINE *e)
193{
192 int n; 194 int n;
195
193 /* Iterate the 'c->sk' stack removing any occurance of 'e' */ 196 /* Iterate the 'c->sk' stack removing any occurance of 'e' */
194 while((n = sk_ENGINE_find(pile->sk, e)) >= 0) 197 while ((n = sk_ENGINE_find(pile->sk, e)) >= 0) {
195 {
196 (void)sk_ENGINE_delete(pile->sk, n); 198 (void)sk_ENGINE_delete(pile->sk, n);
197 pile->uptodate = 0; 199 pile->uptodate = 0;
198 } 200 }
199 if(pile->funct == e) 201 if (pile->funct == e) {
200 {
201 engine_unlocked_finish(e, 0); 202 engine_unlocked_finish(e, 0);
202 pile->funct = NULL; 203 pile->funct = NULL;
203 }
204 } 204 }
205}
205static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb, ENGINE_PILE, ENGINE) 206static IMPLEMENT_LHASH_DOALL_ARG_FN(int_unregister_cb, ENGINE_PILE, ENGINE)
206 207
207void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e) 208void
208 { 209engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
210{
209 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 211 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
210 if(int_table_check(table, 0)) 212 if (int_table_check(table, 0))
211 lh_ENGINE_PILE_doall_arg(&(*table)->piles, 213 lh_ENGINE_PILE_doall_arg(&(*table)->piles,
212 LHASH_DOALL_ARG_FN(int_unregister_cb), 214 LHASH_DOALL_ARG_FN(int_unregister_cb), ENGINE, e);
213 ENGINE, e);
214 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 215 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
215 } 216}
216 217
217static void int_cleanup_cb_doall(ENGINE_PILE *p) 218static void
218 { 219int_cleanup_cb_doall(ENGINE_PILE *p)
220{
219 sk_ENGINE_free(p->sk); 221 sk_ENGINE_free(p->sk);
220 if(p->funct) 222 if (p->funct)
221 engine_unlocked_finish(p->funct, 0); 223 engine_unlocked_finish(p->funct, 0);
222 free(p); 224 free(p);
223 } 225}
224static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb, ENGINE_PILE) 226static IMPLEMENT_LHASH_DOALL_FN(int_cleanup_cb, ENGINE_PILE)
225 227
226void engine_table_cleanup(ENGINE_TABLE **table) 228void
227 { 229engine_table_cleanup(ENGINE_TABLE **table)
230{
228 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 231 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
229 if(*table) 232 if (*table) {
230 {
231 lh_ENGINE_PILE_doall(&(*table)->piles, 233 lh_ENGINE_PILE_doall(&(*table)->piles,
232 LHASH_DOALL_FN(int_cleanup_cb)); 234 LHASH_DOALL_FN(int_cleanup_cb));
233 lh_ENGINE_PILE_free(&(*table)->piles); 235 lh_ENGINE_PILE_free(&(*table)->piles);
234 *table = NULL; 236 *table = NULL;
235 }
236 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
237 } 237 }
238 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
239}
238 240
239/* return a functional reference for a given 'nid' */ 241/* return a functional reference for a given 'nid' */
240#ifndef ENGINE_TABLE_DEBUG 242#ifndef ENGINE_TABLE_DEBUG
241ENGINE *engine_table_select(ENGINE_TABLE **table, int nid) 243ENGINE *
244engine_table_select(ENGINE_TABLE **table, int nid)
242#else 245#else
243ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l) 246ENGINE *
247engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, int l)
244#endif 248#endif
245 { 249{
246 ENGINE *ret = NULL; 250 ENGINE *ret = NULL;
247 ENGINE_PILE tmplate, *fnd=NULL; 251 ENGINE_PILE tmplate, *fnd = NULL;
248 int initres, loop = 0; 252 int initres, loop = 0;
249 253
250 if(!(*table)) 254 if (!(*table)) {
251 {
252#ifdef ENGINE_TABLE_DEBUG 255#ifdef ENGINE_TABLE_DEBUG
253 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing " 256 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing "
254 "registered!\n", f, l, nid); 257 "registered!\n", f, l, nid);
255#endif 258#endif
256 return NULL; 259 return NULL;
257 } 260 }
258 ERR_set_mark(); 261 ERR_set_mark();
259 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); 262 CRYPTO_w_lock(CRYPTO_LOCK_ENGINE);
260 /* Check again inside the lock otherwise we could race against cleanup 263 /* Check again inside the lock otherwise we could race against cleanup
261 * operations. But don't worry about a fprintf(stderr). */ 264 * operations. But don't worry about a fprintf(stderr). */
262 if(!int_table_check(table, 0)) goto end; 265 if (!int_table_check(table, 0))
266 goto end;
263 tmplate.nid = nid; 267 tmplate.nid = nid;
264 fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate); 268 fnd = lh_ENGINE_PILE_retrieve(&(*table)->piles, &tmplate);
265 if(!fnd) goto end; 269 if (!fnd)
266 if(fnd->funct && engine_unlocked_init(fnd->funct)) 270 goto end;
267 { 271 if (fnd->funct && engine_unlocked_init(fnd->funct)) {
268#ifdef ENGINE_TABLE_DEBUG 272#ifdef ENGINE_TABLE_DEBUG
269 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using " 273 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
270 "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id); 274 "ENGINE '%s' cached\n", f, l, nid, fnd->funct->id);
271#endif 275#endif
272 ret = fnd->funct; 276 ret = fnd->funct;
273 goto end; 277 goto end;
274 } 278 }
275 if(fnd->uptodate) 279 if (fnd->uptodate) {
276 {
277 ret = fnd->funct; 280 ret = fnd->funct;
278 goto end; 281 goto end;
279 } 282 }
280trynext: 283trynext:
281 ret = sk_ENGINE_value(fnd->sk, loop++); 284 ret = sk_ENGINE_value(fnd->sk, loop++);
282 if(!ret) 285 if (!ret) {
283 {
284#ifdef ENGINE_TABLE_DEBUG 286#ifdef ENGINE_TABLE_DEBUG
285 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no " 287 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no "
286 "registered implementations would initialise\n", 288 "registered implementations would initialise\n", f, l, nid);
287 f, l, nid);
288#endif 289#endif
289 goto end; 290 goto end;
290 } 291 }
291 /* Try to initialise the ENGINE? */ 292 /* Try to initialise the ENGINE? */
292 if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT)) 293 if ((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT))
293 initres = engine_unlocked_init(ret); 294 initres = engine_unlocked_init(ret);
294 else 295 else
295 initres = 0; 296 initres = 0;
296 if(initres) 297 if (initres) {
297 {
298 /* Update 'funct' */ 298 /* Update 'funct' */
299 if((fnd->funct != ret) && engine_unlocked_init(ret)) 299 if ((fnd->funct != ret) && engine_unlocked_init(ret)) {
300 {
301 /* If there was a previous default we release it. */ 300 /* If there was a previous default we release it. */
302 if(fnd->funct) 301 if (fnd->funct)
303 engine_unlocked_finish(fnd->funct, 0); 302 engine_unlocked_finish(fnd->funct, 0);
304 fnd->funct = ret; 303 fnd->funct = ret;
305#ifdef ENGINE_TABLE_DEBUG 304#ifdef ENGINE_TABLE_DEBUG
306 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, " 305 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, "
307 "setting default to '%s'\n", f, l, nid, ret->id); 306 "setting default to '%s'\n", f, l, nid, ret->id);
308#endif 307#endif
309 } 308 }
310#ifdef ENGINE_TABLE_DEBUG 309#ifdef ENGINE_TABLE_DEBUG
311 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using " 310 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, using "
312 "newly initialised '%s'\n", f, l, nid, ret->id); 311 "newly initialised '%s'\n", f, l, nid, ret->id);
313#endif 312#endif
314 goto end; 313 goto end;
315 } 314 }
316 goto trynext; 315 goto trynext;
317end: 316end:
318 /* If it failed, it is unlikely to succeed again until some future 317 /* If it failed, it is unlikely to succeed again until some future
319 * registrations have taken place. In all cases, we cache. */ 318 * registrations have taken place. In all cases, we cache. */
320 if(fnd) fnd->uptodate = 1; 319 if (fnd)
320 fnd->uptodate = 1;
321#ifdef ENGINE_TABLE_DEBUG 321#ifdef ENGINE_TABLE_DEBUG
322 if(ret) 322 if (ret)
323 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " 323 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
324 "ENGINE '%s'\n", f, l, nid, ret->id); 324 "ENGINE '%s'\n", f, l, nid, ret->id);
325 else 325 else
326 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " 326 fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching "
327 "'no matching ENGINE'\n", f, l, nid); 327 "'no matching ENGINE'\n", f, l, nid);
328#endif 328#endif
329 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); 329 CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE);
330 /* Whatever happened, any failed init()s are not failures in this 330 /* Whatever happened, any failed init()s are not failures in this
331 * context, so clear our error state. */ 331 * context, so clear our error state. */
332 ERR_pop_to_mark(); 332 ERR_pop_to_mark();
333 return ret; 333 return ret;
334 } 334}
335 335
336/* Table enumeration */ 336/* Table enumeration */
337 337
338static void int_cb_doall_arg(ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall) 338static void
339 { 339int_cb_doall_arg(ENGINE_PILE *pile, ENGINE_PILE_DOALL *dall)
340{
340 dall->cb(pile->nid, pile->sk, pile->funct, dall->arg); 341 dall->cb(pile->nid, pile->sk, pile->funct, dall->arg);
341 } 342}
342static IMPLEMENT_LHASH_DOALL_ARG_FN(int_cb, ENGINE_PILE,ENGINE_PILE_DOALL) 343static IMPLEMENT_LHASH_DOALL_ARG_FN(int_cb, ENGINE_PILE, ENGINE_PILE_DOALL)
343 344
344void engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, 345void
345 void *arg) 346engine_table_doall(ENGINE_TABLE *table, engine_table_doall_cb *cb, void *arg)
346 { 347{
347 ENGINE_PILE_DOALL dall; 348 ENGINE_PILE_DOALL dall;
349
348 dall.cb = cb; 350 dall.cb = cb;
349 dall.arg = arg; 351 dall.arg = arg;
350 lh_ENGINE_PILE_doall_arg(&table->piles, LHASH_DOALL_ARG_FN(int_cb), 352 lh_ENGINE_PILE_doall_arg(&table->piles, LHASH_DOALL_ARG_FN(int_cb),
351 ENGINE_PILE_DOALL, &dall); 353 ENGINE_PILE_DOALL, &dall);
352 } 354}