1295016Sjkim/* crypto/store/str_mem.c */
2280304Sjkim/*
3280304Sjkim * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
4280304Sjkim * 2003.
5160814Ssimon */
6160814Ssimon/* ====================================================================
7160814Ssimon * Copyright (c) 2003 The OpenSSL Project.  All rights reserved.
8160814Ssimon *
9160814Ssimon * Redistribution and use in source and binary forms, with or without
10160814Ssimon * modification, are permitted provided that the following conditions
11160814Ssimon * are met:
12160814Ssimon *
13160814Ssimon * 1. Redistributions of source code must retain the above copyright
14280304Sjkim *    notice, this list of conditions and the following disclaimer.
15160814Ssimon *
16160814Ssimon * 2. Redistributions in binary form must reproduce the above copyright
17160814Ssimon *    notice, this list of conditions and the following disclaimer in
18160814Ssimon *    the documentation and/or other materials provided with the
19160814Ssimon *    distribution.
20160814Ssimon *
21160814Ssimon * 3. All advertising materials mentioning features or use of this
22160814Ssimon *    software must display the following acknowledgment:
23160814Ssimon *    "This product includes software developed by the OpenSSL Project
24160814Ssimon *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
25160814Ssimon *
26160814Ssimon * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27160814Ssimon *    endorse or promote products derived from this software without
28160814Ssimon *    prior written permission. For written permission, please contact
29160814Ssimon *    openssl-core@openssl.org.
30160814Ssimon *
31160814Ssimon * 5. Products derived from this software may not be called "OpenSSL"
32160814Ssimon *    nor may "OpenSSL" appear in their names without prior written
33160814Ssimon *    permission of the OpenSSL Project.
34160814Ssimon *
35160814Ssimon * 6. Redistributions of any form whatsoever must retain the following
36160814Ssimon *    acknowledgment:
37160814Ssimon *    "This product includes software developed by the OpenSSL Project
38160814Ssimon *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
39160814Ssimon *
40160814Ssimon * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41160814Ssimon * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42160814Ssimon * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43160814Ssimon * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44160814Ssimon * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45160814Ssimon * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46160814Ssimon * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47160814Ssimon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48160814Ssimon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49160814Ssimon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50160814Ssimon * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51160814Ssimon * OF THE POSSIBILITY OF SUCH DAMAGE.
52160814Ssimon * ====================================================================
53160814Ssimon *
54160814Ssimon * This product includes cryptographic software written by Eric Young
55160814Ssimon * (eay@cryptsoft.com).  This product includes software written by Tim
56160814Ssimon * Hudson (tjh@cryptsoft.com).
57160814Ssimon *
58160814Ssimon */
59160814Ssimon
60160814Ssimon#include <string.h>
61160814Ssimon#include <openssl/err.h>
62160814Ssimon#include "str_locl.h"
63160814Ssimon
64280304Sjkim/*
65280304Sjkim * The memory store is currently highly experimental.  It's meant to become a
66280304Sjkim * base store used by other stores for internal caching (for full caching
67280304Sjkim * support, aging needs to be added).
68280304Sjkim *
69280304Sjkim * The database use is meant to support as much attribute association as
70280304Sjkim * possible, while providing for as small search ranges as possible. This is
71280304Sjkim * currently provided for by sorting the entries by numbers that are composed
72280304Sjkim * of bits set at the positions indicated by attribute type codes.  This
73280304Sjkim * provides for ranges determined by the highest attribute type code value.
74280304Sjkim * A better idea might be to sort by values computed from the range of
75280304Sjkim * attributes associated with the object (basically, the difference between
76280304Sjkim * the highest and lowest attribute type code) and it's distance from a base
77280304Sjkim * (basically, the lowest associated attribute type code).
78280304Sjkim */
79160814Ssimon
80280304Sjkimtypedef struct mem_object_data_st {
81280304Sjkim    STORE_OBJECT *object;
82280304Sjkim    STORE_ATTR_INFO *attr_info;
83280304Sjkim    int references;
84280304Sjkim} MEM_OBJECT_DATA;
85160814Ssimon
86238405SjkimDECLARE_STACK_OF(MEM_OBJECT_DATA)
87280304Sjkimstruct mem_data_st {
88280304Sjkim    /*
89280304Sjkim     * sorted with
90280304Sjkim     * STORE_ATTR_INFO_compare().
91280304Sjkim     */
92280304Sjkim    STACK_OF(MEM_OBJECT_DATA) *data;
93280304Sjkim    /*
94280304Sjkim     * Currently unused, but can
95280304Sjkim     * be used to add attributes
96280304Sjkim     * from parts of the data.
97280304Sjkim     */
98280304Sjkim    unsigned int compute_components:1;
99280304Sjkim};
100160814Ssimon
101238405SjkimDECLARE_STACK_OF(STORE_ATTR_INFO)
102280304Sjkimstruct mem_ctx_st {
103280304Sjkim    /* The type we're searching for */
104280304Sjkim    int type;
105280304Sjkim    /*
106280304Sjkim     * Sets of
107280304Sjkim     * attributes to search for.  Each
108280304Sjkim     * element is a STORE_ATTR_INFO.
109280304Sjkim     */
110280304Sjkim    STACK_OF(STORE_ATTR_INFO) *search_attributes;
111280304Sjkim    /*
112280304Sjkim     * which of the search attributes we
113280304Sjkim     * found a match for, -1 when we still
114280304Sjkim     * haven't found any
115280304Sjkim     */
116280304Sjkim    int search_index;
117280304Sjkim    /* -1 as long as we're searching for the first */
118280304Sjkim    int index;
119280304Sjkim};
120160814Ssimon
121160814Ssimonstatic int mem_init(STORE *s);
122160814Ssimonstatic void mem_clean(STORE *s);
123160814Ssimonstatic STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
124280304Sjkim                                  OPENSSL_ITEM attributes[],
125280304Sjkim                                  OPENSSL_ITEM parameters[]);
126160814Ssimonstatic STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
127280304Sjkim                             OPENSSL_ITEM attributes[],
128280304Sjkim                             OPENSSL_ITEM parameters[]);
129280304Sjkimstatic int mem_store(STORE *s, STORE_OBJECT_TYPES type, STORE_OBJECT *data,
130280304Sjkim                     OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
131160814Ssimonstatic int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
132280304Sjkim                      OPENSSL_ITEM search_attributes[],
133280304Sjkim                      OPENSSL_ITEM add_attributes[],
134280304Sjkim                      OPENSSL_ITEM modify_attributes[],
135280304Sjkim                      OPENSSL_ITEM delete_attributes[],
136280304Sjkim                      OPENSSL_ITEM parameters[]);
137160814Ssimonstatic int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
138280304Sjkim                      OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
139160814Ssimonstatic void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
140280304Sjkim                            OPENSSL_ITEM attributes[],
141280304Sjkim                            OPENSSL_ITEM parameters[]);
142160814Ssimonstatic STORE_OBJECT *mem_list_next(STORE *s, void *handle);
143160814Ssimonstatic int mem_list_end(STORE *s, void *handle);
144160814Ssimonstatic int mem_list_endp(STORE *s, void *handle);
145160814Ssimonstatic int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
146280304Sjkim                    OPENSSL_ITEM parameters[]);
147160814Ssimonstatic int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
148280304Sjkim                      OPENSSL_ITEM parameters[]);
149280304Sjkimstatic int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void));
150160814Ssimon
151280304Sjkimstatic STORE_METHOD store_memory = {
152280304Sjkim    "OpenSSL memory store interface",
153280304Sjkim    mem_init,
154280304Sjkim    mem_clean,
155280304Sjkim    mem_generate,
156280304Sjkim    mem_get,
157280304Sjkim    mem_store,
158280304Sjkim    mem_modify,
159280304Sjkim    NULL,                       /* revoke */
160280304Sjkim    mem_delete,
161280304Sjkim    mem_list_start,
162280304Sjkim    mem_list_next,
163280304Sjkim    mem_list_end,
164280304Sjkim    mem_list_endp,
165280304Sjkim    NULL,                       /* update */
166280304Sjkim    mem_lock,
167280304Sjkim    mem_unlock,
168280304Sjkim    mem_ctrl
169280304Sjkim};
170160814Ssimon
171160814Ssimonconst STORE_METHOD *STORE_Memory(void)
172280304Sjkim{
173280304Sjkim    return &store_memory;
174280304Sjkim}
175160814Ssimon
176160814Ssimonstatic int mem_init(STORE *s)
177280304Sjkim{
178280304Sjkim    return 1;
179280304Sjkim}
180160814Ssimon
181160814Ssimonstatic void mem_clean(STORE *s)
182280304Sjkim{
183280304Sjkim    return;
184280304Sjkim}
185160814Ssimon
186160814Ssimonstatic STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
187280304Sjkim                                  OPENSSL_ITEM attributes[],
188280304Sjkim                                  OPENSSL_ITEM parameters[])
189280304Sjkim{
190280304Sjkim    STOREerr(STORE_F_MEM_GENERATE, STORE_R_NOT_IMPLEMENTED);
191280304Sjkim    return 0;
192280304Sjkim}
193280304Sjkim
194160814Ssimonstatic STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
195280304Sjkim                             OPENSSL_ITEM attributes[],
196280304Sjkim                             OPENSSL_ITEM parameters[])
197280304Sjkim{
198280304Sjkim    void *context = mem_list_start(s, type, attributes, parameters);
199160814Ssimon
200280304Sjkim    if (context) {
201280304Sjkim        STORE_OBJECT *object = mem_list_next(s, context);
202280304Sjkim
203280304Sjkim        if (mem_list_end(s, context))
204280304Sjkim            return object;
205280304Sjkim    }
206280304Sjkim    return NULL;
207280304Sjkim}
208280304Sjkim
209160814Ssimonstatic int mem_store(STORE *s, STORE_OBJECT_TYPES type,
210280304Sjkim                     STORE_OBJECT *data, OPENSSL_ITEM attributes[],
211280304Sjkim                     OPENSSL_ITEM parameters[])
212280304Sjkim{
213280304Sjkim    STOREerr(STORE_F_MEM_STORE, STORE_R_NOT_IMPLEMENTED);
214280304Sjkim    return 0;
215280304Sjkim}
216280304Sjkim
217160814Ssimonstatic int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
218280304Sjkim                      OPENSSL_ITEM search_attributes[],
219280304Sjkim                      OPENSSL_ITEM add_attributes[],
220280304Sjkim                      OPENSSL_ITEM modify_attributes[],
221280304Sjkim                      OPENSSL_ITEM delete_attributes[],
222280304Sjkim                      OPENSSL_ITEM parameters[])
223280304Sjkim{
224280304Sjkim    STOREerr(STORE_F_MEM_MODIFY, STORE_R_NOT_IMPLEMENTED);
225280304Sjkim    return 0;
226280304Sjkim}
227280304Sjkim
228160814Ssimonstatic int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
229280304Sjkim                      OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[])
230280304Sjkim{
231280304Sjkim    STOREerr(STORE_F_MEM_DELETE, STORE_R_NOT_IMPLEMENTED);
232280304Sjkim    return 0;
233280304Sjkim}
234160814Ssimon
235280304Sjkim/*
236280304Sjkim * The list functions may be the hardest to understand.  Basically,
237280304Sjkim * mem_list_start compiles a stack of attribute info elements, and puts that
238280304Sjkim * stack into the context to be returned.  mem_list_next will then find the
239280304Sjkim * first matching element in the store, and then walk all the way to the end
240280304Sjkim * of the store (since any combination of attribute bits above the starting
241280304Sjkim * point may match the searched for bit pattern...).
242280304Sjkim */
243160814Ssimonstatic void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
244280304Sjkim                            OPENSSL_ITEM attributes[],
245280304Sjkim                            OPENSSL_ITEM parameters[])
246280304Sjkim{
247280304Sjkim    struct mem_ctx_st *context =
248280304Sjkim        (struct mem_ctx_st *)OPENSSL_malloc(sizeof(struct mem_ctx_st));
249280304Sjkim    void *attribute_context = NULL;
250280304Sjkim    STORE_ATTR_INFO *attrs = NULL;
251160814Ssimon
252280304Sjkim    if (!context) {
253280304Sjkim        STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
254280304Sjkim        return 0;
255280304Sjkim    }
256280304Sjkim    memset(context, 0, sizeof(struct mem_ctx_st));
257160814Ssimon
258280304Sjkim    attribute_context = STORE_parse_attrs_start(attributes);
259280304Sjkim    if (!attribute_context) {
260280304Sjkim        STOREerr(STORE_F_MEM_LIST_START, ERR_R_STORE_LIB);
261280304Sjkim        goto err;
262280304Sjkim    }
263160814Ssimon
264280304Sjkim    while ((attrs = STORE_parse_attrs_next(attribute_context))) {
265280304Sjkim        if (context->search_attributes == NULL) {
266280304Sjkim            context->search_attributes =
267280304Sjkim                sk_STORE_ATTR_INFO_new(STORE_ATTR_INFO_compare);
268280304Sjkim            if (!context->search_attributes) {
269280304Sjkim                STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
270280304Sjkim                goto err;
271280304Sjkim            }
272280304Sjkim        }
273280304Sjkim        sk_STORE_ATTR_INFO_push(context->search_attributes, attrs);
274280304Sjkim    }
275280304Sjkim    if (!STORE_parse_attrs_endp(attribute_context))
276280304Sjkim        goto err;
277280304Sjkim    STORE_parse_attrs_end(attribute_context);
278280304Sjkim    context->search_index = -1;
279280304Sjkim    context->index = -1;
280280304Sjkim    return context;
281160814Ssimon err:
282280304Sjkim    if (attribute_context)
283280304Sjkim        STORE_parse_attrs_end(attribute_context);
284280304Sjkim    mem_list_end(s, context);
285280304Sjkim    return NULL;
286280304Sjkim}
287280304Sjkim
288160814Ssimonstatic STORE_OBJECT *mem_list_next(STORE *s, void *handle)
289280304Sjkim{
290280304Sjkim    int i;
291280304Sjkim    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
292280304Sjkim    struct mem_object_data_st key = { 0, 0, 1 };
293280304Sjkim    struct mem_data_st *store = (struct mem_data_st *)STORE_get_ex_data(s, 1);
294280304Sjkim    int srch;
295280304Sjkim    int cres = 0;
296160814Ssimon
297280304Sjkim    if (!context) {
298280304Sjkim        STOREerr(STORE_F_MEM_LIST_NEXT, ERR_R_PASSED_NULL_PARAMETER);
299280304Sjkim        return NULL;
300280304Sjkim    }
301280304Sjkim    if (!store) {
302280304Sjkim        STOREerr(STORE_F_MEM_LIST_NEXT, STORE_R_NO_STORE);
303280304Sjkim        return NULL;
304280304Sjkim    }
305160814Ssimon
306280304Sjkim    if (context->search_index == -1) {
307280304Sjkim        for (i = 0;
308280304Sjkim             i < sk_STORE_ATTR_INFO_num(context->search_attributes); i++) {
309280304Sjkim            key.attr_info
310280304Sjkim                = sk_STORE_ATTR_INFO_value(context->search_attributes, i);
311280304Sjkim            srch = sk_MEM_OBJECT_DATA_find_ex(store->data, &key);
312160814Ssimon
313280304Sjkim            if (srch >= 0) {
314280304Sjkim                context->search_index = srch;
315280304Sjkim                break;
316280304Sjkim            }
317280304Sjkim        }
318280304Sjkim    }
319280304Sjkim    if (context->search_index < 0)
320280304Sjkim        return NULL;
321160814Ssimon
322280304Sjkim    key.attr_info =
323280304Sjkim        sk_STORE_ATTR_INFO_value(context->search_attributes,
324280304Sjkim                                 context->search_index);
325280304Sjkim    for (srch = context->search_index;
326280304Sjkim         srch < sk_MEM_OBJECT_DATA_num(store->data)
327280304Sjkim         && STORE_ATTR_INFO_in_range(key.attr_info,
328280304Sjkim                                     sk_MEM_OBJECT_DATA_value(store->data,
329280304Sjkim                                                              srch)->attr_info)
330280304Sjkim         && !(cres =
331280304Sjkim              STORE_ATTR_INFO_in_ex(key.attr_info,
332280304Sjkim                                    sk_MEM_OBJECT_DATA_value(store->data,
333280304Sjkim                                                             srch)->attr_info));
334280304Sjkim         srch++) ;
335280304Sjkim
336280304Sjkim    context->search_index = srch;
337280304Sjkim    if (cres)
338280304Sjkim        return (sk_MEM_OBJECT_DATA_value(store->data, srch))->object;
339280304Sjkim    return NULL;
340280304Sjkim}
341280304Sjkim
342160814Ssimonstatic int mem_list_end(STORE *s, void *handle)
343280304Sjkim{
344280304Sjkim    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
345160814Ssimon
346280304Sjkim    if (!context) {
347280304Sjkim        STOREerr(STORE_F_MEM_LIST_END, ERR_R_PASSED_NULL_PARAMETER);
348280304Sjkim        return 0;
349280304Sjkim    }
350280304Sjkim    if (context && context->search_attributes)
351280304Sjkim        sk_STORE_ATTR_INFO_free(context->search_attributes);
352280304Sjkim    if (context)
353280304Sjkim        OPENSSL_free(context);
354280304Sjkim    return 1;
355280304Sjkim}
356280304Sjkim
357160814Ssimonstatic int mem_list_endp(STORE *s, void *handle)
358280304Sjkim{
359280304Sjkim    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
360160814Ssimon
361280304Sjkim    if (!context
362280304Sjkim        || context->search_index
363280304Sjkim        == sk_STORE_ATTR_INFO_num(context->search_attributes))
364280304Sjkim        return 1;
365280304Sjkim    return 0;
366280304Sjkim}
367280304Sjkim
368160814Ssimonstatic int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
369280304Sjkim                    OPENSSL_ITEM parameters[])
370280304Sjkim{
371280304Sjkim    return 1;
372280304Sjkim}
373280304Sjkim
374160814Ssimonstatic int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
375280304Sjkim                      OPENSSL_ITEM parameters[])
376280304Sjkim{
377280304Sjkim    return 1;
378280304Sjkim}
379280304Sjkim
380280304Sjkimstatic int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void))
381280304Sjkim{
382280304Sjkim    return 1;
383280304Sjkim}
384