1160814Ssimon/* crypto/store/str_mem.c -*- mode:C; c-file-style: "eay" -*- */
2296465Sdelphij/*
3296465Sdelphij * Written by Richard Levitte (richard@levitte.org) for the OpenSSL project
4296465Sdelphij * 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
14296465Sdelphij *    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
64296465Sdelphij/*
65296465Sdelphij * The memory store is currently highly experimental.  It's meant to become a
66296465Sdelphij * base store used by other stores for internal caching (for full caching
67296465Sdelphij * support, aging needs to be added).
68296465Sdelphij *
69296465Sdelphij * The database use is meant to support as much attribute association as
70296465Sdelphij * possible, while providing for as small search ranges as possible. This is
71296465Sdelphij * currently provided for by sorting the entries by numbers that are composed
72296465Sdelphij * of bits set at the positions indicated by attribute type codes.  This
73296465Sdelphij * provides for ranges determined by the highest attribute type code value.
74296465Sdelphij * A better idea might be to sort by values computed from the range of
75296465Sdelphij * attributes associated with the object (basically, the difference between
76296465Sdelphij * the highest and lowest attribute type code) and it's distance from a base
77296465Sdelphij * (basically, the lowest associated attribute type code).
78296465Sdelphij */
79160814Ssimon
80296465Sdelphijstruct mem_object_data_st {
81296465Sdelphij    STORE_OBJECT *object;
82296465Sdelphij    STORE_ATTR_INFO *attr_info;
83296465Sdelphij    int references;
84296465Sdelphij};
85160814Ssimon
86296465Sdelphijstruct mem_data_st {
87296465Sdelphij    /*
88296465Sdelphij     * A stack of mem_object_data_st,
89296465Sdelphij     * sorted with STORE_ATTR_INFO_compare().
90296465Sdelphij     */
91296465Sdelphij    STACK *data;
92296465Sdelphij    /*
93296465Sdelphij     * Currently unused, but can be used to add attributes from parts of the
94296465Sdelphij     * data.
95296465Sdelphij     */
96296465Sdelphij    unsigned int compute_components:1;
97296465Sdelphij};
98160814Ssimon
99296465Sdelphijstruct mem_ctx_st {
100296465Sdelphij    /* The type we're searching for */
101296465Sdelphij    int type;
102296465Sdelphij    /*
103296465Sdelphij     * Sets of attributes to search for.
104296465Sdelphij     * Each element is a STORE_ATTR_INFO.
105296465Sdelphij     */
106296465Sdelphij    STACK *search_attributes;
107296465Sdelphij    /*
108296465Sdelphij     *  which of the search attributes we found a match
109296465Sdelphij     * for, -1 when we still haven't found any
110296465Sdelphij     */
111296465Sdelphij    int search_index;
112296465Sdelphij    /* -1 as long as we're searching for the first */
113296465Sdelphij    int index;
114296465Sdelphij};
115160814Ssimon
116160814Ssimonstatic int mem_init(STORE *s);
117160814Ssimonstatic void mem_clean(STORE *s);
118160814Ssimonstatic STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
119296465Sdelphij                                  OPENSSL_ITEM attributes[],
120296465Sdelphij                                  OPENSSL_ITEM parameters[]);
121160814Ssimonstatic STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
122296465Sdelphij                             OPENSSL_ITEM attributes[],
123296465Sdelphij                             OPENSSL_ITEM parameters[]);
124296465Sdelphijstatic int mem_store(STORE *s, STORE_OBJECT_TYPES type, STORE_OBJECT *data,
125296465Sdelphij                     OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
126160814Ssimonstatic int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
127296465Sdelphij                      OPENSSL_ITEM search_attributes[],
128296465Sdelphij                      OPENSSL_ITEM add_attributes[],
129296465Sdelphij                      OPENSSL_ITEM modify_attributes[],
130296465Sdelphij                      OPENSSL_ITEM delete_attributes[],
131296465Sdelphij                      OPENSSL_ITEM parameters[]);
132160814Ssimonstatic int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
133296465Sdelphij                      OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[]);
134160814Ssimonstatic void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
135296465Sdelphij                            OPENSSL_ITEM attributes[],
136296465Sdelphij                            OPENSSL_ITEM parameters[]);
137160814Ssimonstatic STORE_OBJECT *mem_list_next(STORE *s, void *handle);
138160814Ssimonstatic int mem_list_end(STORE *s, void *handle);
139160814Ssimonstatic int mem_list_endp(STORE *s, void *handle);
140160814Ssimonstatic int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
141296465Sdelphij                    OPENSSL_ITEM parameters[]);
142160814Ssimonstatic int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
143296465Sdelphij                      OPENSSL_ITEM parameters[]);
144296465Sdelphijstatic int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void));
145160814Ssimon
146296465Sdelphijstatic STORE_METHOD store_memory = {
147296465Sdelphij    "OpenSSL memory store interface",
148296465Sdelphij    mem_init,
149296465Sdelphij    mem_clean,
150296465Sdelphij    mem_generate,
151296465Sdelphij    mem_get,
152296465Sdelphij    mem_store,
153296465Sdelphij    mem_modify,
154296465Sdelphij    NULL,                       /* revoke */
155296465Sdelphij    mem_delete,
156296465Sdelphij    mem_list_start,
157296465Sdelphij    mem_list_next,
158296465Sdelphij    mem_list_end,
159296465Sdelphij    mem_list_endp,
160296465Sdelphij    NULL,                       /* update */
161296465Sdelphij    mem_lock,
162296465Sdelphij    mem_unlock,
163296465Sdelphij    mem_ctrl
164296465Sdelphij};
165160814Ssimon
166160814Ssimonconst STORE_METHOD *STORE_Memory(void)
167296465Sdelphij{
168296465Sdelphij    return &store_memory;
169296465Sdelphij}
170160814Ssimon
171160814Ssimonstatic int mem_init(STORE *s)
172296465Sdelphij{
173296465Sdelphij    return 1;
174296465Sdelphij}
175160814Ssimon
176160814Ssimonstatic void mem_clean(STORE *s)
177296465Sdelphij{
178296465Sdelphij    return;
179296465Sdelphij}
180160814Ssimon
181160814Ssimonstatic STORE_OBJECT *mem_generate(STORE *s, STORE_OBJECT_TYPES type,
182296465Sdelphij                                  OPENSSL_ITEM attributes[],
183296465Sdelphij                                  OPENSSL_ITEM parameters[])
184296465Sdelphij{
185296465Sdelphij    STOREerr(STORE_F_MEM_GENERATE, STORE_R_NOT_IMPLEMENTED);
186296465Sdelphij    return 0;
187296465Sdelphij}
188296465Sdelphij
189160814Ssimonstatic STORE_OBJECT *mem_get(STORE *s, STORE_OBJECT_TYPES type,
190296465Sdelphij                             OPENSSL_ITEM attributes[],
191296465Sdelphij                             OPENSSL_ITEM parameters[])
192296465Sdelphij{
193296465Sdelphij    void *context = mem_list_start(s, type, attributes, parameters);
194160814Ssimon
195296465Sdelphij    if (context) {
196296465Sdelphij        STORE_OBJECT *object = mem_list_next(s, context);
197296465Sdelphij
198296465Sdelphij        if (mem_list_end(s, context))
199296465Sdelphij            return object;
200296465Sdelphij    }
201296465Sdelphij    return NULL;
202296465Sdelphij}
203296465Sdelphij
204160814Ssimonstatic int mem_store(STORE *s, STORE_OBJECT_TYPES type,
205296465Sdelphij                     STORE_OBJECT *data, OPENSSL_ITEM attributes[],
206296465Sdelphij                     OPENSSL_ITEM parameters[])
207296465Sdelphij{
208296465Sdelphij    STOREerr(STORE_F_MEM_STORE, STORE_R_NOT_IMPLEMENTED);
209296465Sdelphij    return 0;
210296465Sdelphij}
211296465Sdelphij
212160814Ssimonstatic int mem_modify(STORE *s, STORE_OBJECT_TYPES type,
213296465Sdelphij                      OPENSSL_ITEM search_attributes[],
214296465Sdelphij                      OPENSSL_ITEM add_attributes[],
215296465Sdelphij                      OPENSSL_ITEM modify_attributes[],
216296465Sdelphij                      OPENSSL_ITEM delete_attributes[],
217296465Sdelphij                      OPENSSL_ITEM parameters[])
218296465Sdelphij{
219296465Sdelphij    STOREerr(STORE_F_MEM_MODIFY, STORE_R_NOT_IMPLEMENTED);
220296465Sdelphij    return 0;
221296465Sdelphij}
222296465Sdelphij
223160814Ssimonstatic int mem_delete(STORE *s, STORE_OBJECT_TYPES type,
224296465Sdelphij                      OPENSSL_ITEM attributes[], OPENSSL_ITEM parameters[])
225296465Sdelphij{
226296465Sdelphij    STOREerr(STORE_F_MEM_DELETE, STORE_R_NOT_IMPLEMENTED);
227296465Sdelphij    return 0;
228296465Sdelphij}
229160814Ssimon
230296465Sdelphij/*
231296465Sdelphij * The list functions may be the hardest to understand.  Basically,
232296465Sdelphij * mem_list_start compiles a stack of attribute info elements, and puts that
233296465Sdelphij * stack into the context to be returned.  mem_list_next will then find the
234296465Sdelphij * first matching element in the store, and then walk all the way to the end
235296465Sdelphij * of the store (since any combination of attribute bits above the starting
236296465Sdelphij * point may match the searched for bit pattern...).
237296465Sdelphij */
238160814Ssimonstatic void *mem_list_start(STORE *s, STORE_OBJECT_TYPES type,
239296465Sdelphij                            OPENSSL_ITEM attributes[],
240296465Sdelphij                            OPENSSL_ITEM parameters[])
241296465Sdelphij{
242296465Sdelphij    struct mem_ctx_st *context =
243296465Sdelphij        (struct mem_ctx_st *)OPENSSL_malloc(sizeof(struct mem_ctx_st));
244296465Sdelphij    void *attribute_context = NULL;
245296465Sdelphij    STORE_ATTR_INFO *attrs = NULL;
246160814Ssimon
247296465Sdelphij    if (!context) {
248296465Sdelphij        STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
249296465Sdelphij        return 0;
250296465Sdelphij    }
251296465Sdelphij    memset(context, 0, sizeof(struct mem_ctx_st));
252160814Ssimon
253296465Sdelphij    attribute_context = STORE_parse_attrs_start(attributes);
254296465Sdelphij    if (!attribute_context) {
255296465Sdelphij        STOREerr(STORE_F_MEM_LIST_START, ERR_R_STORE_LIB);
256296465Sdelphij        goto err;
257296465Sdelphij    }
258160814Ssimon
259296465Sdelphij    while ((attrs = STORE_parse_attrs_next(attribute_context))) {
260296465Sdelphij        if (context->search_attributes == NULL) {
261296465Sdelphij            context->search_attributes =
262296465Sdelphij                sk_new((int (*)(const char *const *, const char *const *))
263296465Sdelphij                       STORE_ATTR_INFO_compare);
264296465Sdelphij            if (!context->search_attributes) {
265296465Sdelphij                STOREerr(STORE_F_MEM_LIST_START, ERR_R_MALLOC_FAILURE);
266296465Sdelphij                goto err;
267296465Sdelphij            }
268296465Sdelphij        }
269296465Sdelphij        sk_push(context->search_attributes, (char *)attrs);
270296465Sdelphij    }
271296465Sdelphij    if (!STORE_parse_attrs_endp(attribute_context))
272296465Sdelphij        goto err;
273296465Sdelphij    STORE_parse_attrs_end(attribute_context);
274296465Sdelphij    context->search_index = -1;
275296465Sdelphij    context->index = -1;
276296465Sdelphij    return context;
277160814Ssimon err:
278296465Sdelphij    if (attribute_context)
279296465Sdelphij        STORE_parse_attrs_end(attribute_context);
280296465Sdelphij    mem_list_end(s, context);
281296465Sdelphij    return NULL;
282296465Sdelphij}
283296465Sdelphij
284160814Ssimonstatic STORE_OBJECT *mem_list_next(STORE *s, void *handle)
285296465Sdelphij{
286296465Sdelphij    int i;
287296465Sdelphij    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
288296465Sdelphij    struct mem_object_data_st key = { 0, 0, 1 };
289296465Sdelphij    struct mem_data_st *store = (struct mem_data_st *)STORE_get_ex_data(s, 1);
290296465Sdelphij    int srch;
291296465Sdelphij    int cres = 0;
292160814Ssimon
293296465Sdelphij    if (!context) {
294296465Sdelphij        STOREerr(STORE_F_MEM_LIST_NEXT, ERR_R_PASSED_NULL_PARAMETER);
295296465Sdelphij        return NULL;
296296465Sdelphij    }
297296465Sdelphij    if (!store) {
298296465Sdelphij        STOREerr(STORE_F_MEM_LIST_NEXT, STORE_R_NO_STORE);
299296465Sdelphij        return NULL;
300296465Sdelphij    }
301160814Ssimon
302296465Sdelphij    if (context->search_index == -1) {
303296465Sdelphij        for (i = 0; i < sk_num(context->search_attributes); i++) {
304296465Sdelphij            key.attr_info =
305296465Sdelphij                (STORE_ATTR_INFO *)sk_value(context->search_attributes, i);
306296465Sdelphij            srch = sk_find_ex(store->data, (char *)&key);
307160814Ssimon
308296465Sdelphij            if (srch >= 0) {
309296465Sdelphij                context->search_index = srch;
310296465Sdelphij                break;
311296465Sdelphij            }
312296465Sdelphij        }
313296465Sdelphij    }
314296465Sdelphij    if (context->search_index < 0)
315296465Sdelphij        return NULL;
316160814Ssimon
317296465Sdelphij    key.attr_info =
318296465Sdelphij        (STORE_ATTR_INFO *)sk_value(context->search_attributes,
319296465Sdelphij                                    context->search_index);
320296465Sdelphij    for (srch = context->search_index; srch < sk_num(store->data)
321296465Sdelphij         && STORE_ATTR_INFO_in_range(key.attr_info,
322296465Sdelphij                                     (STORE_ATTR_INFO *)sk_value(store->data,
323296465Sdelphij                                                                 srch))
324296465Sdelphij         && !(cres =
325296465Sdelphij              STORE_ATTR_INFO_in_ex(key.attr_info,
326296465Sdelphij                                    (STORE_ATTR_INFO *)sk_value(store->data,
327296465Sdelphij                                                                srch)));
328296465Sdelphij         srch++) ;
329296465Sdelphij
330296465Sdelphij    context->search_index = srch;
331296465Sdelphij    if (cres)
332296465Sdelphij        return ((struct mem_object_data_st *)sk_value(store->data,
333296465Sdelphij                                                      srch))->object;
334296465Sdelphij    return NULL;
335296465Sdelphij}
336296465Sdelphij
337160814Ssimonstatic int mem_list_end(STORE *s, void *handle)
338296465Sdelphij{
339296465Sdelphij    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
340160814Ssimon
341296465Sdelphij    if (!context) {
342296465Sdelphij        STOREerr(STORE_F_MEM_LIST_END, ERR_R_PASSED_NULL_PARAMETER);
343296465Sdelphij        return 0;
344296465Sdelphij    }
345296465Sdelphij    if (context && context->search_attributes)
346296465Sdelphij        sk_free(context->search_attributes);
347296465Sdelphij    if (context)
348296465Sdelphij        OPENSSL_free(context);
349296465Sdelphij    return 1;
350296465Sdelphij}
351296465Sdelphij
352160814Ssimonstatic int mem_list_endp(STORE *s, void *handle)
353296465Sdelphij{
354296465Sdelphij    struct mem_ctx_st *context = (struct mem_ctx_st *)handle;
355160814Ssimon
356296465Sdelphij    if (!context
357296465Sdelphij        || context->search_index == sk_num(context->search_attributes))
358296465Sdelphij        return 1;
359296465Sdelphij    return 0;
360296465Sdelphij}
361296465Sdelphij
362160814Ssimonstatic int mem_lock(STORE *s, OPENSSL_ITEM attributes[],
363296465Sdelphij                    OPENSSL_ITEM parameters[])
364296465Sdelphij{
365296465Sdelphij    return 1;
366296465Sdelphij}
367296465Sdelphij
368160814Ssimonstatic int mem_unlock(STORE *s, OPENSSL_ITEM attributes[],
369296465Sdelphij                      OPENSSL_ITEM parameters[])
370296465Sdelphij{
371296465Sdelphij    return 1;
372296465Sdelphij}
373296465Sdelphij
374296465Sdelphijstatic int mem_ctrl(STORE *s, int cmd, long l, void *p, void (*f) (void))
375296465Sdelphij{
376296465Sdelphij    return 1;
377296465Sdelphij}
378