1178825Sdfr/* 2178825Sdfr * Copyright (c) 2005 - 2007 Kungliga Tekniska H�gskolan 3178825Sdfr * (Royal Institute of Technology, Stockholm, Sweden). 4178825Sdfr * All rights reserved. 5178825Sdfr * 6178825Sdfr * Redistribution and use in source and binary forms, with or without 7178825Sdfr * modification, are permitted provided that the following conditions 8178825Sdfr * are met: 9178825Sdfr * 10178825Sdfr * 1. Redistributions of source code must retain the above copyright 11178825Sdfr * notice, this list of conditions and the following disclaimer. 12178825Sdfr * 13178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright 14178825Sdfr * notice, this list of conditions and the following disclaimer in the 15178825Sdfr * documentation and/or other materials provided with the distribution. 16178825Sdfr * 17178825Sdfr * 3. Neither the name of the Institute nor the names of its contributors 18178825Sdfr * may be used to endorse or promote products derived from this software 19178825Sdfr * without specific prior written permission. 20178825Sdfr * 21178825Sdfr * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24178825Sdfr * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31178825Sdfr * SUCH DAMAGE. 32178825Sdfr */ 33178825Sdfr 34178825Sdfr#include "hx_locl.h" 35178825SdfrRCSID("$Id: ks_file.c 22465 2008-01-16 14:25:24Z lha $"); 36178825Sdfr 37178825Sdfrtypedef enum { USE_PEM, USE_DER } outformat; 38178825Sdfr 39178825Sdfrstruct ks_file { 40178825Sdfr hx509_certs certs; 41178825Sdfr char *fn; 42178825Sdfr outformat format; 43178825Sdfr}; 44178825Sdfr 45178825Sdfr/* 46178825Sdfr * 47178825Sdfr */ 48178825Sdfr 49178825Sdfrstatic int 50178825Sdfrparse_certificate(hx509_context context, const char *fn, 51178825Sdfr struct hx509_collector *c, 52178825Sdfr const hx509_pem_header *headers, 53178825Sdfr const void *data, size_t len) 54178825Sdfr{ 55178825Sdfr hx509_cert cert; 56178825Sdfr int ret; 57178825Sdfr 58178825Sdfr ret = hx509_cert_init_data(context, data, len, &cert); 59178825Sdfr if (ret) 60178825Sdfr return ret; 61178825Sdfr 62178825Sdfr ret = _hx509_collector_certs_add(context, c, cert); 63178825Sdfr hx509_cert_free(cert); 64178825Sdfr return ret; 65178825Sdfr} 66178825Sdfr 67178825Sdfrstatic int 68178825Sdfrtry_decrypt(hx509_context context, 69178825Sdfr struct hx509_collector *collector, 70178825Sdfr const AlgorithmIdentifier *alg, 71178825Sdfr const EVP_CIPHER *c, 72178825Sdfr const void *ivdata, 73178825Sdfr const void *password, 74178825Sdfr size_t passwordlen, 75178825Sdfr const void *cipher, 76178825Sdfr size_t len) 77178825Sdfr{ 78178825Sdfr heim_octet_string clear; 79178825Sdfr size_t keylen; 80178825Sdfr void *key; 81178825Sdfr int ret; 82178825Sdfr 83178825Sdfr keylen = EVP_CIPHER_key_length(c); 84178825Sdfr 85178825Sdfr key = malloc(keylen); 86178825Sdfr if (key == NULL) { 87178825Sdfr hx509_clear_error_string(context); 88178825Sdfr return ENOMEM; 89178825Sdfr } 90178825Sdfr 91178825Sdfr ret = EVP_BytesToKey(c, EVP_md5(), ivdata, 92178825Sdfr password, passwordlen, 93178825Sdfr 1, key, NULL); 94178825Sdfr if (ret <= 0) { 95178825Sdfr hx509_set_error_string(context, 0, HX509_CRYPTO_INTERNAL_ERROR, 96178825Sdfr "Failed to do string2key for private key"); 97178825Sdfr return HX509_CRYPTO_INTERNAL_ERROR; 98178825Sdfr } 99178825Sdfr 100178825Sdfr clear.data = malloc(len); 101178825Sdfr if (clear.data == NULL) { 102178825Sdfr hx509_set_error_string(context, 0, ENOMEM, 103178825Sdfr "Out of memory to decrypt for private key"); 104178825Sdfr ret = ENOMEM; 105178825Sdfr goto out; 106178825Sdfr } 107178825Sdfr clear.length = len; 108178825Sdfr 109178825Sdfr { 110178825Sdfr EVP_CIPHER_CTX ctx; 111178825Sdfr EVP_CIPHER_CTX_init(&ctx); 112178825Sdfr EVP_CipherInit_ex(&ctx, c, NULL, key, ivdata, 0); 113178825Sdfr EVP_Cipher(&ctx, clear.data, cipher, len); 114178825Sdfr EVP_CIPHER_CTX_cleanup(&ctx); 115178825Sdfr } 116178825Sdfr 117178825Sdfr ret = _hx509_collector_private_key_add(context, 118178825Sdfr collector, 119178825Sdfr alg, 120178825Sdfr NULL, 121178825Sdfr &clear, 122178825Sdfr NULL); 123178825Sdfr 124178825Sdfr memset(clear.data, 0, clear.length); 125178825Sdfr free(clear.data); 126178825Sdfrout: 127178825Sdfr memset(key, 0, keylen); 128178825Sdfr free(key); 129178825Sdfr return ret; 130178825Sdfr} 131178825Sdfr 132178825Sdfrstatic int 133178825Sdfrparse_rsa_private_key(hx509_context context, const char *fn, 134178825Sdfr struct hx509_collector *c, 135178825Sdfr const hx509_pem_header *headers, 136178825Sdfr const void *data, size_t len) 137178825Sdfr{ 138178825Sdfr int ret = 0; 139178825Sdfr const char *enc; 140178825Sdfr 141178825Sdfr enc = hx509_pem_find_header(headers, "Proc-Type"); 142178825Sdfr if (enc) { 143178825Sdfr const char *dek; 144178825Sdfr char *type, *iv; 145178825Sdfr ssize_t ssize, size; 146178825Sdfr void *ivdata; 147178825Sdfr const EVP_CIPHER *cipher; 148178825Sdfr const struct _hx509_password *pw; 149178825Sdfr hx509_lock lock; 150178825Sdfr int i, decrypted = 0; 151178825Sdfr 152178825Sdfr lock = _hx509_collector_get_lock(c); 153178825Sdfr if (lock == NULL) { 154178825Sdfr hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, 155178825Sdfr "Failed to get password for " 156178825Sdfr "password protected file %s", fn); 157178825Sdfr return HX509_ALG_NOT_SUPP; 158178825Sdfr } 159178825Sdfr 160178825Sdfr if (strcmp(enc, "4,ENCRYPTED") != 0) { 161178825Sdfr hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, 162178825Sdfr "RSA key encrypted in unknown method %s " 163178825Sdfr "in file", 164178825Sdfr enc, fn); 165178825Sdfr hx509_clear_error_string(context); 166178825Sdfr return HX509_PARSING_KEY_FAILED; 167178825Sdfr } 168178825Sdfr 169178825Sdfr dek = hx509_pem_find_header(headers, "DEK-Info"); 170178825Sdfr if (dek == NULL) { 171178825Sdfr hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, 172178825Sdfr "Encrypted RSA missing DEK-Info"); 173178825Sdfr return HX509_PARSING_KEY_FAILED; 174178825Sdfr } 175178825Sdfr 176178825Sdfr type = strdup(dek); 177178825Sdfr if (type == NULL) { 178178825Sdfr hx509_clear_error_string(context); 179178825Sdfr return ENOMEM; 180178825Sdfr } 181178825Sdfr 182178825Sdfr iv = strchr(type, ','); 183178825Sdfr if (iv == NULL) { 184178825Sdfr free(type); 185178825Sdfr hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, 186178825Sdfr "IV missing"); 187178825Sdfr return HX509_PARSING_KEY_FAILED; 188178825Sdfr } 189178825Sdfr 190178825Sdfr *iv++ = '\0'; 191178825Sdfr 192178825Sdfr size = strlen(iv); 193178825Sdfr ivdata = malloc(size); 194178825Sdfr if (ivdata == NULL) { 195178825Sdfr hx509_clear_error_string(context); 196178825Sdfr free(type); 197178825Sdfr return ENOMEM; 198178825Sdfr } 199178825Sdfr 200178825Sdfr cipher = EVP_get_cipherbyname(type); 201178825Sdfr if (cipher == NULL) { 202178825Sdfr free(ivdata); 203178825Sdfr hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP, 204178825Sdfr "RSA key encrypted with " 205178825Sdfr "unsupported cipher: %s", 206178825Sdfr type); 207178825Sdfr free(type); 208178825Sdfr return HX509_ALG_NOT_SUPP; 209178825Sdfr } 210178825Sdfr 211178825Sdfr#define PKCS5_SALT_LEN 8 212178825Sdfr 213178825Sdfr ssize = hex_decode(iv, ivdata, size); 214178825Sdfr free(type); 215178825Sdfr type = NULL; 216178825Sdfr iv = NULL; 217178825Sdfr 218178825Sdfr if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) { 219178825Sdfr free(ivdata); 220178825Sdfr hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED, 221178825Sdfr "Salt have wrong length in RSA key file"); 222178825Sdfr return HX509_PARSING_KEY_FAILED; 223178825Sdfr } 224178825Sdfr 225178825Sdfr pw = _hx509_lock_get_passwords(lock); 226178825Sdfr if (pw != NULL) { 227178825Sdfr const void *password; 228178825Sdfr size_t passwordlen; 229178825Sdfr 230178825Sdfr for (i = 0; i < pw->len; i++) { 231178825Sdfr password = pw->val[i]; 232178825Sdfr passwordlen = strlen(password); 233178825Sdfr 234178825Sdfr ret = try_decrypt(context, c, hx509_signature_rsa(), 235178825Sdfr cipher, ivdata, password, passwordlen, 236178825Sdfr data, len); 237178825Sdfr if (ret == 0) { 238178825Sdfr decrypted = 1; 239178825Sdfr break; 240178825Sdfr } 241178825Sdfr } 242178825Sdfr } 243178825Sdfr if (!decrypted) { 244178825Sdfr hx509_prompt prompt; 245178825Sdfr char password[128]; 246178825Sdfr 247178825Sdfr memset(&prompt, 0, sizeof(prompt)); 248178825Sdfr 249178825Sdfr prompt.prompt = "Password for keyfile: "; 250178825Sdfr prompt.type = HX509_PROMPT_TYPE_PASSWORD; 251178825Sdfr prompt.reply.data = password; 252178825Sdfr prompt.reply.length = sizeof(password); 253178825Sdfr 254178825Sdfr ret = hx509_lock_prompt(lock, &prompt); 255178825Sdfr if (ret == 0) 256178825Sdfr ret = try_decrypt(context, c, hx509_signature_rsa(), 257178825Sdfr cipher, ivdata, password, strlen(password), 258178825Sdfr data, len); 259178825Sdfr /* XXX add password to lock password collection ? */ 260178825Sdfr memset(password, 0, sizeof(password)); 261178825Sdfr } 262178825Sdfr free(ivdata); 263178825Sdfr 264178825Sdfr } else { 265178825Sdfr heim_octet_string keydata; 266178825Sdfr 267178825Sdfr keydata.data = rk_UNCONST(data); 268178825Sdfr keydata.length = len; 269178825Sdfr 270178825Sdfr ret = _hx509_collector_private_key_add(context, 271178825Sdfr c, 272178825Sdfr hx509_signature_rsa(), 273178825Sdfr NULL, 274178825Sdfr &keydata, 275178825Sdfr NULL); 276178825Sdfr } 277178825Sdfr 278178825Sdfr return ret; 279178825Sdfr} 280178825Sdfr 281178825Sdfr 282178825Sdfrstruct pem_formats { 283178825Sdfr const char *name; 284178825Sdfr int (*func)(hx509_context, const char *, struct hx509_collector *, 285178825Sdfr const hx509_pem_header *, const void *, size_t); 286178825Sdfr} formats[] = { 287178825Sdfr { "CERTIFICATE", parse_certificate }, 288178825Sdfr { "RSA PRIVATE KEY", parse_rsa_private_key } 289178825Sdfr}; 290178825Sdfr 291178825Sdfr 292178825Sdfrstruct pem_ctx { 293178825Sdfr int flags; 294178825Sdfr struct hx509_collector *c; 295178825Sdfr}; 296178825Sdfr 297178825Sdfrstatic int 298178825Sdfrpem_func(hx509_context context, const char *type, 299178825Sdfr const hx509_pem_header *header, 300178825Sdfr const void *data, size_t len, void *ctx) 301178825Sdfr{ 302178825Sdfr struct pem_ctx *pem_ctx = (struct pem_ctx*)ctx; 303178825Sdfr int ret = 0, j; 304178825Sdfr 305178825Sdfr for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) { 306178825Sdfr const char *q = formats[j].name; 307178825Sdfr if (strcasecmp(type, q) == 0) { 308178825Sdfr ret = (*formats[j].func)(context, NULL, pem_ctx->c, header, data, len); 309178825Sdfr if (ret == 0) 310178825Sdfr break; 311178825Sdfr } 312178825Sdfr } 313178825Sdfr if (j == sizeof(formats)/sizeof(formats[0])) { 314178825Sdfr ret = HX509_UNSUPPORTED_OPERATION; 315178825Sdfr hx509_set_error_string(context, 0, ret, 316178825Sdfr "Found no matching PEM format for %s", type); 317178825Sdfr return ret; 318178825Sdfr } 319178825Sdfr if (ret && (pem_ctx->flags & HX509_CERTS_UNPROTECT_ALL)) 320178825Sdfr return ret; 321178825Sdfr return 0; 322178825Sdfr} 323178825Sdfr 324178825Sdfr/* 325178825Sdfr * 326178825Sdfr */ 327178825Sdfr 328178825Sdfrstatic int 329178825Sdfrfile_init_common(hx509_context context, 330178825Sdfr hx509_certs certs, void **data, int flags, 331178825Sdfr const char *residue, hx509_lock lock, outformat format) 332178825Sdfr{ 333178825Sdfr char *p, *pnext; 334178825Sdfr struct ks_file *f = NULL; 335178825Sdfr hx509_private_key *keys = NULL; 336178825Sdfr int ret; 337178825Sdfr struct pem_ctx pem_ctx; 338178825Sdfr 339178825Sdfr pem_ctx.flags = flags; 340178825Sdfr pem_ctx.c = NULL; 341178825Sdfr 342178825Sdfr *data = NULL; 343178825Sdfr 344178825Sdfr if (lock == NULL) 345178825Sdfr lock = _hx509_empty_lock; 346178825Sdfr 347178825Sdfr f = calloc(1, sizeof(*f)); 348178825Sdfr if (f == NULL) { 349178825Sdfr hx509_clear_error_string(context); 350178825Sdfr return ENOMEM; 351178825Sdfr } 352178825Sdfr f->format = format; 353178825Sdfr 354178825Sdfr f->fn = strdup(residue); 355178825Sdfr if (f->fn == NULL) { 356178825Sdfr hx509_clear_error_string(context); 357178825Sdfr ret = ENOMEM; 358178825Sdfr goto out; 359178825Sdfr } 360178825Sdfr 361178825Sdfr /* 362178825Sdfr * XXX this is broken, the function should parse the file before 363178825Sdfr * overwriting it 364178825Sdfr */ 365178825Sdfr 366178825Sdfr if (flags & HX509_CERTS_CREATE) { 367178825Sdfr ret = hx509_certs_init(context, "MEMORY:ks-file-create", 368178825Sdfr 0, lock, &f->certs); 369178825Sdfr if (ret) 370178825Sdfr goto out; 371178825Sdfr *data = f; 372178825Sdfr return 0; 373178825Sdfr } 374178825Sdfr 375178825Sdfr ret = _hx509_collector_alloc(context, lock, &pem_ctx.c); 376178825Sdfr if (ret) 377178825Sdfr goto out; 378178825Sdfr 379178825Sdfr for (p = f->fn; p != NULL; p = pnext) { 380178825Sdfr FILE *f; 381178825Sdfr 382178825Sdfr pnext = strchr(p, ','); 383178825Sdfr if (pnext) 384178825Sdfr *pnext++ = '\0'; 385178825Sdfr 386178825Sdfr 387178825Sdfr if ((f = fopen(p, "r")) == NULL) { 388178825Sdfr ret = ENOENT; 389178825Sdfr hx509_set_error_string(context, 0, ret, 390178825Sdfr "Failed to open PEM file \"%s\": %s", 391178825Sdfr p, strerror(errno)); 392178825Sdfr goto out; 393178825Sdfr } 394178825Sdfr 395178825Sdfr ret = hx509_pem_read(context, f, pem_func, &pem_ctx); 396178825Sdfr fclose(f); 397178825Sdfr if (ret != 0 && ret != HX509_PARSING_KEY_FAILED) 398178825Sdfr goto out; 399178825Sdfr else if (ret == HX509_PARSING_KEY_FAILED) { 400178825Sdfr size_t length; 401178825Sdfr void *ptr; 402178825Sdfr int i; 403178825Sdfr 404178825Sdfr ret = _hx509_map_file(p, &ptr, &length, NULL); 405178825Sdfr if (ret) { 406178825Sdfr hx509_clear_error_string(context); 407178825Sdfr goto out; 408178825Sdfr } 409178825Sdfr 410178825Sdfr for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) { 411178825Sdfr ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length); 412178825Sdfr if (ret == 0) 413178825Sdfr break; 414178825Sdfr } 415178825Sdfr _hx509_unmap_file(ptr, length); 416178825Sdfr if (ret) 417178825Sdfr goto out; 418178825Sdfr } 419178825Sdfr } 420178825Sdfr 421178825Sdfr ret = _hx509_collector_collect_certs(context, pem_ctx.c, &f->certs); 422178825Sdfr if (ret) 423178825Sdfr goto out; 424178825Sdfr 425178825Sdfr ret = _hx509_collector_collect_private_keys(context, pem_ctx.c, &keys); 426178825Sdfr if (ret == 0) { 427178825Sdfr int i; 428178825Sdfr 429178825Sdfr for (i = 0; keys[i]; i++) 430178825Sdfr _hx509_certs_keys_add(context, f->certs, keys[i]); 431178825Sdfr _hx509_certs_keys_free(context, keys); 432178825Sdfr } 433178825Sdfr 434178825Sdfrout: 435178825Sdfr if (ret == 0) 436178825Sdfr *data = f; 437178825Sdfr else { 438178825Sdfr if (f->fn) 439178825Sdfr free(f->fn); 440178825Sdfr free(f); 441178825Sdfr } 442178825Sdfr if (pem_ctx.c) 443178825Sdfr _hx509_collector_free(pem_ctx.c); 444178825Sdfr 445178825Sdfr return ret; 446178825Sdfr} 447178825Sdfr 448178825Sdfrstatic int 449178825Sdfrfile_init_pem(hx509_context context, 450178825Sdfr hx509_certs certs, void **data, int flags, 451178825Sdfr const char *residue, hx509_lock lock) 452178825Sdfr{ 453178825Sdfr return file_init_common(context, certs, data, flags, residue, lock, USE_PEM); 454178825Sdfr} 455178825Sdfr 456178825Sdfrstatic int 457178825Sdfrfile_init_der(hx509_context context, 458178825Sdfr hx509_certs certs, void **data, int flags, 459178825Sdfr const char *residue, hx509_lock lock) 460178825Sdfr{ 461178825Sdfr return file_init_common(context, certs, data, flags, residue, lock, USE_DER); 462178825Sdfr} 463178825Sdfr 464178825Sdfrstatic int 465178825Sdfrfile_free(hx509_certs certs, void *data) 466178825Sdfr{ 467178825Sdfr struct ks_file *f = data; 468178825Sdfr hx509_certs_free(&f->certs); 469178825Sdfr free(f->fn); 470178825Sdfr free(f); 471178825Sdfr return 0; 472178825Sdfr} 473178825Sdfr 474178825Sdfrstruct store_ctx { 475178825Sdfr FILE *f; 476178825Sdfr outformat format; 477178825Sdfr}; 478178825Sdfr 479178825Sdfrstatic int 480178825Sdfrstore_func(hx509_context context, void *ctx, hx509_cert c) 481178825Sdfr{ 482178825Sdfr struct store_ctx *sc = ctx; 483178825Sdfr heim_octet_string data; 484178825Sdfr int ret; 485178825Sdfr 486178825Sdfr ret = hx509_cert_binary(context, c, &data); 487178825Sdfr if (ret) 488178825Sdfr return ret; 489178825Sdfr 490178825Sdfr switch (sc->format) { 491178825Sdfr case USE_DER: 492178825Sdfr fwrite(data.data, data.length, 1, sc->f); 493178825Sdfr free(data.data); 494178825Sdfr break; 495178825Sdfr case USE_PEM: 496178825Sdfr hx509_pem_write(context, "CERTIFICATE", NULL, sc->f, 497178825Sdfr data.data, data.length); 498178825Sdfr free(data.data); 499178825Sdfr if (_hx509_cert_private_key_exportable(c)) { 500178825Sdfr hx509_private_key key = _hx509_cert_private_key(c); 501178825Sdfr ret = _hx509_private_key_export(context, key, &data); 502178825Sdfr if (ret) 503178825Sdfr break; 504178825Sdfr hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f, 505178825Sdfr data.data, data.length); 506178825Sdfr free(data.data); 507178825Sdfr } 508178825Sdfr break; 509178825Sdfr } 510178825Sdfr 511178825Sdfr return 0; 512178825Sdfr} 513178825Sdfr 514178825Sdfrstatic int 515178825Sdfrfile_store(hx509_context context, 516178825Sdfr hx509_certs certs, void *data, int flags, hx509_lock lock) 517178825Sdfr{ 518178825Sdfr struct ks_file *f = data; 519178825Sdfr struct store_ctx sc; 520178825Sdfr int ret; 521178825Sdfr 522178825Sdfr sc.f = fopen(f->fn, "w"); 523178825Sdfr if (sc.f == NULL) { 524178825Sdfr hx509_set_error_string(context, 0, ENOENT, 525178825Sdfr "Failed to open file %s for writing"); 526178825Sdfr return ENOENT; 527178825Sdfr } 528178825Sdfr sc.format = f->format; 529178825Sdfr 530178825Sdfr ret = hx509_certs_iter(context, f->certs, store_func, &sc); 531178825Sdfr fclose(sc.f); 532178825Sdfr return ret; 533178825Sdfr} 534178825Sdfr 535178825Sdfrstatic int 536178825Sdfrfile_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c) 537178825Sdfr{ 538178825Sdfr struct ks_file *f = data; 539178825Sdfr return hx509_certs_add(context, f->certs, c); 540178825Sdfr} 541178825Sdfr 542178825Sdfrstatic int 543178825Sdfrfile_iter_start(hx509_context context, 544178825Sdfr hx509_certs certs, void *data, void **cursor) 545178825Sdfr{ 546178825Sdfr struct ks_file *f = data; 547178825Sdfr return hx509_certs_start_seq(context, f->certs, cursor); 548178825Sdfr} 549178825Sdfr 550178825Sdfrstatic int 551178825Sdfrfile_iter(hx509_context context, 552178825Sdfr hx509_certs certs, void *data, void *iter, hx509_cert *cert) 553178825Sdfr{ 554178825Sdfr struct ks_file *f = data; 555178825Sdfr return hx509_certs_next_cert(context, f->certs, iter, cert); 556178825Sdfr} 557178825Sdfr 558178825Sdfrstatic int 559178825Sdfrfile_iter_end(hx509_context context, 560178825Sdfr hx509_certs certs, 561178825Sdfr void *data, 562178825Sdfr void *cursor) 563178825Sdfr{ 564178825Sdfr struct ks_file *f = data; 565178825Sdfr return hx509_certs_end_seq(context, f->certs, cursor); 566178825Sdfr} 567178825Sdfr 568178825Sdfrstatic int 569178825Sdfrfile_getkeys(hx509_context context, 570178825Sdfr hx509_certs certs, 571178825Sdfr void *data, 572178825Sdfr hx509_private_key **keys) 573178825Sdfr{ 574178825Sdfr struct ks_file *f = data; 575178825Sdfr return _hx509_certs_keys_get(context, f->certs, keys); 576178825Sdfr} 577178825Sdfr 578178825Sdfrstatic int 579178825Sdfrfile_addkey(hx509_context context, 580178825Sdfr hx509_certs certs, 581178825Sdfr void *data, 582178825Sdfr hx509_private_key key) 583178825Sdfr{ 584178825Sdfr struct ks_file *f = data; 585178825Sdfr return _hx509_certs_keys_add(context, f->certs, key); 586178825Sdfr} 587178825Sdfr 588178825Sdfrstatic struct hx509_keyset_ops keyset_file = { 589178825Sdfr "FILE", 590178825Sdfr 0, 591178825Sdfr file_init_pem, 592178825Sdfr file_store, 593178825Sdfr file_free, 594178825Sdfr file_add, 595178825Sdfr NULL, 596178825Sdfr file_iter_start, 597178825Sdfr file_iter, 598178825Sdfr file_iter_end, 599178825Sdfr NULL, 600178825Sdfr file_getkeys, 601178825Sdfr file_addkey 602178825Sdfr}; 603178825Sdfr 604178825Sdfrstatic struct hx509_keyset_ops keyset_pemfile = { 605178825Sdfr "PEM-FILE", 606178825Sdfr 0, 607178825Sdfr file_init_pem, 608178825Sdfr file_store, 609178825Sdfr file_free, 610178825Sdfr file_add, 611178825Sdfr NULL, 612178825Sdfr file_iter_start, 613178825Sdfr file_iter, 614178825Sdfr file_iter_end, 615178825Sdfr NULL, 616178825Sdfr file_getkeys, 617178825Sdfr file_addkey 618178825Sdfr}; 619178825Sdfr 620178825Sdfrstatic struct hx509_keyset_ops keyset_derfile = { 621178825Sdfr "DER-FILE", 622178825Sdfr 0, 623178825Sdfr file_init_der, 624178825Sdfr file_store, 625178825Sdfr file_free, 626178825Sdfr file_add, 627178825Sdfr NULL, 628178825Sdfr file_iter_start, 629178825Sdfr file_iter, 630178825Sdfr file_iter_end, 631178825Sdfr NULL, 632178825Sdfr file_getkeys, 633178825Sdfr file_addkey 634178825Sdfr}; 635178825Sdfr 636178825Sdfr 637178825Sdfrvoid 638178825Sdfr_hx509_ks_file_register(hx509_context context) 639178825Sdfr{ 640178825Sdfr _hx509_ks_register(context, &keyset_file); 641178825Sdfr _hx509_ks_register(context, &keyset_pemfile); 642178825Sdfr _hx509_ks_register(context, &keyset_derfile); 643178825Sdfr} 644