LCOV - code coverage report
Current view: top level - src - card_7816.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 233 323 72.1 %
Date: 2023-06-12 11:14:12 Functions: 14 15 93.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 101 161 62.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Implement the 7816 portion of the card spec
       3                 :            :  *
       4                 :            :  * This code is licensed under the GNU LGPL, version 2.1 or later.
       5                 :            :  * See the COPYING file in the top-level directory.
       6                 :            :  */
       7                 :            : 
       8                 :            : #include <glib.h>
       9                 :            : 
      10                 :            : #include <string.h>
      11                 :            : 
      12                 :            : #include "vcard.h"
      13                 :            : #include "vcard_emul.h"
      14                 :            : #include "card_7816.h"
      15                 :            : #include "common.h"
      16                 :            : 
      17                 :            : 
      18                 :            : /* Global Platform Card Manager applet AID */
      19                 :            : static const unsigned char gp_aid[] = {
      20                 :            :     0xa0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00 };
      21                 :            : /* Global Platform Card Manager response on select applet */
      22                 :            : static const unsigned char gp_response[] = {
      23                 :            :     0x6F, 0x19, 0x84, 0x08, 0xA0, 0x00, 0x00, 0x00,
      24                 :            :     0x03, 0x00, 0x00, 0x00, 0xA5, 0x0D, 0x9F, 0x6E,
      25                 :            :     0x06, 0x12, 0x91, 0x51, 0x81, 0x01, 0x00, 0x9F,
      26                 :            :     0x65, 0x01, 0xFF};
      27                 :            : 
      28                 :            : 
      29                 :            : /*
      30                 :            :  * set the status bytes based on the status word
      31                 :            :  */
      32                 :            : static void
      33                 :            : vcard_response_set_status(VCardResponse *response, vcard_7816_status_t status)
      34                 :            : {
      35                 :            :     unsigned char sw1, sw2;
      36                 :        157 :     response->b_status = status; /* make sure the status and swX representations
      37                 :            :                                   * are consistent */
      38                 :        157 :     sw1 = (status >> 8) & 0xff;
      39                 :        157 :     sw2 = status & 0xff;
      40                 :        157 :     response->b_sw1 = sw1;
      41                 :        157 :     response->b_sw2 = sw2;
      42                 :        157 :     response->b_data[response->b_len] = sw1;
      43                 :        157 :     response->b_data[response->b_len+1] = sw2;
      44                 :            : }
      45                 :            : 
      46                 :            : /*
      47                 :            :  * set the status bytes in a response buffer
      48                 :            :  */
      49                 :            : void
      50                 :        457 : vcard_response_set_status_bytes(VCardResponse *response,
      51                 :            :                                unsigned char sw1, unsigned char sw2)
      52                 :            : {
      53                 :        457 :     response->b_status = sw1 << 8 | sw2;
      54                 :        457 :     response->b_sw1 = sw1;
      55                 :        457 :     response->b_sw2 = sw2;
      56                 :        457 :     response->b_data[response->b_len] = sw1;
      57                 :        457 :     response->b_data[response->b_len+1] = sw2;
      58                 :        457 : }
      59                 :            : 
      60                 :            : /*
      61                 :            :  * allocate a VCardResponse structure, plus space for the data buffer, and
      62                 :            :  * set up everything but the resonse bytes.
      63                 :            :  */
      64                 :            : VCardResponse *
      65                 :        248 : vcard_response_new_data(const unsigned char *buf, int len)
      66                 :            : {
      67                 :            :     VCardResponse *new_response;
      68                 :            : 
      69                 :        248 :     new_response = g_new0(VCardResponse, 1);
      70                 :        248 :     new_response->b_data = g_malloc(len + 2);
      71                 :        248 :     memcpy(new_response->b_data, buf, len);
      72                 :        248 :     new_response->b_total_len = len+2;
      73                 :        248 :     new_response->b_len = len;
      74                 :        248 :     new_response->b_type = VCARD_MALLOC;
      75                 :        248 :     return new_response;
      76                 :            : }
      77                 :            : 
      78                 :            : static VCardResponse *
      79                 :        227 : vcard_init_buffer_response(VCard *card, const unsigned char *buf, int len)
      80                 :            : {
      81                 :            :     VCardResponse *response;
      82                 :            :     VCardBufferResponse *buffer_response;
      83                 :            : 
      84                 :        227 :     buffer_response = vcard_get_buffer_response(card);
      85         [ -  + ]:        227 :     if (buffer_response) {
      86                 :          0 :         vcard_set_buffer_response(card, NULL);
      87                 :          0 :         vcard_buffer_response_delete(buffer_response);
      88                 :            :     }
      89                 :        227 :     buffer_response = vcard_buffer_response_new(buf, len);
      90         [ -  + ]:        227 :     if (buffer_response == NULL) {
      91                 :            :         return NULL;
      92                 :            :     }
      93         [ +  + ]:        432 :     response = vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES,
      94                 :            :                                                len > 255 ? 0 : len);
      95         [ -  + ]:        227 :     if (response == NULL) {
      96                 :            :         return NULL;
      97                 :            :     }
      98                 :        227 :     vcard_set_buffer_response(card, buffer_response);
      99                 :        227 :     return response;
     100                 :            : }
     101                 :            : 
     102                 :            : /*
     103                 :            :  * general buffer to hold results from APDU calls
     104                 :            :  */
     105                 :            : VCardResponse *
     106                 :        375 : vcard_response_new(VCard *card, const unsigned char *buf,
     107                 :            :                    int len, int Le, vcard_7816_status_t status)
     108                 :            : {
     109                 :            :     VCardResponse *new_response;
     110                 :            : 
     111                 :        375 :     g_debug("%s: Sending response (len = %d, Le = %d)", __func__, len, Le);
     112         [ +  + ]:        375 :     if (len > Le) {
     113                 :        218 :         return vcard_init_buffer_response(card, buf, len);
     114                 :            :     }
     115                 :        157 :     new_response = vcard_response_new_data(buf, len);
     116         [ +  - ]:        157 :     if (new_response == NULL) {
     117                 :            :         return NULL;
     118                 :            :     }
     119                 :            :     vcard_response_set_status(new_response, status);
     120                 :        157 :     return new_response;
     121                 :            : }
     122                 :            : 
     123                 :            : /*
     124                 :            :  * general buffer to hold results from APDU calls
     125                 :            :  */
     126                 :            : VCardResponse *
     127                 :         99 : vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le,
     128                 :            :                          unsigned char sw1, unsigned char sw2)
     129                 :            : {
     130                 :            :     VCardResponse *new_response;
     131                 :            : 
     132                 :         99 :     g_debug("%s: Sending response (len = %d, Le = %d)", __func__, len, Le);
     133         [ +  + ]:         99 :     if (len > Le) {
     134                 :          9 :         return vcard_init_buffer_response(card, buf, len);
     135                 :            :     }
     136                 :         90 :     new_response = vcard_response_new_data(buf, len);
     137         [ +  - ]:         90 :     if (new_response == NULL) {
     138                 :            :         return NULL;
     139                 :            :     }
     140                 :         90 :     vcard_response_set_status_bytes(new_response, sw1, sw2);
     141                 :         90 :     return new_response;
     142                 :            : }
     143                 :            : 
     144                 :            : /*
     145                 :            :  * get a new Response buffer that only has a status.
     146                 :            :  */
     147                 :            : static VCardResponse *
     148                 :          0 : vcard_response_new_status(vcard_7816_status_t status)
     149                 :            : {
     150                 :            :     VCardResponse *new_response;
     151                 :            : 
     152                 :          0 :     new_response = g_new(VCardResponse, 1);
     153                 :          0 :     new_response->b_data = &new_response->b_sw1;
     154                 :          0 :     new_response->b_len = 0;
     155                 :          0 :     new_response->b_total_len = 2;
     156                 :          0 :     new_response->b_type = VCARD_MALLOC_STRUCT;
     157                 :            :     vcard_response_set_status(new_response, status);
     158                 :          0 :     return new_response;
     159                 :            : }
     160                 :            : 
     161                 :            : /*
     162                 :            :  * same as above, but specify the status as separate bytes
     163                 :            :  */
     164                 :            : VCardResponse *
     165                 :        367 : vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2)
     166                 :            : {
     167                 :            :     VCardResponse *new_response;
     168                 :            : 
     169                 :        367 :     new_response = g_new(VCardResponse, 1);
     170                 :        367 :     new_response->b_data = &new_response->b_sw1;
     171                 :        367 :     new_response->b_len = 0;
     172                 :        367 :     new_response->b_total_len = 2;
     173                 :        367 :     new_response->b_type = VCARD_MALLOC_STRUCT;
     174                 :        367 :     vcard_response_set_status_bytes(new_response, sw1, sw2);
     175                 :        367 :     return new_response;
     176                 :            : }
     177                 :            : 
     178                 :            : 
     179                 :            : /*
     180                 :            :  * free the response buffer. The Buffer has a type to handle the buffer
     181                 :            :  * allocated in other ways than through malloc.
     182                 :            :  */
     183                 :            : void
     184                 :        752 : vcard_response_delete(VCardResponse *response)
     185                 :            : {
     186         [ +  - ]:        752 :     if (response == NULL) {
     187                 :            :         return;
     188                 :            :     }
     189   [ +  -  +  -  :        752 :     switch (response->b_type) {
                      + ]
     190                 :        248 :     case VCARD_MALLOC:
     191                 :            :         /* everything was malloc'ed */
     192                 :        248 :         g_free(response->b_data);
     193                 :        248 :         g_free(response);
     194                 :        248 :         break;
     195                 :          0 :     case VCARD_MALLOC_DATA:
     196                 :            :         /* only the data buffer was malloc'ed */
     197                 :          0 :         g_free(response->b_data);
     198                 :          0 :         break;
     199                 :        367 :     case VCARD_MALLOC_STRUCT:
     200                 :            :         /* only the structure was malloc'ed */
     201                 :        367 :         g_free(response);
     202                 :        367 :         break;
     203                 :            :     case VCARD_STATIC:
     204                 :            :         break;
     205                 :          0 :     default:
     206                 :          0 :         g_warn_if_reached();
     207                 :            :     }
     208                 :            : }
     209                 :            : 
     210                 :            : /*
     211                 :            :  * decode the class bit and set our generic type field, channel, and
     212                 :            :  * secure messaging values.
     213                 :            :  */
     214                 :            : static vcard_7816_status_t
     215                 :        751 : vcard_apdu_set_class(VCardAPDU *apdu) {
     216                 :        751 :     apdu->a_channel = 0;
     217                 :        751 :     apdu->a_secure_messaging = 0;
     218                 :        751 :     apdu->a_type = apdu->a_cla & 0xf0;
     219                 :        751 :     apdu->a_gen_type = VCARD_7816_ISO;
     220                 :            : 
     221                 :            :     /* parse the class  tables 8 & 9 of the 7816-4 Part 4 spec */
     222   [ +  +  +  + ]:        751 :     switch (apdu->a_type) {
     223                 :            :         /* we only support the basic types */
     224                 :        724 :     case 0x00:
     225                 :            :     case 0x80:
     226                 :            :     case 0x90:
     227                 :            :     case 0xa0:
     228                 :        724 :         apdu->a_channel = apdu->a_cla & 3;
     229                 :        724 :         apdu->a_secure_messaging = apdu->a_cla & 0xe;
     230                 :        724 :         break;
     231                 :            :     case 0xb0:
     232                 :            :     case 0xc0:
     233                 :            :         break;
     234                 :            : 
     235                 :         23 :     case 0x10:
     236                 :            :     case 0x20:
     237                 :            :     case 0x30:
     238                 :            :     case 0x40:
     239                 :            :     case 0x50:
     240                 :            :     case 0x60:
     241                 :            :     case 0x70:
     242                 :            :         /* Reserved for future use */
     243                 :         23 :         apdu->a_gen_type = VCARD_7816_RFU;
     244                 :         23 :         break;
     245                 :          2 :     case 0xd0:
     246                 :            :     case 0xe0:
     247                 :            :     case 0xf0:
     248                 :            :     default:
     249                 :          2 :         apdu->a_gen_type =
     250         [ +  + ]:          2 :             (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPRIETARY;
     251                 :          2 :         break;
     252                 :            :     }
     253                 :        751 :     return VCARD7816_STATUS_SUCCESS;
     254                 :            : }
     255                 :            : 
     256                 :            : /*
     257                 :            :  * set the Le and Lc fields according to table 5 of the
     258                 :            :  * 7816-4 part 4 spec
     259                 :            :  */
     260                 :            : static vcard_7816_status_t
     261                 :        751 : vcard_apdu_set_length(VCardAPDU *apdu)
     262                 :            : {
     263                 :            :     int L, Le;
     264                 :            : 
     265                 :            :     /* process according to table 5 of the 7816-4 Part 4 spec.
     266                 :            :      * variable names match the variables in the spec */
     267                 :        751 :     L = apdu->a_len-4; /* fixed APDU header */
     268                 :        751 :     apdu->a_Lc = 0;
     269                 :        751 :     apdu->a_Le = 0;
     270                 :        751 :     apdu->a_body = NULL;
     271      [ +  +  + ]:        751 :     switch (L) {
     272                 :            :     case 0:
     273                 :            :         /* 1 minimal apdu */
     274                 :            :         return VCARD7816_STATUS_SUCCESS;
     275                 :        314 :     case 1:
     276                 :            :         /* 2S only return values apdu */
     277                 :            :         /*   zero maps to 256 here */
     278                 :        628 :         apdu->a_Le = apdu->a_header->ah_Le ?
     279         [ +  + ]:        314 :                          apdu->a_header->ah_Le : 256;
     280                 :        314 :         return VCARD7816_STATUS_SUCCESS;
     281                 :        351 :     default:
     282                 :            :         /* if the ah_Le byte is zero and we have more than
     283                 :            :          * 1 byte in the header, then we must be using extended Le and Lc.
     284                 :            :          * process the extended now. */
     285         [ +  + ]:        351 :         if (apdu->a_header->ah_Le == 0) {
     286         [ +  - ]:         12 :             if (L < 3) {
     287                 :            :                 /* coding error, need at least 3 bytes */
     288                 :            :                 return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
     289                 :            :             }
     290                 :            :             /* calculate the first extended value. Could be either Le or Lc */
     291                 :         12 :             Le = (apdu->a_header->ah_body[0] << 8)
     292                 :         12 :                 | apdu->a_header->ah_body[1];
     293         [ -  + ]:         12 :             if (L == 3) {
     294                 :            :                 /* 2E extended, return data only */
     295                 :            :                 /*   zero maps to 65536 */
     296         [ #  # ]:          0 :                 apdu->a_Le = Le ? Le : 65536;
     297                 :          0 :                 return VCARD7816_STATUS_SUCCESS;
     298                 :            :             }
     299         [ +  - ]:         12 :             if (Le == 0) {
     300                 :            :                 /* reserved for future use, probably for next time we need
     301                 :            :                  * to extend the lengths */
     302                 :            :                 return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
     303                 :            :             }
     304                 :            :             /* we know that the first extended value is Lc now */
     305                 :         12 :             apdu->a_Lc = Le;
     306                 :         12 :             apdu->a_body = &apdu->a_header->ah_body[2];
     307         [ +  - ]:         12 :             if (L == Le+3) {
     308                 :            :                 /* 3E extended, only body parameters */
     309                 :            :                 return VCARD7816_STATUS_SUCCESS;
     310                 :            :             }
     311         [ #  # ]:          0 :             if (L == Le+5) {
     312                 :            :                 /* 4E extended, parameters and return data */
     313                 :          0 :                 Le = (apdu->a_data[apdu->a_len-2] << 8)
     314                 :          0 :                     | apdu->a_data[apdu->a_len-1];
     315         [ #  # ]:          0 :                 apdu->a_Le = Le ? Le : 65536;
     316                 :          0 :                 return VCARD7816_STATUS_SUCCESS;
     317                 :            :             }
     318                 :            :             return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
     319                 :            :         }
     320                 :            :         /* not extended */
     321                 :        339 :         apdu->a_Lc = apdu->a_header->ah_Le;
     322                 :        339 :         apdu->a_body = &apdu->a_header->ah_body[0];
     323         [ +  + ]:        339 :         if (L ==  apdu->a_Lc + 1) {
     324                 :            :             /* 3S only body parameters */
     325                 :            :             return VCARD7816_STATUS_SUCCESS;
     326                 :            :         }
     327         [ +  - ]:        140 :         if (L ==  apdu->a_Lc + 2) {
     328                 :            :             /* 4S parameters and return data */
     329                 :        140 :             Le = apdu->a_data[apdu->a_len-1];
     330         [ +  + ]:        140 :             apdu->a_Le = Le ?  Le : 256;
     331                 :        140 :             return VCARD7816_STATUS_SUCCESS;
     332                 :            :         }
     333                 :            :         break;
     334                 :            :     }
     335                 :            :     return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
     336                 :            : }
     337                 :            : 
     338                 :            : /*
     339                 :            :  * create a new APDU from a raw set of bytes. This will decode all the
     340                 :            :  * above fields. users of VCARDAPDU's can then depend on the already decoded
     341                 :            :  * values.
     342                 :            :  */
     343                 :            : VCardAPDU *
     344                 :        752 : vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status)
     345                 :            : {
     346                 :            :     VCardAPDU *new_apdu;
     347                 :            : 
     348                 :        752 :     *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
     349         [ +  + ]:        752 :     if (len < 4) {
     350                 :          1 :         *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH;
     351                 :          1 :         return NULL;
     352                 :            :     }
     353                 :            : 
     354                 :        751 :     new_apdu = g_new(VCardAPDU, 1);
     355                 :        751 :     new_apdu->a_data = g_memdup2(raw_apdu, len);
     356                 :        751 :     new_apdu->a_len = len;
     357                 :        751 :     *status = vcard_apdu_set_class(new_apdu);
     358         [ -  + ]:        751 :     if (*status != VCARD7816_STATUS_SUCCESS) {
     359                 :          0 :         vcard_apdu_delete(new_apdu);
     360                 :          0 :         return NULL;
     361                 :            :     }
     362                 :        751 :     *status = vcard_apdu_set_length(new_apdu);
     363         [ -  + ]:        751 :     if (*status != VCARD7816_STATUS_SUCCESS) {
     364                 :          0 :         vcard_apdu_delete(new_apdu);
     365                 :            :         new_apdu = NULL;
     366                 :            :     }
     367                 :            :     return new_apdu;
     368                 :            : }
     369                 :            : 
     370                 :            : void
     371                 :        752 : vcard_apdu_delete(VCardAPDU *apdu)
     372                 :            : {
     373         [ +  + ]:        752 :     if (apdu == NULL) {
     374                 :            :         return;
     375                 :            :     }
     376                 :        751 :     g_free(apdu->a_data);
     377                 :        751 :     g_free(apdu);
     378                 :            : }
     379                 :            : 
     380                 :            : 
     381                 :            : /*
     382                 :            :  * declare response buffers for all the 7816 defined error codes
     383                 :            :  */
     384                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS)
     385                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING)
     386                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT)
     387                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE)
     388                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED)
     389                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID)
     390                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE)
     391                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED)
     392                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR)
     393                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE)
     394                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE)
     395                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH)
     396                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED)
     397                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED)
     398                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED)
     399                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED)
     400                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(
     401                 :            :                     VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE)
     402                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED)
     403                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED)
     404                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID)
     405                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED)
     406                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF)
     407                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING)
     408                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT)
     409                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS)
     410                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(
     411                 :            :                             VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA)
     412                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED)
     413                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND)
     414                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND)
     415                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE)
     416                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT)
     417                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT)
     418                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT)
     419                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND)
     420                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2)
     421                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID)
     422                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID)
     423                 :            : VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL)
     424                 :            : 
     425                 :            : /*
     426                 :            :  * return a single response code. This function cannot fail. It will always
     427                 :            :  * return a response.
     428                 :            :  */
     429                 :            : VCardResponse *
     430                 :        137 : vcard_make_response(vcard_7816_status_t status)
     431                 :            : {
     432                 :            :     VCardResponse *response;
     433                 :            : 
     434   [ -  -  -  -  :        137 :     switch (status) {
          -  -  -  -  -  
          -  +  -  -  +  
          +  -  -  -  +  
          +  -  -  -  +  
          +  +  +  -  -  
          -  +  -  +  -  
             +  -  -  -  
                      + ]
     435                 :            :     /* known 7816 response codes */
     436                 :            :     case VCARD7816_STATUS_SUCCESS:
     437                 :            :         return VCARD_RESPONSE_GET_STATIC(
     438                 :            :                     VCARD7816_STATUS_SUCCESS);
     439                 :          0 :     case VCARD7816_STATUS_WARNING:
     440                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     441                 :            :                     VCARD7816_STATUS_WARNING);
     442                 :          0 :     case VCARD7816_STATUS_WARNING_RET_CORUPT:
     443                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     444                 :            :                     VCARD7816_STATUS_WARNING_RET_CORUPT);
     445                 :          0 :     case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE:
     446                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     447                 :            :                     VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE);
     448                 :          0 :     case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED:
     449                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     450                 :            :                     VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED);
     451                 :          0 :     case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID:
     452                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     453                 :            :                     VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID);
     454                 :          0 :     case VCARD7816_STATUS_WARNING_CHANGE:
     455                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     456                 :            :                     VCARD7816_STATUS_WARNING_CHANGE);
     457                 :          0 :     case VCARD7816_STATUS_WARNING_FILE_FILLED:
     458                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     459                 :            :                     VCARD7816_STATUS_WARNING_FILE_FILLED);
     460                 :          0 :     case VCARD7816_STATUS_EXC_ERROR:
     461                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     462                 :            :                     VCARD7816_STATUS_EXC_ERROR);
     463                 :          0 :     case VCARD7816_STATUS_EXC_ERROR_CHANGE:
     464                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     465                 :            :                     VCARD7816_STATUS_EXC_ERROR_CHANGE);
     466                 :            :     case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE:
     467                 :            :         return VCARD_RESPONSE_GET_STATIC(
     468                 :            :                     VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
     469                 :          1 :     case VCARD7816_STATUS_ERROR_WRONG_LENGTH:
     470                 :          1 :         return VCARD_RESPONSE_GET_STATIC(
     471                 :            :                     VCARD7816_STATUS_ERROR_WRONG_LENGTH);
     472                 :          0 :     case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED:
     473                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     474                 :            :                     VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED);
     475                 :          0 :     case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED:
     476                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     477                 :            :                     VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED);
     478                 :          1 :     case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED:
     479                 :          1 :         return VCARD_RESPONSE_GET_STATIC(
     480                 :            :                     VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
     481                 :          7 :     case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED:
     482                 :          7 :         return VCARD_RESPONSE_GET_STATIC(
     483                 :            :                     VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
     484                 :          0 :     case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE:
     485                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     486                 :            :                     VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE);
     487                 :          0 :     case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED:
     488                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     489                 :            :                     VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED);
     490                 :          0 :     case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED:
     491                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     492                 :            :                     VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED);
     493                 :         27 :     case VCARD7816_STATUS_ERROR_DATA_INVALID:
     494                 :         27 :         return VCARD_RESPONSE_GET_STATIC(
     495                 :            :                     VCARD7816_STATUS_ERROR_DATA_INVALID);
     496                 :          2 :     case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED:
     497                 :          2 :         return VCARD_RESPONSE_GET_STATIC(
     498                 :            :                     VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
     499                 :          0 :     case VCARD7816_STATUS_ERROR_DATA_NO_EF:
     500                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     501                 :            :                     VCARD7816_STATUS_ERROR_DATA_NO_EF);
     502                 :          0 :     case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING:
     503                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     504                 :            :                     VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING);
     505                 :          0 :     case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT:
     506                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     507                 :            :                     VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT);
     508                 :          3 :     case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS:
     509                 :          3 :         return VCARD_RESPONSE_GET_STATIC(
     510                 :            :                     VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
     511                 :          1 :     case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA:
     512                 :          1 :         return VCARD_RESPONSE_GET_STATIC(
     513                 :            :                     VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA);
     514                 :          1 :     case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED:
     515                 :          1 :         return VCARD_RESPONSE_GET_STATIC(
     516                 :            :                     VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
     517                 :          3 :     case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND:
     518                 :          3 :         return VCARD_RESPONSE_GET_STATIC(
     519                 :            :                     VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
     520                 :          0 :     case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND:
     521                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     522                 :            :                     VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND);
     523                 :          0 :     case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE:
     524                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     525                 :            :                     VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE);
     526                 :          0 :     case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT:
     527                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     528                 :            :                     VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT);
     529                 :         16 :     case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT:
     530                 :         16 :         return VCARD_RESPONSE_GET_STATIC(
     531                 :            :                     VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
     532                 :          0 :     case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT:
     533                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     534                 :            :                     VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT);
     535                 :         14 :     case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND:
     536                 :         14 :         return VCARD_RESPONSE_GET_STATIC(
     537                 :            :                     VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
     538                 :          0 :     case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2:
     539                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     540                 :            :                     VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2);
     541                 :          2 :     case VCARD7816_STATUS_ERROR_INS_CODE_INVALID:
     542                 :          2 :         return VCARD_RESPONSE_GET_STATIC(
     543                 :            :                     VCARD7816_STATUS_ERROR_INS_CODE_INVALID);
     544                 :          0 :     case VCARD7816_STATUS_ERROR_CLA_INVALID:
     545                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     546                 :            :                     VCARD7816_STATUS_ERROR_CLA_INVALID);
     547                 :          0 :     case VCARD7816_STATUS_ERROR_GENERAL:
     548                 :          0 :         return VCARD_RESPONSE_GET_STATIC(
     549                 :            :                     VCARD7816_STATUS_ERROR_GENERAL);
     550                 :          0 :     default:
     551                 :            :         /* we don't know this status code, create a response buffer to
     552                 :            :          * hold it */
     553                 :          0 :         response = vcard_response_new_status(status);
     554         [ #  # ]:          0 :         if (response == NULL) {
     555                 :            :             /* couldn't allocate the buffer, return memmory error */
     556                 :            :             return VCARD_RESPONSE_GET_STATIC(
     557                 :            :                         VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
     558                 :            :         }
     559                 :            :         return response;
     560                 :            :     }
     561                 :            : }
     562                 :            : 
     563                 :            : /*
     564                 :            :  * Add File card support here if you need it.
     565                 :            :  */
     566                 :            : static VCardStatus
     567                 :            : vcard7816_file_system_process_apdu(G_GNUC_UNUSED VCard *card,
     568                 :            :                                    G_GNUC_UNUSED VCardAPDU *apdu,
     569                 :            :                                    VCardResponse **response)
     570                 :            : {
     571                 :            :     /* TODO: if we want to support a virtual file system card, we do it here.
     572                 :            :      * It would probably be a pkcs #15 card type */
     573                 :          0 :     *response = vcard_make_response(
     574                 :            :                     VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
     575                 :            :     return VCARD_DONE;
     576                 :            : }
     577                 :            : 
     578                 :            : /*
     579                 :            :  * VM card (including java cards)
     580                 :            :  */
     581                 :            : static VCardStatus
     582                 :        204 : vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu,
     583                 :            :                           VCardResponse **response)
     584                 :            : {
     585                 :            :     int bytes_to_copy, next_byte_count, count;
     586                 :            :     VCardApplet *current_applet;
     587                 :            :     VCardBufferResponse *buffer_response;
     588                 :            :     vcard_7816_status_t status;
     589                 :            : 
     590                 :            :     /* parse the class first */
     591         [ +  + ]:        204 :     if (apdu->a_gen_type !=  VCARD_7816_ISO) {
     592                 :          1 :         *response = vcard_make_response(
     593                 :            :                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
     594                 :          1 :         return VCARD_DONE;
     595                 :            :     }
     596                 :            : 
     597                 :            :     /* use a switch so that if we need to support secure channel stuff later,
     598                 :            :      * we know where to put it */
     599         [ +  + ]:        203 :     switch (apdu->a_secure_messaging) {
     600                 :            :     case 0x0: /* no SM */
     601                 :            :         break;
     602                 :          1 :     case 0x4: /* proprietary SM */
     603                 :            :     case 0x8: /* header not authenticated */
     604                 :            :     case 0xc: /* header authenticated */
     605                 :            :     default:
     606                 :            :         /* for now, don't try to support secure channel stuff in the
     607                 :            :          * virtual card. */
     608                 :          1 :         *response = vcard_make_response(
     609                 :            :                         VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
     610                 :          1 :         return VCARD_DONE;
     611                 :            :     }
     612                 :            : 
     613                 :            :     /* now parse the instruction */
     614   [ +  +  +  +  :        202 :     switch (apdu->a_ins) {
                   -  + ]
     615                 :          1 :     case  VCARD7816_INS_MANAGE_CHANNEL: /* secure channel op */
     616                 :            :     case  VCARD7816_INS_EXTERNAL_AUTHENTICATE: /* secure channel op */
     617                 :            :     case  VCARD7816_INS_GET_CHALLENGE: /* secure channel op */
     618                 :            :     case  VCARD7816_INS_INTERNAL_AUTHENTICATE: /* secure channel op */
     619                 :            :     case  VCARD7816_INS_ERASE_BINARY: /* applet control op */
     620                 :            :     case  VCARD7816_INS_READ_BINARY: /* applet control op */
     621                 :            :     case  VCARD7816_INS_WRITE_BINARY: /* applet control op */
     622                 :            :     case  VCARD7816_INS_UPDATE_BINARY: /* applet control op */
     623                 :            :     case  VCARD7816_INS_READ_RECORD: /* file op */
     624                 :            :     case  VCARD7816_INS_WRITE_RECORD: /* file op */
     625                 :            :     case  VCARD7816_INS_UPDATE_RECORD: /* file op */
     626                 :            :     case  VCARD7816_INS_APPEND_RECORD: /* file op */
     627                 :            :     case  VCARD7816_INS_ENVELOPE:
     628                 :            :     case  VCARD7816_INS_PUT_DATA:
     629                 :          1 :         *response = vcard_make_response(
     630                 :            :                             VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
     631                 :          1 :         break;
     632                 :            : 
     633                 :         98 :     case  VCARD7816_INS_SELECT_FILE:
     634                 :            :         /* GSC-IS: 5.3.3.2 Select Applet APDU: P1 = 0x04 */
     635         [ +  + ]:         98 :         if (apdu->a_p1 != 0x04) {
     636                 :          1 :             *response = vcard_make_response(
     637                 :            :                             VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
     638                 :          1 :             break;
     639                 :            :         }
     640                 :         97 :         g_debug("%s: Selecting file %s", __func__, hex_dump(apdu->a_body, apdu->a_Lc));
     641                 :            : 
     642                 :            :         /* side effect, deselect the current applet if no applet has been found
     643                 :            :          */
     644                 :         97 :         current_applet = vcard_find_applet(card, apdu->a_body, apdu->a_Lc);
     645                 :         97 :         vcard_select_applet(card, apdu->a_channel, current_applet);
     646         [ +  + ]:         97 :         if (current_applet) {
     647                 :         96 :             VCardApplet *gp_applet = vcard_find_applet(card,
     648                 :            :                 gp_aid, sizeof(gp_aid));
     649         [ +  + ]:         96 :             if (current_applet == gp_applet) {
     650                 :            :                 /* if the new applet is Global Platform Card Manager, we need to
     651                 :            :                  * return a response (from Card Specification v2.3.1):
     652                 :            :                  *
     653                 :            :                  * 6F 19 : FCI Template
     654                 :            :                  *  84 08 : Application / file AID
     655                 :            :                  *   A0 00 00 00 03 00 00 00
     656                 :            :                  *  A5 0D : Proprietary data
     657                 :            :                  *   9F 6E 06 : Application Producution Life Cycle
     658                 :            :                  *    12 91 51 81 01 00
     659                 :            :                  *   9F 65 01 : Maximum Length of data field in comand message
     660                 :            :                  *    FF
     661                 :            :                  */
     662                 :          6 :                 *response = vcard_response_new(card, gp_response,
     663                 :            :                     sizeof(gp_response), apdu->a_Le, VCARD7816_STATUS_SUCCESS);
     664                 :            :             } else {
     665                 :         90 :                 unsigned char fci_template[] = {
     666                 :            :                     0x6F, 0x0B, /* Outer lenght to be replaced later */
     667                 :            :                     0x84, 0x07, /* AID length to be replaced later */
     668                 :            :                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* AID */
     669                 :            :                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     670                 :            :                     0xA5, 0x00}; /* The rest */
     671                 :         90 :                 size_t fci_template_len = 6 + apdu->a_Lc;
     672                 :            :                 /* with GSC-IS 2 applets, we do not need to return anything
     673                 :            :                  * for select applet, but cards generally do, at least this
     674                 :            :                  * FCI template stub:
     675                 :            :                  *
     676                 :            :                  * 6F 0B : FCI Template
     677                 :            :                  *  84 07 : Application / file AID
     678                 :            :                  *   A0 00 00 00 79 03 00
     679                 :            :                  *  A5 00 : Proprietary data
     680                 :            :                  */
     681                 :            :                 /* Insert the correct AID in the structure */
     682         [ -  + ]:         90 :                 g_assert_cmpint(fci_template_len, <=, sizeof(fci_template));
     683                 :         90 :                 fci_template[1] = apdu->a_Lc + 4;
     684                 :         90 :                 fci_template[3] = apdu->a_Lc;
     685                 :         90 :                 memcpy(&fci_template[4], apdu->a_body, apdu->a_Lc);
     686                 :         90 :                 fci_template[apdu->a_Lc + 4] = 0xA5;
     687                 :         90 :                 fci_template[apdu->a_Lc + 5] = 0x00;
     688                 :         90 :                 *response = vcard_response_new(card, fci_template,
     689                 :            :                     fci_template_len, apdu->a_Le, VCARD7816_STATUS_SUCCESS);
     690                 :            :             }
     691                 :            :         } else {
     692                 :            :             /* the real CAC returns (SW1=0x6A, SW2=0x82) */
     693                 :          1 :             *response = vcard_make_response(
     694                 :            :                              VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
     695                 :            :         }
     696                 :            :         break;
     697                 :            : 
     698                 :         49 :     case  VCARD7816_INS_VERIFY:
     699   [ +  +  -  + ]:         49 :         if ((apdu->a_p1 != 0x00) || (apdu->a_p2 != 0x00)) {
     700                 :          3 :             *response = vcard_make_response(
     701                 :            :                             VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
     702                 :            :         } else {
     703         [ +  + ]:         46 :             if (apdu->a_Lc == 0) {
     704                 :            :                 /* If we are already logged in, we should succeed just now */
     705         [ +  + ]:         26 :                 if (vcard_emul_is_logged_in(card)) {
     706                 :         22 :                     *response = vcard_make_response(VCARD7816_STATUS_SUCCESS);
     707                 :         22 :                     break;
     708                 :            :                 }
     709                 :            :                 /* handle pin count if possible (not possible now) */
     710                 :          4 :                 count = vcard_get_login_count(card);
     711         [ +  + ]:          4 :                 if (count < 0) {
     712                 :          2 :                     *response = vcard_make_response(
     713                 :            :                                     VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
     714                 :            :                 } else {
     715                 :          2 :                     if (count > 0xf) {
     716                 :            :                         count = 0xf;
     717                 :            :                     }
     718                 :          4 :                     *response = vcard_response_new_status_bytes(
     719                 :            :                                                 VCARD7816_SW1_WARNING_CHANGE,
     720                 :          2 :                                                                 0xc0 | count);
     721         [ -  + ]:          2 :                     if (*response == NULL) {
     722                 :          0 :                         *response = vcard_make_response(
     723                 :            :                                     VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
     724                 :            :                     }
     725                 :            :                 }
     726                 :            :             } else {
     727                 :         20 :                 status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc);
     728                 :         20 :                 *response = vcard_make_response(status);
     729                 :            :             }
     730                 :            :         }
     731                 :            :         break;
     732                 :            : 
     733                 :         53 :     case VCARD7816_INS_GET_RESPONSE:
     734                 :         53 :         buffer_response = vcard_get_buffer_response(card);
     735         [ +  + ]:         53 :         if (!buffer_response) {
     736                 :          3 :             *response = vcard_make_response(
     737                 :            :                             VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
     738                 :            :             /* handle error */
     739                 :          3 :             break;
     740                 :            :         }
     741                 :         50 :         bytes_to_copy = MIN(buffer_response->len, apdu->a_Le);
     742                 :         50 :         next_byte_count = MIN(256, buffer_response->len - bytes_to_copy);
     743         [ +  + ]:         99 :         *response = vcard_response_new_bytes(
     744                 :            :                         card, buffer_response->current, bytes_to_copy,
     745                 :            :                         apdu->a_Le,
     746                 :            :                         next_byte_count ?
     747                 :            :                         VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS,
     748                 :            :                         next_byte_count);
     749                 :         50 :         buffer_response->current += bytes_to_copy;
     750                 :         50 :         buffer_response->len -= bytes_to_copy;
     751   [ +  -  +  + ]:         50 :         if (*response == NULL || (next_byte_count == 0)) {
     752                 :         49 :             vcard_set_buffer_response(card, NULL);
     753                 :         49 :             vcard_buffer_response_delete(buffer_response);
     754                 :            :         }
     755         [ -  + ]:         50 :         if (*response == NULL) {
     756                 :          0 :             *response =
     757                 :          0 :                 vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
     758                 :            :         }
     759                 :            :         break;
     760                 :            : 
     761                 :          0 :     case VCARD7816_INS_GET_DATA:
     762                 :          0 :         *response =
     763                 :          0 :             vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
     764                 :          0 :         break;
     765                 :            : 
     766                 :          1 :     default:
     767                 :          1 :         *response =
     768                 :          1 :             vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
     769                 :          1 :         break;
     770                 :            :     }
     771                 :            : 
     772                 :            :     /* response should have been set somewhere */
     773   [ -  +  -  + ]:        202 :     g_assert(*response != NULL);
     774                 :            :     return VCARD_DONE;
     775                 :            : }
     776                 :            : 
     777                 :            : 
     778                 :            : /*
     779                 :            :  * APDU processing starts here. This routes the card processing stuff to the
     780                 :            :  * right location.
     781                 :            :  */
     782                 :            : VCardStatus
     783                 :        751 : vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
     784                 :            : {
     785                 :            :     VCardStatus status;
     786                 :            :     VCardBufferResponse *buffer_response;
     787                 :            : 
     788                 :            :     /* first handle any PTS commands, which aren't really APDU's */
     789         [ +  + ]:        751 :     if (apdu->a_gen_type == VCARD_7816_PTS) {
     790                 :            :         /* the PTS responses aren't really responses either */
     791                 :          1 :         *response = vcard_response_new_data(apdu->a_data, apdu->a_len);
     792                 :            :         /* PTS responses have no status bytes */
     793                 :          1 :         (*response)->b_total_len = (*response)->b_len;
     794                 :          1 :         return VCARD_DONE;
     795                 :            :     }
     796                 :        750 :     buffer_response = vcard_get_buffer_response(card);
     797   [ +  +  +  + ]:        750 :     if (buffer_response && apdu->a_ins != VCARD7816_INS_GET_RESPONSE) {
     798                 :            :         /* clear out buffer_response, do not return an error */
     799                 :        177 :         vcard_set_buffer_response(card, NULL);
     800                 :        177 :         vcard_buffer_response_delete(buffer_response);
     801                 :            :     }
     802                 :            : 
     803                 :        750 :     status = vcard_process_applet_apdu(card, apdu, response);
     804         [ +  + ]:        750 :     if (status != VCARD_NEXT) {
     805                 :            :         return status;
     806                 :            :     }
     807   [ -  +  -  - ]:        204 :     switch (vcard_get_type(card)) {
     808                 :            :     case VCARD_FILE_SYSTEM:
     809                 :          0 :         return vcard7816_file_system_process_apdu(card, apdu, response);
     810                 :        204 :     case VCARD_VM:
     811                 :        204 :         return vcard7816_vm_process_apdu(card, apdu, response);
     812                 :            :     case VCARD_DIRECT:
     813                 :            :         /* if we are type direct, then the applet should handle everything */
     814                 :          0 :         g_assert(!"VCARD_DIRECT: applet failure");
     815                 :            :         break;
     816                 :          0 :     default:
     817                 :          0 :         g_warn_if_reached();
     818                 :            :     }
     819                 :          0 :     *response =
     820                 :          0 :         vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
     821                 :          0 :     return VCARD_DONE;
     822                 :            : }
     823                 :            : 
     824                 :            : /* vim: set ts=4 sw=4 tw=0 noet expandtab: */

Generated by: LCOV version 1.14