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