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