LCOV - code coverage report
Current view: top level - scd - atr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 161 0.0 %
Date: 2016-11-29 15:00:56 Functions: 0 1 0.0 %

          Line data    Source code
       1             : /* atr.c - ISO 7816 ATR fucntions
       2             :  * Copyright (C) 2003, 2011 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * GnuPG is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *
      11             :  * GnuPG is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include <config.h>
      21             : #include <errno.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <assert.h>
      26             : 
      27             : #include <gpg-error.h>
      28             : #include "../common/logging.h"
      29             : #include "atr.h"
      30             : 
      31             : static int const fi_table[16] = { 0, 372, 558, 744, 1116,1488, 1860, -1,
      32             :                                   -1, 512, 768, 1024, 1536, 2048, -1, -1 };
      33             : static int const di_table[16] = { -1, 1, 2, 4, 8, 16, -1, -1,
      34             :                                   0, -1, -2, -4, -8, -16, -32, -64};
      35             : 
      36             : 
      37             : /* Dump the ATR in (BUFFER,BUFLEN) to a human readable format and
      38             :    return that as a malloced buffer.  The caller must release this
      39             :    buffer using es_free!  On error this function returns NULL and sets
      40             :    ERRNO.  */
      41             : char *
      42           0 : atr_dump (const void *buffer, size_t buflen)
      43             : {
      44           0 :   const unsigned char *atr = buffer;
      45           0 :   size_t atrlen = buflen;
      46             :   estream_t fp;
      47             :   int have_ta, have_tb, have_tc, have_td;
      48             :   int n_historical;
      49             :   int idx, val;
      50             :   unsigned char chksum;
      51             :   char *result;
      52             : 
      53           0 :   fp = es_fopenmem (0, "rwb,samethread");
      54           0 :   if (!fp)
      55           0 :     return NULL;
      56             : 
      57           0 :   if (!atrlen)
      58             :     {
      59           0 :       es_fprintf (fp, "error: empty ATR\n");
      60           0 :       goto bailout;
      61             :     }
      62             : 
      63           0 :   for (idx=0; idx < atrlen ; idx++)
      64           0 :     es_fprintf (fp, "%s%02X", idx?" ":"", atr[idx]);
      65           0 :   es_putc ('\n', fp);
      66             : 
      67           0 :   if (*atr == 0x3b)
      68           0 :     es_fputs ("Direct convention\n", fp);
      69           0 :   else if (*atr == 0x3f)
      70           0 :     es_fputs ("Inverse convention\n", fp);
      71             :   else
      72           0 :     es_fprintf (fp,"error: invalid TS character 0x%02x\n", *atr);
      73           0 :   if (!--atrlen)
      74           0 :     goto bailout;
      75           0 :   atr++;
      76             : 
      77           0 :   chksum = *atr;
      78           0 :   for (idx=1; idx < atrlen-1; idx++)
      79           0 :     chksum ^= atr[idx];
      80             : 
      81           0 :   have_ta = !!(*atr & 0x10);
      82           0 :   have_tb = !!(*atr & 0x20);
      83           0 :   have_tc = !!(*atr & 0x40);
      84           0 :   have_td = !!(*atr & 0x80);
      85           0 :   n_historical = (*atr & 0x0f);
      86           0 :   es_fprintf (fp, "%d historical characters indicated\n", n_historical);
      87             : 
      88           0 :   if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
      89           0 :     es_fputs ("error: ATR shorter than indicated by format character\n", fp);
      90           0 :   if (!--atrlen)
      91           0 :     goto bailout;
      92           0 :   atr++;
      93             : 
      94           0 :   if (have_ta)
      95             :     {
      96           0 :       es_fputs ("TA1: F=", fp);
      97           0 :       val = fi_table[(*atr >> 4) & 0x0f];
      98           0 :       if (!val)
      99           0 :         es_fputs ("internal clock", fp);
     100           0 :       else if (val == -1)
     101           0 :         es_fputs ("RFU", fp);
     102             :       else
     103           0 :         es_fprintf (fp, "%d", val);
     104           0 :       es_fputs (" D=", fp);
     105           0 :       val = di_table[*atr & 0x0f];
     106           0 :       if (!val)
     107           0 :         es_fputs ("[impossible value]\n", fp);
     108           0 :       else if (val == -1)
     109           0 :         es_fputs ("RFU\n", fp);
     110           0 :       else if (val < 0 )
     111           0 :         es_fprintf (fp, "1/%d\n", val);
     112             :       else
     113           0 :         es_fprintf (fp, "%d\n", val);
     114             : 
     115           0 :       if (!--atrlen)
     116           0 :         goto bailout;
     117           0 :       atr++;
     118             :     }
     119             : 
     120           0 :   if (have_tb)
     121             :     {
     122           0 :       es_fprintf (fp, "TB1: II=%d PI1=%d%s\n",
     123           0 :                   ((*atr >> 5) & 3), (*atr & 0x1f),
     124           0 :                   (*atr & 0x80)? " [high bit not cleared]":"");
     125           0 :       if (!--atrlen)
     126           0 :         goto bailout;
     127           0 :       atr++;
     128             :     }
     129             : 
     130           0 :   if (have_tc)
     131             :     {
     132           0 :       if (*atr == 255)
     133           0 :         es_fputs ("TC1: guard time shortened to 1 etu\n", fp);
     134             :       else
     135           0 :         es_fprintf (fp, "TC1: (extra guard time) N=%d\n", *atr);
     136             : 
     137           0 :       if (!--atrlen)
     138           0 :         goto bailout;
     139           0 :       atr++;
     140             :     }
     141             : 
     142           0 :   if (have_td)
     143             :     {
     144           0 :       have_ta = !!(*atr & 0x10);
     145           0 :       have_tb = !!(*atr & 0x20);
     146           0 :       have_tc = !!(*atr & 0x40);
     147           0 :       have_td = !!(*atr & 0x80);
     148           0 :       es_fprintf (fp, "TD1: protocol T%d supported\n", (*atr & 0x0f));
     149             : 
     150           0 :       if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
     151           0 :         es_fputs ("error: ATR shorter than indicated by format character\n",
     152             :                   fp);
     153             : 
     154           0 :       if (!--atrlen)
     155           0 :         goto bailout;
     156           0 :       atr++;
     157             :     }
     158             :   else
     159           0 :     have_ta = have_tb = have_tc = have_td = 0;
     160             : 
     161           0 :   if (have_ta)
     162             :     {
     163           0 :       es_fprintf (fp, "TA2: (PTS) %stoggle, %splicit, T=%02X\n",
     164           0 :                   (*atr & 0x80)? "no-":"",
     165           0 :                   (*atr & 0x10)? "im": "ex",
     166           0 :                   (*atr & 0x0f));
     167           0 :       if ((*atr & 0x60))
     168           0 :         es_fprintf (fp, "note: reserved bits are set (TA2=0x%02X)\n", *atr);
     169           0 :       if (!--atrlen)
     170           0 :         goto bailout;
     171           0 :       atr++;
     172             :     }
     173             : 
     174           0 :   if (have_tb)
     175             :     {
     176           0 :       es_fprintf (fp, "TB2: PI2=%d\n", *atr);
     177           0 :       if (!--atrlen)
     178           0 :         goto bailout;
     179           0 :       atr++;
     180             :     }
     181             : 
     182           0 :   if (have_tc)
     183             :     {
     184           0 :       es_fprintf (fp, "TC2: PWI=%d\n", *atr);
     185           0 :       if (!--atrlen)
     186           0 :         goto bailout;
     187           0 :       atr++;
     188             :     }
     189             : 
     190           0 :   if (have_td)
     191             :     {
     192           0 :       have_ta = !!(*atr & 0x10);
     193           0 :       have_tb = !!(*atr & 0x20);
     194           0 :       have_tc = !!(*atr & 0x40);
     195           0 :       have_td = !!(*atr & 0x80);
     196           0 :       es_fprintf (fp, "TD2: protocol T%d supported\n", *atr & 0x0f);
     197             : 
     198           0 :       if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
     199           0 :         es_fputs ("error: ATR shorter than indicated by format character\n",
     200             :                   fp);
     201             : 
     202           0 :       if (!--atrlen)
     203           0 :         goto bailout;
     204           0 :       atr++;
     205             :     }
     206             :   else
     207           0 :     have_ta = have_tb = have_tc = have_td = 0;
     208             : 
     209           0 :   for (idx = 3; have_ta || have_tb || have_tc || have_td; idx++)
     210             :     {
     211           0 :       if (have_ta)
     212             :         {
     213           0 :           es_fprintf (fp, "TA%d: IFSC=%d\n", idx, *atr);
     214           0 :           if (!--atrlen)
     215           0 :             goto bailout;
     216           0 :           atr++;
     217             :         }
     218             : 
     219           0 :       if (have_tb)
     220             :         {
     221           0 :           es_fprintf (fp, "TB%d: BWI=%d CWI=%d\n",
     222           0 :                    idx, (*atr >> 4) & 0x0f, *atr & 0x0f);
     223           0 :           if (!--atrlen)
     224           0 :             goto bailout;
     225           0 :           atr++;
     226             :         }
     227             : 
     228           0 :       if (have_tc)
     229             :         {
     230           0 :           es_fprintf (fp, "TC%d: 0x%02X\n", idx, *atr);
     231           0 :           if (!--atrlen)
     232           0 :             goto bailout;
     233           0 :           atr++;
     234             :         }
     235             : 
     236           0 :       if (have_td)
     237             :         {
     238           0 :           have_ta = !!(*atr & 0x10);
     239           0 :           have_tb = !!(*atr & 0x20);
     240           0 :           have_tc = !!(*atr & 0x40);
     241           0 :           have_td = !!(*atr & 0x80);
     242           0 :           es_fprintf (fp, "TD%d: protocol T%d supported\n", idx, *atr & 0x0f);
     243             : 
     244           0 :           if (have_ta + have_tb + have_tc + have_td + n_historical > atrlen)
     245           0 :             es_fputs ("error: "
     246             :                       "ATR shorter than indicated by format character\n",
     247             :                       fp);
     248             : 
     249           0 :           if (!--atrlen)
     250           0 :             goto bailout;
     251           0 :           atr++;
     252             :         }
     253             :       else
     254           0 :         have_ta = have_tb = have_tc = have_td = 0;
     255             :     }
     256             : 
     257           0 :   if (n_historical + 1 > atrlen)
     258           0 :     es_fputs ("error: ATR shorter than required for historical bytes "
     259             :               "and checksum\n", fp);
     260             : 
     261           0 :   if (n_historical)
     262             :     {
     263           0 :       es_fputs ("HCH:", fp);
     264           0 :       for (; n_historical && atrlen ; n_historical--, atrlen--, atr++)
     265           0 :         es_fprintf (fp, " %02X", *atr);
     266           0 :       es_putc ('\n', fp);
     267             :     }
     268             : 
     269           0 :   if (!atrlen)
     270           0 :     es_fputs ("error: checksum missing\n", fp);
     271           0 :   else if (*atr == chksum)
     272           0 :     es_fprintf (fp, "TCK: %02X (good)\n", *atr);
     273             :   else
     274           0 :     es_fprintf (fp, "TCK: %02X (bad; computed %02X)\n", *atr, chksum);
     275             : 
     276           0 :   atrlen--;
     277           0 :   if (atrlen)
     278           0 :     es_fprintf (fp, "error: %u bytes garbage at end of ATR\n",
     279             :                 (unsigned int)atrlen );
     280             : 
     281             :  bailout:
     282           0 :   es_putc ('\0', fp); /* We want a string.  */
     283           0 :   if (es_fclose_snatch (fp, (void**)&result, NULL))
     284             :     {
     285           0 :       log_error ("oops: es_fclose_snatch failed: %s\n", strerror (errno));
     286           0 :       return NULL;
     287             :     }
     288             : 
     289           0 :   return result;
     290             : }

Generated by: LCOV version 1.11