1295009Sjkim/* crypto/store/str_mem.c */
2280297Sjkim/*
3280297Sjkim * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
4280297Sjkim * 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
14280297Sjkim *    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
64280297Sjkim/*
65280297Sjkim * The memory store is currently highly experimental.  It's meant to become a
66280297Sjkim * base store used by other stores for internal caching (for full caching
67280297Sjkim * support, aging needs to be added).
68280297Sjkim *
69280297Sjkim * The database use is meant to support as much attribute association as
70280297Sjkim * possible, while providing for as small search ranges as possible. This is
71280297Sjkim * currently provided for by sorting the entries by numbers that are composed
72280297Sjkim * of bits set at the positions indicated by attribute type codes.  This
73280297Sjkim * provides for ranges determined by the highest attribute type code value.
74280297Sjkim * A better idea might be to sort by values computed from the range of
75280297Sjkim * attributes associated with the object (basically, the difference between
76280297Sjkim * the highest and lowest attribute type code) and it's distance from a base
77280297Sjkim * (basically, the lowest associated attribute type code).
78280297Sjkim */
79160814Ssimon
80280297Sjkimtypedef struct mem_object_data_st {
81280297Sjkim    STORE_OBJECT *object;
82280297Sjkim    STORE_ATTR_INFO *attr_info;
83280297Sjkim    int references;
84280297Sjkim} MEM_OBJECT_DATA;
85160814Ssimon
86238405SjkimDECLARE_STACK_OF(MEM_OBJECT_DATA)
87280297Sjkimstruct mem_data_st {
88280297Sjkim    /*
89280297Sjkim     * sorted with
90280297Sjkim     * STORE_ATTR_INFO_compare().
91280297Sjkim     */
92280297Sjkim    STACK_OF(MEM_OBJECT_DATA) *data;
93280297Sjkim    /*
94280297Sjkim     * Currently unused, but can
95280297Sjkim     * be used to add attributes
96280297Sjkim     * from parts of the data.
97280297Sjkim     */
98280297Sjkim    unsigned int compute_components:1;
99280297Sjkim};
100160814Ssimon
101238405SjkimDECLARE_STACK_OF(STORE_ATTR_INFO)
102280297Sjkimstruct mem_ctx_st {
103280297Sjkim    /* The type we're searching for */
104280297Sjkim    int type;
105280297Sjkim    /*
106280297Sjkim     * Sets of
107280297Sjkim     * attributes to search for.  Each
108280297Sjkim     * element is a STORE_ATTR_INFO.
109280297Sjkim     */
110280297Sjkim    STACK_OF(STORE_ATTR_INFO) *search_attributes;
111280297Sjkim    /*
112280297Sjkim     * which of the search attributes we
113280297Sjkim     * found a match for, -1 when we still
114280297Sjkim     * haven't found any
115280297Sjkim     */
116280297Sjkim    int search_index;
117280297Sjkim    /* -1 as long as we're searching for the first */
118280297Sjkim    int index;
119280297Sjkim};
120160814Ssimon
121160814Ssimonstatic int mem_init(STORE *s);
122160814Ssimonstatic void mem_clean(STORE *s);
123160814Ssimonstatic STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
124280297Sjkim                                  OPENSSL_ITEM attributes[],
125280297Sjkim                                  OPENSSL_ITEM parameters[]);
126160814Ssimonstatic STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
127280297Sjkim                             OPENSSL_ITEM attributes[],
128280297Sjkim                             OPENSSL_ITEM parameters[]);
129280297Sjkimstatic int mem_store(STORE *s, STORE_OBJECT_TYPES type, STORE_OBJECT *data,
130280297Sjkim                     OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
131160814Ssimonstatic int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
132280297Sjkim                      OPENSSL_ITEM search_attributes[],
133280297Sjkim                      OPENSSL_ITEM add_attributes[],
134280297Sjkim                      OPENSSL_ITEM modify_attributes[],
135280297Sjkim                      OPENSSL_ITEM delete_attributes[],
136280297Sjkim                      OPENSSL_ITEM parameters[]);
137160814Ssimonstatic int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
138280297Sjkim                      OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
139160814Ssimonstatic void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
140280297Sjkim                            OPENSSL_ITEM attributes[],
141280297Sjkim                            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[],
146280297Sjkim                    OPENSSL_ITEM parameters[]);
147160814Ssimonstatic int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
148280297Sjkim                      OPENSSL_ITEM parameters[]);
149280297Sjkimstatic int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void));
150160814Ssimon
151280297Sjkimstatic STORE_METHOD store_memory = {
152280297Sjkim    "OpenSSL memory store interface",
153280297Sjkim    mem_init,
154280297Sjkim    mem_clean,
155280297Sjkim    mem_generate,
156280297Sjkim    mem_get,
157280297Sjkim    mem_store,
158280297Sjkim    mem_modify,
159280297Sjkim    NULL,                       /* revoke */
160280297Sjkim    mem_delete,
161280297Sjkim    mem_list_start,
162280297Sjkim    mem_list_next,
163280297Sjkim    mem_list_end,
164280297Sjkim    mem_list_endp,
165280297Sjkim    NULL,                       /* update */
166280297Sjkim    mem_lock,
167280297Sjkim    mem_unlock,
168280297Sjkim    mem_ctrl
169280297Sjkim};
170160814Ssimon
171160814Ssimonconst STORE_METHOD *STORE_Memory(void)
172280297Sjkim{
173280297Sjkim    return &store_memory;
174280297Sjkim}
175160814Ssimon
176160814Ssimonstatic int mem_init(STORE *s)
177280297Sjkim{
178280297Sjkim    return 1;
179280297Sjkim}
180160814Ssimon
181160814Ssimonstatic void mem_clean(STORE *s)
182280297Sjkim{
183280297Sjkim    return;
184280297Sjkim}
185160814Ssimon
186160814Ssimonstatic STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
187280297Sjkim                                  OPENSSL_ITEM attributes[],
188280297Sjkim                                  OPENSSL_ITEM parameters[])
189280297Sjkim{
190280297Sjkim    STOREerr(STORE_F_MEM_GENERATE, STORE_R_NOT_IMPLEMENTED);
191280297Sjkim    return 0;
192280297Sjkim}
193280297Sjkim
194160814Ssimonstatic STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
195280297Sjkim                             OPENSSL_ITEM attributes[],
196280297Sjkim                             OPENSSL_ITEM parameters[])
197280297Sjkim{
198280297Sjkim    void *context = mem_list_start(s, type, attributes, parameters);
199160814Ssimon
200280297Sjkim    if (context) {
201280297Sjkim        STORE_OBJECT *object = mem_list_next(s, context);
202280297Sjkim
203280297Sjkim        if (mem_list_end(s, context))
204280297Sjkim            return object;
205280297Sjkim    }
206280297Sjkim    return NULL;
207280297Sjkim}
208280297Sjkim
209160814Ssimonstatic int mem_store(STORE *s, STORE_OBJECT_TYPES type,
210280297Sjkim                     STORE_OBJECT *data, OPENSSL_ITEM attributes[],
211280297Sjkim                     OPENSSL_ITEM parameters[])
212280297Sjkim{
213280297Sjkim    STOREerr(STORE_F_MEM_STORE, STORE_R_NOT_IMPLEMENTED);
214280297Sjkim    return 0;
215280297Sjkim}
216280297Sjkim
217160814Ssimonstatic int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
218280297Sjkim                      OPENSSL_ITEM search_attributes[],
219280297Sjkim                      OPENSSL_ITEM add_attributes[],
220280297Sjkim                      OPENSSL_ITEM modify_attributes[],
221280297Sjkim                      OPENSSL_ITEM delete_attributes[],
222280297Sjkim                      OPENSSL_ITEM parameters[])
223280297Sjkim{
224280297Sjkim    STOREerr(STORE_F_MEM_MODIFY, STORE_R_NOT_IMPLEMENTED);
225280297Sjkim    return 0;
226280297Sjkim}
227280297Sjkim
228160814Ssimonstatic int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
229280297Sjkim                      OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[])
230280297Sjkim{
231280297Sjkim    STOREerr(STORE_F_MEM_DELETE, STORE_R_NOT_IMPLEMENTED);
232280297Sjkim    return 0;
233280297Sjkim}
234160814Ssimon
235280297Sjkim/*
236280297Sjkim * The list functions may be the hardest to understand.  Basically,
237280297Sjkim * mem_list_start compiles a stack of attribute info elements, and puts that
238280297Sjkim * stack into the context to be returned.  mem_list_next will then find the
239280297Sjkim * first matching element in the store, and then walk all the way to the end
240280297Sjkim * of the store (since any combination of attribute bits above the starting
241280297Sjkim * point may match the searched for bit pattern...).
242280297Sjkim */
243160814Ssimonstatic void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
244280297Sjkim                            OPENSSL_ITEM attributes[],
245280297Sjkim                            OPENSSL_ITEM parameters[])
246280297Sjkim{
247280297Sjkim    struct mem_ctx_st *context =
248280297Sjkim        (struct mem_ctx_st *)OPENSSL_malloc(sizeof(struct mem_ctx_st));
249280297Sjkim    void *attribute_context = NULL;
250280297Sjkim    STORE_ATTR_INFO *attrs = NULL;
251160814Ssimon
252280297Sjkim    if (!context) {
253280297Sjkim        STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
254280297Sjkim        return 0;
255280297Sjkim    }
256280297Sjkim    memset(context, 0, sizeof(struct mem_ctx_st));
257160814Ssimon
258280297Sjkim    attribute_context = STORE_parse_attrs_start(attributes);
259280297Sjkim    if (!attribute_context) {
260280297Sjkim        STOREerr(STORE_F_MEM_LIST_START, ERR_R_STORE_LIB);
261280297Sjkim        goto err;
262280297Sjkim    }
263160814Ssimon
264280297Sjkim    while ((attrs = STORE_parse_attrs_next(attribute_context))) {
265280297Sjkim        if (context->search_attributes == NULL) {
266280297Sjkim            context->search_attributes =
267280297Sjkim                sk_STORE_ATTR_INFO_new(STORE_ATTR_INFO_compare);
268280297Sjkim            if (!context->search_attributes) {
269280297Sjkim                STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
270280297Sjkim                goto err;
271280297Sjkim            }
272280297Sjkim        }
273280297Sjkim        sk_STORE_ATTR_INFO_push(context->search_attributes, attrs);
274280297Sjkim    }
275280297Sjkim    if (!STORE_parse_attrs_endp(attribute_context))
276280297Sjkim        goto err;
277280297Sjkim    STORE_parse_attrs_end(attribute_context);
278280297Sjkim    context->search_index = -1;
279280297Sjkim    context->index = -1;
280280297Sjkim    return context;
281160814Ssimon err:
282280297Sjkim    if (attribute_context)
283280297Sjkim        STORE_parse_attrs_end(attribute_context);
284280297Sjkim    mem_list_end(s, context);
285280297Sjkim    return NULL;
286280297Sjkim}
287280297Sjkim
288160814Ssimonstatic STORE_OBJECT *mem_list_next(STORE *s, void *handle)
289280297Sjkim{
290280297Sjkim    int i;
291280297Sjkim    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
292280297Sjkim    struct mem_object_data_st key = { 0, 0, 1 };
293280297Sjkim    struct mem_data_st *store = (struct mem_data_st *)STORE_get_ex_data(s, 1);
294280297Sjkim    int srch;
295280297Sjkim    int cres = 0;
296160814Ssimon
297280297Sjkim    if (!context) {
298280297Sjkim        STOREerr(STORE_F_MEM_LIST_NEXT, ERR_R_PASSED_NULL_PARAMETER);
299280297Sjkim        return NULL;
300280297Sjkim    }
301280297Sjkim    if (!store) {
302280297Sjkim        STOREerr(STORE_F_MEM_LIST_NEXT, STORE_R_NO_STORE);
303280297Sjkim        return NULL;
304280297Sjkim    }
305160814Ssimon
306280297Sjkim    if (context->search_index == -1) {
307280297Sjkim        for (i = 0;
308280297Sjkim             i < sk_STORE_ATTR_INFO_num(context->search_attributes); i++) {
309280297Sjkim            key.attr_info
310280297Sjkim                = sk_STORE_ATTR_INFO_value(context->search_attributes, i);
311280297Sjkim            srch = sk_MEM_OBJECT_DATA_find_ex(store->data, &key);
312160814Ssimon
313280297Sjkim            if (srch >= 0) {
314280297Sjkim                context->search_index = srch;
315280297Sjkim                break;
316280297Sjkim            }
317280297Sjkim        }
318280297Sjkim    }
319280297Sjkim    if (context->search_index < 0)
320280297Sjkim        return NULL;
321160814Ssimon
322280297Sjkim    key.attr_info =
323280297Sjkim        sk_STORE_ATTR_INFO_value(context->search_attributes,
324280297Sjkim                                 context->search_index);
325280297Sjkim    for (srch = context->search_index;
326280297Sjkim         srch < sk_MEM_OBJECT_DATA_num(store->data)
327280297Sjkim         && STORE_ATTR_INFO_in_range(key.attr_info,
328280297Sjkim                                     sk_MEM_OBJECT_DATA_value(store->data,
329280297Sjkim                                                              srch)->attr_info)
330280297Sjkim         && !(cres =
331280297Sjkim              STORE_ATTR_INFO_in_ex(key.attr_info,
332280297Sjkim                                    sk_MEM_OBJECT_DATA_value(store->data,
333280297Sjkim                                                             srch)->attr_info));
334280297Sjkim         srch++) ;
335280297Sjkim
336280297Sjkim    context->search_index = srch;
337280297Sjkim    if (cres)
338280297Sjkim        return (sk_MEM_OBJECT_DATA_value(store->data, srch))->object;
339280297Sjkim    return NULL;
340280297Sjkim}
341280297Sjkim
342160814Ssimonstatic int mem_list_end(STORE *s, void *handle)
343280297Sjkim{
344280297Sjkim    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
345160814Ssimon
346280297Sjkim    if (!context) {
347280297Sjkim        STOREerr(STORE_F_MEM_LIST_END, ERR_R_PASSED_NULL_PARAMETER);
348280297Sjkim        return 0;
349280297Sjkim    }
350280297Sjkim    if (context && context->search_attributes)
351280297Sjkim        sk_STORE_ATTR_INFO_free(context->search_attributes);
352280297Sjkim    if (context)
353280297Sjkim        OPENSSL_free(context);
354280297Sjkim    return 1;
355280297Sjkim}
356280297Sjkim
357160814Ssimonstatic int mem_list_endp(STORE *s, void *handle)
358280297Sjkim{
359280297Sjkim    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
360160814Ssimon
361280297Sjkim    if (!context
362280297Sjkim        || context->search_index
363280297Sjkim        == sk_STORE_ATTR_INFO_num(context->search_attributes))
364280297Sjkim        return 1;
365280297Sjkim    return 0;
366280297Sjkim}
367280297Sjkim
368160814Ssimonstatic int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
369280297Sjkim                    OPENSSL_ITEM parameters[])
370280297Sjkim{
371280297Sjkim    return 1;
372280297Sjkim}
373280297Sjkim
374160814Ssimonstatic int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
375280297Sjkim                      OPENSSL_ITEM parameters[])
376280297Sjkim{
377280297Sjkim    return 1;
378280297Sjkim}
379280297Sjkim
380280297Sjkimstatic int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void))
381280297Sjkim{
382280297Sjkim    return 1;
383280297Sjkim}
384