1178825Sdfr/* 2233294Sstas * Copyright (c) 2004 - 2007 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 9178825Sdfr * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 20178825Sdfr * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825Sdfr 36178825Sdfrstruct private_key { 37178825Sdfr AlgorithmIdentifier alg; 38178825Sdfr hx509_private_key private_key; 39178825Sdfr heim_octet_string localKeyId; 40178825Sdfr}; 41178825Sdfr 42178825Sdfrstruct hx509_collector { 43178825Sdfr hx509_lock lock; 44178825Sdfr hx509_certs unenvelop_certs; 45178825Sdfr hx509_certs certs; 46178825Sdfr struct { 47178825Sdfr struct private_key **data; 48178825Sdfr size_t len; 49178825Sdfr } val; 50178825Sdfr}; 51178825Sdfr 52178825Sdfr 53178825Sdfrint 54178825Sdfr_hx509_collector_alloc(hx509_context context, hx509_lock lock, struct hx509_collector **collector) 55178825Sdfr{ 56178825Sdfr struct hx509_collector *c; 57178825Sdfr int ret; 58178825Sdfr 59178825Sdfr *collector = NULL; 60178825Sdfr 61178825Sdfr c = calloc(1, sizeof(*c)); 62178825Sdfr if (c == NULL) { 63178825Sdfr hx509_set_error_string(context, 0, ENOMEM, "out of memory"); 64178825Sdfr return ENOMEM; 65178825Sdfr } 66178825Sdfr c->lock = lock; 67178825Sdfr 68178825Sdfr ret = hx509_certs_init(context, "MEMORY:collector-unenvelop-cert", 69178825Sdfr 0,NULL, &c->unenvelop_certs); 70178825Sdfr if (ret) { 71178825Sdfr free(c); 72178825Sdfr return ret; 73178825Sdfr } 74178825Sdfr c->val.data = NULL; 75178825Sdfr c->val.len = 0; 76178825Sdfr ret = hx509_certs_init(context, "MEMORY:collector-tmp-store", 77178825Sdfr 0, NULL, &c->certs); 78178825Sdfr if (ret) { 79178825Sdfr hx509_certs_free(&c->unenvelop_certs); 80178825Sdfr free(c); 81178825Sdfr return ret; 82178825Sdfr } 83178825Sdfr 84178825Sdfr *collector = c; 85178825Sdfr return 0; 86178825Sdfr} 87178825Sdfr 88178825Sdfrhx509_lock 89178825Sdfr_hx509_collector_get_lock(struct hx509_collector *c) 90178825Sdfr{ 91178825Sdfr return c->lock; 92178825Sdfr} 93178825Sdfr 94178825Sdfr 95178825Sdfrint 96178825Sdfr_hx509_collector_certs_add(hx509_context context, 97178825Sdfr struct hx509_collector *c, 98178825Sdfr hx509_cert cert) 99178825Sdfr{ 100178825Sdfr return hx509_certs_add(context, c->certs, cert); 101178825Sdfr} 102178825Sdfr 103178825Sdfrstatic void 104178825Sdfrfree_private_key(struct private_key *key) 105178825Sdfr{ 106178825Sdfr free_AlgorithmIdentifier(&key->alg); 107178825Sdfr if (key->private_key) 108233294Sstas hx509_private_key_free(&key->private_key); 109178825Sdfr der_free_octet_string(&key->localKeyId); 110178825Sdfr free(key); 111178825Sdfr} 112178825Sdfr 113178825Sdfrint 114178825Sdfr_hx509_collector_private_key_add(hx509_context context, 115233294Sstas struct hx509_collector *c, 116178825Sdfr const AlgorithmIdentifier *alg, 117178825Sdfr hx509_private_key private_key, 118178825Sdfr const heim_octet_string *key_data, 119178825Sdfr const heim_octet_string *localKeyId) 120178825Sdfr{ 121178825Sdfr struct private_key *key; 122178825Sdfr void *d; 123178825Sdfr int ret; 124178825Sdfr 125178825Sdfr key = calloc(1, sizeof(*key)); 126178825Sdfr if (key == NULL) 127178825Sdfr return ENOMEM; 128178825Sdfr 129178825Sdfr d = realloc(c->val.data, (c->val.len + 1) * sizeof(c->val.data[0])); 130178825Sdfr if (d == NULL) { 131178825Sdfr free(key); 132178825Sdfr hx509_set_error_string(context, 0, ENOMEM, "Out of memory"); 133178825Sdfr return ENOMEM; 134178825Sdfr } 135178825Sdfr c->val.data = d; 136233294Sstas 137178825Sdfr ret = copy_AlgorithmIdentifier(alg, &key->alg); 138178825Sdfr if (ret) { 139178825Sdfr hx509_set_error_string(context, 0, ret, "Failed to copy " 140178825Sdfr "AlgorithmIdentifier"); 141178825Sdfr goto out; 142178825Sdfr } 143178825Sdfr if (private_key) { 144178825Sdfr key->private_key = private_key; 145178825Sdfr } else { 146233294Sstas ret = hx509_parse_private_key(context, alg, 147178825Sdfr key_data->data, key_data->length, 148233294Sstas HX509_KEY_FORMAT_DER, 149178825Sdfr &key->private_key); 150178825Sdfr if (ret) 151178825Sdfr goto out; 152178825Sdfr } 153178825Sdfr if (localKeyId) { 154178825Sdfr ret = der_copy_octet_string(localKeyId, &key->localKeyId); 155178825Sdfr if (ret) { 156233294Sstas hx509_set_error_string(context, 0, ret, 157178825Sdfr "Failed to copy localKeyId"); 158178825Sdfr goto out; 159178825Sdfr } 160178825Sdfr } else 161178825Sdfr memset(&key->localKeyId, 0, sizeof(key->localKeyId)); 162178825Sdfr 163178825Sdfr c->val.data[c->val.len] = key; 164178825Sdfr c->val.len++; 165178825Sdfr 166178825Sdfrout: 167178825Sdfr if (ret) 168178825Sdfr free_private_key(key); 169178825Sdfr 170178825Sdfr return ret; 171178825Sdfr} 172178825Sdfr 173178825Sdfrstatic int 174178825Sdfrmatch_localkeyid(hx509_context context, 175178825Sdfr struct private_key *value, 176178825Sdfr hx509_certs certs) 177178825Sdfr{ 178178825Sdfr hx509_cert cert; 179178825Sdfr hx509_query q; 180178825Sdfr int ret; 181178825Sdfr 182178825Sdfr if (value->localKeyId.length == 0) { 183178825Sdfr hx509_set_error_string(context, 0, HX509_LOCAL_ATTRIBUTE_MISSING, 184178825Sdfr "No local key attribute on private key"); 185178825Sdfr return HX509_LOCAL_ATTRIBUTE_MISSING; 186178825Sdfr } 187178825Sdfr 188178825Sdfr _hx509_query_clear(&q); 189178825Sdfr q.match |= HX509_QUERY_MATCH_LOCAL_KEY_ID; 190233294Sstas 191178825Sdfr q.local_key_id = &value->localKeyId; 192233294Sstas 193178825Sdfr ret = hx509_certs_find(context, certs, &q, &cert); 194178825Sdfr if (ret == 0) { 195233294Sstas 196178825Sdfr if (value->private_key) 197178825Sdfr _hx509_cert_assign_key(cert, value->private_key); 198178825Sdfr hx509_cert_free(cert); 199178825Sdfr } 200178825Sdfr return ret; 201178825Sdfr} 202178825Sdfr 203178825Sdfrstatic int 204178825Sdfrmatch_keys(hx509_context context, struct private_key *value, hx509_certs certs) 205178825Sdfr{ 206178825Sdfr hx509_cursor cursor; 207178825Sdfr hx509_cert c; 208178825Sdfr int ret, found = HX509_CERT_NOT_FOUND; 209178825Sdfr 210178825Sdfr if (value->private_key == NULL) { 211233294Sstas hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING, 212178825Sdfr "No private key to compare with"); 213178825Sdfr return HX509_PRIVATE_KEY_MISSING; 214178825Sdfr } 215178825Sdfr 216178825Sdfr ret = hx509_certs_start_seq(context, certs, &cursor); 217178825Sdfr if (ret) 218178825Sdfr return ret; 219178825Sdfr 220178825Sdfr c = NULL; 221178825Sdfr while (1) { 222178825Sdfr ret = hx509_certs_next_cert(context, certs, cursor, &c); 223178825Sdfr if (ret) 224178825Sdfr break; 225178825Sdfr if (c == NULL) 226178825Sdfr break; 227178825Sdfr if (_hx509_cert_private_key(c)) { 228178825Sdfr hx509_cert_free(c); 229178825Sdfr continue; 230178825Sdfr } 231178825Sdfr 232178825Sdfr ret = _hx509_match_keys(c, value->private_key); 233178825Sdfr if (ret) { 234178825Sdfr _hx509_cert_assign_key(c, value->private_key); 235178825Sdfr hx509_cert_free(c); 236178825Sdfr found = 0; 237178825Sdfr break; 238178825Sdfr } 239178825Sdfr hx509_cert_free(c); 240178825Sdfr } 241178825Sdfr 242178825Sdfr hx509_certs_end_seq(context, certs, cursor); 243178825Sdfr 244178825Sdfr if (found) 245178825Sdfr hx509_clear_error_string(context); 246178825Sdfr 247178825Sdfr return found; 248178825Sdfr} 249178825Sdfr 250178825Sdfrint 251233294Sstas_hx509_collector_collect_certs(hx509_context context, 252178825Sdfr struct hx509_collector *c, 253178825Sdfr hx509_certs *ret_certs) 254178825Sdfr{ 255178825Sdfr hx509_certs certs; 256233294Sstas int ret; 257233294Sstas size_t i; 258178825Sdfr 259178825Sdfr *ret_certs = NULL; 260178825Sdfr 261178825Sdfr ret = hx509_certs_init(context, "MEMORY:collector-store", 0, NULL, &certs); 262178825Sdfr if (ret) 263178825Sdfr return ret; 264178825Sdfr 265178825Sdfr ret = hx509_certs_merge(context, certs, c->certs); 266178825Sdfr if (ret) { 267178825Sdfr hx509_certs_free(&certs); 268178825Sdfr return ret; 269178825Sdfr } 270178825Sdfr 271178825Sdfr for (i = 0; i < c->val.len; i++) { 272178825Sdfr ret = match_localkeyid(context, c->val.data[i], certs); 273178825Sdfr if (ret == 0) 274178825Sdfr continue; 275178825Sdfr ret = match_keys(context, c->val.data[i], certs); 276178825Sdfr if (ret == 0) 277178825Sdfr continue; 278178825Sdfr } 279178825Sdfr 280178825Sdfr *ret_certs = certs; 281178825Sdfr 282178825Sdfr return 0; 283178825Sdfr} 284178825Sdfr 285178825Sdfrint 286233294Sstas_hx509_collector_collect_private_keys(hx509_context context, 287178825Sdfr struct hx509_collector *c, 288178825Sdfr hx509_private_key **keys) 289178825Sdfr{ 290233294Sstas size_t i, nkeys; 291178825Sdfr 292178825Sdfr *keys = NULL; 293178825Sdfr 294178825Sdfr for (i = 0, nkeys = 0; i < c->val.len; i++) 295178825Sdfr if (c->val.data[i]->private_key) 296178825Sdfr nkeys++; 297178825Sdfr 298178825Sdfr *keys = calloc(nkeys + 1, sizeof(**keys)); 299178825Sdfr if (*keys == NULL) { 300178825Sdfr hx509_set_error_string(context, 0, ENOMEM, "malloc - out of memory"); 301178825Sdfr return ENOMEM; 302178825Sdfr } 303178825Sdfr 304178825Sdfr for (i = 0, nkeys = 0; i < c->val.len; i++) { 305178825Sdfr if (c->val.data[i]->private_key) { 306178825Sdfr (*keys)[nkeys++] = c->val.data[i]->private_key; 307178825Sdfr c->val.data[i]->private_key = NULL; 308178825Sdfr } 309178825Sdfr } 310233294Sstas (*keys)[nkeys] = NULL; 311178825Sdfr 312178825Sdfr return 0; 313178825Sdfr} 314178825Sdfr 315178825Sdfr 316178825Sdfrvoid 317178825Sdfr_hx509_collector_free(struct hx509_collector *c) 318178825Sdfr{ 319233294Sstas size_t i; 320178825Sdfr 321178825Sdfr if (c->unenvelop_certs) 322178825Sdfr hx509_certs_free(&c->unenvelop_certs); 323178825Sdfr if (c->certs) 324178825Sdfr hx509_certs_free(&c->certs); 325178825Sdfr for (i = 0; i < c->val.len; i++) 326178825Sdfr free_private_key(c->val.data[i]); 327178825Sdfr if (c->val.data) 328178825Sdfr free(c->val.data); 329178825Sdfr free(c); 330178825Sdfr} 331