xref: /freebsd/crypto/heimdal/lib/hx509/collector.c (revision c19800e8cd5640693f36f2040db4ab5e8d738146)
1c19800e8SDoug Rabson /*
2c19800e8SDoug Rabson  * 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 RCSID("$Id: collector.c 20778 2007-06-01 22:04:13Z lha $");
36c19800e8SDoug Rabson 
37c19800e8SDoug Rabson struct private_key {
38c19800e8SDoug Rabson     AlgorithmIdentifier alg;
39c19800e8SDoug Rabson     hx509_private_key private_key;
40c19800e8SDoug Rabson     heim_octet_string localKeyId;
41c19800e8SDoug Rabson };
42c19800e8SDoug Rabson 
43c19800e8SDoug Rabson struct hx509_collector {
44c19800e8SDoug Rabson     hx509_lock lock;
45c19800e8SDoug Rabson     hx509_certs unenvelop_certs;
46c19800e8SDoug Rabson     hx509_certs certs;
47c19800e8SDoug Rabson     struct {
48c19800e8SDoug Rabson 	struct private_key **data;
49c19800e8SDoug Rabson 	size_t len;
50c19800e8SDoug Rabson     } val;
51c19800e8SDoug Rabson };
52c19800e8SDoug Rabson 
53c19800e8SDoug Rabson 
54c19800e8SDoug Rabson int
55c19800e8SDoug Rabson _hx509_collector_alloc(hx509_context context, hx509_lock lock, struct hx509_collector **collector)
56c19800e8SDoug Rabson {
57c19800e8SDoug Rabson     struct hx509_collector *c;
58c19800e8SDoug Rabson     int ret;
59c19800e8SDoug Rabson 
60c19800e8SDoug Rabson     *collector = NULL;
61c19800e8SDoug Rabson 
62c19800e8SDoug Rabson     c = calloc(1, sizeof(*c));
63c19800e8SDoug Rabson     if (c == NULL) {
64c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ENOMEM, "out of memory");
65c19800e8SDoug Rabson 	return ENOMEM;
66c19800e8SDoug Rabson     }
67c19800e8SDoug Rabson     c->lock = lock;
68c19800e8SDoug Rabson 
69c19800e8SDoug Rabson     ret = hx509_certs_init(context, "MEMORY:collector-unenvelop-cert",
70c19800e8SDoug Rabson 			   0,NULL, &c->unenvelop_certs);
71c19800e8SDoug Rabson     if (ret) {
72c19800e8SDoug Rabson 	free(c);
73c19800e8SDoug Rabson 	return ret;
74c19800e8SDoug Rabson     }
75c19800e8SDoug Rabson     c->val.data = NULL;
76c19800e8SDoug Rabson     c->val.len = 0;
77c19800e8SDoug Rabson     ret = hx509_certs_init(context, "MEMORY:collector-tmp-store",
78c19800e8SDoug Rabson 			   0, NULL, &c->certs);
79c19800e8SDoug Rabson     if (ret) {
80c19800e8SDoug Rabson 	hx509_certs_free(&c->unenvelop_certs);
81c19800e8SDoug Rabson 	free(c);
82c19800e8SDoug Rabson 	return ret;
83c19800e8SDoug Rabson     }
84c19800e8SDoug Rabson 
85c19800e8SDoug Rabson     *collector = c;
86c19800e8SDoug Rabson     return 0;
87c19800e8SDoug Rabson }
88c19800e8SDoug Rabson 
89c19800e8SDoug Rabson hx509_lock
90c19800e8SDoug Rabson _hx509_collector_get_lock(struct hx509_collector *c)
91c19800e8SDoug Rabson {
92c19800e8SDoug Rabson     return c->lock;
93c19800e8SDoug Rabson }
94c19800e8SDoug Rabson 
95c19800e8SDoug Rabson 
96c19800e8SDoug Rabson int
97c19800e8SDoug Rabson _hx509_collector_certs_add(hx509_context context,
98c19800e8SDoug Rabson 			   struct hx509_collector *c,
99c19800e8SDoug Rabson 			   hx509_cert cert)
100c19800e8SDoug Rabson {
101c19800e8SDoug Rabson     return hx509_certs_add(context, c->certs, cert);
102c19800e8SDoug Rabson }
103c19800e8SDoug Rabson 
104c19800e8SDoug Rabson static void
105c19800e8SDoug Rabson free_private_key(struct private_key *key)
106c19800e8SDoug Rabson {
107c19800e8SDoug Rabson     free_AlgorithmIdentifier(&key->alg);
108c19800e8SDoug Rabson     if (key->private_key)
109c19800e8SDoug Rabson 	_hx509_private_key_free(&key->private_key);
110c19800e8SDoug Rabson     der_free_octet_string(&key->localKeyId);
111c19800e8SDoug Rabson     free(key);
112c19800e8SDoug Rabson }
113c19800e8SDoug Rabson 
114c19800e8SDoug Rabson int
115c19800e8SDoug Rabson _hx509_collector_private_key_add(hx509_context context,
116c19800e8SDoug Rabson 				 struct hx509_collector *c,
117c19800e8SDoug Rabson 				 const AlgorithmIdentifier *alg,
118c19800e8SDoug Rabson 				 hx509_private_key private_key,
119c19800e8SDoug Rabson 				 const heim_octet_string *key_data,
120c19800e8SDoug Rabson 				 const heim_octet_string *localKeyId)
121c19800e8SDoug Rabson {
122c19800e8SDoug Rabson     struct private_key *key;
123c19800e8SDoug Rabson     void *d;
124c19800e8SDoug Rabson     int ret;
125c19800e8SDoug Rabson 
126c19800e8SDoug Rabson     key = calloc(1, sizeof(*key));
127c19800e8SDoug Rabson     if (key == NULL)
128c19800e8SDoug Rabson 	return ENOMEM;
129c19800e8SDoug Rabson 
130c19800e8SDoug Rabson     d = realloc(c->val.data, (c->val.len + 1) * sizeof(c->val.data[0]));
131c19800e8SDoug Rabson     if (d == NULL) {
132c19800e8SDoug Rabson 	free(key);
133c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
134c19800e8SDoug Rabson 	return ENOMEM;
135c19800e8SDoug Rabson     }
136c19800e8SDoug Rabson     c->val.data = d;
137c19800e8SDoug Rabson 
138c19800e8SDoug Rabson     ret = copy_AlgorithmIdentifier(alg, &key->alg);
139c19800e8SDoug Rabson     if (ret) {
140c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ret, "Failed to copy "
141c19800e8SDoug Rabson 			       "AlgorithmIdentifier");
142c19800e8SDoug Rabson 	goto out;
143c19800e8SDoug Rabson     }
144c19800e8SDoug Rabson     if (private_key) {
145c19800e8SDoug Rabson 	key->private_key = private_key;
146c19800e8SDoug Rabson     } else {
147c19800e8SDoug Rabson 	ret = _hx509_parse_private_key(context, &alg->algorithm,
148c19800e8SDoug Rabson 				       key_data->data, key_data->length,
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
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
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
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;
256c19800e8SDoug Rabson     int ret, i;
257c19800e8SDoug Rabson 
258c19800e8SDoug Rabson     *ret_certs = NULL;
259c19800e8SDoug Rabson 
260c19800e8SDoug Rabson     ret = hx509_certs_init(context, "MEMORY:collector-store", 0, NULL, &certs);
261c19800e8SDoug Rabson     if (ret)
262c19800e8SDoug Rabson 	return ret;
263c19800e8SDoug Rabson 
264c19800e8SDoug Rabson     ret = hx509_certs_merge(context, certs, c->certs);
265c19800e8SDoug Rabson     if (ret) {
266c19800e8SDoug Rabson 	hx509_certs_free(&certs);
267c19800e8SDoug Rabson 	return ret;
268c19800e8SDoug Rabson     }
269c19800e8SDoug Rabson 
270c19800e8SDoug Rabson     for (i = 0; i < c->val.len; i++) {
271c19800e8SDoug Rabson 	ret = match_localkeyid(context, c->val.data[i], certs);
272c19800e8SDoug Rabson 	if (ret == 0)
273c19800e8SDoug Rabson 	    continue;
274c19800e8SDoug Rabson 	ret = match_keys(context, c->val.data[i], certs);
275c19800e8SDoug Rabson 	if (ret == 0)
276c19800e8SDoug Rabson 	    continue;
277c19800e8SDoug Rabson     }
278c19800e8SDoug Rabson 
279c19800e8SDoug Rabson     *ret_certs = certs;
280c19800e8SDoug Rabson 
281c19800e8SDoug Rabson     return 0;
282c19800e8SDoug Rabson }
283c19800e8SDoug Rabson 
284c19800e8SDoug Rabson int
285c19800e8SDoug Rabson _hx509_collector_collect_private_keys(hx509_context context,
286c19800e8SDoug Rabson 				      struct hx509_collector *c,
287c19800e8SDoug Rabson 				      hx509_private_key **keys)
288c19800e8SDoug Rabson {
289c19800e8SDoug Rabson     int i, nkeys;
290c19800e8SDoug Rabson 
291c19800e8SDoug Rabson     *keys = NULL;
292c19800e8SDoug Rabson 
293c19800e8SDoug Rabson     for (i = 0, nkeys = 0; i < c->val.len; i++)
294c19800e8SDoug Rabson 	if (c->val.data[i]->private_key)
295c19800e8SDoug Rabson 	    nkeys++;
296c19800e8SDoug Rabson 
297c19800e8SDoug Rabson     *keys = calloc(nkeys + 1, sizeof(**keys));
298c19800e8SDoug Rabson     if (*keys == NULL) {
299c19800e8SDoug Rabson 	hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
300c19800e8SDoug Rabson 	return ENOMEM;
301c19800e8SDoug Rabson     }
302c19800e8SDoug Rabson 
303c19800e8SDoug Rabson     for (i = 0, nkeys = 0; i < c->val.len; i++) {
304c19800e8SDoug Rabson  	if (c->val.data[i]->private_key) {
305c19800e8SDoug Rabson 	    (*keys)[nkeys++] = c->val.data[i]->private_key;
306c19800e8SDoug Rabson 	    c->val.data[i]->private_key = NULL;
307c19800e8SDoug Rabson 	}
308c19800e8SDoug Rabson     }
309c19800e8SDoug Rabson     (*keys)[nkeys++] = NULL;
310c19800e8SDoug Rabson 
311c19800e8SDoug Rabson     return 0;
312c19800e8SDoug Rabson }
313c19800e8SDoug Rabson 
314c19800e8SDoug Rabson 
315c19800e8SDoug Rabson void
316c19800e8SDoug Rabson _hx509_collector_free(struct hx509_collector *c)
317c19800e8SDoug Rabson {
318c19800e8SDoug Rabson     int i;
319c19800e8SDoug Rabson 
320c19800e8SDoug Rabson     if (c->unenvelop_certs)
321c19800e8SDoug Rabson 	hx509_certs_free(&c->unenvelop_certs);
322c19800e8SDoug Rabson     if (c->certs)
323c19800e8SDoug Rabson 	hx509_certs_free(&c->certs);
324c19800e8SDoug Rabson     for (i = 0; i < c->val.len; i++)
325c19800e8SDoug Rabson 	free_private_key(c->val.data[i]);
326c19800e8SDoug Rabson     if (c->val.data)
327c19800e8SDoug Rabson 	free(c->val.data);
328c19800e8SDoug Rabson     free(c);
329c19800e8SDoug Rabson }
330