1178825Sdfr/* 2233294Sstas * Copyright (c) 2004 - 2007 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 5178825Sdfr * 6233294Sstas * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 7178825Sdfr * 8233294Sstas * Redistribution and use in source and binary forms, with or without 9233294Sstas * modification, are permitted provided that the following conditions 10233294Sstas * are met: 11178825Sdfr * 12233294Sstas * 1. Redistributions of source code must retain the above copyright 13233294Sstas * notice, this list of conditions and the following disclaimer. 14178825Sdfr * 15233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 16233294Sstas * notice, this list of conditions and the following disclaimer in the 17233294Sstas * documentation and/or other materials provided with the distribution. 18178825Sdfr * 19233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 20233294Sstas * may be used to endorse or promote products derived from this software 21233294Sstas * without specific prior written permission. 22233294Sstas * 23233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 24233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 27233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33233294Sstas * SUCH DAMAGE. 34178825Sdfr */ 35178825Sdfr 36178825Sdfr#include "hx_locl.h" 37178825Sdfr 38178825Sdfr/** 39178825Sdfr * @page page_keyset Certificate store operations 40178825Sdfr * 41178825Sdfr * Type of certificates store: 42178825Sdfr * - MEMORY 43178825Sdfr * In memory based format. Doesnt support storing. 44233294Sstas * - FILE 45178825Sdfr * FILE supports raw DER certicates and PEM certicates. When PEM is 46178825Sdfr * used the file can contain may certificates and match private 47178825Sdfr * keys. Support storing the certificates. DER format only supports 48178825Sdfr * on certificate and no private key. 49178825Sdfr * - PEM-FILE 50178825Sdfr * Same as FILE, defaulting to PEM encoded certificates. 51178825Sdfr * - PEM-FILE 52178825Sdfr * Same as FILE, defaulting to DER encoded certificates. 53178825Sdfr * - PKCS11 54178825Sdfr * - PKCS12 55178825Sdfr * - DIR 56178825Sdfr * - KEYCHAIN 57178825Sdfr * Apple Mac OS X KeyChain backed keychain object. 58178825Sdfr * 59178825Sdfr * See the library functions here: @ref hx509_keyset 60178825Sdfr */ 61178825Sdfr 62178825Sdfrstruct hx509_certs_data { 63233294Sstas unsigned int ref; 64178825Sdfr struct hx509_keyset_ops *ops; 65178825Sdfr void *ops_data; 66178825Sdfr}; 67178825Sdfr 68178825Sdfrstatic struct hx509_keyset_ops * 69178825Sdfr_hx509_ks_type(hx509_context context, const char *type) 70178825Sdfr{ 71178825Sdfr int i; 72178825Sdfr 73178825Sdfr for (i = 0; i < context->ks_num_ops; i++) 74178825Sdfr if (strcasecmp(type, context->ks_ops[i]->name) == 0) 75178825Sdfr return context->ks_ops[i]; 76178825Sdfr 77178825Sdfr return NULL; 78178825Sdfr} 79178825Sdfr 80178825Sdfrvoid 81178825Sdfr_hx509_ks_register(hx509_context context, struct hx509_keyset_ops *ops) 82178825Sdfr{ 83178825Sdfr struct hx509_keyset_ops **val; 84178825Sdfr 85178825Sdfr if (_hx509_ks_type(context, ops->name)) 86178825Sdfr return; 87178825Sdfr 88233294Sstas val = realloc(context->ks_ops, 89178825Sdfr (context->ks_num_ops + 1) * sizeof(context->ks_ops[0])); 90178825Sdfr if (val == NULL) 91178825Sdfr return; 92178825Sdfr val[context->ks_num_ops] = ops; 93178825Sdfr context->ks_ops = val; 94178825Sdfr context->ks_num_ops++; 95178825Sdfr} 96178825Sdfr 97178825Sdfr/** 98178825Sdfr * Open or creates a new hx509 certificate store. 99178825Sdfr * 100178825Sdfr * @param context A hx509 context 101178825Sdfr * @param name name of the store, format is TYPE:type-specific-string, 102178825Sdfr * if NULL is used the MEMORY store is used. 103178825Sdfr * @param flags list of flags: 104178825Sdfr * - HX509_CERTS_CREATE create a new keystore of the specific TYPE. 105178825Sdfr * - HX509_CERTS_UNPROTECT_ALL fails if any private key failed to be extracted. 106178825Sdfr * @param lock a lock that unlocks the certificates store, use NULL to 107178825Sdfr * select no password/certifictes/prompt lock (see @ref page_lock). 108178825Sdfr * @param certs return pointer, free with hx509_certs_free(). 109178825Sdfr * 110178825Sdfr * @ingroup hx509_keyset 111178825Sdfr */ 112178825Sdfr 113178825Sdfrint 114178825Sdfrhx509_certs_init(hx509_context context, 115178825Sdfr const char *name, int flags, 116178825Sdfr hx509_lock lock, hx509_certs *certs) 117178825Sdfr{ 118178825Sdfr struct hx509_keyset_ops *ops; 119178825Sdfr const char *residue; 120178825Sdfr hx509_certs c; 121178825Sdfr char *type; 122178825Sdfr int ret; 123178825Sdfr 124178825Sdfr *certs = NULL; 125178825Sdfr 126178825Sdfr residue = strchr(name, ':'); 127178825Sdfr if (residue) { 128178825Sdfr type = malloc(residue - name + 1); 129178825Sdfr if (type) 130178825Sdfr strlcpy(type, name, residue - name + 1); 131178825Sdfr residue++; 132178825Sdfr if (residue[0] == '\0') 133178825Sdfr residue = NULL; 134178825Sdfr } else { 135178825Sdfr type = strdup("MEMORY"); 136178825Sdfr residue = name; 137178825Sdfr } 138178825Sdfr if (type == NULL) { 139178825Sdfr hx509_clear_error_string(context); 140178825Sdfr return ENOMEM; 141178825Sdfr } 142233294Sstas 143178825Sdfr ops = _hx509_ks_type(context, type); 144178825Sdfr if (ops == NULL) { 145233294Sstas hx509_set_error_string(context, 0, ENOENT, 146178825Sdfr "Keyset type %s is not supported", type); 147178825Sdfr free(type); 148178825Sdfr return ENOENT; 149178825Sdfr } 150178825Sdfr free(type); 151178825Sdfr c = calloc(1, sizeof(*c)); 152178825Sdfr if (c == NULL) { 153178825Sdfr hx509_clear_error_string(context); 154178825Sdfr return ENOMEM; 155178825Sdfr } 156178825Sdfr c->ops = ops; 157178825Sdfr c->ref = 1; 158178825Sdfr 159178825Sdfr ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock); 160178825Sdfr if (ret) { 161178825Sdfr free(c); 162178825Sdfr return ret; 163178825Sdfr } 164178825Sdfr 165178825Sdfr *certs = c; 166178825Sdfr return 0; 167178825Sdfr} 168178825Sdfr 169178825Sdfr/** 170178825Sdfr * Write the certificate store to stable storage. 171178825Sdfr * 172178825Sdfr * @param context A hx509 context. 173178825Sdfr * @param certs a certificate store to store. 174178825Sdfr * @param flags currently unused, use 0. 175178825Sdfr * @param lock a lock that unlocks the certificates store, use NULL to 176178825Sdfr * select no password/certifictes/prompt lock (see @ref page_lock). 177178825Sdfr * 178178825Sdfr * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION if 179178825Sdfr * the certificate store doesn't support the store operation. 180178825Sdfr * 181178825Sdfr * @ingroup hx509_keyset 182178825Sdfr */ 183178825Sdfr 184178825Sdfrint 185178825Sdfrhx509_certs_store(hx509_context context, 186178825Sdfr hx509_certs certs, 187178825Sdfr int flags, 188178825Sdfr hx509_lock lock) 189178825Sdfr{ 190178825Sdfr if (certs->ops->store == NULL) { 191178825Sdfr hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, 192178825Sdfr "keystore if type %s doesn't support " 193178825Sdfr "store operation", 194178825Sdfr certs->ops->name); 195178825Sdfr return HX509_UNSUPPORTED_OPERATION; 196178825Sdfr } 197178825Sdfr 198178825Sdfr return (*certs->ops->store)(context, certs, certs->ops_data, flags, lock); 199178825Sdfr} 200178825Sdfr 201178825Sdfr 202178825Sdfrhx509_certs 203233294Sstashx509_certs_ref(hx509_certs certs) 204178825Sdfr{ 205178825Sdfr if (certs == NULL) 206178825Sdfr return NULL; 207233294Sstas if (certs->ref == 0) 208233294Sstas _hx509_abort("certs refcount == 0 on ref"); 209233294Sstas if (certs->ref == UINT_MAX) 210233294Sstas _hx509_abort("certs refcount == UINT_MAX on ref"); 211178825Sdfr certs->ref++; 212178825Sdfr return certs; 213178825Sdfr} 214178825Sdfr 215178825Sdfr/** 216178825Sdfr * Free a certificate store. 217178825Sdfr * 218178825Sdfr * @param certs certificate store to free. 219178825Sdfr * 220178825Sdfr * @ingroup hx509_keyset 221178825Sdfr */ 222178825Sdfr 223178825Sdfrvoid 224178825Sdfrhx509_certs_free(hx509_certs *certs) 225178825Sdfr{ 226178825Sdfr if (*certs) { 227233294Sstas if ((*certs)->ref == 0) 228233294Sstas _hx509_abort("cert refcount == 0 on free"); 229178825Sdfr if (--(*certs)->ref > 0) 230178825Sdfr return; 231178825Sdfr 232178825Sdfr (*(*certs)->ops->free)(*certs, (*certs)->ops_data); 233178825Sdfr free(*certs); 234178825Sdfr *certs = NULL; 235178825Sdfr } 236178825Sdfr} 237178825Sdfr 238178825Sdfr/** 239178825Sdfr * Start the integration 240178825Sdfr * 241178825Sdfr * @param context a hx509 context. 242178825Sdfr * @param certs certificate store to iterate over 243178825Sdfr * @param cursor cursor that will keep track of progress, free with 244178825Sdfr * hx509_certs_end_seq(). 245178825Sdfr * 246178825Sdfr * @return Returns an hx509 error code. HX509_UNSUPPORTED_OPERATION is 247178825Sdfr * returned if the certificate store doesn't support the iteration 248178825Sdfr * operation. 249178825Sdfr * 250178825Sdfr * @ingroup hx509_keyset 251178825Sdfr */ 252178825Sdfr 253178825Sdfrint 254178825Sdfrhx509_certs_start_seq(hx509_context context, 255178825Sdfr hx509_certs certs, 256178825Sdfr hx509_cursor *cursor) 257178825Sdfr{ 258178825Sdfr int ret; 259178825Sdfr 260178825Sdfr if (certs->ops->iter_start == NULL) { 261233294Sstas hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION, 262233294Sstas "Keyset type %s doesn't support iteration", 263178825Sdfr certs->ops->name); 264178825Sdfr return HX509_UNSUPPORTED_OPERATION; 265178825Sdfr } 266178825Sdfr 267178825Sdfr ret = (*certs->ops->iter_start)(context, certs, certs->ops_data, cursor); 268178825Sdfr if (ret) 269178825Sdfr return ret; 270178825Sdfr 271178825Sdfr return 0; 272178825Sdfr} 273178825Sdfr 274178825Sdfr/** 275178825Sdfr * Get next ceritificate from the certificate keystore pointed out by 276178825Sdfr * cursor. 277178825Sdfr * 278178825Sdfr * @param context a hx509 context. 279178825Sdfr * @param certs certificate store to iterate over. 280178825Sdfr * @param cursor cursor that keeps track of progress. 281178825Sdfr * @param cert return certificate next in store, NULL if the store 282178825Sdfr * contains no more certificates. Free with hx509_cert_free(). 283178825Sdfr * 284178825Sdfr * @return Returns an hx509 error code. 285178825Sdfr * 286178825Sdfr * @ingroup hx509_keyset 287178825Sdfr */ 288178825Sdfr 289178825Sdfrint 290178825Sdfrhx509_certs_next_cert(hx509_context context, 291178825Sdfr hx509_certs certs, 292178825Sdfr hx509_cursor cursor, 293178825Sdfr hx509_cert *cert) 294178825Sdfr{ 295178825Sdfr *cert = NULL; 296178825Sdfr return (*certs->ops->iter)(context, certs, certs->ops_data, cursor, cert); 297178825Sdfr} 298178825Sdfr 299178825Sdfr/** 300178825Sdfr * End the iteration over certificates. 301178825Sdfr * 302178825Sdfr * @param context a hx509 context. 303178825Sdfr * @param certs certificate store to iterate over. 304178825Sdfr * @param cursor cursor that will keep track of progress, freed. 305178825Sdfr * 306178825Sdfr * @return Returns an hx509 error code. 307178825Sdfr * 308178825Sdfr * @ingroup hx509_keyset 309178825Sdfr */ 310178825Sdfr 311178825Sdfrint 312178825Sdfrhx509_certs_end_seq(hx509_context context, 313178825Sdfr hx509_certs certs, 314178825Sdfr hx509_cursor cursor) 315178825Sdfr{ 316178825Sdfr (*certs->ops->iter_end)(context, certs, certs->ops_data, cursor); 317178825Sdfr return 0; 318178825Sdfr} 319178825Sdfr 320178825Sdfr/** 321178825Sdfr * Iterate over all certificates in a keystore and call an function 322178825Sdfr * for each fo them. 323178825Sdfr * 324178825Sdfr * @param context a hx509 context. 325178825Sdfr * @param certs certificate store to iterate over. 326178825Sdfr * @param func function to call for each certificate. The function 327178825Sdfr * should return non-zero to abort the iteration, that value is passed 328233294Sstas * back to the caller of hx509_certs_iter_f(). 329178825Sdfr * @param ctx context variable that will passed to the function. 330178825Sdfr * 331178825Sdfr * @return Returns an hx509 error code. 332178825Sdfr * 333178825Sdfr * @ingroup hx509_keyset 334178825Sdfr */ 335178825Sdfr 336178825Sdfrint 337233294Sstashx509_certs_iter_f(hx509_context context, 338233294Sstas hx509_certs certs, 339233294Sstas int (*func)(hx509_context, void *, hx509_cert), 340233294Sstas void *ctx) 341178825Sdfr{ 342178825Sdfr hx509_cursor cursor; 343178825Sdfr hx509_cert c; 344178825Sdfr int ret; 345178825Sdfr 346178825Sdfr ret = hx509_certs_start_seq(context, certs, &cursor); 347178825Sdfr if (ret) 348178825Sdfr return ret; 349233294Sstas 350178825Sdfr while (1) { 351178825Sdfr ret = hx509_certs_next_cert(context, certs, cursor, &c); 352178825Sdfr if (ret) 353178825Sdfr break; 354178825Sdfr if (c == NULL) { 355178825Sdfr ret = 0; 356178825Sdfr break; 357178825Sdfr } 358178825Sdfr ret = (*func)(context, ctx, c); 359178825Sdfr hx509_cert_free(c); 360178825Sdfr if (ret) 361178825Sdfr break; 362178825Sdfr } 363178825Sdfr 364178825Sdfr hx509_certs_end_seq(context, certs, cursor); 365178825Sdfr 366178825Sdfr return ret; 367178825Sdfr} 368178825Sdfr 369233294Sstas/** 370233294Sstas * Iterate over all certificates in a keystore and call an function 371233294Sstas * for each fo them. 372233294Sstas * 373233294Sstas * @param context a hx509 context. 374233294Sstas * @param certs certificate store to iterate over. 375233294Sstas * @param func function to call for each certificate. The function 376233294Sstas * should return non-zero to abort the iteration, that value is passed 377233294Sstas * back to the caller of hx509_certs_iter(). 378233294Sstas * 379233294Sstas * @return Returns an hx509 error code. 380233294Sstas * 381233294Sstas * @ingroup hx509_keyset 382233294Sstas */ 383178825Sdfr 384233294Sstas#ifdef __BLOCKS__ 385233294Sstas 386233294Sstasstatic int 387233294Sstascerts_iter(hx509_context context, void *ctx, hx509_cert cert) 388233294Sstas{ 389233294Sstas int (^func)(hx509_cert) = ctx; 390233294Sstas return func(cert); 391233294Sstas} 392233294Sstas 393178825Sdfr/** 394233294Sstas * Iterate over all certificates in a keystore and call an block 395233294Sstas * for each fo them. 396178825Sdfr * 397178825Sdfr * @param context a hx509 context. 398233294Sstas * @param certs certificate store to iterate over. 399233294Sstas * @param func block to call for each certificate. The function 400233294Sstas * should return non-zero to abort the iteration, that value is passed 401233294Sstas * back to the caller of hx509_certs_iter(). 402233294Sstas * 403233294Sstas * @return Returns an hx509 error code. 404233294Sstas * 405233294Sstas * @ingroup hx509_keyset 406233294Sstas */ 407233294Sstas 408233294Sstasint 409233294Sstashx509_certs_iter(hx509_context context, 410233294Sstas hx509_certs certs, 411233294Sstas int (^func)(hx509_cert)) 412233294Sstas{ 413233294Sstas return hx509_certs_iter_f(context, certs, certs_iter, func); 414233294Sstas} 415233294Sstas#endif 416233294Sstas 417233294Sstas 418233294Sstas/** 419233294Sstas * Function to use to hx509_certs_iter_f() as a function argument, the 420233294Sstas * ctx variable to hx509_certs_iter_f() should be a FILE file descriptor. 421233294Sstas * 422233294Sstas * @param context a hx509 context. 423233294Sstas * @param ctx used by hx509_certs_iter_f(). 424178825Sdfr * @param c a certificate 425178825Sdfr * 426178825Sdfr * @return Returns an hx509 error code. 427178825Sdfr * 428178825Sdfr * @ingroup hx509_keyset 429178825Sdfr */ 430178825Sdfr 431178825Sdfrint 432178825Sdfrhx509_ci_print_names(hx509_context context, void *ctx, hx509_cert c) 433178825Sdfr{ 434178825Sdfr Certificate *cert; 435178825Sdfr hx509_name n; 436178825Sdfr char *s, *i; 437178825Sdfr 438178825Sdfr cert = _hx509_get_cert(c); 439178825Sdfr 440178825Sdfr _hx509_name_from_Name(&cert->tbsCertificate.subject, &n); 441178825Sdfr hx509_name_to_string(n, &s); 442178825Sdfr hx509_name_free(&n); 443178825Sdfr _hx509_name_from_Name(&cert->tbsCertificate.issuer, &n); 444178825Sdfr hx509_name_to_string(n, &i); 445178825Sdfr hx509_name_free(&n); 446178825Sdfr fprintf(ctx, "subject: %s\nissuer: %s\n", s, i); 447178825Sdfr free(s); 448178825Sdfr free(i); 449178825Sdfr return 0; 450178825Sdfr} 451178825Sdfr 452178825Sdfr/** 453178825Sdfr * Add a certificate to the certificiate store. 454178825Sdfr * 455178825Sdfr * The receiving keyset certs will either increase reference counter 456178825Sdfr * of the cert or make a deep copy, either way, the caller needs to 457178825Sdfr * free the cert itself. 458178825Sdfr * 459178825Sdfr * @param context a hx509 context. 460178825Sdfr * @param certs certificate store to add the certificate to. 461178825Sdfr * @param cert certificate to add. 462178825Sdfr * 463178825Sdfr * @return Returns an hx509 error code. 464178825Sdfr * 465178825Sdfr * @ingroup hx509_keyset 466178825Sdfr */ 467178825Sdfr 468178825Sdfrint 469178825Sdfrhx509_certs_add(hx509_context context, hx509_certs certs, hx509_cert cert) 470178825Sdfr{ 471178825Sdfr if (certs->ops->add == NULL) { 472233294Sstas hx509_set_error_string(context, 0, ENOENT, 473233294Sstas "Keyset type %s doesn't support add operation", 474178825Sdfr certs->ops->name); 475178825Sdfr return ENOENT; 476178825Sdfr } 477178825Sdfr 478178825Sdfr return (*certs->ops->add)(context, certs, certs->ops_data, cert); 479178825Sdfr} 480178825Sdfr 481178825Sdfr/** 482178825Sdfr * Find a certificate matching the query. 483178825Sdfr * 484178825Sdfr * @param context a hx509 context. 485178825Sdfr * @param certs certificate store to search. 486178825Sdfr * @param q query allocated with @ref hx509_query functions. 487178825Sdfr * @param r return certificate (or NULL on error), should be freed 488178825Sdfr * with hx509_cert_free(). 489178825Sdfr * 490178825Sdfr * @return Returns an hx509 error code. 491178825Sdfr * 492178825Sdfr * @ingroup hx509_keyset 493178825Sdfr */ 494178825Sdfr 495178825Sdfrint 496178825Sdfrhx509_certs_find(hx509_context context, 497233294Sstas hx509_certs certs, 498178825Sdfr const hx509_query *q, 499178825Sdfr hx509_cert *r) 500178825Sdfr{ 501178825Sdfr hx509_cursor cursor; 502178825Sdfr hx509_cert c; 503178825Sdfr int ret; 504178825Sdfr 505178825Sdfr *r = NULL; 506178825Sdfr 507178825Sdfr _hx509_query_statistic(context, 0, q); 508178825Sdfr 509178825Sdfr if (certs->ops->query) 510178825Sdfr return (*certs->ops->query)(context, certs, certs->ops_data, q, r); 511178825Sdfr 512178825Sdfr ret = hx509_certs_start_seq(context, certs, &cursor); 513178825Sdfr if (ret) 514178825Sdfr return ret; 515178825Sdfr 516178825Sdfr c = NULL; 517178825Sdfr while (1) { 518178825Sdfr ret = hx509_certs_next_cert(context, certs, cursor, &c); 519178825Sdfr if (ret) 520178825Sdfr break; 521178825Sdfr if (c == NULL) 522178825Sdfr break; 523178825Sdfr if (_hx509_query_match_cert(context, q, c)) { 524178825Sdfr *r = c; 525178825Sdfr break; 526178825Sdfr } 527178825Sdfr hx509_cert_free(c); 528178825Sdfr } 529178825Sdfr 530178825Sdfr hx509_certs_end_seq(context, certs, cursor); 531178825Sdfr if (ret) 532178825Sdfr return ret; 533233294Sstas /** 534233294Sstas * Return HX509_CERT_NOT_FOUND if no certificate in certs matched 535233294Sstas * the query. 536233294Sstas */ 537178825Sdfr if (c == NULL) { 538178825Sdfr hx509_clear_error_string(context); 539178825Sdfr return HX509_CERT_NOT_FOUND; 540178825Sdfr } 541178825Sdfr 542178825Sdfr return 0; 543178825Sdfr} 544178825Sdfr 545233294Sstas/** 546233294Sstas * Filter certificate matching the query. 547233294Sstas * 548233294Sstas * @param context a hx509 context. 549233294Sstas * @param certs certificate store to search. 550233294Sstas * @param q query allocated with @ref hx509_query functions. 551233294Sstas * @param result the filtered certificate store, caller must free with 552233294Sstas * hx509_certs_free(). 553233294Sstas * 554233294Sstas * @return Returns an hx509 error code. 555233294Sstas * 556233294Sstas * @ingroup hx509_keyset 557233294Sstas */ 558233294Sstas 559233294Sstasint 560233294Sstashx509_certs_filter(hx509_context context, 561233294Sstas hx509_certs certs, 562233294Sstas const hx509_query *q, 563233294Sstas hx509_certs *result) 564233294Sstas{ 565233294Sstas hx509_cursor cursor; 566233294Sstas hx509_cert c; 567233294Sstas int ret, found = 0; 568233294Sstas 569233294Sstas _hx509_query_statistic(context, 0, q); 570233294Sstas 571233294Sstas ret = hx509_certs_init(context, "MEMORY:filter-certs", 0, 572233294Sstas NULL, result); 573233294Sstas if (ret) 574233294Sstas return ret; 575233294Sstas 576233294Sstas ret = hx509_certs_start_seq(context, certs, &cursor); 577233294Sstas if (ret) { 578233294Sstas hx509_certs_free(result); 579233294Sstas return ret; 580233294Sstas } 581233294Sstas 582233294Sstas c = NULL; 583233294Sstas while (1) { 584233294Sstas ret = hx509_certs_next_cert(context, certs, cursor, &c); 585233294Sstas if (ret) 586233294Sstas break; 587233294Sstas if (c == NULL) 588233294Sstas break; 589233294Sstas if (_hx509_query_match_cert(context, q, c)) { 590233294Sstas hx509_certs_add(context, *result, c); 591233294Sstas found = 1; 592233294Sstas } 593233294Sstas hx509_cert_free(c); 594233294Sstas } 595233294Sstas 596233294Sstas hx509_certs_end_seq(context, certs, cursor); 597233294Sstas if (ret) { 598233294Sstas hx509_certs_free(result); 599233294Sstas return ret; 600233294Sstas } 601233294Sstas 602233294Sstas /** 603233294Sstas * Return HX509_CERT_NOT_FOUND if no certificate in certs matched 604233294Sstas * the query. 605233294Sstas */ 606233294Sstas if (!found) { 607233294Sstas hx509_certs_free(result); 608233294Sstas hx509_clear_error_string(context); 609233294Sstas return HX509_CERT_NOT_FOUND; 610233294Sstas } 611233294Sstas 612233294Sstas return 0; 613233294Sstas} 614233294Sstas 615233294Sstas 616178825Sdfrstatic int 617178825Sdfrcerts_merge_func(hx509_context context, void *ctx, hx509_cert c) 618178825Sdfr{ 619178825Sdfr return hx509_certs_add(context, (hx509_certs)ctx, c); 620178825Sdfr} 621178825Sdfr 622178825Sdfr/** 623178825Sdfr * Merge a certificate store into another. The from store is keep 624178825Sdfr * intact. 625178825Sdfr * 626178825Sdfr * @param context a hx509 context. 627178825Sdfr * @param to the store to merge into. 628178825Sdfr * @param from the store to copy the object from. 629178825Sdfr * 630178825Sdfr * @return Returns an hx509 error code. 631178825Sdfr * 632178825Sdfr * @ingroup hx509_keyset 633178825Sdfr */ 634178825Sdfr 635178825Sdfrint 636178825Sdfrhx509_certs_merge(hx509_context context, hx509_certs to, hx509_certs from) 637178825Sdfr{ 638178825Sdfr if (from == NULL) 639178825Sdfr return 0; 640233294Sstas return hx509_certs_iter_f(context, from, certs_merge_func, to); 641178825Sdfr} 642178825Sdfr 643178825Sdfr/** 644178825Sdfr * Same a hx509_certs_merge() but use a lock and name to describe the 645178825Sdfr * from source. 646178825Sdfr * 647178825Sdfr * @param context a hx509 context. 648178825Sdfr * @param to the store to merge into. 649178825Sdfr * @param lock a lock that unlocks the certificates store, use NULL to 650178825Sdfr * select no password/certifictes/prompt lock (see @ref page_lock). 651178825Sdfr * @param name name of the source store 652178825Sdfr * 653178825Sdfr * @return Returns an hx509 error code. 654178825Sdfr * 655178825Sdfr * @ingroup hx509_keyset 656178825Sdfr */ 657178825Sdfr 658178825Sdfrint 659178825Sdfrhx509_certs_append(hx509_context context, 660178825Sdfr hx509_certs to, 661178825Sdfr hx509_lock lock, 662178825Sdfr const char *name) 663178825Sdfr{ 664178825Sdfr hx509_certs s; 665178825Sdfr int ret; 666178825Sdfr 667178825Sdfr ret = hx509_certs_init(context, name, 0, lock, &s); 668178825Sdfr if (ret) 669178825Sdfr return ret; 670178825Sdfr ret = hx509_certs_merge(context, to, s); 671178825Sdfr hx509_certs_free(&s); 672178825Sdfr return ret; 673178825Sdfr} 674178825Sdfr 675178825Sdfr/** 676178825Sdfr * Get one random certificate from the certificate store. 677178825Sdfr * 678178825Sdfr * @param context a hx509 context. 679178825Sdfr * @param certs a certificate store to get the certificate from. 680178825Sdfr * @param c return certificate, should be freed with hx509_cert_free(). 681178825Sdfr * 682178825Sdfr * @return Returns an hx509 error code. 683178825Sdfr * 684178825Sdfr * @ingroup hx509_keyset 685178825Sdfr */ 686178825Sdfr 687178825Sdfrint 688178825Sdfrhx509_get_one_cert(hx509_context context, hx509_certs certs, hx509_cert *c) 689178825Sdfr{ 690178825Sdfr hx509_cursor cursor; 691178825Sdfr int ret; 692178825Sdfr 693178825Sdfr *c = NULL; 694178825Sdfr 695178825Sdfr ret = hx509_certs_start_seq(context, certs, &cursor); 696178825Sdfr if (ret) 697178825Sdfr return ret; 698178825Sdfr 699178825Sdfr ret = hx509_certs_next_cert(context, certs, cursor, c); 700178825Sdfr if (ret) 701178825Sdfr return ret; 702178825Sdfr 703178825Sdfr hx509_certs_end_seq(context, certs, cursor); 704178825Sdfr return 0; 705178825Sdfr} 706178825Sdfr 707178825Sdfrstatic int 708178825Sdfrcerts_info_stdio(void *ctx, const char *str) 709178825Sdfr{ 710178825Sdfr FILE *f = ctx; 711178825Sdfr fprintf(f, "%s\n", str); 712178825Sdfr return 0; 713178825Sdfr} 714178825Sdfr 715178825Sdfr/** 716178825Sdfr * Print some info about the certificate store. 717178825Sdfr * 718178825Sdfr * @param context a hx509 context. 719178825Sdfr * @param certs certificate store to print information about. 720178825Sdfr * @param func function that will get each line of the information, if 721178825Sdfr * NULL is used the data is printed on a FILE descriptor that should 722178825Sdfr * be passed in ctx, if ctx also is NULL, stdout is used. 723178825Sdfr * @param ctx parameter to func. 724178825Sdfr * 725178825Sdfr * @return Returns an hx509 error code. 726178825Sdfr * 727178825Sdfr * @ingroup hx509_keyset 728178825Sdfr */ 729178825Sdfr 730178825Sdfrint 731233294Sstashx509_certs_info(hx509_context context, 732178825Sdfr hx509_certs certs, 733178825Sdfr int (*func)(void *, const char *), 734178825Sdfr void *ctx) 735178825Sdfr{ 736178825Sdfr if (func == NULL) { 737178825Sdfr func = certs_info_stdio; 738178825Sdfr if (ctx == NULL) 739178825Sdfr ctx = stdout; 740178825Sdfr } 741178825Sdfr if (certs->ops->printinfo == NULL) { 742178825Sdfr (*func)(ctx, "No info function for certs"); 743178825Sdfr return 0; 744178825Sdfr } 745178825Sdfr return (*certs->ops->printinfo)(context, certs, certs->ops_data, 746178825Sdfr func, ctx); 747178825Sdfr} 748178825Sdfr 749178825Sdfrvoid 750178825Sdfr_hx509_pi_printf(int (*func)(void *, const char *), void *ctx, 751178825Sdfr const char *fmt, ...) 752178825Sdfr{ 753178825Sdfr va_list ap; 754178825Sdfr char *str; 755178825Sdfr 756178825Sdfr va_start(ap, fmt); 757178825Sdfr vasprintf(&str, fmt, ap); 758178825Sdfr va_end(ap); 759178825Sdfr if (str == NULL) 760178825Sdfr return; 761178825Sdfr (*func)(ctx, str); 762178825Sdfr free(str); 763178825Sdfr} 764178825Sdfr 765178825Sdfrint 766233294Sstas_hx509_certs_keys_get(hx509_context context, 767233294Sstas hx509_certs certs, 768178825Sdfr hx509_private_key **keys) 769178825Sdfr{ 770178825Sdfr if (certs->ops->getkeys == NULL) { 771178825Sdfr *keys = NULL; 772178825Sdfr return 0; 773178825Sdfr } 774178825Sdfr return (*certs->ops->getkeys)(context, certs, certs->ops_data, keys); 775178825Sdfr} 776178825Sdfr 777178825Sdfrint 778233294Sstas_hx509_certs_keys_add(hx509_context context, 779233294Sstas hx509_certs certs, 780178825Sdfr hx509_private_key key) 781178825Sdfr{ 782178825Sdfr if (certs->ops->addkey == NULL) { 783178825Sdfr hx509_set_error_string(context, 0, EINVAL, 784178825Sdfr "keystore if type %s doesn't support " 785178825Sdfr "key add operation", 786178825Sdfr certs->ops->name); 787178825Sdfr return EINVAL; 788178825Sdfr } 789178825Sdfr return (*certs->ops->addkey)(context, certs, certs->ops_data, key); 790178825Sdfr} 791178825Sdfr 792178825Sdfr 793178825Sdfrvoid 794178825Sdfr_hx509_certs_keys_free(hx509_context context, 795178825Sdfr hx509_private_key *keys) 796178825Sdfr{ 797178825Sdfr int i; 798178825Sdfr for (i = 0; keys[i]; i++) 799233294Sstas hx509_private_key_free(&keys[i]); 800178825Sdfr free(keys); 801178825Sdfr} 802