1/* crypto/store/str_mem.c -*- mode:C; c-file-style: "eay" -*- */ 2/* 3 * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project 4 * 2003. 5 */ 6/* ==================================================================== 7 * Copyright (c) 2003 The OpenSSL Project. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in 18 * the documentation and/or other materials provided with the 19 * distribution. 20 * 21 * 3. All advertising materials mentioning features or use of this 22 * software must display the following acknowledgment: 23 * "This product includes software developed by the OpenSSL Project 24 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 25 * 26 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 27 * endorse or promote products derived from this software without 28 * prior written permission. For written permission, please contact 29 * openssl-core@openssl.org. 30 * 31 * 5. Products derived from this software may not be called "OpenSSL" 32 * nor may "OpenSSL" appear in their names without prior written 33 * permission of the OpenSSL Project. 34 * 35 * 6. Redistributions of any form whatsoever must retain the following 36 * acknowledgment: 37 * "This product includes software developed by the OpenSSL Project 38 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 39 * 40 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 41 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 43 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 44 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 45 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 46 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 47 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 49 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 51 * OF THE POSSIBILITY OF SUCH DAMAGE. 52 * ==================================================================== 53 * 54 * This product includes cryptographic software written by Eric Young 55 * (eay@cryptsoft.com). This product includes software written by Tim 56 * Hudson (tjh@cryptsoft.com). 57 * 58 */ 59 60#include <string.h> 61#include <openssl/err.h> 62#include "str_locl.h" 63 64/* 65 * The memory store is currently highly experimental. It's meant to become a 66 * base store used by other stores for internal caching (for full caching 67 * support, aging needs to be added). 68 * 69 * The database use is meant to support as much attribute association as 70 * possible, while providing for as small search ranges as possible. This is 71 * currently provided for by sorting the entries by numbers that are composed 72 * of bits set at the positions indicated by attribute type codes. This 73 * provides for ranges determined by the highest attribute type code value. 74 * A better idea might be to sort by values computed from the range of 75 * attributes associated with the object (basically, the difference between 76 * the highest and lowest attribute type code) and it's distance from a base 77 * (basically, the lowest associated attribute type code). 78 */ 79 80typedef struct mem_object_data_st { 81 STORE_OBJECT *object; 82 STORE_ATTR_INFO *attr_info; 83 int references; 84} MEM_OBJECT_DATA; 85 86DECLARE_STACK_OF(MEM_OBJECT_DATA) 87struct mem_data_st { 88 /* 89 * sorted with 90 * STORE_ATTR_INFO_compare(). 91 */ 92 STACK_OF(MEM_OBJECT_DATA) *data; 93 /* 94 * Currently unused, but can 95 * be used to add attributes 96 * from parts of the data. 97 */ 98 unsigned int compute_components:1; 99}; 100 101DECLARE_STACK_OF(STORE_ATTR_INFO) 102struct mem_ctx_st { 103 /* The type we're searching for */ 104 int type; 105 /* 106 * Sets of 107 * attributes to search for. Each 108 * element is a STORE_ATTR_INFO. 109 */ 110 STACK_OF(STORE_ATTR_INFO) *search_attributes; 111 /* 112 * which of the search attributes we 113 * found a match for, -1 when we still 114 * haven't found any 115 */ 116 int search_index; 117 /* -1 as long as we're searching for the first */ 118 int index; 119}; 120 121static int mem_init(STORE *s); 122static void mem_clean(STORE *s); 123static STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type, 124 OPENSSL_ITEM attributes[], 125 OPENSSL_ITEM parameters[]); 126static STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type, 127 OPENSSL_ITEM attributes[], 128 OPENSSL_ITEM parameters[]); 129static int mem_store(STORE *s, STORE_OBJECT_TYPES type, STORE_OBJECT *data, 130 OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]); 131static int mem_modify(STORE *s, STORE_OBJECT_TYPES type, 132 OPENSSL_ITEM search_attributes[], 133 OPENSSL_ITEM add_attributes[], 134 OPENSSL_ITEM modify_attributes[], 135 OPENSSL_ITEM delete_attributes[], 136 OPENSSL_ITEM parameters[]); 137static int mem_delete(STORE *s, STORE_OBJECT_TYPES type, 138 OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]); 139static void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type, 140 OPENSSL_ITEM attributes[], 141 OPENSSL_ITEM parameters[]); 142static STORE_OBJECT *mem_list_next(STORE *s, void *handle); 143static int mem_list_end(STORE *s, void *handle); 144static int mem_list_endp(STORE *s, void *handle); 145static int mem_lock(STORE *s, OPENSSL_ITEM attributes[], 146 OPENSSL_ITEM parameters[]); 147static int mem_unlock(STORE *s, OPENSSL_ITEM attributes[], 148 OPENSSL_ITEM parameters[]); 149static int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void)); 150 151static STORE_METHOD store_memory = { 152 "OpenSSL memory store interface", 153 mem_init, 154 mem_clean, 155 mem_generate, 156 mem_get, 157 mem_store, 158 mem_modify, 159 NULL, /* revoke */ 160 mem_delete, 161 mem_list_start, 162 mem_list_next, 163 mem_list_end, 164 mem_list_endp, 165 NULL, /* update */ 166 mem_lock, 167 mem_unlock, 168 mem_ctrl 169}; 170 171const STORE_METHOD *STORE_Memory(void) 172{ 173 return &store_memory; 174} 175 176static int mem_init(STORE *s) 177{ 178 return 1; 179} 180 181static void mem_clean(STORE *s) 182{ 183 return; 184} 185 186static STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type, 187 OPENSSL_ITEM attributes[], 188 OPENSSL_ITEM parameters[]) 189{ 190 STOREerr(STORE_F_MEM_GENERATE, STORE_R_NOT_IMPLEMENTED); 191 return 0; 192} 193 194static STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type, 195 OPENSSL_ITEM attributes[], 196 OPENSSL_ITEM parameters[]) 197{ 198 void *context = mem_list_start(s, type, attributes, parameters); 199 200 if (context) { 201 STORE_OBJECT *object = mem_list_next(s, context); 202 203 if (mem_list_end(s, context)) 204 return object; 205 } 206 return NULL; 207} 208 209static int mem_store(STORE *s, STORE_OBJECT_TYPES type, 210 STORE_OBJECT *data, OPENSSL_ITEM attributes[], 211 OPENSSL_ITEM parameters[]) 212{ 213 STOREerr(STORE_F_MEM_STORE, STORE_R_NOT_IMPLEMENTED); 214 return 0; 215} 216 217static int mem_modify(STORE *s, STORE_OBJECT_TYPES type, 218 OPENSSL_ITEM search_attributes[], 219 OPENSSL_ITEM add_attributes[], 220 OPENSSL_ITEM modify_attributes[], 221 OPENSSL_ITEM delete_attributes[], 222 OPENSSL_ITEM parameters[]) 223{ 224 STOREerr(STORE_F_MEM_MODIFY, STORE_R_NOT_IMPLEMENTED); 225 return 0; 226} 227 228static int mem_delete(STORE *s, STORE_OBJECT_TYPES type, 229 OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]) 230{ 231 STOREerr(STORE_F_MEM_DELETE, STORE_R_NOT_IMPLEMENTED); 232 return 0; 233} 234 235/* 236 * The list functions may be the hardest to understand. Basically, 237 * mem_list_start compiles a stack of attribute info elements, and puts that 238 * stack into the context to be returned. mem_list_next will then find the 239 * first matching element in the store, and then walk all the way to the end 240 * of the store (since any combination of attribute bits above the starting 241 * point may match the searched for bit pattern...). 242 */ 243static void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type, 244 OPENSSL_ITEM attributes[], 245 OPENSSL_ITEM parameters[]) 246{ 247 struct mem_ctx_st *context = 248 (struct mem_ctx_st *)OPENSSL_malloc(sizeof(struct mem_ctx_st)); 249 void *attribute_context = NULL; 250 STORE_ATTR_INFO *attrs = NULL; 251 252 if (!context) { 253 STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE); 254 return 0; 255 } 256 memset(context, 0, sizeof(struct mem_ctx_st)); 257 258 attribute_context = STORE_parse_attrs_start(attributes); 259 if (!attribute_context) { 260 STOREerr(STORE_F_MEM_LIST_START, ERR_R_STORE_LIB); 261 goto err; 262 } 263 264 while ((attrs = STORE_parse_attrs_next(attribute_context))) { 265 if (context->search_attributes == NULL) { 266 context->search_attributes = 267 sk_STORE_ATTR_INFO_new(STORE_ATTR_INFO_compare); 268 if (!context->search_attributes) { 269 STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE); 270 goto err; 271 } 272 } 273 sk_STORE_ATTR_INFO_push(context->search_attributes, attrs); 274 } 275 if (!STORE_parse_attrs_endp(attribute_context)) 276 goto err; 277 STORE_parse_attrs_end(attribute_context); 278 context->search_index = -1; 279 context->index = -1; 280 return context; 281 err: 282 if (attribute_context) 283 STORE_parse_attrs_end(attribute_context); 284 mem_list_end(s, context); 285 return NULL; 286} 287 288static STORE_OBJECT *mem_list_next(STORE *s, void *handle) 289{ 290 int i; 291 struct mem_ctx_st *context = (struct mem_ctx_st *)handle; 292 struct mem_object_data_st key = { 0, 0, 1 }; 293 struct mem_data_st *store = (struct mem_data_st *)STORE_get_ex_data(s, 1); 294 int srch; 295 int cres = 0; 296 297 if (!context) { 298 STOREerr(STORE_F_MEM_LIST_NEXT, ERR_R_PASSED_NULL_PARAMETER); 299 return NULL; 300 } 301 if (!store) { 302 STOREerr(STORE_F_MEM_LIST_NEXT, STORE_R_NO_STORE); 303 return NULL; 304 } 305 306 if (context->search_index == -1) { 307 for (i = 0; 308 i < sk_STORE_ATTR_INFO_num(context->search_attributes); i++) { 309 key.attr_info 310 = sk_STORE_ATTR_INFO_value(context->search_attributes, i); 311 srch = sk_MEM_OBJECT_DATA_find_ex(store->data, &key); 312 313 if (srch >= 0) { 314 context->search_index = srch; 315 break; 316 } 317 } 318 } 319 if (context->search_index < 0) 320 return NULL; 321 322 key.attr_info = 323 sk_STORE_ATTR_INFO_value(context->search_attributes, 324 context->search_index); 325 for (srch = context->search_index; 326 srch < sk_MEM_OBJECT_DATA_num(store->data) 327 && STORE_ATTR_INFO_in_range(key.attr_info, 328 sk_MEM_OBJECT_DATA_value(store->data, 329 srch)->attr_info) 330 && !(cres = 331 STORE_ATTR_INFO_in_ex(key.attr_info, 332 sk_MEM_OBJECT_DATA_value(store->data, 333 srch)->attr_info)); 334 srch++) ; 335 336 context->search_index = srch; 337 if (cres) 338 return (sk_MEM_OBJECT_DATA_value(store->data, srch))->object; 339 return NULL; 340} 341 342static int mem_list_end(STORE *s, void *handle) 343{ 344 struct mem_ctx_st *context = (struct mem_ctx_st *)handle; 345 346 if (!context) { 347 STOREerr(STORE_F_MEM_LIST_END, ERR_R_PASSED_NULL_PARAMETER); 348 return 0; 349 } 350 if (context && context->search_attributes) 351 sk_STORE_ATTR_INFO_free(context->search_attributes); 352 if (context) 353 OPENSSL_free(context); 354 return 1; 355} 356 357static int mem_list_endp(STORE *s, void *handle) 358{ 359 struct mem_ctx_st *context = (struct mem_ctx_st *)handle; 360 361 if (!context 362 || context->search_index 363 == sk_STORE_ATTR_INFO_num(context->search_attributes)) 364 return 1; 365 return 0; 366} 367 368static int mem_lock(STORE *s, OPENSSL_ITEM attributes[], 369 OPENSSL_ITEM parameters[]) 370{ 371 return 1; 372} 373 374static int mem_unlock(STORE *s, OPENSSL_ITEM attributes[], 375 OPENSSL_ITEM parameters[]) 376{ 377 return 1; 378} 379 380static int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void)) 381{ 382 return 1; 383} 384