LCOV - code coverage report
Current view: top level - src - card_7816.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 72.3 % 321 232
Test Date: 2025-12-04 16:15:14 Functions: 93.3 % 15 14
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 63.9 % 155 99

             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                 :         158 :     response->b_status = status; /* make sure the status and swX representations
      37                 :             :                                   * are consistent */
      38                 :         158 :     sw1 = (status >> 8) & 0xff;
      39                 :         158 :     sw2 = status & 0xff;
      40                 :         158 :     response->b_sw1 = sw1;
      41                 :         158 :     response->b_sw2 = sw2;
      42                 :         158 :     response->b_data[response->b_len] = sw1;
      43                 :         158 :     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                 :         249 : vcard_response_new_data(const unsigned char *buf, int len)
      66                 :             : {
      67                 :             :     VCardResponse *new_response;
      68                 :             : 
      69                 :         249 :     new_response = g_new0(VCardResponse, 1);
      70                 :         249 :     new_response->b_data = g_malloc(len + 2);
      71                 :         249 :     memcpy(new_response->b_data, buf, len);
      72                 :         249 :     new_response->b_total_len = len+2;
      73                 :         249 :     new_response->b_len = len;
      74                 :         249 :     new_response->b_type = VCARD_MALLOC;
      75                 :         249 :     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                 :         376 : 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                 :         376 :     g_debug("%s: Sending response (len = %d, Le = %d)", __func__, len, Le);
     112         [ +  + ]:         376 :     if (len > Le) {
     113                 :         218 :         return vcard_init_buffer_response(card, buf, len);
     114                 :             :     }
     115                 :         158 :     new_response = vcard_response_new_data(buf, len);
     116         [ +  - ]:         158 :     if (new_response == NULL) {
     117                 :             :         return NULL;
     118                 :             :     }
     119                 :             :     vcard_response_set_status(new_response, status);
     120                 :         158 :     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                 :         249 :     case VCARD_MALLOC:
     191                 :             :         /* everything was malloc'ed */
     192                 :         249 :         g_free(response->b_data);
     193                 :         249 :         g_free(response);
     194                 :         249 :         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                 :             :     if (*status != VCARD7816_STATUS_SUCCESS) {
     359                 :             :         vcard_apdu_delete(new_apdu);
     360                 :             :         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                 :         136 : vcard_make_response(vcard_7816_status_t status)
     431                 :             : {
     432                 :             :     VCardResponse *response;
     433                 :             : 
     434   [ -  -  -  -  :         136 :     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                 :           0 :     case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE:
     467                 :           0 :         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                 :          26 :     case VCARD7816_STATUS_ERROR_DATA_INVALID:
     494                 :          26 :         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                 :             :         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 2.0-1