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