1178825Sdfr/*
2178825Sdfr * Copyright (c) 2005 - 2006 Kungliga Tekniska H�gskolan
3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden).
4178825Sdfr * All rights reserved.
5178825Sdfr *
6178825Sdfr * Redistribution and use in source and binary forms, with or without
7178825Sdfr * modification, are permitted provided that the following conditions
8178825Sdfr * are met:
9178825Sdfr *
10178825Sdfr * 1. Redistributions of source code must retain the above copyright
11178825Sdfr *    notice, this list of conditions and the following disclaimer.
12178825Sdfr *
13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright
14178825Sdfr *    notice, this list of conditions and the following disclaimer in the
15178825Sdfr *    documentation and/or other materials provided with the distribution.
16178825Sdfr *
17178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors
18178825Sdfr *    may be used to endorse or promote products derived from this software
19178825Sdfr *    without specific prior written permission.
20178825Sdfr *
21178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24178825Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31178825Sdfr * SUCH DAMAGE.
32178825Sdfr */
33178825Sdfr
34178825Sdfr#include "hx_locl.h"
35178825SdfrRCSID("Id$");
36178825Sdfr
37178825Sdfr/*
38178825Sdfr * Should use two hash/tree certificates intead of a array.  Criteria
39178825Sdfr * should be subject and subjectKeyIdentifier since those two are
40178825Sdfr * commonly seached on in CMS and path building.
41178825Sdfr */
42178825Sdfr
43178825Sdfrstruct mem_data {
44178825Sdfr    char *name;
45178825Sdfr    struct {
46178825Sdfr	unsigned long len;
47178825Sdfr	hx509_cert *val;
48178825Sdfr    } certs;
49178825Sdfr    hx509_private_key *keys;
50178825Sdfr};
51178825Sdfr
52178825Sdfrstatic int
53178825Sdfrmem_init(hx509_context context,
54178825Sdfr	 hx509_certs certs, void **data, int flags,
55178825Sdfr	 const char *residue, hx509_lock lock)
56178825Sdfr{
57178825Sdfr    struct mem_data *mem;
58178825Sdfr    mem = calloc(1, sizeof(*mem));
59178825Sdfr    if (mem == NULL)
60178825Sdfr	return ENOMEM;
61178825Sdfr    if (residue == NULL || residue[0] == '\0')
62178825Sdfr	residue = "anonymous";
63178825Sdfr    mem->name = strdup(residue);
64178825Sdfr    if (mem->name == NULL) {
65178825Sdfr	free(mem);
66178825Sdfr	return ENOMEM;
67178825Sdfr    }
68178825Sdfr    *data = mem;
69178825Sdfr    return 0;
70178825Sdfr}
71178825Sdfr
72178825Sdfrstatic int
73178825Sdfrmem_free(hx509_certs certs, void *data)
74178825Sdfr{
75178825Sdfr    struct mem_data *mem = data;
76178825Sdfr    unsigned long i;
77178825Sdfr
78178825Sdfr    for (i = 0; i < mem->certs.len; i++)
79178825Sdfr	hx509_cert_free(mem->certs.val[i]);
80178825Sdfr    free(mem->certs.val);
81178825Sdfr    for (i = 0; mem->keys && mem->keys[i]; i++)
82178825Sdfr	_hx509_private_key_free(&mem->keys[i]);
83178825Sdfr    free(mem->keys);
84178825Sdfr    free(mem->name);
85178825Sdfr    free(mem);
86178825Sdfr
87178825Sdfr    return 0;
88178825Sdfr}
89178825Sdfr
90178825Sdfrstatic int
91178825Sdfrmem_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
92178825Sdfr{
93178825Sdfr    struct mem_data *mem = data;
94178825Sdfr    hx509_cert *val;
95178825Sdfr
96178825Sdfr    val = realloc(mem->certs.val,
97178825Sdfr		  (mem->certs.len + 1) * sizeof(mem->certs.val[0]));
98178825Sdfr    if (val == NULL)
99178825Sdfr	return ENOMEM;
100178825Sdfr
101178825Sdfr    mem->certs.val = val;
102178825Sdfr    mem->certs.val[mem->certs.len] = hx509_cert_ref(c);
103178825Sdfr    mem->certs.len++;
104178825Sdfr
105178825Sdfr    return 0;
106178825Sdfr}
107178825Sdfr
108178825Sdfrstatic int
109178825Sdfrmem_iter_start(hx509_context context,
110178825Sdfr	       hx509_certs certs,
111178825Sdfr	       void *data,
112178825Sdfr	       void **cursor)
113178825Sdfr{
114178825Sdfr    unsigned long *iter = malloc(sizeof(*iter));
115178825Sdfr
116178825Sdfr    if (iter == NULL)
117178825Sdfr	return ENOMEM;
118178825Sdfr
119178825Sdfr    *iter = 0;
120178825Sdfr    *cursor = iter;
121178825Sdfr
122178825Sdfr    return 0;
123178825Sdfr}
124178825Sdfr
125178825Sdfrstatic int
126178825Sdfrmem_iter(hx509_context contexst,
127178825Sdfr	 hx509_certs certs,
128178825Sdfr	 void *data,
129178825Sdfr	 void *cursor,
130178825Sdfr	 hx509_cert *cert)
131178825Sdfr{
132178825Sdfr    unsigned long *iter = cursor;
133178825Sdfr    struct mem_data *mem = data;
134178825Sdfr
135178825Sdfr    if (*iter >= mem->certs.len) {
136178825Sdfr	*cert = NULL;
137178825Sdfr	return 0;
138178825Sdfr    }
139178825Sdfr
140178825Sdfr    *cert = hx509_cert_ref(mem->certs.val[*iter]);
141178825Sdfr    (*iter)++;
142178825Sdfr    return 0;
143178825Sdfr}
144178825Sdfr
145178825Sdfrstatic int
146178825Sdfrmem_iter_end(hx509_context context,
147178825Sdfr	     hx509_certs certs,
148178825Sdfr	     void *data,
149178825Sdfr	     void *cursor)
150178825Sdfr{
151178825Sdfr    free(cursor);
152178825Sdfr    return 0;
153178825Sdfr}
154178825Sdfr
155178825Sdfrstatic int
156178825Sdfrmem_getkeys(hx509_context context,
157178825Sdfr	     hx509_certs certs,
158178825Sdfr	     void *data,
159178825Sdfr	     hx509_private_key **keys)
160178825Sdfr{
161178825Sdfr    struct mem_data *mem = data;
162178825Sdfr    int i;
163178825Sdfr
164178825Sdfr    for (i = 0; mem->keys && mem->keys[i]; i++)
165178825Sdfr	;
166178825Sdfr    *keys = calloc(i + 1, sizeof(**keys));
167178825Sdfr    for (i = 0; mem->keys && mem->keys[i]; i++) {
168178825Sdfr	(*keys)[i] = _hx509_private_key_ref(mem->keys[i]);
169178825Sdfr	if ((*keys)[i] == NULL) {
170178825Sdfr	    while (--i >= 0)
171178825Sdfr		_hx509_private_key_free(&(*keys)[i]);
172178825Sdfr	    hx509_set_error_string(context, 0, ENOMEM, "out of memory");
173178825Sdfr	    return ENOMEM;
174178825Sdfr	}
175178825Sdfr    }
176178825Sdfr    (*keys)[i] = NULL;
177178825Sdfr    return 0;
178178825Sdfr}
179178825Sdfr
180178825Sdfrstatic int
181178825Sdfrmem_addkey(hx509_context context,
182178825Sdfr	   hx509_certs certs,
183178825Sdfr	   void *data,
184178825Sdfr	   hx509_private_key key)
185178825Sdfr{
186178825Sdfr    struct mem_data *mem = data;
187178825Sdfr    void *ptr;
188178825Sdfr    int i;
189178825Sdfr
190178825Sdfr    for (i = 0; mem->keys && mem->keys[i]; i++)
191178825Sdfr	;
192178825Sdfr    ptr = realloc(mem->keys, (i + 2) * sizeof(*mem->keys));
193178825Sdfr    if (ptr == NULL) {
194178825Sdfr	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
195178825Sdfr	return ENOMEM;
196178825Sdfr    }
197178825Sdfr    mem->keys = ptr;
198178825Sdfr    mem->keys[i++] = _hx509_private_key_ref(key);
199178825Sdfr    mem->keys[i++] = NULL;
200178825Sdfr    return 0;
201178825Sdfr}
202178825Sdfr
203178825Sdfr
204178825Sdfrstatic struct hx509_keyset_ops keyset_mem = {
205178825Sdfr    "MEMORY",
206178825Sdfr    0,
207178825Sdfr    mem_init,
208178825Sdfr    NULL,
209178825Sdfr    mem_free,
210178825Sdfr    mem_add,
211178825Sdfr    NULL,
212178825Sdfr    mem_iter_start,
213178825Sdfr    mem_iter,
214178825Sdfr    mem_iter_end,
215178825Sdfr    NULL,
216178825Sdfr    mem_getkeys,
217178825Sdfr    mem_addkey
218178825Sdfr};
219178825Sdfr
220178825Sdfrvoid
221178825Sdfr_hx509_ks_mem_register(hx509_context context)
222178825Sdfr{
223178825Sdfr    _hx509_ks_register(context, &keyset_mem);
224178825Sdfr}
225