LCOV - code coverage report
Current view: top level - source4/heimdal/lib/hx509 - ks_file.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 96 274 35.0 %
Date: 2021-09-23 10:06:22 Functions: 11 19 57.9 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2005 - 2007 Kungliga Tekniska Högskolan
       3             :  * (Royal Institute of Technology, Stockholm, Sweden).
       4             :  * All rights reserved.
       5             :  *
       6             :  * Redistribution and use in source and binary forms, with or without
       7             :  * modification, are permitted provided that the following conditions
       8             :  * are met:
       9             :  *
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  *
      13             :  * 2. Redistributions in binary form must reproduce the above copyright
      14             :  *    notice, this list of conditions and the following disclaimer in the
      15             :  *    documentation and/or other materials provided with the distribution.
      16             :  *
      17             :  * 3. Neither the name of the Institute nor the names of its contributors
      18             :  *    may be used to endorse or promote products derived from this software
      19             :  *    without specific prior written permission.
      20             :  *
      21             :  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
      22             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      23             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      24             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
      25             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      27             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      28             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      29             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      30             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      31             :  * SUCH DAMAGE.
      32             :  */
      33             : 
      34             : #include "hx_locl.h"
      35             : 
      36             : typedef enum { USE_PEM, USE_DER } outformat;
      37             : 
      38             : struct ks_file {
      39             :     hx509_certs certs;
      40             :     char *fn;
      41             :     outformat format;
      42             : };
      43             : 
      44             : /*
      45             :  *
      46             :  */
      47             : 
      48             : static int
      49         188 : parse_certificate(hx509_context context, const char *fn,
      50             :                   struct hx509_collector *c,
      51             :                   const hx509_pem_header *headers,
      52             :                   const void *data, size_t len,
      53             :                   const AlgorithmIdentifier *ai)
      54             : {
      55             :     hx509_cert cert;
      56             :     int ret;
      57             : 
      58         188 :     ret = hx509_cert_init_data(context, data, len, &cert);
      59         188 :     if (ret)
      60           0 :         return ret;
      61             : 
      62         188 :     ret = _hx509_collector_certs_add(context, c, cert);
      63         188 :     hx509_cert_free(cert);
      64         188 :     return ret;
      65             : }
      66             : 
      67             : static int
      68           0 : try_decrypt(hx509_context context,
      69             :             struct hx509_collector *collector,
      70             :             const AlgorithmIdentifier *alg,
      71             :             const EVP_CIPHER *c,
      72             :             const void *ivdata,
      73             :             const void *password,
      74             :             size_t passwordlen,
      75             :             const void *cipher,
      76             :             size_t len)
      77             : {
      78             :     heim_octet_string clear;
      79             :     size_t keylen;
      80             :     void *key;
      81             :     int ret;
      82             : 
      83           0 :     keylen = EVP_CIPHER_key_length(c);
      84             : 
      85           0 :     key = malloc(keylen);
      86           0 :     if (key == NULL) {
      87           0 :         hx509_clear_error_string(context);
      88           0 :         return ENOMEM;
      89             :     }
      90             : 
      91           0 :     ret = EVP_BytesToKey(c, EVP_md5(), ivdata,
      92             :                          password, passwordlen,
      93             :                          1, key, NULL);
      94           0 :     if (ret <= 0) {
      95           0 :         hx509_set_error_string(context, 0, HX509_CRYPTO_INTERNAL_ERROR,
      96             :                                "Failed to do string2key for private key");
      97           0 :         return HX509_CRYPTO_INTERNAL_ERROR;
      98             :     }
      99             : 
     100           0 :     clear.data = malloc(len);
     101           0 :     if (clear.data == NULL) {
     102           0 :         hx509_set_error_string(context, 0, ENOMEM,
     103             :                                "Out of memory to decrypt for private key");
     104           0 :         ret = ENOMEM;
     105           0 :         goto out;
     106             :     }
     107           0 :     clear.length = len;
     108             : 
     109             :     {
     110             :         EVP_CIPHER_CTX ctx;
     111           0 :         EVP_CIPHER_CTX_init(&ctx);
     112           0 :         EVP_CipherInit_ex(&ctx, c, NULL, key, ivdata, 0);
     113           0 :         EVP_Cipher(&ctx, clear.data, cipher, len);
     114           0 :         EVP_CIPHER_CTX_cleanup(&ctx);
     115             :     }
     116             : 
     117           0 :     ret = _hx509_collector_private_key_add(context,
     118             :                                            collector,
     119             :                                            alg,
     120             :                                            NULL,
     121             :                                            &clear,
     122             :                                            NULL);
     123             : 
     124           0 :     memset(clear.data, 0, clear.length);
     125           0 :     free(clear.data);
     126           0 : out:
     127           0 :     memset(key, 0, keylen);
     128           0 :     free(key);
     129           0 :     return ret;
     130             : }
     131             : 
     132             : static int
     133           0 : parse_pkcs8_private_key(hx509_context context, const char *fn,
     134             :                         struct hx509_collector *c,
     135             :                         const hx509_pem_header *headers,
     136             :                         const void *data, size_t length,
     137             :                         const AlgorithmIdentifier *ai)
     138             : {
     139             :     PKCS8PrivateKeyInfo ki;
     140             :     heim_octet_string keydata;
     141             : 
     142             :     int ret;
     143             : 
     144           0 :     ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL);
     145           0 :     if (ret)
     146           0 :         return ret;
     147             : 
     148           0 :     keydata.data = rk_UNCONST(data);
     149           0 :     keydata.length = length;
     150             : 
     151           0 :     ret = _hx509_collector_private_key_add(context,
     152             :                                            c,
     153             :                                            &ki.privateKeyAlgorithm,
     154             :                                            NULL,
     155             :                                            &ki.privateKey,
     156             :                                            &keydata);
     157           0 :     free_PKCS8PrivateKeyInfo(&ki);
     158           0 :     return ret;
     159             : }
     160             : 
     161             : static int
     162          94 : parse_pem_private_key(hx509_context context, const char *fn,
     163             :                       struct hx509_collector *c,
     164             :                       const hx509_pem_header *headers,
     165             :                       const void *data, size_t len,
     166             :                       const AlgorithmIdentifier *ai)
     167             : {
     168          94 :     int ret = 0;
     169             :     const char *enc;
     170             : 
     171          94 :     enc = hx509_pem_find_header(headers, "Proc-Type");
     172          94 :     if (enc) {
     173             :         const char *dek;
     174             :         char *type, *iv;
     175             :         ssize_t ssize, size;
     176             :         void *ivdata;
     177             :         const EVP_CIPHER *cipher;
     178             :         const struct _hx509_password *pw;
     179             :         hx509_lock lock;
     180           0 :         int decrypted = 0;
     181             :         size_t i;
     182             : 
     183           0 :         lock = _hx509_collector_get_lock(c);
     184           0 :         if (lock == NULL) {
     185           0 :             hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
     186             :                                    "Failed to get password for "
     187             :                                    "password protected file %s", fn);
     188           0 :             return HX509_ALG_NOT_SUPP;
     189             :         }
     190             : 
     191           0 :         if (strcmp(enc, "4,ENCRYPTED") != 0) {
     192           0 :             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     193             :                                    "Private key encrypted in unknown method %s "
     194             :                                    "in file",
     195             :                                    enc, fn);
     196           0 :             hx509_clear_error_string(context);
     197           0 :             return HX509_PARSING_KEY_FAILED;
     198             :         }
     199             : 
     200           0 :         dek = hx509_pem_find_header(headers, "DEK-Info");
     201           0 :         if (dek == NULL) {
     202           0 :             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     203             :                                    "Encrypted private key missing DEK-Info");
     204           0 :             return HX509_PARSING_KEY_FAILED;
     205             :         }
     206             : 
     207           0 :         type = strdup(dek);
     208           0 :         if (type == NULL) {
     209           0 :             hx509_clear_error_string(context);
     210           0 :             return ENOMEM;
     211             :         }
     212             : 
     213           0 :         iv = strchr(type, ',');
     214           0 :         if (iv == NULL) {
     215           0 :             free(type);
     216           0 :             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     217             :                                    "IV missing");
     218           0 :             return HX509_PARSING_KEY_FAILED;
     219             :         }
     220             : 
     221           0 :         *iv++ = '\0';
     222             : 
     223           0 :         size = strlen(iv);
     224           0 :         ivdata = malloc(size);
     225           0 :         if (ivdata == NULL) {
     226           0 :             hx509_clear_error_string(context);
     227           0 :             free(type);
     228           0 :             return ENOMEM;
     229             :         }
     230             : 
     231           0 :         cipher = EVP_get_cipherbyname(type);
     232           0 :         if (cipher == NULL) {
     233           0 :             free(ivdata);
     234           0 :             hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
     235             :                                    "Private key encrypted with "
     236             :                                    "unsupported cipher: %s",
     237             :                                    type);
     238           0 :             free(type);
     239           0 :             return HX509_ALG_NOT_SUPP;
     240             :         }
     241             : 
     242             : #define PKCS5_SALT_LEN 8
     243             : 
     244           0 :         ssize = hex_decode(iv, ivdata, size);
     245           0 :         free(type);
     246           0 :         type = NULL;
     247           0 :         iv = NULL;
     248             : 
     249           0 :         if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) {
     250           0 :             free(ivdata);
     251           0 :             hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
     252             :                                    "Salt have wrong length in "
     253             :                                    "private key file");
     254           0 :             return HX509_PARSING_KEY_FAILED;
     255             :         }
     256             : 
     257           0 :         pw = _hx509_lock_get_passwords(lock);
     258           0 :         if (pw != NULL) {
     259             :             const void *password;
     260             :             size_t passwordlen;
     261             : 
     262           0 :             for (i = 0; i < pw->len; i++) {
     263           0 :                 password = pw->val[i];
     264           0 :                 passwordlen = strlen(password);
     265             : 
     266           0 :                 ret = try_decrypt(context, c, ai, cipher, ivdata,
     267             :                                   password, passwordlen, data, len);
     268           0 :                 if (ret == 0) {
     269           0 :                     decrypted = 1;
     270           0 :                     break;
     271             :                 }
     272             :             }
     273             :         }
     274           0 :         if (!decrypted) {
     275             :             hx509_prompt prompt;
     276             :             char password[128];
     277             : 
     278           0 :             memset(&prompt, 0, sizeof(prompt));
     279             : 
     280           0 :             prompt.prompt = "Password for keyfile: ";
     281           0 :             prompt.type = HX509_PROMPT_TYPE_PASSWORD;
     282           0 :             prompt.reply.data = password;
     283           0 :             prompt.reply.length = sizeof(password);
     284             : 
     285           0 :             ret = hx509_lock_prompt(lock, &prompt);
     286           0 :             if (ret == 0)
     287           0 :                 ret = try_decrypt(context, c, ai, cipher, ivdata, password,
     288             :                                   strlen(password), data, len);
     289             :             /* XXX add password to lock password collection ? */
     290           0 :             memset(password, 0, sizeof(password));
     291             :         }
     292           0 :         free(ivdata);
     293             : 
     294             :     } else {
     295             :         heim_octet_string keydata;
     296             : 
     297          94 :         keydata.data = rk_UNCONST(data);
     298          94 :         keydata.length = len;
     299             : 
     300          94 :         ret = _hx509_collector_private_key_add(context, c, ai, NULL,
     301             :                                                &keydata, NULL);
     302             :     }
     303             : 
     304          86 :     return ret;
     305             : }
     306             : 
     307             : 
     308             : struct pem_formats {
     309             :     const char *name;
     310             :     int (*func)(hx509_context, const char *, struct hx509_collector *,
     311             :                 const hx509_pem_header *, const void *, size_t,
     312             :                 const AlgorithmIdentifier *);
     313             :     const AlgorithmIdentifier *(*ai)(void);
     314             : } formats[] = {
     315             :     { "CERTIFICATE", parse_certificate, NULL },
     316             :     { "PRIVATE KEY", parse_pkcs8_private_key, NULL },
     317             :     { "RSA PRIVATE KEY", parse_pem_private_key, hx509_signature_rsa },
     318             :     { "EC PRIVATE KEY", parse_pem_private_key, hx509_signature_ecPublicKey }
     319             : };
     320             : 
     321             : 
     322             : struct pem_ctx {
     323             :     int flags;
     324             :     struct hx509_collector *c;
     325             : };
     326             : 
     327             : static int
     328         282 : pem_func(hx509_context context, const char *type,
     329             :          const hx509_pem_header *header,
     330             :          const void *data, size_t len, void *ctx)
     331             : {
     332         282 :     struct pem_ctx *pem_ctx = (struct pem_ctx*)ctx;
     333         282 :     int ret = 0;
     334             :     size_t j;
     335             : 
     336         470 :     for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) {
     337         470 :         const char *q = formats[j].name;
     338         470 :         if (strcasecmp(type, q) == 0) {
     339         282 :             const AlgorithmIdentifier *ai = NULL;
     340         282 :             if (formats[j].ai != NULL)
     341          94 :                 ai = (*formats[j].ai)();
     342             : 
     343         282 :             ret = (*formats[j].func)(context, NULL, pem_ctx->c,
     344             :                                      header, data, len, ai);
     345         282 :             if (ret && (pem_ctx->flags & HX509_CERTS_UNPROTECT_ALL)) {
     346           0 :                 hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
     347             :                                        "Failed parseing PEM format %s", type);
     348           0 :                 return ret;
     349             :             }
     350         258 :             break;
     351             :         }
     352             :     }
     353         282 :     if (j == sizeof(formats)/sizeof(formats[0])) {
     354           0 :         ret = HX509_UNSUPPORTED_OPERATION;
     355           0 :         hx509_set_error_string(context, 0, ret,
     356             :                                "Found no matching PEM format for %s", type);
     357           0 :         return ret;
     358             :     }
     359         258 :     return 0;
     360             : }
     361             : 
     362             : /*
     363             :  *
     364             :  */
     365             : 
     366             : static int
     367         226 : file_init_common(hx509_context context,
     368             :                  hx509_certs certs, void **data, int flags,
     369             :                  const char *residue, hx509_lock lock, outformat format)
     370             : {
     371             :     char *p, *pnext;
     372         226 :     struct ks_file *ksf = NULL;
     373         226 :     hx509_private_key *keys = NULL;
     374             :     int ret;
     375             :     struct pem_ctx pem_ctx;
     376             : 
     377         226 :     pem_ctx.flags = flags;
     378         226 :     pem_ctx.c = NULL;
     379             : 
     380         226 :     *data = NULL;
     381             : 
     382         226 :     if (lock == NULL)
     383         104 :         lock = _hx509_empty_lock;
     384             : 
     385         226 :     ksf = calloc(1, sizeof(*ksf));
     386         226 :     if (ksf == NULL) {
     387           0 :         hx509_clear_error_string(context);
     388           0 :         return ENOMEM;
     389             :     }
     390         226 :     ksf->format = format;
     391             : 
     392         226 :     ksf->fn = strdup(residue);
     393         226 :     if (ksf->fn == NULL) {
     394           0 :         hx509_clear_error_string(context);
     395           0 :         ret = ENOMEM;
     396           0 :         goto out;
     397             :     }
     398             : 
     399             :     /*
     400             :      * XXX this is broken, the function should parse the file before
     401             :      * overwriting it
     402             :      */
     403             : 
     404         226 :     if (flags & HX509_CERTS_CREATE) {
     405           0 :         ret = hx509_certs_init(context, "MEMORY:ks-file-create",
     406             :                                0, lock, &ksf->certs);
     407           0 :         if (ret)
     408           0 :             goto out;
     409           0 :         *data = ksf;
     410           0 :         return 0;
     411             :     }
     412             : 
     413         226 :     ret = _hx509_collector_alloc(context, lock, &pem_ctx.c);
     414         226 :     if (ret)
     415           0 :         goto out;
     416             : 
     417         524 :     for (p = ksf->fn; p != NULL; p = pnext) {
     418             :         FILE *f;
     419             : 
     420         320 :         pnext = strchr(p, ',');
     421         320 :         if (pnext)
     422         132 :             *pnext++ = '\0';
     423             : 
     424             : 
     425         320 :         if ((f = fopen(p, "r")) == NULL) {
     426          38 :             ret = ENOENT;
     427          38 :             hx509_set_error_string(context, 0, ret,
     428             :                                    "Failed to open PEM file \"%s\": %s",
     429          38 :                                    p, strerror(errno));
     430          38 :             goto out;
     431             :         }
     432         282 :         rk_cloexec_file(f);
     433             : 
     434         282 :         ret = hx509_pem_read(context, f, pem_func, &pem_ctx);
     435         282 :         fclose(f);
     436         282 :         if (ret != 0 && ret != HX509_PARSING_KEY_FAILED)
     437             :             goto out;
     438         282 :         else if (ret == HX509_PARSING_KEY_FAILED) {
     439             :             size_t length;
     440             :             void *ptr;
     441             :             size_t i;
     442             : 
     443           0 :             ret = rk_undumpdata(p, &ptr, &length);
     444           0 :             if (ret) {
     445           0 :                 hx509_clear_error_string(context);
     446           0 :                 goto out;
     447             :             }
     448             : 
     449           0 :             for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
     450           0 :                 const AlgorithmIdentifier *ai = NULL;
     451           0 :                 if (formats[i].ai != NULL)
     452           0 :                     ai = (*formats[i].ai)();
     453             : 
     454           0 :                 ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length, ai);
     455           0 :                 if (ret == 0)
     456           0 :                     break;
     457             :             }
     458           0 :             rk_xfree(ptr);
     459           0 :             if (ret) {
     460           0 :                 hx509_clear_error_string(context);
     461           0 :                 goto out;
     462             :             }
     463             :         }
     464             :     }
     465             : 
     466         188 :     ret = _hx509_collector_collect_certs(context, pem_ctx.c, &ksf->certs);
     467         188 :     if (ret)
     468           0 :         goto out;
     469             : 
     470         188 :     ret = _hx509_collector_collect_private_keys(context, pem_ctx.c, &keys);
     471         188 :     if (ret == 0) {
     472             :         int i;
     473             : 
     474         266 :         for (i = 0; keys[i]; i++)
     475          94 :             _hx509_certs_keys_add(context, ksf->certs, keys[i]);
     476         188 :         _hx509_certs_keys_free(context, keys);
     477             :     }
     478             : 
     479         226 : out:
     480         226 :     if (ret == 0)
     481         188 :         *data = ksf;
     482             :     else {
     483          38 :         if (ksf->fn)
     484          38 :             free(ksf->fn);
     485          38 :         free(ksf);
     486             :     }
     487         226 :     if (pem_ctx.c)
     488         226 :         _hx509_collector_free(pem_ctx.c);
     489             : 
     490         210 :     return ret;
     491             : }
     492             : 
     493             : static int
     494         226 : file_init_pem(hx509_context context,
     495             :               hx509_certs certs, void **data, int flags,
     496             :               const char *residue, hx509_lock lock)
     497             : {
     498         226 :     return file_init_common(context, certs, data, flags, residue, lock, USE_PEM);
     499             : }
     500             : 
     501             : static int
     502           0 : file_init_der(hx509_context context,
     503             :               hx509_certs certs, void **data, int flags,
     504             :               const char *residue, hx509_lock lock)
     505             : {
     506           0 :     return file_init_common(context, certs, data, flags, residue, lock, USE_DER);
     507             : }
     508             : 
     509             : static int
     510          80 : file_free(hx509_certs certs, void *data)
     511             : {
     512          80 :     struct ks_file *ksf = data;
     513          80 :     hx509_certs_free(&ksf->certs);
     514          80 :     free(ksf->fn);
     515          80 :     free(ksf);
     516          80 :     return 0;
     517             : }
     518             : 
     519             : struct store_ctx {
     520             :     FILE *f;
     521             :     outformat format;
     522             : };
     523             : 
     524             : static int
     525           0 : store_func(hx509_context context, void *ctx, hx509_cert c)
     526             : {
     527           0 :     struct store_ctx *sc = ctx;
     528             :     heim_octet_string data;
     529             :     int ret;
     530             : 
     531           0 :     ret = hx509_cert_binary(context, c, &data);
     532           0 :     if (ret)
     533           0 :         return ret;
     534             : 
     535           0 :     switch (sc->format) {
     536           0 :     case USE_DER:
     537           0 :         fwrite(data.data, data.length, 1, sc->f);
     538           0 :         free(data.data);
     539           0 :         break;
     540           0 :     case USE_PEM:
     541           0 :         hx509_pem_write(context, "CERTIFICATE", NULL, sc->f,
     542           0 :                         data.data, data.length);
     543           0 :         free(data.data);
     544           0 :         if (_hx509_cert_private_key_exportable(c)) {
     545           0 :             hx509_private_key key = _hx509_cert_private_key(c);
     546           0 :             ret = _hx509_private_key_export(context, key,
     547             :                                             HX509_KEY_FORMAT_DER, &data);
     548           0 :             if (ret)
     549           0 :                 break;
     550           0 :             hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f,
     551           0 :                             data.data, data.length);
     552           0 :             free(data.data);
     553             :         }
     554           0 :         break;
     555             :     }
     556             : 
     557           0 :     return 0;
     558             : }
     559             : 
     560             : static int
     561           0 : file_store(hx509_context context,
     562             :            hx509_certs certs, void *data, int flags, hx509_lock lock)
     563             : {
     564           0 :     struct ks_file *ksf = data;
     565             :     struct store_ctx sc;
     566             :     int ret;
     567             : 
     568           0 :     sc.f = fopen(ksf->fn, "w");
     569           0 :     if (sc.f == NULL) {
     570           0 :         hx509_set_error_string(context, 0, ENOENT,
     571             :                                "Failed to open file %s for writing");
     572           0 :         return ENOENT;
     573             :     }
     574           0 :     rk_cloexec_file(sc.f);
     575           0 :     sc.format = ksf->format;
     576             : 
     577           0 :     ret = hx509_certs_iter_f(context, ksf->certs, store_func, &sc);
     578           0 :     fclose(sc.f);
     579           0 :     return ret;
     580             : }
     581             : 
     582             : static int
     583           0 : file_add(hx509_context context, hx509_certs certs, void *data, hx509_cert c)
     584             : {
     585           0 :     struct ks_file *ksf = data;
     586           0 :     return hx509_certs_add(context, ksf->certs, c);
     587             : }
     588             : 
     589             : static int
     590         366 : file_iter_start(hx509_context context,
     591             :                 hx509_certs certs, void *data, void **cursor)
     592             : {
     593         366 :     struct ks_file *ksf = data;
     594         366 :     return hx509_certs_start_seq(context, ksf->certs, cursor);
     595             : }
     596             : 
     597             : static int
     598         570 : file_iter(hx509_context context,
     599             :           hx509_certs certs, void *data, void *iter, hx509_cert *cert)
     600             : {
     601         570 :     struct ks_file *ksf = data;
     602         570 :     return hx509_certs_next_cert(context, ksf->certs, iter, cert);
     603             : }
     604             : 
     605             : static int
     606         366 : file_iter_end(hx509_context context,
     607             :               hx509_certs certs,
     608             :               void *data,
     609             :               void *cursor)
     610             : {
     611         366 :     struct ks_file *ksf = data;
     612         366 :     return hx509_certs_end_seq(context, ksf->certs, cursor);
     613             : }
     614             : 
     615             : static int
     616           0 : file_getkeys(hx509_context context,
     617             :              hx509_certs certs,
     618             :              void *data,
     619             :              hx509_private_key **keys)
     620             : {
     621           0 :     struct ks_file *ksf = data;
     622           0 :     return _hx509_certs_keys_get(context, ksf->certs, keys);
     623             : }
     624             : 
     625             : static int
     626           0 : file_addkey(hx509_context context,
     627             :              hx509_certs certs,
     628             :              void *data,
     629             :              hx509_private_key key)
     630             : {
     631           0 :     struct ks_file *ksf = data;
     632           0 :     return _hx509_certs_keys_add(context, ksf->certs, key);
     633             : }
     634             : 
     635             : static struct hx509_keyset_ops keyset_file = {
     636             :     "FILE",
     637             :     0,
     638             :     file_init_pem,
     639             :     file_store,
     640             :     file_free,
     641             :     file_add,
     642             :     NULL,
     643             :     file_iter_start,
     644             :     file_iter,
     645             :     file_iter_end,
     646             :     NULL,
     647             :     file_getkeys,
     648             :     file_addkey
     649             : };
     650             : 
     651             : static struct hx509_keyset_ops keyset_pemfile = {
     652             :     "PEM-FILE",
     653             :     0,
     654             :     file_init_pem,
     655             :     file_store,
     656             :     file_free,
     657             :     file_add,
     658             :     NULL,
     659             :     file_iter_start,
     660             :     file_iter,
     661             :     file_iter_end,
     662             :     NULL,
     663             :     file_getkeys,
     664             :     file_addkey
     665             : };
     666             : 
     667             : static struct hx509_keyset_ops keyset_derfile = {
     668             :     "DER-FILE",
     669             :     0,
     670             :     file_init_der,
     671             :     file_store,
     672             :     file_free,
     673             :     file_add,
     674             :     NULL,
     675             :     file_iter_start,
     676             :     file_iter,
     677             :     file_iter_end,
     678             :     NULL,
     679             :     file_getkeys,
     680             :     file_addkey
     681             : };
     682             : 
     683             : 
     684             : void
     685      908739 : _hx509_ks_file_register(hx509_context context)
     686             : {
     687      908739 :     _hx509_ks_register(context, &keyset_file);
     688      908739 :     _hx509_ks_register(context, &keyset_pemfile);
     689      908739 :     _hx509_ks_register(context, &keyset_derfile);
     690      908739 : }

Generated by: LCOV version 1.13