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