diff options
Diffstat (limited to 'src/lib/libssl/src/crypto/engine/eng_table.c')
-rw-r--r-- | src/lib/libssl/src/crypto/engine/eng_table.c | 94 |
1 files changed, 24 insertions, 70 deletions
diff --git a/src/lib/libssl/src/crypto/engine/eng_table.c b/src/lib/libssl/src/crypto/engine/eng_table.c index c69a84a8bf..8879a267d1 100644 --- a/src/lib/libssl/src/crypto/engine/eng_table.c +++ b/src/lib/libssl/src/crypto/engine/eng_table.c | |||
@@ -52,49 +52,31 @@ | |||
52 | * | 52 | * |
53 | */ | 53 | */ |
54 | 54 | ||
55 | #include "cryptlib.h" | ||
55 | #include <openssl/evp.h> | 56 | #include <openssl/evp.h> |
56 | #include <openssl/engine.h> | 57 | #include <openssl/lhash.h> |
57 | #include "eng_int.h" | 58 | #include "eng_int.h" |
58 | 59 | ||
59 | /* This is the type of item in the 'implementation' table. Each 'nid' hashes to | ||
60 | * a (potentially NULL) ENGINE_PILE structure which contains a stack of ENGINE* | ||
61 | * pointers. These pointers aren't references, because they're inserted and | ||
62 | * removed during ENGINE creation and ENGINE destruction. They point to ENGINEs | ||
63 | * that *exist* (ie. have a structural reference count greater than zero) rather | ||
64 | * than ENGINEs that are *functional*. Each pointer in those stacks are to | ||
65 | * ENGINEs that implements the algorithm corresponding to each 'nid'. */ | ||
66 | |||
67 | /* The type of the items in the table */ | 60 | /* The type of the items in the table */ |
68 | typedef struct st_engine_pile | 61 | typedef struct st_engine_pile |
69 | { | 62 | { |
70 | /* The 'nid' of the algorithm/mode this ENGINE_PILE structure represents | 63 | /* The 'nid' of this algorithm/mode */ |
71 | * */ | ||
72 | int nid; | 64 | int nid; |
73 | /* A stack of ENGINE pointers for ENGINEs that support this | 65 | /* ENGINEs that implement this algorithm/mode. */ |
74 | * algorithm/mode. In the event that 'funct' is NULL, the first entry in | ||
75 | * this stack that initialises will be set as 'funct' and assumed as the | ||
76 | * default for operations of this type. */ | ||
77 | STACK_OF(ENGINE) *sk; | 66 | STACK_OF(ENGINE) *sk; |
78 | /* The default ENGINE to perform this algorithm/mode. */ | 67 | /* The default ENGINE to perform this algorithm/mode. */ |
79 | ENGINE *funct; | 68 | ENGINE *funct; |
80 | /* This value optimises engine_table_select(). If it is called it sets | 69 | /* Zero if 'sk' is newer than the cached 'funct', non-zero otherwise */ |
81 | * this value to 1. Any changes to this ENGINE_PILE resets it to zero. | ||
82 | * As such, no ENGINE_init() thrashing is done unless ENGINEs | ||
83 | * continually register (and/or unregister). */ | ||
84 | int uptodate; | 70 | int uptodate; |
85 | } ENGINE_PILE; | 71 | } ENGINE_PILE; |
86 | 72 | ||
87 | /* The type of the hash table of ENGINE_PILE structures such that each are | 73 | /* The type exposed in eng_int.h */ |
88 | * unique and keyed by the 'nid' value. */ | ||
89 | struct st_engine_table | 74 | struct st_engine_table |
90 | { | 75 | { |
91 | LHASH piles; | 76 | LHASH piles; |
92 | }; /* ENGINE_TABLE */ | 77 | }; /* ENGINE_TABLE */ |
93 | 78 | ||
94 | /* This value stores global options controlling behaviour of (mostly) the | 79 | /* Global flags (ENGINE_TABLE_FLAG_***). */ |
95 | * engine_table_select() function. It's a bitmask of flag values of the form | ||
96 | * ENGINE_TABLE_FLAG_*** (as defined in engine.h) and is controlled by the | ||
97 | * ENGINE_[get|set]_table_flags() function. */ | ||
98 | static unsigned int table_flags = 0; | 80 | static unsigned int table_flags = 0; |
99 | 81 | ||
100 | /* API function manipulating 'table_flags' */ | 82 | /* API function manipulating 'table_flags' */ |
@@ -121,10 +103,8 @@ static IMPLEMENT_LHASH_COMP_FN(engine_pile_cmp, const ENGINE_PILE *) | |||
121 | static int int_table_check(ENGINE_TABLE **t, int create) | 103 | static int int_table_check(ENGINE_TABLE **t, int create) |
122 | { | 104 | { |
123 | LHASH *lh; | 105 | LHASH *lh; |
124 | if(*t) | 106 | if(*t) return 1; |
125 | return 1; | 107 | if(!create) return 0; |
126 | if(!create) | ||
127 | return 0; | ||
128 | if((lh = lh_new(LHASH_HASH_FN(engine_pile_hash), | 108 | if((lh = lh_new(LHASH_HASH_FN(engine_pile_hash), |
129 | LHASH_COMP_FN(engine_pile_cmp))) == NULL) | 109 | LHASH_COMP_FN(engine_pile_cmp))) == NULL) |
130 | return 0; | 110 | return 0; |
@@ -154,8 +134,7 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, | |||
154 | if(!fnd) | 134 | if(!fnd) |
155 | { | 135 | { |
156 | fnd = OPENSSL_malloc(sizeof(ENGINE_PILE)); | 136 | fnd = OPENSSL_malloc(sizeof(ENGINE_PILE)); |
157 | if(!fnd) | 137 | if(!fnd) goto end; |
158 | goto end; | ||
159 | fnd->uptodate = 1; | 138 | fnd->uptodate = 1; |
160 | fnd->nid = *nids; | 139 | fnd->nid = *nids; |
161 | fnd->sk = sk_ENGINE_new_null(); | 140 | fnd->sk = sk_ENGINE_new_null(); |
@@ -164,11 +143,11 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, | |||
164 | OPENSSL_free(fnd); | 143 | OPENSSL_free(fnd); |
165 | goto end; | 144 | goto end; |
166 | } | 145 | } |
167 | fnd->funct= NULL; | 146 | fnd->funct = NULL; |
168 | lh_insert(&(*table)->piles, fnd); | 147 | lh_insert(&(*table)->piles, fnd); |
169 | } | 148 | } |
170 | /* A registration shouldn't add duplciate entries */ | 149 | /* A registration shouldn't add duplciate entries */ |
171 | sk_ENGINE_delete_ptr(fnd->sk, e); | 150 | (void)sk_ENGINE_delete_ptr(fnd->sk, e); |
172 | /* if 'setdefault', this ENGINE goes to the head of the list */ | 151 | /* if 'setdefault', this ENGINE goes to the head of the list */ |
173 | if(!sk_ENGINE_push(fnd->sk, e)) | 152 | if(!sk_ENGINE_push(fnd->sk, e)) |
174 | goto end; | 153 | goto end; |
@@ -185,6 +164,7 @@ int engine_table_register(ENGINE_TABLE **table, ENGINE_CLEANUP_CB *cleanup, | |||
185 | if(fnd->funct) | 164 | if(fnd->funct) |
186 | engine_unlocked_finish(fnd->funct, 0); | 165 | engine_unlocked_finish(fnd->funct, 0); |
187 | fnd->funct = e; | 166 | fnd->funct = e; |
167 | fnd->uptodate = 1; | ||
188 | } | 168 | } |
189 | nids++; | 169 | nids++; |
190 | } | 170 | } |
@@ -199,8 +179,7 @@ static void int_unregister_cb(ENGINE_PILE *pile, ENGINE *e) | |||
199 | /* Iterate the 'c->sk' stack removing any occurance of 'e' */ | 179 | /* Iterate the 'c->sk' stack removing any occurance of 'e' */ |
200 | while((n = sk_ENGINE_find(pile->sk, e)) >= 0) | 180 | while((n = sk_ENGINE_find(pile->sk, e)) >= 0) |
201 | { | 181 | { |
202 | sk_ENGINE_delete(pile->sk, n); | 182 | (void)sk_ENGINE_delete(pile->sk, n); |
203 | /* "touch" this ENGINE_CIPHER */ | ||
204 | pile->uptodate = 0; | 183 | pile->uptodate = 0; |
205 | } | 184 | } |
206 | if(pile->funct == e) | 185 | if(pile->funct == e) |
@@ -239,9 +218,7 @@ void engine_table_cleanup(ENGINE_TABLE **table) | |||
239 | CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); | 218 | CRYPTO_w_unlock(CRYPTO_LOCK_ENGINE); |
240 | } | 219 | } |
241 | 220 | ||
242 | /* Exposed API function to get a functional reference from the implementation | 221 | /* return a functional reference for a given 'nid' */ |
243 | * table (ie. try to get a functional reference from the tabled structural | ||
244 | * references) for a given cipher 'nid' */ | ||
245 | #ifndef ENGINE_TABLE_DEBUG | 222 | #ifndef ENGINE_TABLE_DEBUG |
246 | ENGINE *engine_table_select(ENGINE_TABLE **table, int nid) | 223 | ENGINE *engine_table_select(ENGINE_TABLE **table, int nid) |
247 | #else | 224 | #else |
@@ -252,25 +229,21 @@ ENGINE *engine_table_select_tmp(ENGINE_TABLE **table, int nid, const char *f, in | |||
252 | ENGINE_PILE tmplate, *fnd=NULL; | 229 | ENGINE_PILE tmplate, *fnd=NULL; |
253 | int initres, loop = 0; | 230 | int initres, loop = 0; |
254 | 231 | ||
255 | /* If 'engine_ciphers' is NULL, then it's absolutely *sure* that no | ||
256 | * ENGINEs have registered any implementations! */ | ||
257 | if(!(*table)) | 232 | if(!(*table)) |
258 | { | 233 | { |
259 | #ifdef ENGINE_TABLE_DEBUG | 234 | #ifdef ENGINE_TABLE_DEBUG |
260 | fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, no " | 235 | fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, nothing " |
261 | "registered for anything!\n", f, l, nid); | 236 | "registered!\n", f, l, nid); |
262 | #endif | 237 | #endif |
263 | return NULL; | 238 | return NULL; |
264 | } | 239 | } |
265 | CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); | 240 | CRYPTO_w_lock(CRYPTO_LOCK_ENGINE); |
266 | /* Check again inside the lock otherwise we could race against cleanup | 241 | /* Check again inside the lock otherwise we could race against cleanup |
267 | * operations. But don't worry about a fprintf(stderr). */ | 242 | * operations. But don't worry about a fprintf(stderr). */ |
268 | if(!int_table_check(table, 0)) | 243 | if(!int_table_check(table, 0)) goto end; |
269 | goto end; | ||
270 | tmplate.nid = nid; | 244 | tmplate.nid = nid; |
271 | fnd = lh_retrieve(&(*table)->piles, &tmplate); | 245 | fnd = lh_retrieve(&(*table)->piles, &tmplate); |
272 | if(!fnd) | 246 | if(!fnd) goto end; |
273 | goto end; | ||
274 | if(fnd->funct && engine_unlocked_init(fnd->funct)) | 247 | if(fnd->funct && engine_unlocked_init(fnd->funct)) |
275 | { | 248 | { |
276 | #ifdef ENGINE_TABLE_DEBUG | 249 | #ifdef ENGINE_TABLE_DEBUG |
@@ -296,34 +269,19 @@ trynext: | |||
296 | #endif | 269 | #endif |
297 | goto end; | 270 | goto end; |
298 | } | 271 | } |
299 | #if 0 | 272 | /* Try to initialise the ENGINE? */ |
300 | /* Don't need to get a reference if we hold the lock. If the locking has | ||
301 | * to change in future, that would be different ... */ | ||
302 | ret->struct_ref++; engine_ref_debug(ret, 0, 1) | ||
303 | #endif | ||
304 | /* Try and initialise the ENGINE if it's already functional *or* if the | ||
305 | * ENGINE_TABLE_FLAG_NOINIT flag is not set. */ | ||
306 | if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT)) | 273 | if((ret->funct_ref > 0) || !(table_flags & ENGINE_TABLE_FLAG_NOINIT)) |
307 | initres = engine_unlocked_init(ret); | 274 | initres = engine_unlocked_init(ret); |
308 | else | 275 | else |
309 | initres = 0; | 276 | initres = 0; |
310 | #if 0 | ||
311 | /* Release the structural reference */ | ||
312 | ret->struct_ref--; engine_ref_debug(ret, 0, -1); | ||
313 | #endif | ||
314 | if(initres) | 277 | if(initres) |
315 | { | 278 | { |
316 | /* If we didn't have a default (functional reference) for this | 279 | /* Update 'funct' */ |
317 | * 'nid' (or we had one but for whatever reason we're now | ||
318 | * initialising a different one), use this opportunity to set | ||
319 | * 'funct'. */ | ||
320 | if((fnd->funct != ret) && engine_unlocked_init(ret)) | 280 | if((fnd->funct != ret) && engine_unlocked_init(ret)) |
321 | { | 281 | { |
322 | /* If there was a previous default we release it. */ | 282 | /* If there was a previous default we release it. */ |
323 | if(fnd->funct) | 283 | if(fnd->funct) |
324 | engine_unlocked_finish(fnd->funct, 0); | 284 | engine_unlocked_finish(fnd->funct, 0); |
325 | /* We got an extra functional reference for the | ||
326 | * per-'nid' default */ | ||
327 | fnd->funct = ret; | 285 | fnd->funct = ret; |
328 | #ifdef ENGINE_TABLE_DEBUG | 286 | #ifdef ENGINE_TABLE_DEBUG |
329 | fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, " | 287 | fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, " |
@@ -338,13 +296,9 @@ trynext: | |||
338 | } | 296 | } |
339 | goto trynext; | 297 | goto trynext; |
340 | end: | 298 | end: |
341 | /* Whatever happened - we should "untouch" our uptodate file seeing as | 299 | /* If it failed, it is unlikely to succeed again until some future |
342 | * we have tried our best to find a functional reference for 'nid'. If | 300 | * registrations have taken place. In all cases, we cache. */ |
343 | * it failed, it is unlikely to succeed again until some future | 301 | if(fnd) fnd->uptodate = 1; |
344 | * registrations (or unregistrations) have taken place that affect that | ||
345 | * 'nid'. */ | ||
346 | if(fnd) | ||
347 | fnd->uptodate = 1; | ||
348 | #ifdef ENGINE_TABLE_DEBUG | 302 | #ifdef ENGINE_TABLE_DEBUG |
349 | if(ret) | 303 | if(ret) |
350 | fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " | 304 | fprintf(stderr, "engine_table_dbg: %s:%d, nid=%d, caching " |