Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/hx509/collector.c
34879 views
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
int
54
_hx509_collector_alloc(hx509_context context, hx509_lock lock, struct hx509_collector **collector)
55
{
56
struct hx509_collector *c;
57
int ret;
58
59
*collector = NULL;
60
61
c = calloc(1, sizeof(*c));
62
if (c == NULL) {
63
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
64
return ENOMEM;
65
}
66
c->lock = lock;
67
68
ret = hx509_certs_init(context, "MEMORY:collector-unenvelop-cert",
69
0,NULL, &c->unenvelop_certs);
70
if (ret) {
71
free(c);
72
return ret;
73
}
74
c->val.data = NULL;
75
c->val.len = 0;
76
ret = hx509_certs_init(context, "MEMORY:collector-tmp-store",
77
0, NULL, &c->certs);
78
if (ret) {
79
hx509_certs_free(&c->unenvelop_certs);
80
free(c);
81
return ret;
82
}
83
84
*collector = c;
85
return 0;
86
}
87
88
hx509_lock
89
_hx509_collector_get_lock(struct hx509_collector *c)
90
{
91
return c->lock;
92
}
93
94
95
int
96
_hx509_collector_certs_add(hx509_context context,
97
struct hx509_collector *c,
98
hx509_cert cert)
99
{
100
return hx509_certs_add(context, c->certs, cert);
101
}
102
103
static void
104
free_private_key(struct private_key *key)
105
{
106
free_AlgorithmIdentifier(&key->alg);
107
if (key->private_key)
108
hx509_private_key_free(&key->private_key);
109
der_free_octet_string(&key->localKeyId);
110
free(key);
111
}
112
113
int
114
_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
key = calloc(1, sizeof(*key));
126
if (key == NULL)
127
return ENOMEM;
128
129
d = realloc(c->val.data, (c->val.len + 1) * sizeof(c->val.data[0]));
130
if (d == NULL) {
131
free(key);
132
hx509_set_error_string(context, 0, ENOMEM, "Out of memory");
133
return ENOMEM;
134
}
135
c->val.data = d;
136
137
ret = copy_AlgorithmIdentifier(alg, &key->alg);
138
if (ret) {
139
hx509_set_error_string(context, 0, ret, "Failed to copy "
140
"AlgorithmIdentifier");
141
goto out;
142
}
143
if (private_key) {
144
key->private_key = private_key;
145
} else {
146
ret = hx509_parse_private_key(context, alg,
147
key_data->data, key_data->length,
148
HX509_KEY_FORMAT_DER,
149
&key->private_key);
150
if (ret)
151
goto out;
152
}
153
if (localKeyId) {
154
ret = der_copy_octet_string(localKeyId, &key->localKeyId);
155
if (ret) {
156
hx509_set_error_string(context, 0, ret,
157
"Failed to copy localKeyId");
158
goto out;
159
}
160
} else
161
memset(&key->localKeyId, 0, sizeof(key->localKeyId));
162
163
c->val.data[c->val.len] = key;
164
c->val.len++;
165
166
out:
167
if (ret)
168
free_private_key(key);
169
170
return ret;
171
}
172
173
static int
174
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
if (value->localKeyId.length == 0) {
183
hx509_set_error_string(context, 0, HX509_LOCAL_ATTRIBUTE_MISSING,
184
"No local key attribute on private key");
185
return HX509_LOCAL_ATTRIBUTE_MISSING;
186
}
187
188
_hx509_query_clear(&q);
189
q.match |= HX509_QUERY_MATCH_LOCAL_KEY_ID;
190
191
q.local_key_id = &value->localKeyId;
192
193
ret = hx509_certs_find(context, certs, &q, &cert);
194
if (ret == 0) {
195
196
if (value->private_key)
197
_hx509_cert_assign_key(cert, value->private_key);
198
hx509_cert_free(cert);
199
}
200
return ret;
201
}
202
203
static int
204
match_keys(hx509_context context, struct private_key *value, hx509_certs certs)
205
{
206
hx509_cursor cursor;
207
hx509_cert c;
208
int ret, found = HX509_CERT_NOT_FOUND;
209
210
if (value->private_key == NULL) {
211
hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
212
"No private key to compare with");
213
return HX509_PRIVATE_KEY_MISSING;
214
}
215
216
ret = hx509_certs_start_seq(context, certs, &cursor);
217
if (ret)
218
return ret;
219
220
c = NULL;
221
while (1) {
222
ret = hx509_certs_next_cert(context, certs, cursor, &c);
223
if (ret)
224
break;
225
if (c == NULL)
226
break;
227
if (_hx509_cert_private_key(c)) {
228
hx509_cert_free(c);
229
continue;
230
}
231
232
ret = _hx509_match_keys(c, value->private_key);
233
if (ret) {
234
_hx509_cert_assign_key(c, value->private_key);
235
hx509_cert_free(c);
236
found = 0;
237
break;
238
}
239
hx509_cert_free(c);
240
}
241
242
hx509_certs_end_seq(context, certs, cursor);
243
244
if (found)
245
hx509_clear_error_string(context);
246
247
return found;
248
}
249
250
int
251
_hx509_collector_collect_certs(hx509_context context,
252
struct hx509_collector *c,
253
hx509_certs *ret_certs)
254
{
255
hx509_certs certs;
256
int ret;
257
size_t i;
258
259
*ret_certs = NULL;
260
261
ret = hx509_certs_init(context, "MEMORY:collector-store", 0, NULL, &certs);
262
if (ret)
263
return ret;
264
265
ret = hx509_certs_merge(context, certs, c->certs);
266
if (ret) {
267
hx509_certs_free(&certs);
268
return ret;
269
}
270
271
for (i = 0; i < c->val.len; i++) {
272
ret = match_localkeyid(context, c->val.data[i], certs);
273
if (ret == 0)
274
continue;
275
ret = match_keys(context, c->val.data[i], certs);
276
if (ret == 0)
277
continue;
278
}
279
280
*ret_certs = certs;
281
282
return 0;
283
}
284
285
int
286
_hx509_collector_collect_private_keys(hx509_context context,
287
struct hx509_collector *c,
288
hx509_private_key **keys)
289
{
290
size_t i, nkeys;
291
292
*keys = NULL;
293
294
for (i = 0, nkeys = 0; i < c->val.len; i++)
295
if (c->val.data[i]->private_key)
296
nkeys++;
297
298
*keys = calloc(nkeys + 1, sizeof(**keys));
299
if (*keys == NULL) {
300
hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory");
301
return ENOMEM;
302
}
303
304
for (i = 0, nkeys = 0; i < c->val.len; i++) {
305
if (c->val.data[i]->private_key) {
306
(*keys)[nkeys++] = c->val.data[i]->private_key;
307
c->val.data[i]->private_key = NULL;
308
}
309
}
310
(*keys)[nkeys] = NULL;
311
312
return 0;
313
}
314
315
316
void
317
_hx509_collector_free(struct hx509_collector *c)
318
{
319
size_t i;
320
321
if (c->unenvelop_certs)
322
hx509_certs_free(&c->unenvelop_certs);
323
if (c->certs)
324
hx509_certs_free(&c->certs);
325
for (i = 0; i < c->val.len; i++)
326
free_private_key(c->val.data[i]);
327
if (c->val.data)
328
free(c->val.data);
329
free(c);
330
}
331
332