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