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 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 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 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 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 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 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; 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 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 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