LCOV - code coverage report
Current view: top level - src - vcard_emul_nss.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 400 523 76.5 %
Date: 2022-06-17 11:31:56 Functions: 30 33 90.9 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 178 326 54.6 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * This is the actual card emulator.
       3                 :            :  *
       4                 :            :  * These functions can be implemented in different ways on different platforms
       5                 :            :  * using the underlying system primitives. For Linux it uses NSS, though direct
       6                 :            :  * to PKCS #11, openssl+pkcs11, or even gnu crypto libraries+pkcs #11 could be
       7                 :            :  * used. On Windows CAPI could be used.
       8                 :            :  *
       9                 :            :  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
      10                 :            :  * See the COPYING file in the top-level directory.
      11                 :            :  */
      12                 :            : #include "config.h"
      13                 :            : 
      14                 :            : #include <glib.h>
      15                 :            : 
      16                 :            : #include "common.h"
      17                 :            : 
      18                 :            : /*
      19                 :            :  * NSS headers
      20                 :            :  */
      21                 :            : 
      22                 :            : /* avoid including prototypes.h that redefines uint32 */
      23                 :            : #define NO_NSPR_10_SUPPORT
      24                 :            : 
      25                 :            : #include <nss.h>
      26                 :            : #include <pk11pub.h>
      27                 :            : #include <cert.h>
      28                 :            : #include <keyhi.h>
      29                 :            : #include <secmod.h>
      30                 :            : #include <prthread.h>
      31                 :            : #include <secerr.h>
      32                 :            : #include <secoid.h>
      33                 :            : #include <secmodt.h>
      34                 :            : #include <sechash.h>
      35                 :            : 
      36                 :            : #include "vcard.h"
      37                 :            : #include "card_7816t.h"
      38                 :            : #include "vcard_emul.h"
      39                 :            : #include "vreader.h"
      40                 :            : #include "vevent.h"
      41                 :            : 
      42                 :            : #include "vcardt_internal.h"
      43                 :            : #if defined(ENABLE_PCSC)
      44                 :            : #include "capcsc.h"
      45                 :            : #endif
      46                 :            : 
      47                 :            : 
      48                 :            : typedef enum {
      49                 :            :     VCardEmulUnknown = -1,
      50                 :            :     VCardEmulFalse = 0,
      51                 :            :     VCardEmulTrue = 1
      52                 :            : } VCardEmulTriState;
      53                 :            : 
      54                 :            : struct VCardKeyStruct {
      55                 :            :     CERTCertificate *cert;
      56                 :            :     PK11SlotInfo *slot;
      57                 :            :     VCardEmulTriState failedX509;
      58                 :            : };
      59                 :            : 
      60                 :            : 
      61                 :            : typedef struct VirtualReaderOptionsStruct VirtualReaderOptions;
      62                 :            : 
      63                 :            : struct VReaderEmulStruct {
      64                 :            :     PK11SlotInfo *slot;
      65                 :            :     VCardEmulType default_type;
      66                 :            :     char *type_params;
      67                 :            :     PRBool present;
      68                 :            :     int     series;
      69                 :            :     VCard *saved_vcard;
      70                 :            : };
      71                 :            : 
      72                 :            : /*
      73                 :            :  *  NSS Specific options
      74                 :            :  */
      75                 :            : struct VirtualReaderOptionsStruct {
      76                 :            :     char *name;
      77                 :            :     char *vname;
      78                 :            :     VCardEmulType card_type;
      79                 :            :     char *type_params;
      80                 :            :     char **cert_name;
      81                 :            :     int cert_count;
      82                 :            : };
      83                 :            : 
      84                 :            : enum {
      85                 :            :     USE_HW_NO,
      86                 :            :     USE_HW_YES,
      87                 :            :     USE_HW_REMOVABLE,
      88                 :            : };
      89                 :            : 
      90                 :            : struct VCardEmulOptionsStruct {
      91                 :            :     char *nss_db;
      92                 :            :     VirtualReaderOptions *vreader;
      93                 :            :     int vreader_count;
      94                 :            :     VCardEmulType hw_card_type;
      95                 :            :     char *hw_type_params;
      96                 :            :     int use_hw;
      97                 :            : };
      98                 :            : 
      99                 :            : static int nss_emul_init;
     100                 :            : 
     101                 :            : /* if we have more that just the slot, define
     102                 :            :  * VCardEmulStruct here */
     103                 :            : 
     104                 :            : /*
     105                 :            :  * allocate the set of arrays for certs, cert_len, key
     106                 :            :  */
     107                 :            : static void
     108                 :          5 : vcard_emul_alloc_arrays(unsigned char ***certsp, int **cert_lenp,
     109                 :            :                         VCardKey ***keysp, int cert_count)
     110                 :            : {
     111   [ -  +  -  - ]:          5 :     *certsp = g_new(unsigned char *, cert_count);
     112   [ -  +  -  - ]:          5 :     *cert_lenp = g_new(int, cert_count);
     113   [ -  +  -  - ]:          5 :     *keysp = g_new(VCardKey *, cert_count);
     114                 :          5 : }
     115                 :            : 
     116                 :            : /*
     117                 :            :  * Emulator specific card information
     118                 :            :  */
     119                 :            : typedef struct CardEmulCardStruct CardEmulPrivate;
     120                 :            : 
     121                 :            : static VCardEmul *
     122                 :            : vcard_emul_new_card(PK11SlotInfo *slot)
     123                 :            : {
     124                 :          5 :     PK11_ReferenceSlot(slot);
     125                 :            :     /* currently we don't need anything other than the slot */
     126                 :            :     return (VCardEmul *)slot;
     127                 :            : }
     128                 :            : 
     129                 :            : static void
     130                 :          4 : vcard_emul_delete_card(VCardEmul *vcard_emul)
     131                 :            : {
     132                 :            :     PK11SlotInfo *slot = (PK11SlotInfo *)vcard_emul;
     133         [ +  - ]:          4 :     if (slot == NULL) {
     134                 :            :         return;
     135                 :            :     }
     136                 :          4 :     PK11_FreeSlot(slot);
     137                 :            : }
     138                 :            : 
     139                 :            : static PK11SlotInfo *
     140                 :            : vcard_emul_card_get_slot(VCard *card)
     141                 :            : {
     142                 :            :     /* note, the card is holding the reference, no need to get another one */
     143                 :         99 :     return (PK11SlotInfo *)vcard_get_private(card);
     144                 :            : }
     145                 :            : 
     146                 :            : 
     147                 :            : /*
     148                 :            :  * key functions
     149                 :            :  */
     150                 :            : /* private constructure */
     151                 :            : static VCardKey *
     152                 :         11 : vcard_emul_make_key(PK11SlotInfo *slot, CERTCertificate *cert)
     153                 :            : {
     154                 :            :     VCardKey *key;
     155                 :            : 
     156                 :         11 :     key = g_new(VCardKey, 1);
     157                 :         11 :     key->slot = PK11_ReferenceSlot(slot);
     158                 :         11 :     key->cert = CERT_DupCertificate(cert);
     159                 :         11 :     key->failedX509 = VCardEmulUnknown;
     160                 :         11 :     return key;
     161                 :            : }
     162                 :            : 
     163                 :            : /* destructor */
     164                 :            : void
     165                 :          8 : vcard_emul_delete_key(VCardKey *key)
     166                 :            : {
     167   [ +  -  +  - ]:          8 :     if (!nss_emul_init || (key == NULL)) {
     168                 :            :         return;
     169                 :            :     }
     170         [ +  - ]:          8 :     if (key->cert) {
     171                 :          8 :         CERT_DestroyCertificate(key->cert);
     172                 :            :     }
     173         [ +  - ]:          8 :     if (key->slot) {
     174                 :          8 :         PK11_FreeSlot(key->slot);
     175                 :            :     }
     176                 :          8 :     g_free(key);
     177                 :            : }
     178                 :            : 
     179                 :            : /*
     180                 :            :  * grab the nss key from a VCardKey. If it doesn't exist, try to look it up
     181                 :            :  */
     182                 :            : static SECKEYPrivateKey *
     183                 :            : vcard_emul_get_nss_key(VCardKey *key)
     184                 :            : {
     185                 :            :     /* NOTE: if we aren't logged into the token, this could return NULL */
     186                 :         19 :     return PK11_FindPrivateKeyFromCert(key->slot, key->cert, NULL);
     187                 :            : }
     188                 :            : 
     189                 :            : /*
     190                 :            :  * Map NSS errors to 7816 errors
     191                 :            :  */
     192                 :            : static vcard_7816_status_t
     193                 :          1 : vcard_emul_map_error(int error)
     194                 :            : {
     195   [ +  -  -  - ]:          1 :     switch (error) {
     196                 :            :     case SEC_ERROR_TOKEN_NOT_LOGGED_IN:
     197                 :            :         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
     198                 :          1 :     case SEC_ERROR_BAD_DATA:
     199                 :            :     case SEC_ERROR_OUTPUT_LEN:
     200                 :            :     case SEC_ERROR_INPUT_LEN:
     201                 :            :     case SEC_ERROR_INVALID_ARGS:
     202                 :            :     case SEC_ERROR_INVALID_ALGORITHM:
     203                 :            :     case SEC_ERROR_NO_KEY:
     204                 :            :     case SEC_ERROR_INVALID_KEY:
     205                 :            :     case SEC_ERROR_DECRYPTION_DISALLOWED:
     206                 :            :     case SEC_ERROR_PKCS11_GENERAL_ERROR:
     207                 :          1 :         return VCARD7816_STATUS_ERROR_DATA_INVALID;
     208                 :          0 :     case SEC_ERROR_NO_MEMORY:
     209                 :          0 :         return VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
     210                 :          0 :     default:
     211                 :          0 :         g_debug("error %x", 0x2000 + error);
     212                 :          0 :         g_warn_if_reached();
     213                 :            :     }
     214                 :          0 :     return VCARD7816_STATUS_EXC_ERROR_CHANGE;
     215                 :            : }
     216                 :            : 
     217                 :            : /* get RSA bits */
     218                 :            : int
     219                 :         11 : vcard_emul_rsa_bits(VCardKey *key)
     220                 :            : {
     221                 :            :     SECKEYPublicKey *pub_key;
     222                 :            :     int bits = -1;
     223                 :            : 
     224         [ -  + ]:         11 :     if (key == NULL) {
     225                 :            :         /* couldn't get the key, indicate that we aren't logged in */
     226                 :            :         return -1;
     227                 :            :     }
     228                 :         11 :     pub_key = CERT_ExtractPublicKey(key->cert);
     229         [ -  + ]:         11 :     if (pub_key == NULL) {
     230                 :            :         /* couldn't get the key, indicate that we aren't logged in */
     231                 :            :         return -1;
     232                 :            :     }
     233                 :            : 
     234                 :         11 :     bits = SECKEY_PublicKeyStrengthInBits(pub_key);
     235                 :         11 :     SECKEY_DestroyPublicKey(pub_key);
     236                 :         11 :     return bits;
     237                 :            : }
     238                 :            : 
     239                 :            : /* RSA sign/decrypt with the key, signature happens 'in place' */
     240                 :            : vcard_7816_status_t
     241                 :         19 : vcard_emul_rsa_op(VCard *card, VCardKey *key,
     242                 :            :                   unsigned char *buffer, int buffer_size)
     243                 :            : {
     244                 :            :     SECKEYPrivateKey *priv_key;
     245                 :            :     unsigned signature_len;
     246                 :            :     PK11SlotInfo *slot;
     247                 :            :     SECStatus rv;
     248                 :            :     unsigned char buf[2048];
     249                 :            :     unsigned char *bp = NULL;
     250                 :            :     int pad_len;
     251                 :            :     vcard_7816_status_t ret = VCARD7816_STATUS_SUCCESS;
     252                 :            : 
     253         [ -  + ]:         19 :     assert(buffer_size >= 0);
     254   [ +  -  -  + ]:         19 :     if ((!nss_emul_init) || (key == NULL)) {
     255                 :            :         /* couldn't get the key, indicate that we aren't logged in */
     256                 :            :         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
     257                 :            :     }
     258                 :            :     priv_key = vcard_emul_get_nss_key(key);
     259         [ -  + ]:         19 :     if (priv_key == NULL) {
     260                 :            :         /* couldn't get the key, indicate that we aren't logged in */
     261                 :            :         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
     262                 :            :     }
     263                 :            :     slot = vcard_emul_card_get_slot(card);
     264                 :            : 
     265                 :            :     /*
     266                 :            :      * this is only true of the rsa signature
     267                 :            :      */
     268                 :         19 :     signature_len = PK11_SignatureLen(priv_key);
     269         [ -  + ]:         19 :     if ((unsigned)buffer_size != signature_len) {
     270                 :            :         ret = VCARD7816_STATUS_ERROR_DATA_INVALID;
     271                 :          0 :         goto cleanup;
     272                 :            :     }
     273                 :            :     /* be able to handle larger keys if necessary */
     274                 :            :     bp = &buf[0];
     275         [ -  + ]:         19 :     if (sizeof(buf) < signature_len) {
     276                 :          0 :         bp = g_malloc(signature_len);
     277                 :            :     }
     278                 :            : 
     279                 :            :     /*
     280                 :            :      * do the raw operations. Some tokens claim to do CKM_RSA_X_509, but then
     281                 :            :      * choke when they try to do the actual operations. Try to detect
     282                 :            :      * those cases and treat them as if the token didn't claim support for
     283                 :            :      * X_509.
     284                 :            :      */
     285         [ +  + ]:         19 :     if (key->failedX509 != VCardEmulTrue
     286         [ +  + ]:         12 :                               && PK11_DoesMechanism(slot, CKM_RSA_X_509)) {
     287                 :         11 :         rv = PK11_PrivDecryptRaw(priv_key, bp, &signature_len, signature_len,
     288                 :            :                                  buffer, buffer_size);
     289         [ +  - ]:         11 :         if (rv == SECSuccess) {
     290         [ -  + ]:         11 :             assert((unsigned)buffer_size == signature_len);
     291                 :         11 :             memcpy(buffer, bp, signature_len);
     292                 :         11 :             key->failedX509 = VCardEmulFalse;
     293                 :         11 :             goto cleanup;
     294                 :            :         }
     295                 :            :         /*
     296                 :            :          * we've had a successful X509 operation, this failure must be
     297                 :            :          * something else
     298                 :            :          */
     299         [ #  # ]:          0 :         if (key->failedX509 == VCardEmulFalse) {
     300                 :          0 :             ret = vcard_emul_map_error(PORT_GetError());
     301                 :          0 :             goto cleanup;
     302                 :            :         }
     303                 :            :         /*
     304                 :            :          * key->failedX509 must be Unknown at this point, try the
     305                 :            :          * non-x_509 case
     306                 :            :          */
     307                 :            :     }
     308                 :            :     /* token does not support CKM_RSA_X509, emulate that with CKM_RSA_PKCS */
     309                 :            :     /* is this a PKCS #1 formatted signature? */
     310   [ +  +  +  + ]:          8 :     if ((buffer[0] == 0) && (buffer[1] == 1)) {
     311                 :            :         int i;
     312                 :            : 
     313         [ +  - ]:        576 :         for (i = 2; i < buffer_size; i++) {
     314                 :            :             /* rsa signature pad */
     315         [ +  + ]:        576 :             if (buffer[i] != 0xff) {
     316                 :            :                 break;
     317                 :            :             }
     318                 :            :         }
     319   [ +  -  +  - ]:          6 :         if ((i < buffer_size) && (buffer[i] == 0)) {
     320                 :            :             /* yes, we have a properly formatted PKCS #1 signature */
     321                 :            :             /*
     322                 :            :              * NOTE: even if we accidentally got an encrypt buffer, which
     323                 :            :              * through sheer luck started with 00, 01, ff, 00, it won't matter
     324                 :            :              * because the resulting Sign operation will effectively decrypt
     325                 :            :              * the real buffer.
     326                 :            :              */
     327                 :            :             SECItem signature;
     328                 :            :             SECItem hash;
     329                 :            : 
     330                 :          6 :             i++;
     331                 :          6 :             hash.data = &buffer[i];
     332                 :          6 :             hash.len = buffer_size - i;
     333                 :          6 :             signature.data = bp;
     334                 :          6 :             signature.len = signature_len;
     335                 :          6 :             rv = PK11_Sign(priv_key,  &signature, &hash);
     336         [ -  + ]:          6 :             if (rv != SECSuccess) {
     337                 :          0 :                 ret = vcard_emul_map_error(PORT_GetError());
     338                 :          0 :                 goto cleanup;
     339                 :            :             }
     340         [ -  + ]:          6 :             assert((unsigned)buffer_size == signature.len);
     341                 :          6 :             memcpy(buffer, bp, signature.len);
     342                 :            :             /*
     343                 :            :              * we got here because either the X509 attempt failed, or the
     344                 :            :              * token couldn't do the X509 operation, in either case stay
     345                 :            :              * with the PKCS version for future operations on this key
     346                 :            :              */
     347                 :          6 :             key->failedX509 = VCardEmulTrue;
     348                 :          6 :             goto cleanup;
     349                 :            :         }
     350                 :            :     }
     351                 :            :     /* We can not do raw RSA operation and the bytes do not look like PKCS#1.5
     352                 :            :      * Assuming it is deciphering operation.
     353                 :            :      */
     354                 :          2 :     rv = PK11_PrivDecryptPKCS1(priv_key, bp, &signature_len, buffer_size, buffer, buffer_size);
     355         [ +  + ]:          2 :     if (rv != SECSuccess) {
     356                 :            :         /* The assumption was wrong. Give up */
     357                 :          1 :         ret = vcard_emul_map_error(PORT_GetError());
     358                 :          1 :         goto cleanup;
     359                 :            :     }
     360                 :          1 :     pad_len = buffer_size - signature_len;
     361         [ -  + ]:          1 :     if (pad_len < 4) {
     362                 :            :         ret = VCARD7816_STATUS_ERROR_GENERAL;
     363                 :          0 :         goto cleanup;
     364                 :            :     }
     365                 :            :     /*
     366                 :            :      * OK now we've decrypted the payload, package it up in PKCS #1 for the
     367                 :            :      * upper layer.
     368                 :            :      */
     369                 :          1 :     buffer[0] = 0;
     370                 :          1 :     buffer[1] = 2; /* RSA_encrypt  */
     371                 :          1 :     pad_len -= 3; /* format is 0 || 2 || pad || 0 || data */
     372                 :            :     /*
     373                 :            :      * padding for PKCS #1 encrypted data is a string of random bytes. The
     374                 :            :      * random bytes protect against potential decryption attacks against RSA.
     375                 :            :      * Since PrivDecrypt has already stripped those bytes, we can't reconstruct
     376                 :            :      * them. This shouldn't matter to the upper level code which should just
     377                 :            :      * strip this code out anyway, so We'll pad with a constant 3.
     378                 :            :      */
     379                 :          1 :     memset(&buffer[2], 0x03, pad_len);
     380                 :          1 :     pad_len += 2; /* index to the end of the pad */
     381                 :          1 :     buffer[pad_len] = 0;
     382                 :            :     pad_len++; /* index to the start of the data */
     383                 :          1 :     memcpy(&buffer[pad_len], bp, signature_len);
     384                 :            :     /*
     385                 :            :      * we got here because either the X509 attempt failed, or the
     386                 :            :      * token couldn't do the X509 operation, in either case stay
     387                 :            :      * with the PKCS version for future operations on this key
     388                 :            :      */
     389                 :          1 :     key->failedX509 = VCardEmulTrue;
     390                 :         19 : cleanup:
     391         [ -  + ]:         19 :     if (bp != buf) {
     392                 :          0 :         g_free(bp);
     393                 :            :     }
     394                 :         19 :     SECKEY_DestroyPrivateKey(priv_key);
     395                 :         19 :     return ret;
     396                 :            : }
     397                 :            : 
     398                 :            : /*
     399                 :            :  * Login functions
     400                 :            :  */
     401                 :            : /* return the number of login attempts still possible on the card. if unknown,
     402                 :            :  * return -1 */
     403                 :            : int
     404                 :          4 : vcard_emul_get_login_count(G_GNUC_UNUSED VCard *card)
     405                 :            : {
     406                 :          4 :     return -1;
     407                 :            : }
     408                 :            : 
     409                 :            : /* login into the card, return the 7816 status word (sw2 || sw1) */
     410                 :            : vcard_7816_status_t
     411                 :         20 : vcard_emul_login(VCard *card, unsigned char *pin, int pin_len)
     412                 :            : {
     413                 :            :     PK11SlotInfo *slot;
     414                 :            :     unsigned char *pin_string;
     415                 :            :     int i;
     416                 :            :     SECStatus rv;
     417                 :            : 
     418         [ -  + ]:         20 :     if (!nss_emul_init) {
     419                 :            :         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
     420                 :            :     }
     421                 :            :     slot = vcard_emul_card_get_slot(card);
     422                 :            :      /* We depend on the PKCS #11 module internal login state here because we
     423                 :            :       * create a separate process to handle each guest instance. If we needed
     424                 :            :       * to handle multiple guests from one process, then we would need to keep
     425                 :            :       * a lot of extra state in our card structure
     426                 :            :       * */
     427                 :         20 :     pin_string = g_malloc(pin_len+1);
     428                 :         20 :     memcpy(pin_string, pin, pin_len);
     429                 :         20 :     pin_string[pin_len] = 0;
     430                 :            : 
     431                 :            :     /* handle CAC expanded pins correctly */
     432   [ +  +  +  + ]:         44 :     for (i = pin_len-1; i >= 0 && (pin_string[i] == 0xff); i--) {
     433                 :         24 :         pin_string[i] = 0;
     434                 :            :     }
     435                 :            : 
     436                 :            :     /* If using an emulated card, make sure to log out of any already logged in
     437                 :            :      * session. */
     438                 :         20 :     vcard_emul_logout(card);
     439                 :            : 
     440                 :         20 :     rv = PK11_Authenticate(slot, PR_FALSE, pin_string);
     441                 :         20 :     memset(pin_string, 0, pin_len);  /* don't let the pin hang around in memory
     442                 :            :                                         to be snooped */
     443                 :         20 :     g_free(pin_string);
     444         [ -  + ]:         20 :     if (rv == SECSuccess) {
     445                 :            :         return VCARD7816_STATUS_SUCCESS;
     446                 :            :     }
     447                 :            :     /* map the error from port get error */
     448                 :            :     return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
     449                 :            : }
     450                 :            : 
     451                 :            : int
     452                 :         26 : vcard_emul_is_logged_in(VCard *card)
     453                 :            : {
     454                 :            :     PK11SlotInfo *slot;
     455                 :            : 
     456         [ +  - ]:         26 :     if (!nss_emul_init) {
     457                 :            :         return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
     458                 :            :     }
     459                 :            : 
     460                 :            :     slot = vcard_emul_card_get_slot(card);
     461                 :            :      /* We depend on the PKCS #11 module internal login state here because we
     462                 :            :       * create a separate process to handle each guest instance. If we needed
     463                 :            :       * to handle multiple guests from one process, then we would need to keep
     464                 :            :       * a lot of extra state in our card structure
     465                 :            :       */
     466                 :            : 
     467                 :            :     /* If we do not need log in, we present the token as "logged in" */
     468         [ +  + ]:         26 :     if (PK11_NeedLogin(slot) == PR_FALSE) {
     469                 :            :         return 1;
     470                 :            :     }
     471                 :            : 
     472                 :            :     /* For the tokens that require login, delegate to NSS to figure out the
     473                 :            :      * login status */
     474                 :         20 :     return !!PK11_IsLoggedIn(slot, NULL);
     475                 :            : }
     476                 :            : 
     477                 :            : void
     478                 :         34 : vcard_emul_logout(VCard *card)
     479                 :            : {
     480                 :            :     PK11SlotInfo *slot;
     481                 :            : 
     482         [ +  - ]:         34 :     if (!nss_emul_init) {
     483                 :            :         return;
     484                 :            :     }
     485                 :            : 
     486                 :            :     slot = vcard_emul_card_get_slot(card);
     487         [ +  + ]:         34 :     if (PK11_IsLoggedIn(slot, NULL)) {
     488                 :         14 :         PK11_Logout(slot); /* NOTE: ignoring SECStatus return value */
     489                 :            :     }
     490                 :            : }
     491                 :            : 
     492                 :            : void
     493                 :         14 : vcard_emul_reset(VCard *card, G_GNUC_UNUSED VCardPower power)
     494                 :            : {
     495                 :            :     /*
     496                 :            :      * if we reset the card (either power on or power off), we lose our login
     497                 :            :      * state
     498                 :            :      */
     499                 :         14 :     vcard_emul_logout(card);
     500                 :            : 
     501                 :            :     /* TODO: we may also need to send insertion/removal events? */
     502                 :         14 : }
     503                 :            : 
     504                 :            : static VReader *
     505                 :          4 : vcard_emul_find_vreader_from_slot(PK11SlotInfo *slot)
     506                 :            : {
     507                 :          4 :     VReaderList *reader_list = vreader_get_reader_list();
     508                 :            :     VReaderListEntry *current_entry;
     509                 :            : 
     510         [ -  + ]:          4 :     if (reader_list == NULL) {
     511                 :            :         return NULL;
     512                 :            :     }
     513         [ +  - ]:          6 :     for (current_entry = vreader_list_get_first(reader_list); current_entry;
     514                 :          2 :                         current_entry = vreader_list_get_next(current_entry)) {
     515                 :          6 :         VReader *reader = vreader_list_get_reader(current_entry);
     516                 :          6 :         VReaderEmul *reader_emul = vreader_get_private(reader);
     517         [ +  + ]:          6 :         if (reader_emul->slot == slot) {
     518                 :          4 :             vreader_list_delete(reader_list);
     519                 :          4 :             return reader;
     520                 :            :         }
     521                 :          2 :         vreader_free(reader);
     522                 :            :     }
     523                 :            : 
     524                 :          0 :     vreader_list_delete(reader_list);
     525                 :          0 :     return NULL;
     526                 :            : }
     527                 :            : 
     528                 :            : /*
     529                 :            :  * create a new reader emul
     530                 :            :  */
     531                 :            : static VReaderEmul *
     532                 :          7 : vreader_emul_new(PK11SlotInfo *slot, VCardEmulType type, const char *params)
     533                 :            : {
     534                 :            :     VReaderEmul *new_reader_emul;
     535                 :            : 
     536                 :          7 :     new_reader_emul = g_new(VReaderEmul, 1);
     537                 :            : 
     538                 :          7 :     new_reader_emul->slot = PK11_ReferenceSlot(slot);
     539                 :          7 :     new_reader_emul->default_type = type;
     540                 :          7 :     new_reader_emul->type_params = g_strdup(params);
     541                 :          7 :     new_reader_emul->present = PR_FALSE;
     542                 :          7 :     new_reader_emul->series = 0;
     543                 :          7 :     new_reader_emul->saved_vcard = NULL;
     544                 :          7 :     return new_reader_emul;
     545                 :            : }
     546                 :            : 
     547                 :            : static void
     548                 :          4 : vreader_emul_delete(VReaderEmul *vreader_emul)
     549                 :            : {
     550         [ +  - ]:          4 :     if (vreader_emul == NULL) {
     551                 :            :         return;
     552                 :            :     }
     553                 :          4 :     vcard_free(vreader_emul->saved_vcard);
     554         [ +  - ]:          4 :     if (vreader_emul->slot) {
     555                 :          4 :         PK11_FreeSlot(vreader_emul->slot);
     556                 :            :     }
     557                 :          4 :     g_free(vreader_emul->type_params);
     558                 :          4 :     g_free(vreader_emul);
     559                 :            : }
     560                 :            : 
     561                 :            : /*
     562                 :            :  *  TODO: move this to emulater non-specific file
     563                 :            :  */
     564                 :            : static VCardEmulType
     565                 :          5 : vcard_emul_get_type(VReader *vreader)
     566                 :            : {
     567                 :            :     VReaderEmul *vreader_emul;
     568                 :            : 
     569                 :          5 :     vreader_emul = vreader_get_private(vreader);
     570   [ +  -  -  + ]:          5 :     if (vreader_emul && vreader_emul->default_type != VCARD_EMUL_NONE) {
     571                 :            :         return vreader_emul->default_type;
     572                 :            :     }
     573                 :            : 
     574                 :          0 :     return vcard_emul_type_select(vreader);
     575                 :            : }
     576                 :            : /*
     577                 :            :  *  TODO: move this to emulater non-specific file
     578                 :            :  */
     579                 :            : static const char *
     580                 :            : vcard_emul_get_type_params(VReader *vreader)
     581                 :            : {
     582                 :            :     VReaderEmul *vreader_emul;
     583                 :            : 
     584                 :          5 :     vreader_emul = vreader_get_private(vreader);
     585   [ -  +  +  + ]:          5 :     if (vreader_emul && vreader_emul->type_params) {
     586                 :            :         return vreader_emul->type_params;
     587                 :            :     }
     588                 :            : 
     589                 :            :     return "";
     590                 :            : }
     591                 :            : 
     592                 :            : /* pull the slot out of the reader private data */
     593                 :            : static PK11SlotInfo *
     594                 :            : vcard_emul_reader_get_slot(VReader *vreader)
     595                 :            : {
     596                 :          9 :     VReaderEmul *vreader_emul = vreader_get_private(vreader);
     597   [ +  -  -  + ]:          9 :     if (vreader_emul == NULL) {
     598                 :            :         return NULL;
     599                 :            :     }
     600                 :          9 :     return vreader_emul->slot;
     601                 :            : }
     602                 :            : 
     603                 :            : /*
     604                 :            :  *  Card ATR's map to physical cards. vcard_alloc_atr will set appropriate
     605                 :            :  *  historical bytes for any software emulated card. The remaining bytes can be
     606                 :            :  *  used to indicate the actual emulator
     607                 :            :  */
     608                 :            : static unsigned char *nss_atr;
     609                 :            : static int nss_atr_len;
     610                 :            : 
     611                 :            : void
     612                 :          0 : vcard_emul_get_atr(G_GNUC_UNUSED VCard *card, unsigned char *atr, int *atr_len)
     613                 :            : {
     614                 :            :     int len;
     615         [ #  # ]:          0 :     assert(atr != NULL);
     616                 :            : 
     617         [ #  # ]:          0 :     if (nss_atr == NULL) {
     618                 :          0 :         nss_atr = vcard_alloc_atr("NSS", &nss_atr_len);
     619                 :            :     }
     620                 :          0 :     len = MIN(nss_atr_len, *atr_len);
     621                 :          0 :     memcpy(atr, nss_atr, len);
     622                 :          0 :     *atr_len = len;
     623                 :          0 : }
     624                 :            : 
     625                 :            : static SECStatus
     626                 :          5 : vcard_emul_create_serial(VCard *card, unsigned char *data, int len)
     627                 :            : {
     628                 :            :     HASH_HashType hashType;
     629                 :            :     HASHContext *hashContext = NULL;
     630                 :            :     unsigned char digest[32];
     631                 :          5 :     unsigned int digestLen = 0;
     632                 :            : 
     633                 :          5 :     hashType = HASH_GetHashTypeByOidTag(SEC_OID_SHA256);
     634                 :          5 :     hashContext = HASH_Create(hashType);
     635         [ +  - ]:          5 :     if (hashContext == NULL) {
     636                 :            :         return SECFailure;
     637                 :            :     }
     638                 :            : 
     639                 :          5 :     HASH_Begin(hashContext);
     640                 :          5 :     HASH_Update(hashContext, data, len);
     641                 :          5 :     HASH_End(hashContext, digest, &digestLen, 32);
     642                 :          5 :     HASH_Destroy(hashContext);
     643                 :            : 
     644                 :          5 :     vcard_set_serial(card, digest, (size_t) digestLen);
     645                 :            : 
     646                 :          5 :     return SECSuccess;
     647                 :            : }
     648                 :            : 
     649                 :            : /*
     650                 :            :  * create a new card from certs and keys
     651                 :            :  */
     652                 :            : static VCard *
     653                 :          5 : vcard_emul_make_card(VReader *reader,
     654                 :            :                      unsigned char * const *certs, int *cert_len,
     655                 :            :                      VCardKey *keys[], int cert_count)
     656                 :            : {
     657                 :            :     VCardEmul *vcard_emul;
     658                 :            :     VCard *vcard;
     659                 :            :     PK11SlotInfo *slot;
     660                 :            :     VCardEmulType type;
     661                 :            :     const char *params;
     662                 :            : 
     663                 :          5 :     g_debug("%s: called", __func__);
     664                 :            : 
     665                 :          5 :     type = vcard_emul_get_type(reader);
     666                 :            : 
     667                 :            :     /* ignore the inserted card */
     668         [ -  + ]:          5 :     if (type == VCARD_EMUL_NONE) {
     669                 :            :         return NULL;
     670                 :            :     }
     671                 :            :     slot = vcard_emul_reader_get_slot(reader);
     672         [ -  + ]:          5 :     if (slot == NULL) {
     673                 :            :         return NULL;
     674                 :            :     }
     675                 :            : 
     676                 :            :     params = vcard_emul_get_type_params(reader);
     677                 :            :     /* params these can be NULL */
     678                 :            : 
     679                 :            :     vcard_emul = vcard_emul_new_card(slot);
     680                 :            :     if (vcard_emul == NULL) {
     681                 :            :         return NULL;
     682                 :            :     }
     683                 :          5 :     vcard = vcard_new(vcard_emul, vcard_emul_delete_card);
     684         [ -  + ]:          5 :     if (vcard == NULL) {
     685                 :            :         vcard_emul_delete_card(vcard_emul);
     686                 :          0 :         return NULL;
     687                 :            :     }
     688                 :            : 
     689         [ +  - ]:          5 :     if (cert_count > 0) {
     690                 :          5 :         vcard_emul_create_serial(vcard, certs[0], cert_len[0]);
     691                 :            :     }
     692                 :            : 
     693                 :          5 :     vcard_init(reader, vcard, type, params, certs, cert_len, keys, cert_count);
     694                 :          5 :     return vcard;
     695                 :            : }
     696                 :            : 
     697                 :            : 
     698                 :            : /*
     699                 :            :  * 'clone' a physical card as a virtual card
     700                 :            :  */
     701                 :            : static VCard *
     702                 :          4 : vcard_emul_mirror_card(VReader *vreader)
     703                 :            : {
     704                 :            :     /*
     705                 :            :      * lookup certs using the C_FindObjects. The Stan Cert handle won't give
     706                 :            :      * us the real certs until we log in.
     707                 :            :      */
     708                 :            :     PK11GenericObject *firstObj, *thisObj;
     709                 :            :     int cert_count;
     710                 :            :     unsigned char **certs;
     711                 :            :     int *cert_len;
     712                 :            :     VCardKey **keys;
     713                 :            :     PK11SlotInfo *slot;
     714                 :            :     VCard *card;
     715                 :            : 
     716                 :          4 :     g_debug("%s: called", __func__);
     717                 :            : 
     718                 :            :     slot = vcard_emul_reader_get_slot(vreader);
     719         [ -  + ]:          4 :     if (slot == NULL) {
     720                 :            :         return NULL;
     721                 :            :     }
     722                 :            : 
     723                 :          4 :     firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
     724         [ +  + ]:          4 :     if (firstObj == NULL) {
     725                 :            :         return NULL;
     726                 :            :     }
     727                 :            : 
     728                 :            :     /* count the certs */
     729                 :            :     cert_count = 0;
     730         [ +  + ]:          4 :     for (thisObj = firstObj; thisObj;
     731                 :          2 :                              thisObj = PK11_GetNextGenericObject(thisObj)) {
     732                 :          2 :         cert_count++;
     733                 :            :     }
     734                 :            : 
     735                 :            :     /* allocate the arrays */
     736                 :          2 :     vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
     737                 :            : 
     738                 :            :     /* fill in the arrays */
     739                 :            :     cert_count = 0;
     740         [ +  + ]:          4 :     for (thisObj = firstObj; thisObj;
     741                 :          2 :                              thisObj = PK11_GetNextGenericObject(thisObj)) {
     742                 :            :         SECItem derCert;
     743                 :            :         CERTCertificate *cert;
     744                 :            :         SECStatus rv;
     745                 :            : 
     746                 :          2 :         g_debug("%s: Found certificate", __func__);
     747                 :          2 :         rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
     748                 :            :                                    CKA_VALUE, &derCert);
     749         [ -  + ]:          2 :         if (rv != SECSuccess) {
     750                 :          0 :             continue;
     751                 :            :         }
     752                 :            :         /* create floating temp cert. This gives us a cert structure even if
     753                 :            :          * the token isn't logged in */
     754                 :          2 :         cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
     755                 :            :                                        NULL, PR_FALSE, PR_TRUE);
     756                 :          2 :         SECITEM_FreeItem(&derCert, PR_FALSE);
     757         [ -  + ]:          2 :         if (cert == NULL) {
     758                 :          0 :             continue;
     759                 :            :         }
     760                 :            : 
     761                 :          2 :         certs[cert_count] = cert->derCert.data;
     762                 :          2 :         cert_len[cert_count] = cert->derCert.len;
     763                 :          2 :         keys[cert_count] = vcard_emul_make_key(slot, cert);
     764                 :          2 :         cert_count++;
     765                 :          2 :         CERT_DestroyCertificate(cert); /* key obj still has a reference */
     766                 :            :     }
     767                 :          2 :     PK11_DestroyGenericObjects(firstObj);
     768                 :            : 
     769                 :            :     /* now create the card */
     770                 :          2 :     card = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
     771                 :          2 :     g_free(certs);
     772                 :          2 :     g_free(cert_len);
     773                 :          2 :     g_free(keys);
     774                 :            : 
     775                 :          2 :     return card;
     776                 :            : }
     777                 :            : 
     778                 :            : static VCardEmulType default_card_type = VCARD_EMUL_NONE;
     779                 :            : static const char *default_type_params = "";
     780                 :            : 
     781                 :            : /*
     782                 :            :  * This thread looks for card and reader insertions and puts events on the
     783                 :            :  * event queue
     784                 :            :  */
     785                 :            : static void
     786                 :          2 : vcard_emul_event_thread(void *arg)
     787                 :            : {
     788                 :            :     PK11SlotInfo *slot;
     789                 :            :     VReader *vreader;
     790                 :            :     VReaderEmul *vreader_emul;
     791                 :            :     VCard *vcard;
     792                 :            :     SECMODModule *module = (SECMODModule *)arg;
     793                 :            : 
     794                 :            :     do {
     795                 :            :         /*
     796                 :            :          * XXX - the latency value doesn't matter one bit. you only get no
     797                 :            :          * blocking (flags |= CKF_DONT_BLOCK) or PKCS11_WAIT_LATENCY (==500),
     798                 :            :          * hard coded in coolkey.  And it isn't coolkey's fault - the timeout
     799                 :            :          * value we pass get's dropped on the floor before C_WaitForSlotEvent
     800                 :            :          * is called.
     801                 :            :          */
     802                 :          6 :         slot = SECMOD_WaitForAnyTokenEvent(module, 0, 500);
     803         [ -  + ]:          4 :         if (slot == NULL) {
     804                 :            :             /* this could be just a no event indication */
     805         [ #  # ]:          0 :             if (PORT_GetError() == SEC_ERROR_NO_EVENT) {
     806                 :          0 :                 continue;
     807                 :            :             }
     808                 :            :             break;
     809                 :            :         }
     810                 :          4 :         vreader = vcard_emul_find_vreader_from_slot(slot);
     811         [ -  + ]:          4 :         if (vreader == NULL) {
     812                 :            :             /* new vreader */
     813                 :          0 :             vreader_emul = vreader_emul_new(slot, default_card_type,
     814                 :            :                                             default_type_params);
     815                 :          0 :             vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
     816                 :            :                                   vreader_emul_delete);
     817                 :          0 :             PK11_FreeSlot(slot);
     818                 :            :             slot = NULL;
     819                 :          0 :             vreader_add_reader(vreader);
     820                 :          0 :             vreader_free(vreader);
     821                 :          0 :             continue;
     822                 :            :         }
     823                 :            :         /* card remove/insert */
     824                 :          4 :         vreader_emul = vreader_get_private(vreader);
     825         [ +  - ]:          4 :         if (PK11_IsPresent(slot)) {
     826                 :          4 :             int series = PK11_GetSlotSeries(slot);
     827         [ -  + ]:          4 :             if (series != vreader_emul->series) {
     828         [ #  # ]:          0 :                 if (vreader_emul->present) {
     829                 :          0 :                     vreader_insert_card(vreader, NULL);
     830                 :            :                 }
     831                 :          0 :                 vcard = vcard_emul_mirror_card(vreader);
     832                 :          0 :                 vreader_insert_card(vreader, vcard);
     833                 :          0 :                 vcard_free(vcard);
     834                 :            :             }
     835                 :          4 :             vreader_emul->series = series;
     836                 :          4 :             vreader_emul->present = 1;
     837                 :          4 :             vreader_free(vreader);
     838                 :          4 :             PK11_FreeSlot(slot);
     839                 :          4 :             continue;
     840                 :            :         }
     841         [ #  # ]:          0 :         if (vreader_emul->present) {
     842                 :          0 :             vreader_insert_card(vreader, NULL);
     843                 :            :         }
     844                 :          0 :         vreader_emul->series = 0;
     845                 :          0 :         vreader_emul->present = 0;
     846                 :          0 :         PK11_FreeSlot(slot);
     847                 :          0 :         vreader_free(vreader);
     848                 :            :     } while (1);
     849                 :          0 : }
     850                 :            : 
     851                 :            : /* if the card is inserted when we start up, make sure our state is correct */
     852                 :            : static void
     853                 :          7 : vcard_emul_init_series(VReader *vreader, G_GNUC_UNUSED VCard *vcard)
     854                 :            : {
     855                 :          7 :     VReaderEmul *vreader_emul = vreader_get_private(vreader);
     856                 :          7 :     PK11SlotInfo *slot = vreader_emul->slot;
     857                 :            : 
     858                 :          7 :     vreader_emul->present = PK11_IsPresent(slot);
     859                 :          7 :     vreader_emul->series = PK11_GetSlotSeries(slot);
     860         [ -  + ]:          7 :     if (vreader_emul->present == 0) {
     861                 :          0 :         vreader_insert_card(vreader, NULL);
     862                 :            :     }
     863                 :          7 : }
     864                 :            : 
     865                 :            : /*
     866                 :            :  * each module has a separate wait call, create a thread for each module that
     867                 :            :  * we are using.
     868                 :            :  */
     869                 :            : static void
     870                 :            : vcard_emul_new_event_thread(SECMODModule *module)
     871                 :            : {
     872                 :          2 :     PR_CreateThread(PR_SYSTEM_THREAD, vcard_emul_event_thread,
     873                 :            :                      module, PR_PRIORITY_HIGH, PR_GLOBAL_THREAD,
     874                 :            :                      PR_UNJOINABLE_THREAD, 0);
     875                 :          2 : }
     876                 :            : 
     877                 :            : static const VCardEmulOptions default_options = {
     878                 :            :     .nss_db = NULL,
     879                 :            :     .vreader = NULL,
     880                 :            :     .vreader_count = 0,
     881                 :            :     .hw_card_type = VCARD_EMUL_CAC,
     882                 :            :     .hw_type_params = NULL,
     883                 :            :     .use_hw = USE_HW_YES,
     884                 :            : };
     885                 :            : 
     886                 :            : 
     887                 :            : /*
     888                 :            :  *  NSS needs the app to supply a password prompt. In our case the only time
     889                 :            :  *  the password is supplied is as part of the Login APDU. The actual password
     890                 :            :  *  is passed in the pw_arg in that case. In all other cases pw_arg should be
     891                 :            :  *  NULL.
     892                 :            :  */
     893                 :            : static char *
     894                 :         16 : vcard_emul_get_password(G_GNUC_UNUSED PK11SlotInfo *slot, PRBool retries, void *pw_arg)
     895                 :            : {
     896                 :            :     /* if it didn't work the first time, don't keep trying */
     897         [ +  - ]:         16 :     if (retries) {
     898                 :            :         return NULL;
     899                 :            :     }
     900                 :            :     /* we are looking up a password when we don't have one in hand */
     901         [ +  - ]:         16 :     if (pw_arg == NULL) {
     902                 :            :         return NULL;
     903                 :            :     }
     904                 :            :     /* TODO: we really should verify that were are using the right slot */
     905                 :         16 :     return PORT_Strdup(pw_arg);
     906                 :            : }
     907                 :            : 
     908                 :            : /* Force a card removal even if the card is not physically removed */
     909                 :            : VCardEmulError
     910                 :          2 : vcard_emul_force_card_remove(VReader *vreader)
     911                 :            : {
     912   [ +  -  +  + ]:          2 :     if (!nss_emul_init || (vreader_card_is_present(vreader) != VREADER_OK)) {
     913                 :          1 :         return VCARD_EMUL_FAIL; /* card is already removed */
     914                 :            :     }
     915                 :            : 
     916                 :            :     /* OK, remove it */
     917                 :          1 :     vreader_insert_card(vreader, NULL);
     918                 :          1 :     return VCARD_EMUL_OK;
     919                 :            : }
     920                 :            : 
     921                 :            : /* Re-insert of a card that has been removed by force removal */
     922                 :            : VCardEmulError
     923                 :          2 : vcard_emul_force_card_insert(VReader *vreader)
     924                 :            : {
     925                 :            :     VReaderEmul *vreader_emul;
     926                 :            :     VCard *vcard;
     927                 :            : 
     928   [ +  -  +  + ]:          2 :     if (!nss_emul_init || (vreader_card_is_present(vreader) == VREADER_OK)) {
     929                 :          1 :         return VCARD_EMUL_FAIL; /* card is already removed */
     930                 :            :     }
     931                 :          1 :     vreader_emul = vreader_get_private(vreader);
     932                 :            : 
     933                 :            :     /* if it's a softcard, get the saved vcard from the reader emul structure */
     934         [ +  - ]:          1 :     if (vreader_emul->saved_vcard) {
     935                 :          1 :         vcard = vcard_reference(vreader_emul->saved_vcard);
     936                 :            :     } else {
     937                 :            :         /* it must be a physical card, rebuild it */
     938         [ #  # ]:          0 :         if (!PK11_IsPresent(vreader_emul->slot)) {
     939                 :            :             /* physical card has been removed, not way to reinsert it */
     940                 :            :             return VCARD_EMUL_FAIL;
     941                 :            :         }
     942                 :          0 :         vcard = vcard_emul_mirror_card(vreader);
     943                 :            :     }
     944                 :          1 :     vreader_insert_card(vreader, vcard);
     945                 :          1 :     vcard_free(vcard);
     946                 :            : 
     947                 :          1 :     return VCARD_EMUL_OK;
     948                 :            : }
     949                 :            : 
     950                 :            : /* Previously we returned FAIL if no readers found. This makes
     951                 :            :  * no sense when using hardware, since there may be no readers connected
     952                 :            :  * at the time vcard_emul_init is called, but they will be properly
     953                 :            :  * recognized later. So Instead return FAIL only if no_hw==1 and no
     954                 :            :  * vcards can be created (indicates error with certificates provided
     955                 :            :  * or db), or if any other higher level error (NSS error, missing coolkey). */
     956                 :            : static int vcard_emul_init_called;
     957                 :            : static NSSInitContext *nss_ctx = NULL;
     958                 :            : 
     959                 :            : VCardEmulError
     960                 :          7 : vcard_emul_init(const VCardEmulOptions *options)
     961                 :            : {
     962                 :            :     PRBool has_readers = PR_FALSE;
     963                 :            :     VReader *vreader;
     964                 :            :     VReaderEmul *vreader_emul;
     965                 :            :     SECMODListLock *module_lock;
     966                 :            :     SECMODModuleList *module_list;
     967                 :            :     SECMODModuleList *mlp;
     968                 :            :     int i;
     969                 :            :     gchar *path = NULL;
     970                 :            :     const gchar *nss_db;
     971                 :            : 
     972                 :          7 :     g_debug("%s: called", __func__);
     973                 :            : 
     974         [ +  + ]:          7 :     if (vcard_emul_init_called) {
     975                 :            :         return VCARD_EMUL_INIT_ALREADY_INITED;
     976                 :            :     }
     977                 :          6 :     vcard_emul_init_called = 1;
     978                 :          6 :     vreader_init();
     979                 :          6 :     vevent_queue_init();
     980                 :            : 
     981         [ -  + ]:          6 :     if (options == NULL) {
     982                 :            :         options = &default_options;
     983                 :            :     }
     984                 :            : 
     985                 :            : #if defined(ENABLE_PCSC)
     986                 :            :     if (options->use_hw && options->hw_card_type == VCARD_EMUL_PASSTHRU) {
     987                 :            :         if (options->vreader_count > 0) {
     988                 :            :             fprintf(stderr, "Error: you cannot use a soft card and "
     989                 :            :                             "a passthru card simultaneously.\n");
     990                 :            :             return VCARD_EMUL_FAIL;
     991                 :            :         }
     992                 :            : 
     993                 :            :         if (capcsc_init()) {
     994                 :            :             fprintf(stderr, "Error initializing PCSC interface.\n");
     995                 :            :             return VCARD_EMUL_FAIL;
     996                 :            :         }
     997                 :            : 
     998                 :            :         g_debug("%s: returning with passthrough initialized", __func__);
     999                 :            :         return VCARD_EMUL_OK;
    1000                 :            :     }
    1001                 :            : #endif
    1002                 :            : 
    1003                 :            :     /* first initialize NSS */
    1004                 :          6 :     nss_db = options->nss_db;
    1005         [ -  + ]:          6 :     if (nss_db == NULL) {
    1006                 :            : #ifndef _WIN32
    1007                 :            :         nss_db = "/etc/pki/nssdb";
    1008                 :            : #else
    1009                 :            :         const gchar * const *config_dirs = g_get_system_config_dirs();
    1010                 :            :         if (config_dirs == NULL || config_dirs[0] == NULL) {
    1011                 :            :             return VCARD_EMUL_FAIL;
    1012                 :            :         }
    1013                 :            : 
    1014                 :            :         path = g_build_filename(config_dirs[0], "pki", "nssdb", NULL);
    1015                 :            :         nss_db = path;
    1016                 :            : #endif
    1017                 :            :     }
    1018                 :            : 
    1019                 :          6 :     nss_ctx = NSS_InitContext(nss_db, "", "", "", NULL, NSS_INIT_READONLY);
    1020         [ +  + ]:          6 :     if (nss_ctx == NULL) {
    1021                 :          1 :         g_debug("%s: NSS_InitContext failed. Does the DB directory '%s' exist?",
    1022                 :            :                 __func__, nss_db);
    1023                 :          1 :         g_free(path);
    1024                 :          1 :         return VCARD_EMUL_FAIL;
    1025                 :            :     }
    1026                 :          5 :     g_free(path);
    1027                 :            :     path = NULL;
    1028                 :            : 
    1029                 :            :     /* Set password callback function */
    1030                 :          5 :     PK11_SetPasswordFunc(vcard_emul_get_password);
    1031                 :            : 
    1032                 :            :     /* set up soft cards emulated by software certs rather than physical cards
    1033                 :            :      * */
    1034         [ +  + ]:          8 :     for (i = 0; i < options->vreader_count; i++) {
    1035                 :            :         int j;
    1036                 :            :         int cert_count;
    1037                 :            :         unsigned char **certs;
    1038                 :            :         int *cert_len;
    1039                 :            :         VCardKey **keys;
    1040                 :            :         PK11SlotInfo *slot;
    1041                 :            : 
    1042                 :          3 :         slot = PK11_FindSlotByName(options->vreader[i].name);
    1043         [ -  + ]:          3 :         if (slot == NULL) {
    1044                 :          0 :             continue;
    1045                 :            :         }
    1046                 :          3 :         vreader_emul = vreader_emul_new(slot, options->vreader[i].card_type,
    1047                 :          3 :                                         options->vreader[i].type_params);
    1048                 :          3 :         vreader = vreader_new(options->vreader[i].vname, vreader_emul,
    1049                 :            :                               vreader_emul_delete);
    1050                 :          3 :         vreader_add_reader(vreader);
    1051                 :            : 
    1052                 :          3 :         vcard_emul_alloc_arrays(&certs, &cert_len, &keys,
    1053                 :          3 :                                 options->vreader[i].cert_count);
    1054                 :            : 
    1055                 :            :         cert_count = 0;
    1056         [ +  + ]:         12 :         for (j = 0; j < options->vreader[i].cert_count; j++) {
    1057                 :            :             /* we should have a better way of identifying certs than by
    1058                 :            :              * nickname here */
    1059                 :          9 :             CERTCertificate *cert = PK11_FindCertFromNickname(
    1060                 :          9 :                                         options->vreader[i].cert_name[j],
    1061                 :            :                                         NULL);
    1062         [ -  + ]:          9 :             if (cert == NULL) {
    1063                 :          0 :                 continue;
    1064                 :            :             }
    1065                 :          9 :             certs[cert_count] = cert->derCert.data;
    1066                 :          9 :             cert_len[cert_count] = cert->derCert.len;
    1067                 :          9 :             keys[cert_count] = vcard_emul_make_key(slot, cert);
    1068                 :            :             /* this is safe because the key is still holding a cert reference */
    1069                 :          9 :             CERT_DestroyCertificate(cert);
    1070                 :          9 :             cert_count++;
    1071                 :            :         }
    1072         [ +  - ]:          3 :         if (cert_count) {
    1073                 :          3 :             VCard *vcard = vcard_emul_make_card(vreader, certs, cert_len,
    1074                 :            :                                                 keys, cert_count);
    1075                 :          3 :             vreader_insert_card(vreader, vcard);
    1076                 :          3 :             vcard_emul_init_series(vreader, vcard);
    1077                 :            :             /* allow insertion and removal of soft cards */
    1078                 :          3 :             vreader_emul->saved_vcard = vcard_reference(vcard);
    1079                 :          3 :             vcard_free(vcard);
    1080                 :          3 :             vreader_free(vreader);
    1081                 :            :             has_readers = PR_TRUE;
    1082                 :            :         }
    1083                 :          3 :         PK11_FreeSlot(slot);
    1084                 :          3 :         g_free(certs);
    1085                 :          3 :         g_free(cert_len);
    1086                 :          3 :         g_free(keys);
    1087                 :            :     }
    1088                 :            : 
    1089                 :            :     /* if we aren't suppose to use hw, skip looking up hardware tokens */
    1090         [ +  + ]:          5 :     if (!options->use_hw) {
    1091                 :          3 :         nss_emul_init = has_readers;
    1092                 :          3 :         g_debug("%s: returning: Not using HW", __func__);
    1093                 :          3 :         return has_readers ? VCARD_EMUL_OK : VCARD_EMUL_FAIL;
    1094                 :            :     }
    1095                 :            : 
    1096                 :            :     /* make sure we have some PKCS #11 module loaded */
    1097                 :          2 :     module_lock = SECMOD_GetDefaultModuleListLock();
    1098                 :          2 :     module_list = SECMOD_GetDefaultModuleList();
    1099                 :            : 
    1100                 :            :     /* now examine all the slots, finding which should be readers */
    1101                 :            :     /* We should control this with options. For now we mirror out any
    1102                 :            :      * removable hardware slot */
    1103                 :          2 :     default_card_type = options->hw_card_type;
    1104                 :          2 :     default_type_params = g_strdup(options->hw_type_params);
    1105                 :            : 
    1106                 :          2 :     SECMOD_GetReadLock(module_lock);
    1107         [ +  + ]:          6 :     for (mlp = module_list; mlp; mlp = mlp->next) {
    1108                 :          4 :         SECMODModule *module = mlp->module;
    1109                 :            : 
    1110                 :            :         /* Ignore the internal module */
    1111   [ +  -  +  + ]:          4 :         if (module == NULL || module == SECMOD_GetInternalModule()) {
    1112                 :          2 :             continue;
    1113                 :            :         }
    1114                 :            : 
    1115                 :          2 :         g_debug("%s: Listing modules, trying %s", __func__, module->commonName);
    1116         [ +  + ]:          6 :         for (i = 0; i < module->slotCount; i++) {
    1117                 :          4 :             PK11SlotInfo *slot = module->slots[i];
    1118                 :            : 
    1119                 :            :             /* only map removable HW slots */
    1120   [ +  -  +  - ]:          4 :             if (slot == NULL || !PK11_IsRemovable(slot) ||
    1121   [ -  +  -  - ]:          4 :                 (options->use_hw == USE_HW_YES && !PK11_IsHW(slot))) {
    1122                 :          0 :                 continue;
    1123                 :            :             }
    1124         [ -  + ]:          4 :             if (strcmp("E-Gate 0 0", PK11_GetSlotName(slot)) == 0) {
    1125                 :            :                 /*
    1126                 :            :                  * coolkey <= 1.1.0-20 emulates this reader if it can't find
    1127                 :            :                  * any hardware readers. This causes problems, warn user of
    1128                 :            :                  * problems.
    1129                 :            :                  */
    1130                 :          0 :                 fprintf(stderr, "known bad coolkey version - see "
    1131                 :            :                         "https://bugzilla.redhat.com/show_bug.cgi?id=802435\n");
    1132                 :          0 :                 continue;
    1133                 :            :             }
    1134                 :          4 :             vreader_emul = vreader_emul_new(slot, options->hw_card_type,
    1135                 :          4 :                                             options->hw_type_params);
    1136                 :          4 :             vreader = vreader_new(PK11_GetSlotName(slot), vreader_emul,
    1137                 :            :                                   vreader_emul_delete);
    1138                 :          4 :             vreader_add_reader(vreader);
    1139                 :          4 :             g_debug("%s: Added reader from slot %s", __func__,
    1140                 :            :                     PK11_GetSlotName(slot));
    1141                 :            : 
    1142         [ +  - ]:          4 :             if (PK11_IsPresent(slot)) {
    1143                 :            :                 VCard *vcard;
    1144                 :          4 :                 vcard = vcard_emul_mirror_card(vreader);
    1145                 :          4 :                 vreader_insert_card(vreader, vcard);
    1146                 :          4 :                 vcard_emul_init_series(vreader, vcard);
    1147                 :          4 :                 g_debug("%s: Added card to the reader %s", __func__,
    1148                 :            :                         vreader_get_name(vreader));
    1149                 :          4 :                 vcard_free(vcard);
    1150                 :            :             }
    1151                 :          4 :             vreader_free(vreader);
    1152                 :            :         }
    1153                 :            :         vcard_emul_new_event_thread(module);
    1154                 :            :     }
    1155                 :          2 :     SECMOD_ReleaseReadLock(module_lock);
    1156                 :          2 :     nss_emul_init = PR_TRUE;
    1157                 :            : 
    1158                 :          2 :     return VCARD_EMUL_OK;
    1159                 :            : }
    1160                 :            : 
    1161                 :            : /* Recreate card insert events for all readers (user should
    1162                 :            :  * deduce implied reader insert. perhaps do a reader insert as well?)
    1163                 :            :  */
    1164                 :            : void
    1165                 :          0 : vcard_emul_replay_insertion_events(void)
    1166                 :            : {
    1167                 :            :     VReaderListEntry *current_entry;
    1168                 :            :     VReaderListEntry *next_entry;
    1169                 :          0 :     VReaderList *list = vreader_get_reader_list();
    1170                 :            : 
    1171         [ #  # ]:          0 :     for (current_entry = vreader_list_get_first(list); current_entry;
    1172                 :            :             current_entry = next_entry) {
    1173                 :          0 :         VReader *vreader = vreader_list_get_reader(current_entry);
    1174                 :          0 :         next_entry = vreader_list_get_next(current_entry);
    1175                 :          0 :         vreader_queue_card_event(vreader);
    1176                 :            :     }
    1177                 :            : 
    1178                 :          0 :     vreader_list_delete(list);
    1179                 :          0 : }
    1180                 :            : 
    1181                 :            : VCardEmulError
    1182                 :          4 : vcard_emul_finalize(void)
    1183                 :            : {
    1184                 :            :     SECStatus rv;
    1185                 :            : 
    1186                 :          4 :     rv = NSS_ShutdownContext(nss_ctx);
    1187         [ +  + ]:          4 :     if (rv != SECSuccess) {
    1188                 :          2 :         g_debug("%s: NSS_ShutdownContext failed.", __func__);
    1189                 :          2 :         return VCARD_EMUL_FAIL;
    1190                 :            :     }
    1191                 :          2 :     nss_ctx = NULL;
    1192                 :            : 
    1193                 :          2 :     return VCARD_EMUL_OK;
    1194                 :            : }
    1195                 :            : 
    1196                 :            : /*
    1197                 :            :  *  Silly little functions to help parsing our argument string
    1198                 :            :  */
    1199                 :            : static int
    1200                 :            : count_tokens(const char *str, char token, char token_end)
    1201                 :            : {
    1202                 :            :     int count = 0;
    1203                 :            : 
    1204         [ +  - ]:         72 :     for (; *str; str++) {
    1205         [ +  + ]:         72 :         if (*str == token) {
    1206                 :          8 :             count++;
    1207                 :            :         }
    1208         [ +  + ]:         72 :         if (*str == token_end) {
    1209                 :            :             break;
    1210                 :            :         }
    1211                 :            :     }
    1212                 :            :     return count;
    1213                 :            : }
    1214                 :            : 
    1215                 :            : static const char *
    1216                 :         69 : strip(const char *str)
    1217                 :            : {
    1218   [ +  +  +  + ]:         81 :     for (; *str && isspace(*str); str++) {
    1219                 :            :     }
    1220                 :         69 :     return str;
    1221                 :            : }
    1222                 :            : 
    1223                 :            : static const char *
    1224                 :          7 : find_blank(const char *str)
    1225                 :            : {
    1226   [ +  +  +  + ]:         42 :     for (; *str && !isspace(*str); str++) {
    1227                 :            :     }
    1228                 :          7 :     return str;
    1229                 :            : }
    1230                 :            : 
    1231                 :            : 
    1232                 :            : /*
    1233                 :            :  *  We really want to use some existing argument parsing library here. That
    1234                 :            :  *  would give us a consistent look */
    1235                 :            : static VCardEmulOptions options;
    1236                 :            : #define READER_STEP 4
    1237                 :            : 
    1238                 :            : /* Expects "args" to be at the beginning of a token (ie right after the ','
    1239                 :            :  * ending the previous token), and puts the next token start in "token",
    1240                 :            :  * and its length in "token_length". "token" will not be nul-terminated.
    1241                 :            :  * After calling the macro, "args" will be advanced to the beginning of
    1242                 :            :  * the next token.
    1243                 :            :  */
    1244                 :            : #define NEXT_TOKEN(token) \
    1245                 :            :             (token) = args; \
    1246                 :            :             args = strpbrk(args, ",)"); \
    1247                 :            :             if (args == NULL || *args == 0 || *args == ')') { \
    1248                 :            :                 fprintf(stderr, "Error: invalid soft specification.\n"); \
    1249                 :            :                 goto fail; \
    1250                 :            :             } \
    1251                 :            :             (token##_length) = args - (token); \
    1252                 :            :             args = strip(args+1);
    1253                 :            : 
    1254                 :            : VCardEmulOptions *
    1255                 :          7 : vcard_emul_options(const char *args)
    1256                 :            : {
    1257                 :            :     int i, j, reader_count = 0;
    1258                 :            :     VCardEmulOptions *opts;
    1259                 :            : 
    1260                 :            :     /* Allow the future use of allocating the options structure on the fly */
    1261                 :          7 :     memcpy(&options, &default_options, sizeof(options));
    1262                 :            :     opts = &options;
    1263                 :            : 
    1264                 :            :     do {
    1265                 :         19 :         args = strip(args); /* strip off the leading spaces */
    1266         [ -  + ]:         19 :         if (*args == ',') {
    1267                 :          0 :             args++;
    1268                 :          0 :             continue;
    1269                 :            :         }
    1270                 :            :         /* soft=(slot_name,virt_name,emul_type,emul_flags,cert_1, (no eol)
    1271                 :            :          *       cert_2,cert_3...) */
    1272         [ +  + ]:         19 :         if (strncmp(args, "soft=", 5) == 0) {
    1273                 :            :             const char *name;
    1274                 :            :             size_t name_length;
    1275                 :            :             const char *vname;
    1276                 :            :             size_t vname_length;
    1277                 :            :             const char *type_params;
    1278                 :            :             size_t type_params_length;
    1279                 :            :             char type_str[100];
    1280                 :            :             VCardEmulType type;
    1281                 :            :             int count;
    1282                 :            :             VirtualReaderOptions *vreaderOpt;
    1283                 :            : 
    1284                 :          4 :             args = strip(args + 5);
    1285         [ -  + ]:          4 :             if (*args != '(') {
    1286                 :          0 :                 fprintf(stderr, "Error: invalid soft specification.\n");
    1287                 :          0 :                 goto fail;
    1288                 :            :             }
    1289                 :          4 :             args = strip(args+1);
    1290                 :            : 
    1291   [ +  -  +  -  :          4 :             NEXT_TOKEN(name)
                   -  + ]
    1292   [ +  -  +  -  :          4 :             NEXT_TOKEN(vname)
                   -  + ]
    1293   [ +  -  +  -  :          4 :             NEXT_TOKEN(type_params)
                   -  + ]
    1294                 :          4 :             type_params_length = MIN(type_params_length, sizeof(type_str)-1);
    1295                 :          4 :             memcpy(type_str, type_params, type_params_length);
    1296                 :          4 :             type_str[type_params_length] = '\0';
    1297                 :          4 :             type = vcard_emul_type_from_string(type_str);
    1298         [ -  + ]:          4 :             if (type == VCARD_EMUL_NONE) {
    1299                 :          0 :                 fprintf(stderr, "Error: invalid smartcard type '%s'.\n",
    1300                 :            :                         type_str);
    1301                 :          0 :                 goto fail;
    1302                 :            :             }
    1303                 :            : 
    1304   [ +  -  +  -  :          4 :             NEXT_TOKEN(type_params)
                   -  + ]
    1305                 :            : 
    1306         [ -  + ]:          4 :             if (*args == 0) {
    1307                 :          0 :                 fprintf(stderr, "Error: missing cert specification.\n");
    1308                 :          0 :                 goto fail;
    1309                 :            :             }
    1310                 :            : 
    1311         [ +  - ]:          4 :             if (opts->vreader_count >= reader_count) {
    1312                 :          4 :                 reader_count += READER_STEP;
    1313   [ -  +  -  - ]:          4 :                 opts->vreader = g_renew(VirtualReaderOptions, opts->vreader,
    1314                 :            :                                         reader_count);
    1315                 :            :             }
    1316                 :          4 :             vreaderOpt = &opts->vreader[opts->vreader_count];
    1317                 :          4 :             vreaderOpt->name = g_strndup(name, name_length);
    1318                 :          4 :             vreaderOpt->vname = g_strndup(vname, vname_length);
    1319                 :          4 :             vreaderOpt->card_type = type;
    1320                 :          4 :             vreaderOpt->type_params =
    1321                 :          4 :                 g_strndup(type_params, type_params_length);
    1322                 :          4 :             count = count_tokens(args, ',', ')') + 1;
    1323                 :          4 :             vreaderOpt->cert_count = count;
    1324   [ -  +  -  - ]:          4 :             vreaderOpt->cert_name = g_new(char *, count);
    1325         [ +  + ]:         16 :             for (i = 0; i < count; i++) {
    1326                 :            :                 const char *cert = args;
    1327                 :         12 :                 args = strpbrk(args, ",)");
    1328                 :         12 :                 vreaderOpt->cert_name[i] = g_strndup(cert, args - cert);
    1329                 :         12 :                 args = strip(args+1);
    1330                 :            :             }
    1331         [ -  + ]:          4 :             if (*args == ')') {
    1332                 :          0 :                 args++;
    1333                 :            :             }
    1334                 :          4 :             opts->vreader_count++;
    1335                 :            :         /* use_hw= */
    1336         [ +  + ]:         15 :         } else if (strncmp(args, "use_hw=", 7) == 0) {
    1337                 :          7 :             args = strip(args+7);
    1338   [ +  -  +  +  :          7 :             if (*args == '0' || *args == 'N' || *args == 'n' || *args == 'F') {
                   -  + ]
    1339                 :          4 :                 opts->use_hw = USE_HW_NO;
    1340         [ +  - ]:          3 :             } else if (strncmp(args, "removable", 9) == 0) {
    1341                 :          3 :                 opts->use_hw = USE_HW_REMOVABLE;
    1342                 :            :             } else {
    1343                 :          0 :                 opts->use_hw = USE_HW_YES;
    1344                 :            :             }
    1345                 :          7 :             args = find_blank(args);
    1346                 :            :         /* hw_type= */
    1347         [ -  + ]:          8 :         } else if (strncmp(args, "hw_type=", 8) == 0) {
    1348                 :          0 :             args = strip(args+8);
    1349                 :          0 :             opts->hw_card_type = vcard_emul_type_from_string(args);
    1350         [ #  # ]:          0 :             if (opts->hw_card_type == VCARD_EMUL_NONE) {
    1351                 :          0 :                 fprintf(stderr, "Error: invalid smartcard type '%s'.\n",
    1352                 :            :                         args);
    1353                 :          0 :                 goto fail;
    1354                 :            :             }
    1355                 :          0 :             args = find_blank(args);
    1356                 :            :         /* hw_params= */
    1357         [ -  + ]:          8 :         } else if (strncmp(args, "hw_params=", 10) == 0) {
    1358                 :            :             const char *params;
    1359                 :            : 
    1360         [ #  # ]:          0 :             if (opts->hw_type_params != NULL) {
    1361                 :          0 :                 fprintf(stderr, "Error: redefinition of hw_params= is not allowed.\n");
    1362                 :          0 :                 goto fail;
    1363                 :            :             }
    1364                 :          0 :             args = strip(args+10);
    1365                 :            :             params = args;
    1366                 :          0 :             args = find_blank(args);
    1367                 :          0 :             opts->hw_type_params = g_strndup(params, args-params);
    1368                 :            :         /* db="/data/base/path" */
    1369         [ +  + ]:          8 :         } else if (strncmp(args, "db=", 3) == 0) {
    1370                 :            :             const char *db;
    1371                 :            : 
    1372         [ -  + ]:          7 :             if (opts->nss_db != NULL) {
    1373                 :          0 :                 fprintf(stderr, "Error: redefinition of db= is not allowed.\n");
    1374                 :          0 :                 goto fail;
    1375                 :            :             }
    1376                 :          7 :             args = strip(args+3);
    1377         [ -  + ]:          7 :             if (*args != '"') {
    1378                 :          0 :                 fprintf(stderr, "Error: you must quote the file path.\n");
    1379                 :          0 :                 goto fail;
    1380                 :            :             }
    1381                 :          7 :             args++;
    1382                 :            :             db = args;
    1383                 :          7 :             args = strpbrk(args, "\"\n");
    1384         [ -  + ]:          7 :             if (args == NULL) {
    1385                 :          0 :                 fprintf(stderr, "Error: invalid db argument.\n");
    1386                 :          0 :                 goto fail;
    1387                 :            :             }
    1388                 :          7 :             opts->nss_db = g_strndup(db, args-db);
    1389         [ +  - ]:          7 :             if (*args != 0) {
    1390                 :          7 :                 args++;
    1391                 :            :             }
    1392         [ -  + ]:          1 :         } else if (strncmp(args, "nssemul", 7) == 0) {
    1393                 :          0 :             opts->hw_card_type = VCARD_EMUL_CAC;
    1394                 :          0 :             opts->use_hw = USE_HW_YES;
    1395                 :          0 :             args = find_blank(args + 7);
    1396                 :            : #if defined(ENABLE_PCSC)
    1397                 :            :         } else if (strncmp(args, "passthru", 8) == 0) {
    1398                 :            :             opts->hw_card_type = VCARD_EMUL_PASSTHRU;
    1399                 :            :             opts->use_hw = USE_HW_YES;
    1400                 :            :             args = find_blank(args + 8);
    1401                 :            : #endif
    1402                 :            :         } else {
    1403                 :          1 :             fprintf(stderr, "Error: Unknown smartcard specification.\n");
    1404                 :          1 :             goto fail;
    1405                 :            :         }
    1406         [ +  + ]:         18 :     } while (*args != 0);
    1407                 :            : 
    1408                 :            :     return opts;
    1409                 :            : 
    1410                 :            : fail:
    1411                 :            :     /* Clean up what was allocated above on failure */
    1412         [ -  + ]:          1 :     for (i = 0; i < opts->vreader_count; i++) {
    1413                 :          0 :         g_free(opts->vreader[i].name);
    1414                 :          0 :         g_free(opts->vreader[i].vname);
    1415                 :          0 :         g_free(opts->vreader[i].type_params);
    1416         [ #  # ]:          0 :         for (j = 0; j < opts->vreader[i].cert_count; j++) {
    1417                 :          0 :             g_free(opts->vreader[i].cert_name[j]);
    1418                 :            :         }
    1419                 :          0 :         g_free(opts->vreader[i].cert_name);
    1420                 :            :     }
    1421                 :          1 :     g_free(opts->vreader);
    1422                 :          1 :     g_free(opts->hw_type_params);
    1423                 :          1 :     g_free(opts->nss_db);
    1424                 :          1 :     return NULL;
    1425                 :            : }
    1426                 :            : 
    1427                 :            : unsigned char *
    1428                 :          6 : vcard_emul_read_object(VCard *card, const char *label,
    1429                 :            :     unsigned int *ret_len)
    1430                 :            : {
    1431                 :            :     PK11SlotInfo *slot;
    1432                 :            :     PK11GenericObject *obj, *firstObj, *myObj = NULL;
    1433                 :            :     SECItem result;
    1434                 :            :     SECStatus r;
    1435                 :            :     unsigned char *ret;
    1436                 :            : 
    1437                 :            :     slot = vcard_emul_card_get_slot(card);
    1438                 :            : 
    1439                 :          6 :     firstObj = PK11_FindGenericObjects(slot, CKO_DATA);
    1440                 :          6 :     g_debug("%s: Search for generic objects: got %p", __func__, firstObj);
    1441         [ -  + ]:          6 :     for (obj = firstObj; obj; obj = PK11_GetNextGenericObject(obj)) {
    1442                 :            :         int found = 0;
    1443                 :          0 :         r = PK11_ReadRawAttribute(PK11_TypeGeneric, obj,
    1444                 :            :             CKA_LABEL, &result);
    1445         [ #  # ]:          0 :         if (r != SECSuccess) {
    1446                 :          0 :             PK11_DestroyGenericObjects(firstObj);
    1447                 :          0 :             return NULL;
    1448                 :            :         }
    1449                 :            : 
    1450         [ #  # ]:          0 :         if (strlen(label) == result.len
    1451         [ #  # ]:          0 :             && memcmp(label, result.data, result.len) == 0)
    1452                 :            :             found = 1;
    1453                 :            : 
    1454                 :          0 :         PORT_Free(result.data);
    1455                 :          0 :         result.data = NULL;
    1456                 :            : 
    1457         [ #  # ]:          0 :         if (found) {
    1458                 :          0 :             PK11_UnlinkGenericObject(obj);
    1459                 :            :             myObj = obj;
    1460                 :          0 :             break;
    1461                 :            :         }
    1462                 :            :     }
    1463                 :          6 :     PK11_DestroyGenericObjects(firstObj);
    1464                 :            : 
    1465         [ +  - ]:          6 :     if (!myObj)
    1466                 :            :         return NULL;
    1467                 :            : 
    1468                 :          0 :     r = PK11_ReadRawAttribute(PK11_TypeGeneric, myObj,
    1469                 :            :         CKA_VALUE, &result);
    1470                 :          0 :     PK11_DestroyGenericObject(myObj);
    1471         [ #  # ]:          0 :     if (r != SECSuccess)
    1472                 :            :         return NULL;
    1473                 :            : 
    1474                 :          0 :     *ret_len = result.len;
    1475                 :          0 :     ret = g_memdup2(result.data, result.len);
    1476                 :          0 :     PORT_Free(result.data);
    1477                 :          0 :     return ret;
    1478                 :            : }
    1479                 :            : 
    1480                 :            : void
    1481                 :          0 : vcard_emul_usage(void)
    1482                 :            : {
    1483                 :          0 :    fprintf(stderr,
    1484                 :            : "emul args: comma separated list of the following arguments\n"
    1485                 :            : " db={nss_database}               (default sql:/etc/pki/nssdb)\n"
    1486                 :            : " use_hw=[yes|no|removable]       (default yes)\n"
    1487                 :            : " hw_type={card_type_to_emulate}  (default CAC)\n"
    1488                 :            : " hw_params={param_for_card}      (default \"\")\n"
    1489                 :            : " nssemul                         (alias for use_hw=yes, hw_type=CAC)\n"
    1490                 :            : #if defined(ENABLE_PCSC)
    1491                 :            : " passthru                        (alias for use_hw=yes, hw_type=PASSTHRU)\n"
    1492                 :            : #endif
    1493                 :            : " soft=({slot_name},{vreader_name},{card_type_to_emulate},{params_for_card},\n"
    1494                 :            : "       {cert1},{cert2},{cert3}    (default none)\n"
    1495                 :            : "\n"
    1496                 :            : "  {nss_database}          The location of the NSS cert & key database\n"
    1497                 :            : "  {card_type_to_emulate}  What card interface to present to the guest\n"
    1498                 :            : "  {param_for_card}        Card interface specific parameters\n"
    1499                 :            : "  {slot_name}             NSS slot that contains the certs\n"
    1500                 :            : "  {vreader_name}          Virtual reader name to present to the guest\n"
    1501                 :            : "  {certN}                 Nickname of the certificate n on the virtual card\n"
    1502                 :            : "\n"
    1503                 :            : "These parameters come as a single string separated by blanks or newlines."
    1504                 :            : "\n"
    1505                 :            : "Unless use_hw is set to no, all tokens that look like removable hardware\n"
    1506                 :            : "tokens will be presented to the guest using the emulator specified by\n"
    1507                 :            : "hw_type, and parameters of hw_params. If use_hw is set to 'removable', "
    1508                 :            : "present any removable token.\n"
    1509                 :            : "\n"
    1510                 :            : "If more one or more soft= parameters are specified, these readers will be\n"
    1511                 :            : "presented to the guest\n"
    1512                 :            : #if defined(ENABLE_PCSC)
    1513                 :            : "\n"
    1514                 :            : "If a hw_type of PASSTHRU is given, a connection will be made to the hardware\n"
    1515                 :            : "using libpcscslite.  Note that in that case, no soft cards are permitted.\n"
    1516                 :            : #endif
    1517                 :            : );
    1518                 :          0 : }
    1519                 :            : /* vim: set ts=4 sw=4 tw=0 noet expandtab: */

Generated by: LCOV version 1.14