1c19800e8SDoug Rabson /*
2*ae771770SStanislav Sedov * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
3c19800e8SDoug Rabson * (Royal Institute of Technology, Stockholm, Sweden).
4c19800e8SDoug Rabson * All rights reserved.
5c19800e8SDoug Rabson *
6c19800e8SDoug Rabson * Redistribution and use in source and binary forms, with or without
7c19800e8SDoug Rabson * modification, are permitted provided that the following conditions
8c19800e8SDoug Rabson * are met:
9c19800e8SDoug Rabson *
10c19800e8SDoug Rabson * 1. Redistributions of source code must retain the above copyright
11c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer.
12c19800e8SDoug Rabson *
13c19800e8SDoug Rabson * 2. Redistributions in binary form must reproduce the above copyright
14c19800e8SDoug Rabson * notice, this list of conditions and the following disclaimer in the
15c19800e8SDoug Rabson * documentation and/or other materials provided with the distribution.
16c19800e8SDoug Rabson *
17c19800e8SDoug Rabson * 3. Neither the name of the Institute nor the names of its contributors
18c19800e8SDoug Rabson * may be used to endorse or promote products derived from this software
19c19800e8SDoug Rabson * without specific prior written permission.
20c19800e8SDoug Rabson *
21c19800e8SDoug Rabson * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22c19800e8SDoug Rabson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c19800e8SDoug Rabson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c19800e8SDoug Rabson * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25c19800e8SDoug Rabson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c19800e8SDoug Rabson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c19800e8SDoug Rabson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c19800e8SDoug Rabson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c19800e8SDoug Rabson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c19800e8SDoug Rabson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c19800e8SDoug Rabson * SUCH DAMAGE.
32c19800e8SDoug Rabson */
33c19800e8SDoug Rabson
34c19800e8SDoug Rabson #include "hx_locl.h"
35c19800e8SDoug Rabson
36c19800e8SDoug Rabson struct private_key {
37c19800e8SDoug Rabson AlgorithmIdentifier alg;
38c19800e8SDoug Rabson hx509_private_key private_key;
39c19800e8SDoug Rabson heim_octet_string localKeyId;
40c19800e8SDoug Rabson };
41c19800e8SDoug Rabson
42c19800e8SDoug Rabson struct hx509_collector {
43c19800e8SDoug Rabson hx509_lock lock;
44c19800e8SDoug Rabson hx509_certs unenvelop_certs;
45c19800e8SDoug Rabson hx509_certs certs;
46c19800e8SDoug Rabson struct {
47c19800e8SDoug Rabson struct private_key **data;
48c19800e8SDoug Rabson size_t len;
49c19800e8SDoug Rabson } val;
50c19800e8SDoug Rabson };
51c19800e8SDoug Rabson
52c19800e8SDoug Rabson
53c19800e8SDoug Rabson int
_hx509_collector_alloc(hx509_context context,hx509_lock lock,struct hx509_collector ** collector)54c19800e8SDoug Rabson _hx509_collector_alloc(hx509_context context, hx509_lock lock, struct hx509_collector **collector)
55c19800e8SDoug Rabson {
56c19800e8SDoug Rabson struct hx509_collector *c;
57c19800e8SDoug Rabson int ret;
58c19800e8SDoug Rabson
59c19800e8SDoug Rabson *collector = NULL;
60c19800e8SDoug Rabson
61c19800e8SDoug Rabson c = calloc(1, sizeof(*c));
62c19800e8SDoug Rabson if (c == NULL) {
63c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "out of memory");
64c19800e8SDoug Rabson return ENOMEM;
65c19800e8SDoug Rabson }
66c19800e8SDoug Rabson c->lock = lock;
67c19800e8SDoug Rabson
68c19800e8SDoug Rabson ret = hx509_certs_init(context, "MEMORY:collector-unenvelop-cert",
69c19800e8SDoug Rabson 0,NULL, &c->unenvelop_certs);
70c19800e8SDoug Rabson if (ret) {
71c19800e8SDoug Rabson free(c);
72c19800e8SDoug Rabson return ret;
73c19800e8SDoug Rabson }
74c19800e8SDoug Rabson c->val.data = NULL;
75c19800e8SDoug Rabson c->val.len = 0;
76c19800e8SDoug Rabson ret = hx509_certs_init(context, "MEMORY:collector-tmp-store",
77c19800e8SDoug Rabson 0, NULL, &c->certs);
78c19800e8SDoug Rabson if (ret) {
79c19800e8SDoug Rabson hx509_certs_free(&c->unenvelop_certs);
80c19800e8SDoug Rabson free(c);
81c19800e8SDoug Rabson return ret;
82c19800e8SDoug Rabson }
83c19800e8SDoug Rabson
84c19800e8SDoug Rabson *collector = c;
85c19800e8SDoug Rabson return 0;
86c19800e8SDoug Rabson }
87c19800e8SDoug Rabson
88c19800e8SDoug Rabson hx509_lock
_hx509_collector_get_lock(struct hx509_collector * c)89c19800e8SDoug Rabson _hx509_collector_get_lock(struct hx509_collector *c)
90c19800e8SDoug Rabson {
91c19800e8SDoug Rabson return c->lock;
92c19800e8SDoug Rabson }
93c19800e8SDoug Rabson
94c19800e8SDoug Rabson
95c19800e8SDoug Rabson int
_hx509_collector_certs_add(hx509_context context,struct hx509_collector * c,hx509_cert cert)96c19800e8SDoug Rabson _hx509_collector_certs_add(hx509_context context,
97c19800e8SDoug Rabson struct hx509_collector *c,
98c19800e8SDoug Rabson hx509_cert cert)
99c19800e8SDoug Rabson {
100c19800e8SDoug Rabson return hx509_certs_add(context, c->certs, cert);
101c19800e8SDoug Rabson }
102c19800e8SDoug Rabson
103c19800e8SDoug Rabson static void
free_private_key(struct private_key * key)104c19800e8SDoug Rabson free_private_key(struct private_key *key)
105c19800e8SDoug Rabson {
106c19800e8SDoug Rabson free_AlgorithmIdentifier(&key->alg);
107c19800e8SDoug Rabson if (key->private_key)
108*ae771770SStanislav Sedov hx509_private_key_free(&key->private_key);
109c19800e8SDoug Rabson der_free_octet_string(&key->localKeyId);
110c19800e8SDoug Rabson free(key);
111c19800e8SDoug Rabson }
112c19800e8SDoug Rabson
113c19800e8SDoug Rabson int
_hx509_collector_private_key_add(hx509_context context,struct hx509_collector * c,const AlgorithmIdentifier * alg,hx509_private_key private_key,const heim_octet_string * key_data,const heim_octet_string * localKeyId)114c19800e8SDoug Rabson _hx509_collector_private_key_add(hx509_context context,
115c19800e8SDoug Rabson struct hx509_collector *c,
116c19800e8SDoug Rabson const AlgorithmIdentifier *alg,
117c19800e8SDoug Rabson hx509_private_key private_key,
118c19800e8SDoug Rabson const heim_octet_string *key_data,
119c19800e8SDoug Rabson const heim_octet_string *localKeyId)
120c19800e8SDoug Rabson {
121c19800e8SDoug Rabson struct private_key *key;
122c19800e8SDoug Rabson void *d;
123c19800e8SDoug Rabson int ret;
124c19800e8SDoug Rabson
125c19800e8SDoug Rabson key = calloc(1, sizeof(*key));
126c19800e8SDoug Rabson if (key == NULL)
127c19800e8SDoug Rabson return ENOMEM;
128c19800e8SDoug Rabson
129c19800e8SDoug Rabson d = realloc(c->val.data, (c->val.len + 1) * sizeof(c->val.data[0]));
130c19800e8SDoug Rabson if (d == NULL) {
131c19800e8SDoug Rabson free(key);
132c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
133c19800e8SDoug Rabson return ENOMEM;
134c19800e8SDoug Rabson }
135c19800e8SDoug Rabson c->val.data = d;
136c19800e8SDoug Rabson
137c19800e8SDoug Rabson ret = copy_AlgorithmIdentifier(alg, &key->alg);
138c19800e8SDoug Rabson if (ret) {
139c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret, "Failed to copy "
140c19800e8SDoug Rabson "AlgorithmIdentifier");
141c19800e8SDoug Rabson goto out;
142c19800e8SDoug Rabson }
143c19800e8SDoug Rabson if (private_key) {
144c19800e8SDoug Rabson key->private_key = private_key;
145c19800e8SDoug Rabson } else {
146*ae771770SStanislav Sedov ret = hx509_parse_private_key(context, alg,
147c19800e8SDoug Rabson key_data->data, key_data->length,
148*ae771770SStanislav Sedov HX509_KEY_FORMAT_DER,
149c19800e8SDoug Rabson &key->private_key);
150c19800e8SDoug Rabson if (ret)
151c19800e8SDoug Rabson goto out;
152c19800e8SDoug Rabson }
153c19800e8SDoug Rabson if (localKeyId) {
154c19800e8SDoug Rabson ret = der_copy_octet_string(localKeyId, &key->localKeyId);
155c19800e8SDoug Rabson if (ret) {
156c19800e8SDoug Rabson hx509_set_error_string(context, 0, ret,
157c19800e8SDoug Rabson "Failed to copy localKeyId");
158c19800e8SDoug Rabson goto out;
159c19800e8SDoug Rabson }
160c19800e8SDoug Rabson } else
161c19800e8SDoug Rabson memset(&key->localKeyId, 0, sizeof(key->localKeyId));
162c19800e8SDoug Rabson
163c19800e8SDoug Rabson c->val.data[c->val.len] = key;
164c19800e8SDoug Rabson c->val.len++;
165c19800e8SDoug Rabson
166c19800e8SDoug Rabson out:
167c19800e8SDoug Rabson if (ret)
168c19800e8SDoug Rabson free_private_key(key);
169c19800e8SDoug Rabson
170c19800e8SDoug Rabson return ret;
171c19800e8SDoug Rabson }
172c19800e8SDoug Rabson
173c19800e8SDoug Rabson static int
match_localkeyid(hx509_context context,struct private_key * value,hx509_certs certs)174c19800e8SDoug Rabson match_localkeyid(hx509_context context,
175c19800e8SDoug Rabson struct private_key *value,
176c19800e8SDoug Rabson hx509_certs certs)
177c19800e8SDoug Rabson {
178c19800e8SDoug Rabson hx509_cert cert;
179c19800e8SDoug Rabson hx509_query q;
180c19800e8SDoug Rabson int ret;
181c19800e8SDoug Rabson
182c19800e8SDoug Rabson if (value->localKeyId.length == 0) {
183c19800e8SDoug Rabson hx509_set_error_string(context, 0, HX509_LOCAL_ATTRIBUTE_MISSING,
184c19800e8SDoug Rabson "No local key attribute on private key");
185c19800e8SDoug Rabson return HX509_LOCAL_ATTRIBUTE_MISSING;
186c19800e8SDoug Rabson }
187c19800e8SDoug Rabson
188c19800e8SDoug Rabson _hx509_query_clear(&q);
189c19800e8SDoug Rabson q.match |= HX509_QUERY_MATCH_LOCAL_KEY_ID;
190c19800e8SDoug Rabson
191c19800e8SDoug Rabson q.local_key_id = &value->localKeyId;
192c19800e8SDoug Rabson
193c19800e8SDoug Rabson ret = hx509_certs_find(context, certs, &q, &cert);
194c19800e8SDoug Rabson if (ret == 0) {
195c19800e8SDoug Rabson
196c19800e8SDoug Rabson if (value->private_key)
197c19800e8SDoug Rabson _hx509_cert_assign_key(cert, value->private_key);
198c19800e8SDoug Rabson hx509_cert_free(cert);
199c19800e8SDoug Rabson }
200c19800e8SDoug Rabson return ret;
201c19800e8SDoug Rabson }
202c19800e8SDoug Rabson
203c19800e8SDoug Rabson static int
match_keys(hx509_context context,struct private_key * value,hx509_certs certs)204c19800e8SDoug Rabson match_keys(hx509_context context, struct private_key *value, hx509_certs certs)
205c19800e8SDoug Rabson {
206c19800e8SDoug Rabson hx509_cursor cursor;
207c19800e8SDoug Rabson hx509_cert c;
208c19800e8SDoug Rabson int ret, found = HX509_CERT_NOT_FOUND;
209c19800e8SDoug Rabson
210c19800e8SDoug Rabson if (value->private_key == NULL) {
211c19800e8SDoug Rabson hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
212c19800e8SDoug Rabson "No private key to compare with");
213c19800e8SDoug Rabson return HX509_PRIVATE_KEY_MISSING;
214c19800e8SDoug Rabson }
215c19800e8SDoug Rabson
216c19800e8SDoug Rabson ret = hx509_certs_start_seq(context, certs, &cursor);
217c19800e8SDoug Rabson if (ret)
218c19800e8SDoug Rabson return ret;
219c19800e8SDoug Rabson
220c19800e8SDoug Rabson c = NULL;
221c19800e8SDoug Rabson while (1) {
222c19800e8SDoug Rabson ret = hx509_certs_next_cert(context, certs, cursor, &c);
223c19800e8SDoug Rabson if (ret)
224c19800e8SDoug Rabson break;
225c19800e8SDoug Rabson if (c == NULL)
226c19800e8SDoug Rabson break;
227c19800e8SDoug Rabson if (_hx509_cert_private_key(c)) {
228c19800e8SDoug Rabson hx509_cert_free(c);
229c19800e8SDoug Rabson continue;
230c19800e8SDoug Rabson }
231c19800e8SDoug Rabson
232c19800e8SDoug Rabson ret = _hx509_match_keys(c, value->private_key);
233c19800e8SDoug Rabson if (ret) {
234c19800e8SDoug Rabson _hx509_cert_assign_key(c, value->private_key);
235c19800e8SDoug Rabson hx509_cert_free(c);
236c19800e8SDoug Rabson found = 0;
237c19800e8SDoug Rabson break;
238c19800e8SDoug Rabson }
239c19800e8SDoug Rabson hx509_cert_free(c);
240c19800e8SDoug Rabson }
241c19800e8SDoug Rabson
242c19800e8SDoug Rabson hx509_certs_end_seq(context, certs, cursor);
243c19800e8SDoug Rabson
244c19800e8SDoug Rabson if (found)
245c19800e8SDoug Rabson hx509_clear_error_string(context);
246c19800e8SDoug Rabson
247c19800e8SDoug Rabson return found;
248c19800e8SDoug Rabson }
249c19800e8SDoug Rabson
250c19800e8SDoug Rabson int
_hx509_collector_collect_certs(hx509_context context,struct hx509_collector * c,hx509_certs * ret_certs)251c19800e8SDoug Rabson _hx509_collector_collect_certs(hx509_context context,
252c19800e8SDoug Rabson struct hx509_collector *c,
253c19800e8SDoug Rabson hx509_certs *ret_certs)
254c19800e8SDoug Rabson {
255c19800e8SDoug Rabson hx509_certs certs;
256*ae771770SStanislav Sedov int ret;
257*ae771770SStanislav Sedov size_t i;
258c19800e8SDoug Rabson
259c19800e8SDoug Rabson *ret_certs = NULL;
260c19800e8SDoug Rabson
261c19800e8SDoug Rabson ret = hx509_certs_init(context, "MEMORY:collector-store", 0, NULL, &certs);
262c19800e8SDoug Rabson if (ret)
263c19800e8SDoug Rabson return ret;
264c19800e8SDoug Rabson
265c19800e8SDoug Rabson ret = hx509_certs_merge(context, certs, c->certs);
266c19800e8SDoug Rabson if (ret) {
267c19800e8SDoug Rabson hx509_certs_free(&certs);
268c19800e8SDoug Rabson return ret;
269c19800e8SDoug Rabson }
270c19800e8SDoug Rabson
271c19800e8SDoug Rabson for (i = 0; i < c->val.len; i++) {
272c19800e8SDoug Rabson ret = match_localkeyid(context, c->val.data[i], certs);
273c19800e8SDoug Rabson if (ret == 0)
274c19800e8SDoug Rabson continue;
275c19800e8SDoug Rabson ret = match_keys(context, c->val.data[i], certs);
276c19800e8SDoug Rabson if (ret == 0)
277c19800e8SDoug Rabson continue;
278c19800e8SDoug Rabson }
279c19800e8SDoug Rabson
280c19800e8SDoug Rabson *ret_certs = certs;
281c19800e8SDoug Rabson
282c19800e8SDoug Rabson return 0;
283c19800e8SDoug Rabson }
284c19800e8SDoug Rabson
285c19800e8SDoug Rabson int
_hx509_collector_collect_private_keys(hx509_context context,struct hx509_collector * c,hx509_private_key ** keys)286c19800e8SDoug Rabson _hx509_collector_collect_private_keys(hx509_context context,
287c19800e8SDoug Rabson struct hx509_collector *c,
288c19800e8SDoug Rabson hx509_private_key **keys)
289c19800e8SDoug Rabson {
290*ae771770SStanislav Sedov size_t i, nkeys;
291c19800e8SDoug Rabson
292c19800e8SDoug Rabson *keys = NULL;
293c19800e8SDoug Rabson
294c19800e8SDoug Rabson for (i = 0, nkeys = 0; i < c->val.len; i++)
295c19800e8SDoug Rabson if (c->val.data[i]->private_key)
296c19800e8SDoug Rabson nkeys++;
297c19800e8SDoug Rabson
298c19800e8SDoug Rabson *keys = calloc(nkeys + 1, sizeof(**keys));
299c19800e8SDoug Rabson if (*keys == NULL) {
300c19800e8SDoug Rabson hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
301c19800e8SDoug Rabson return ENOMEM;
302c19800e8SDoug Rabson }
303c19800e8SDoug Rabson
304c19800e8SDoug Rabson for (i = 0, nkeys = 0; i < c->val.len; i++) {
305c19800e8SDoug Rabson if (c->val.data[i]->private_key) {
306c19800e8SDoug Rabson (*keys)[nkeys++] = c->val.data[i]->private_key;
307c19800e8SDoug Rabson c->val.data[i]->private_key = NULL;
308c19800e8SDoug Rabson }
309c19800e8SDoug Rabson }
310*ae771770SStanislav Sedov (*keys)[nkeys] = NULL;
311c19800e8SDoug Rabson
312c19800e8SDoug Rabson return 0;
313c19800e8SDoug Rabson }
314c19800e8SDoug Rabson
315c19800e8SDoug Rabson
316c19800e8SDoug Rabson void
_hx509_collector_free(struct hx509_collector * c)317c19800e8SDoug Rabson _hx509_collector_free(struct hx509_collector *c)
318c19800e8SDoug Rabson {
319*ae771770SStanislav Sedov size_t i;
320c19800e8SDoug Rabson
321c19800e8SDoug Rabson if (c->unenvelop_certs)
322c19800e8SDoug Rabson hx509_certs_free(&c->unenvelop_certs);
323c19800e8SDoug Rabson if (c->certs)
324c19800e8SDoug Rabson hx509_certs_free(&c->certs);
325c19800e8SDoug Rabson for (i = 0; i < c->val.len; i++)
326c19800e8SDoug Rabson free_private_key(c->val.data[i]);
327c19800e8SDoug Rabson if (c->val.data)
328c19800e8SDoug Rabson free(c->val.data);
329c19800e8SDoug Rabson free(c);
330c19800e8SDoug Rabson }
331