Archivo de la categoría: ISO 7816

Todo lo relacionado a la generalización del estándar de ISO 7816 relacionado con la tecnología Smart Card

Driver SmartCard VISA Alpha0.1

GTY_EMV_Chip_MEM_150930_12x5_1600

Hola estoy trabajando en este driver para lectura de tarjetas visa, una de las clases principales que compone este programa es la siguiente:

/*
 * Version 2.0 Revision 1
 *
 * 01/03/2014
 *
 * Copyright 2013-2016 gigaDatta, S.A.
 * Julio Francisco Chinchilla Valenzuela - gigadatta@gmail.com
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */

package com.gd.creditcard.visa;

import com.gd.creditcard.entitys.CreditCard;
import com.gd.creditcard.tlv.utils.EMVTags;
import com.gd.smartcard.SCardConexion;
import com.gd.utils.ByteConverts;
import com.gd.utils.ByteEngine;
import javax.smartcardio.ATR;

import javax.smartcardio.CardException;

/**
 *
 * @author Julio Chinchilla
 */
public final class VisaSCDataRead extends CreditCard {

    public VisaSCDataRead(int pcsc, String protocol) throws CardException, Exception {
        SCardConexion c = new SCardConexion();
        ATR atr = c.connect(pcsc, protocol);
        setAtr(com.gd.utils.ByteConverts.byteToHex(atr.getBytes()));
        VisaCardCheck checkVisa = new VisaCardCheck(atr);
        if (checkVisa.isVisaCard()) {
            setIssuerData(checkVisa.getIssuerData());
            c.transmit(APDU.VISA);
            byte[] visaData = c.transmit(APDU.RECORD0C).getData();
            c.transmit(APDU.PAYSYSDDF01);
            byte[] paySysData = c.transmit(APDU.RECORD0C).getData();
            scannData(visaData, paySysData);
        } else {
            throw new Exception("No es una tarjeta visa");
        }
    }

    public void scannData(byte[] visaData, byte[] paySysData) {
        setNumber(VisaNumberScanner(visaData));
        setDateExpiration(VisaDateExpireScanner(visaData));
        int cardHolderName = ByteEngine.find(visaData, EMVTags.CardHolderName);
        int trackData = ByteEngine.find(visaData, EMVTags.Track1DiscretionaryData);
        setName(ByteConverts.byteToASCII(visaData,cardHolderName+3,(trackData == -1)?visaData.length-1:trackData-3));
        setPaySys(PaySysScanner(paySysData));
    }

    private String PaySysScanner(byte[] paySysData) {
        int trackData = ByteEngine.find(paySysData, EMVTags.ApplicationPreferredName);
        int applIndicator = ByteEngine.find(paySysData, EMVTags.ApplicationPriorityIndicator);
        return ByteConverts.byteToASCII(paySysData,trackData+3,(trackData+3<applIndicator)?applIndicator-1:paySysData.length-1);
    }

    private String VisaNumberScanner (byte[] data) {
        String num = ByteConverts.byteToHex(data,4,11).replace(" ","");
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < num.length(); i++) {
            sb.append(num.charAt(i));
            if( ((i+1) % 4) == 0) {
                sb.append(" ");
            }
        }
        return sb.toString();
    }

    private String VisaDateExpireScanner (byte[] data) {
        String d = ByteConverts.byteToHex(data,12,14).replace(" ","").substring(1, 5);
        String year = d.substring(0, 2);
        String month = d.substring(2,4);
        return month.concat("/").concat(year);
    }

}

Bancos-en-guatemala1

Como veran es una fase alfa aún en desarrollo, el proyecto se encuentra completo en GitHub VISASmartCardDriver0.1A entre las características del driver es que este cuenta con una lista aún en construcción que posee los emisores de tarjetas visa para Guatemala, en este caso los bancos del país. Entre la lista recavada hasta el momento se encuentran:

0x17 0xB1 BANCO INDUSTRIAL
0x06 0x1B BANRURAL
0x18 0x60 BANRURAL
0x18 0x64 BANRURAL
0x08 0x8B G&T CONTINENTAL
0x15 0x19 BANTRAB

 

/*
 * Version 2.0 Revision 1
 *
 * 01/03/2014
 *
 * Copyright 2013-2016 gigaDatta, S.A.
 * Julio Francisco Chinchilla Valenzuela - gigadatta@gmail.com
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */
package com.gd.creditcard.cardissuer;

import java.nio.ByteBuffer;
import java.util.Map;
import java.util.TreeMap;

/**
 *
 * @author Julio Chinchilla
 */
public class VISAIssuerDataGTM {

    public final Map<Short, String> IssuerData = new TreeMap<>();

    public VISAIssuerDataGTM() {
        IssuerData.put(ByteBuffer.wrap(new byte[] {(byte)0x17,(byte)0xB1}).getShort(), "BANCO INDUSTRIAL");
        IssuerData.put(ByteBuffer.wrap(new byte[] {(byte)0x06,(byte)0x1B}).getShort(), "BANRURAL");
        IssuerData.put(ByteBuffer.wrap(new byte[] {(byte)0x18,(byte)0x60}).getShort(), "BANRURAL");
        IssuerData.put(ByteBuffer.wrap(new byte[] {(byte)0x18,(byte)0x64}).getShort(), "BANRURAL");
        IssuerData.put(ByteBuffer.wrap(new byte[] {(byte)0x08,(byte)0x8B}).getShort(), "BANRURAL");
        IssuerData.put(ByteBuffer.wrap(new byte[] {(byte)0x17,(byte)0xAE}).getShort(), "G&T CONTINENTAL");
        IssuerData.put(ByteBuffer.wrap(new byte[] {(byte)0x15,(byte)0x19}).getShort(), "BANTRAB");
    }

}

Estos bytes asociados corresponden al ATR de la tarjeta, específicamente a los bytes en las posiciones 9 y 10, los cuales son conocidos como “Issuer Data”, en fín el driver solo lee los datos mas importantes o que he considerado hasta el momento, ya que la data que se recava es mucho más extensa, si quisieran determinar a exactitud los records extraidos en la data, les recomiendo esta herramienta: TLV Utilities. La cual sirve para parsear los extraído en las aplicaciones que posee el chip regidos bajo el estándar EMV.

Este driver recoge información de los AID’s principales de las tarjetas Visa:

card_large

00 A4 04 00 07 A0 00 00 00 03 10 10

00 A4 04 00 0E 31 50 41 59 2E 53 59 53 2E 44 44 46 30 31

 

Y por si se lo preguntan, el código CVV no viene en los records del chip,  ya que por estandar este se genera en base al número de la tarjeta, el emisor y un algoritmo propio del emisor, esto se hace por seguridad.

Accediendo al nuevo chip Smart Card del DPI (Fase I)

ChipDPI2La curiosidad nos ha llevado lejos, y en esta ocasión no ha sido la excepción. Tengo que decir en palabras bastante simples y resumidas, que la lectura de datos de la zona pública es bastante sencilla. No obstante otros datos como la fotografía principalmente, se encuentran almacenados en una zona de seguridad criptográfica, haciendo así casi imposible la lectura de este dato (de momento aunque seguimos curioseando). En esta fase inicial no pudimos obtener algunos datos que la aplicación oficial de Renap muestra, como lo son el Serial y el MRZ, pero en compensación logramos acceder a otros datos que la aplicación pública de Renap no muestra, como lo son el nuevo y polémico campo ETNIA asi tambien nos topamos con 2 datos mas que en realidad no sabemos que son, en total accedimos a 31 datos del chip, no esta mal para un primer comienzo aunque sentimos que no es suficiente, pero bueno en definitiva el resultado de esta primera investigación fue el siguiente:

Características:

ATR: Anteriormente había publicado un post (muy apresuradamente) donde mencionaba el nuevo ATR, por lo visto estaba equivocado y por eso lo puse en modo oculto. Tal parece ser que ahora ya no se utilizarán 2 ATR para todos los chips como el anterior fabricante, sino que ahora será un ATR por cada DPI (admito que puedo estar equivocado), pero la nueva forma del ATR es la siguiente:

3B FD 96 00 00 81 31 FE 45 00 00 01 XX XX XX XX 00 00 00 00 00 00 XX

Como podrán ver son 4 bytes que varían (256ˆ4 – 1) el último byte tambien varía pero este es un checksum correspondiente a todo el ATR pueden revisar un artículo anterior donde está como calcular el checksum de un ATR aquí. Lo que nos hizo falta fue realizar mas lecturas para corroborar esto. Por lo que hacemos la corrección correspondiente en este post.

Datos:

Logramos acceder a 31 datos del CHIP entre ellos 3 que la aplicación pública de Renap no muestra, los listamos a continuación:

CAMPO DESCRIPCIÓN
Gentilicio No sabemos bien el propósito de este campo, pero este se encuentra antes del CUI y al principio de la Zona Pública
CUI Código Único de Identificación
Primer Nombre Primer nombre del ciudadano
Segundo Nombre Segundo Nombre del ciudadano
Primer Apellido Primer apellido del ciudadano
Segundo Apellido Segundo apellido del ciudadano
Apellido de Casada Apellido de casada de la ciudadana si lo tuviese
Sexo Género sexual del ciudadano, Masculino o Femenino
Departamento de nacimiento Departamento donde nació el ciudadano
Municipio de nacimiento Municipio donde nació el ciudadano
País de nacimiento Pais donde nació la persona
Fecha de nacimiento Fecha de nacimiento de la persona
Fecha de emisión Fecha de emisión del documento
Fecha de vencimiento Fecha de vencimiento del documento
Nacionalidad País de nacionalidad
Estado Civil Estado Civil del ciudadano
Departamento de Vecindad Departamento donde está avecindado el ciudadano
Municipio de Vecindad Municipio donde está avecindadno el ciudadano
Libro Libro de la partida de nacimiento
Folio Folio de la partida de nacimiento
Partida Número de partida de nacimiento
Etnia Grupo Etnico al cual pertenece el ciudadano
Número de Cédula Número de Cédula de ciudadano si lo posee
Departamento de Cédula Departamento en el cual fue extendida la cédula
Municipio de Cédula Municipio en el cual fue extendida la cédual
DESCONOCIDO_0 No sabemos que dato es este, lo único que se identifica como S/N
Sabe leer Si el ciudadano sabe leer S/N
Sabe escribir Si el ciudadano sabe escribir S/N
Oficial Activo Si el ciudadano es un oficial activo del ejercito o la policía S/N
Profesión Profesión del ciudadano
DESCONOCIDO_1 En primera instancia concluimos que puede ser el puesto o cargo que desempeña el ciudadano, pero no es una conclusión final

Aca algunas capturas de lo que se logró hacer en una primera instancia:

 

1454566_702330666550607_4502002852617539329_n 10351478_702330669883940_7378564346226784771_n 10959731_702330689883938_3208707829978063719_n

En una segunda instancia, cambiamos los APDU de lectura y encontramos el dato DESCONOCIDO_1 el cual suponemos pertenece al cargo o puesto que desempeña el ciudadano, este campo es diferente al de Profesión:

dpi2 dpi22

Al momento este es el resultado de nuestra Fase I, seguimos curioseando el chip y mas adelante cuando tengamos mas resultados comento en este blog todo lo que me sea permitido publicar.

Sobrevaloración y Retención de la Firma-e en Guatemala

No es muy común usar este espacio para expresar una opinión personal, seré breve y espero este espacio sirva para dar a conocer como están las cosas aca en Guatemala:

El DNI Electrónico de Perú, es fabricado exactamente por la misma empresa que fabrica el DPI en Guatemala, Oberthur Technologies. En Perú este documento no es obligatorio sino que opcional, tiene un precio de 40 Soles lo que vendría a ser unos Q105.00 aproximadamente, lo que impulsa el RENIEC ente emisor del DNI Electronico Peruano, es la firma electrónica, la firma electrónica es un concepto jurídico, equivalente electrónico al de la firma manuscrita, donde una persona acepta el contenido de un mensaje electrónico a través de cualquier medio electrónico válido, esto es un gran impulsor del Gobierno Digital. Aca en Guatemala el ente emisor y autorizado legalmente para emitir firma electrónica es la Cámara de Comercio, y tiene un precio de Q.1,000.00, aunque RENAP liberara las herramientas para realizar firma electrónica con el DPI, este no tiene validez jurídica ya que esta fue otorgada a Cámara de Comercio. El DPI vale Q.80.00, pero tener el negocio de Firma Electrónica por parte de Cámara de Comercio a Q. 1,000.00 y que esté amparado por la ley, no se vale. Todos ya tenemos firma electrónica, solo que muy pocos saben que ya la poseen y aunque la del DPI no tiene validez jurídica, no deberían de pagar mil quetzales por adquirirla.imagen-dni-electronico-peru

 

En conclusión, en Guatemala ya todos tenemos Firma Electrónica, solo que no tiene validéz jurídica, hay que pagar por otro documento sobrevalorado que cuesta Q.1000.00

Comprobación de ATR mediante Suma de Verificación XOR [Código Java]

FE26DS8GJ7MQAYF.MEDIUMCada vez que conectamos un SmartCard y hacemos la conexión correspondiente, obtenemos la cadena de respuesta del Chip conocida como ATR, pero ¿como verificar si el ATR recibido es correcto? para ello la norma ISO estable que el último byte recibido corresponde a uno de verificación desde el byte T0 hasta el Tj, donde T0 es el segundo byte del atr en mención y el byte Tj corresponde al penúltimo, por lo que el último es un byte de comprobación. Para ello se debe de usar una suma de verificación XOR.

ISO7816_23

Por ejemplo y para hacerlo de manera sencilla el ATR siguiente se comprobarían de la siguiente manera:

3B DB 96 00 80 B1 FE 45 1F 83 00 31 C0 64 C3 08 01 00 0F 90 00 9B

3B sería el byte incial, el cual se omite
DB 96 00 80 B1 FE 45 1F 83 00 31 C0 64 C3 08 01 00 0F 90 00 Sería la serie de bytes a comprobar (T0 – Tj)
9B sería la suma de verificación de los bytes T0 – Tj
por lo cual si la suma de verifciación xor desde T0 hasta Tj es distinta de 9B, este ATR estaría incorrecto o alterado.

 

A continuación un código de java que facilita la comprobación debida.

/*
 * Version 1.0 Revision 1
 *
 * 18/08/2014
 *
 * Copyright 2014 bit502
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &amp;quot;AS IS&amp;quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */



/**
 *
 * @author Julio Chinchilla
 */
public class ATRVerify {

    /**
     * Función que recibe un ATR en formato String con separador de espacio
     * entre cada byte, la función formatea la cadena de caracteres quitándole
     * los espacios en blanco, posteriormente separa los bytes T0 hasta TJ en
     * el String t0tj y separa el byte de comprobación final TCK, luego utiliza
     * la función getXORCheckSumValue para obtener la suma verificativa y lo
     * compara con el byte TCK, si los bytes coinciden la respuesta será true
     * de lo contrario será false, y el ATR a verificar estará incorrecto
     * @param atr ATR con espacios entre bytes
     * @return
     */
    public static boolean checkATRStrWS (String atr) {
        boolean resp = false;
        String t0tj = atr.replaceAll(&amp;quot;\\s&amp;quot;,&amp;quot;&amp;quot;);
        String tck = atr.substring(atr.length()-2, atr.length());
        t0tj = t0tj.substring(2, t0tj.length()-2);
        if (getXORCheckSumValue(t0tj).equals(tck))
            resp = true;
        return resp;
    }

    /**
     * Función que recibe un ATR en formato String con separador de espacio
     * entre cada byte, posteriormente separa los bytes T0 hasta TJ en
     * el String t0tj y separa el byte de comprobación final TCK, luego utiliza
     * la función getXORCheckSumValue para obtener la suma verificativa y lo
     * compara con el byte TCK, si los bytes coinciden la respuesta será true
     * de lo contrario será false, y el ATR a verificar estará incorrecto
     * @param atr ATR sin espacios entre bytes
     * @return
     */
    public static boolean checkATRStr (String atr) {
        boolean resp = false;
        String t0tj = atr.substring(2, atr.length()-2);;
        String tck = atr.substring(atr.length()-2, atr.length());
        if (getXORCheckSumValue(t0tj).equals(tck))
            resp = true;
        return resp;
    }

    /**
     * Función que realiza una suma de verificación a una cadena String en
     * formato Hexadecimal con el operador XOR
     * @param bytes Cadena String en formato hexadecimal a analizar
     * @see &amp;lt;a href=&amp;quot;http://es.wikipedia.org/wiki/Suma_de_verificaci%C3%B3n&amp;quot;&amp;gt;WikiES: Suma de verificación&amp;lt;/a&amp;gt;
     * @return String de comprobación mediante Suma de Verificación HEX
     */
    private static String getXORCheckSumValue (String bytes) {
        int cc = 0;
        for (int i = 0; i &amp;lt; bytes.length(); i=(i+2)) {
            if (i==0){
                cc = Integer.parseInt(bytes.substring(i, i+2), 16) &amp;amp; (0x00FF);
            } else {
                cc^=(Integer.parseInt(bytes.substring(i, i+2),16)&amp;amp;(0x00FF));
                cc=cc&amp;amp;(0x00FF);
            }
        }
        return Integer.toString(cc, 16).toUpperCase();
    }

}

Su forma de uso es la siguiente:

/**
 *
 * @author Julio
 */
public class ATRVerify {

    public static final String GT01 = &amp;quot;3B DB 96 00 80 B1 FE 45 1F 83 00 31 C0 64 C3 08 01 00 0F 90 00 9B&amp;quot;;
    public static final String GT02 = &amp;quot;3BDB960080B1FE451F830031C064C7FC10000F90007A&amp;quot;;
    public static final String ATR1 = &amp;quot;3B DB 18 00 80 1F 03 00 31 C0 64 77 E3 03 00 82 90 00 4F&amp;quot;;

    public static void main(String[] args) {
        System.out.println(checkATRStrWS(GT02));
        System.out.println(checkATRStr(GT02));
        System.out.println(checkATRStrWS(ATR1));
    }

}

ATR’s Utilizados por el RENAP en el DPI

Que es el ATR:
atr
Una Respuesta al reajuste (ATR) es una salida de mensaje por un contacto de tarjeta inteligente conforme a 7.816 normas ISO / IEC, tras el rearme eléctrico de el chip de la tarjeta por un lector de tarjetas. El ATR transmite información acerca de los parámetros de comunicación propuestas por la tarjeta, y la naturaleza de la tarjeta y el estado.

Por extensión, ATR a menudo se refiere a un mensaje obtenido de una tarjeta inteligente en un estadio temprano de la comunicación; o desde el lector de tarjetas utilizado para acceder a la tarjeta, que puede transformar el mensaje de la tarjeta en un formato de ATR-como (esto ocurre por ejemplo, para algunos lectores de tarjetas de PC / SC [1] [2] al acceder a un 14,443 tarjeta inteligente ISO / IEC) .

Los ATR utilizados por el RENAP son los siguientes:
3B DB 96 00 80 B1 FE 45 1F 83 00 31 C0 64 C3 08 01 00 0F 90 00 9B
3B DB 96 00 80 B1 FE 45 1F 83 00 31 C0 64 C7 FC 10 00 0F 90 00 7A

Aca dejo un código que hace la conexión SmartCard utilizando el primer ejemplo que desarrollamos aca en bit502 http://goo.gl/9MkNxt este código lee el ATR y comprueba si es un DPI emitido por el RENAP
imagen-oficial-DPI-2013-oficial

/*
 * 17/08/2014
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an &quot;AS IS&quot; BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 */

package test;

import com.gd.smartcard.SCardConexion;
import javax.smartcardio.CardException;

/**
* @version 1.0 Agosto de 2014
* @author Julio Chinchilla
*/
public class DPIVerify {
    
    //ATR's utilizados por el RENAP en la generación del DPI 
    public static final String GT01 = "3B DB 96 00 80 B1 FE 45 1F 83 00 31 C0 64 C3 08 01 00 0F 90 00 9B";
    public static final String GT02 = "3B DB 96 00 80 B1 FE 45 1F 83 00 31 C0 64 C7 FC 10 00 0F 90 00 7A";

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) throws CardException {
        String atr = getATR();
        if (atr.equals(GT01) | atr.equals(GT02))
            System.out.println("El ATR es: "+ atr);
        else
            System.err.println("Este documento no es un DPI");
    }
    
    /**
     * Funcion que hace una conexión SmartCard utilizando la clase de conexión
     * SmartCard estandar desarrollada antriormente http://goo.gl/9MkNxt esta
     * conexión tiene conexión al dispositivo 0, utilizando el protocolo por 
     * default con el parámetro "*"
     * @return ATR de la tarjeta
     * @throws CardException 
     */
    private static String getATR() throws CardException {
        SCardConexion sc = new SCardConexion();
        String atr = byteToHex(sc.connect(0, "*").getBytes());
        sc.disconnect();
        return atr;
    }
    
    /**
     * Función que transforma una cadena de bytes a su valor Hexadecimal en un
     * tipo de dato String, con espacios entre cada byte
     * @param data Array de bytes
     * @return Valor del array de bytes en formato Hexadecimal con espacios
     * entre cada byte
     */
    private static String byteToHex(byte[] data)  {
        StringBuilder localStringBuilder = new StringBuilder();
        for (int i = 0; i < data.length; i++)  {
            String str;
            if ((str=Integer.toHexString(data[i]&0xFF).toUpperCase()).length()==1) {
                localStringBuilder.append(0);
            }
        localStringBuilder.append(str).append(" ");
        }
        return localStringBuilder.substring(0, localStringBuilder.length() - 1);
    }
    
}

Lista completa de respuestas en bytes para Comandos APDU SmartCard

apduresponses

SW1 SW2 Info/
Warning/
Error/
Security
Description
6 E Class not supported.
61 I Response bytes still available
61 XX I Command successfully executed; ‘XX’ bytes of data are available and can be requested using GET RESPONSE.
62 W State of non-volatile memory unchanged
62 00 W No information given (NV-Ram not changed)
62 01 W NV-Ram not changed 1.
62 81 W Part of returned data may be corrupted
62 82 W End of file/record reached before reading Le bytes
62 83 W Selected file invalidated
62 84 W Selected file is not valid. FCI not formated according to ISO
62 85 W No Purse Engine enslaved for R3bc
62 A2 W Wrong R-MAC
62 A4 W Card locked (during reset( ))
62 CX W Counter with value x (command dependent)
62 F1 W Wrong C-MAC
62 F3 W Internal reset
62 F5 W Default agent locked
62 F7 W Cardholder locked
62 F8 W Basement is current agent
62 F9 W CALC Key Set not unblocked
62 FX W
62 XX W RFU
63 W State of non-volatile memory changed
63 00 W No information given (NV-Ram changed)
63 81 W File filled up by the last write. Loading/updating is not allowed.
63 82 W Card key not supported.
63 83 W Reader key not supported.
63 84 W Plaintext transmission not supported.
63 85 W Secured transmission not supported.
63 86 W Volatile memory is not available.
63 87 W Non-volatile memory is not available.
63 88 W Key number not valid.
63 89 W Key length is not correct.
63 C0 W Verify fail, no try left.
63 C1 W Verify fail, 1 try left.
63 C2 W Verify fail, 2 tries left.
63 C3 W Verify fail, 3 tries left.
63 CX W Counter with value x (command dependent)
63 FX W
63 XX W RFU
64 E State of non-volatile memory unchanged
64 00 E No information given (NV-Ram not changed)
64 01 E Command timeout.
64 XX E RFU
65 E State of non-volatile memory changed
65 00 E No information given
65 01 E Write error. Memory failure. There have been problems in writing or reading the EEPROM. Other hardware problems may also bring this error.
65 81 E Memory failure
65 FX E
65 XX E RFU
66 S
66 69 S Incorrect Encryption/Decryption Padding
66 XX S
67 E
67 00 E Wrong length
67 XX E length incorrect (procedure)(ISO 7816-3)
68 E Functions in CLA not supported
68 00 E No information given (The request function is not supported by the card)
68 81 E Logical channel not supported
68 82 E Secure messaging not supported
68 83 E Last command of the chain expected
68 84 E Command chaining not supported
68 FX E
68 XX E RFU
69 E Command not allowed
69 00 E No information given (Command not allowed)
69 81 E Command incompatible with file structure
69 82 E Security condition not satisfied.
69 83 E Authentication method blocked
69 84 E Referenced data reversibly blocked (invalidated)
69 85 E Conditions of use not satisfied
69 86 E Command not allowed (no current EF)
69 87 E Expected secure messaging (SM) object missing
69 88 E Incorrect secure messaging (SM) data object
69 96 E Data must be updated again
69 F0 E Permission Denied
69 F1 E Permission Denied – Missing Privilege
69 FX E
69 XX E RFU
6A E Wrong parameter(s) P1-P2
6A 00 E No information given (Bytes P1 and/or P2 are incorrect)
6A 80 E The parameters in the data field are incorrect.
6A 81 E Function not supported
6A 82 E File not found
6A 83 E Record not found
6A 84 E There is insufficient memory space in record or file
6A 85 E Lc inconsistent with TLV structure
6A 86 E Incorrect P1 or P2 parameter.
6A 87 E Lc inconsistent with P1-P2
6A 88 E Referenced data not found
6A 89 E File already exists
6A 8A E DF name already exists.
6A F0 E Wrong parameter value
6A FX E
6A XX E RFU
6B E
6B 00 E Wrong parameter(s) P1-P2
6B XX E Reference incorrect (procedure byte), (ISO 7816-3)
6C E Wrong length Le
6C 00 E Incorrect P3 length.
6C XX E xx = exact Le
6D E
6D 00 E Instruction code not supported or invalid
6D XX E Instruction code not programmed or invalid (procedure byte), (ISO 7816-3)
6E E
6E 00 E Class not supported
6E XX E Instruction class not supported (procedure byte), (ISO 7816-3)
6F E Internal exception
6F 00 E Command aborted – more exact diagnosis not possible (e.g., operating system error).
6F FF E Card dead (overuse, …)
6F XX E No precise diagnosis (procedure byte), (ISO 7816-3)
9-
90 00 I Command successfully executed (OK).
90 04 W PIN not succesfully verified, 3 or more PIN tries left
90 08 Key/file not found
90 80 W Unblock Try Counter has reached zero
91 01 States.activity, States.lock Status or States.lockable has wrong value
91 02 Transaction number reached its limit
92 10 E No more storage available.
93 01 Integrity error
93 02 Candidate S2 invalid
94 01 Candidate currency code does not match purse currency
94 02 Candidate amount too high
94 03 Candidate amount too low
94 05 Problems in the data field
94 07 Bad currency : purse engine has no slot with R3bc currency
94 08 R3bc currency not supported in purse engine
95 80 Bad sequence
96 81 Slave not found
97 00 PIN blocked and Unblock Try Counter is 1 or 2
97 02 Main keys are blocked
97 04 PIN not succesfully verified, 3 or more PIN tries left
97 84 Base key
97 85 Limit exceeded – C-MAC key
97 86 SM error – Limit exceeded – R-MAC key
97 87 Limit exceeded – sequence counter
97 88 Limit exceeded – R-MAC length
97 89 Service not available
98 04 E Access conditions not satisfied.
99 00 1 PIN try left
99 04 PIN not succesfully verified, 1 PIN try left
99 85 Wrong status – Cardholder lock
99 86 E Missing privilege
99 87 PIN is not installed
99 88 Wrong status – R-MAC state
9A 00 2 PIN try left
9A 04 PIN not succesfully verified, 2 PIN try left
9A 71 Wrong parameter value – Double agent AID
9A 72 Wrong parameter value – Double agent Type
9D 05 E Incorrect certificate type
9D 07 E Incorrect session data size
9D 08 E Incorrect DIR file record size
9D 09 E Incorrect FCI record size
9D 0A E Incorrect code size
9D 10 E Insufficient memory to load application
9D 11 E Invalid AID
9D 12 E Duplicate AID
9D 13 E Application previously loaded
9D 14 E Application history list full
9D 15 E Application not open
9D 17 E Invalid offset
9D 18 E Application already loaded
9D 19 E Invalid certificate
9D 1A E Invalid signature
9D 1B E Invalid KTU
9D 1D E MSM controls not set
9D 1E E Application signature does not exist
9D 1F E KTU does not exist
9D 20 E Application not loaded
9D 21 E Invalid Open command data length
9D 30 E Check data parameter is incorrect (invalid start address)
9D 31 E Check data parameter is incorrect (invalid length)
9D 32 E Check data parameter is incorrect (illegal memory check area)
9D 40 E Invalid MSM Controls ciphertext
9D 41 E MSM controls already set
9D 42 E Set MSM Controls data length less than 2 bytes
9D 43 E Invalid MSM Controls data length
9D 44 E Excess MSM Controls ciphertext
9D 45 E Verification of MSM Controls data failed
9D 50 E Invalid MCD Issuer production ID
9D 51 E Invalid MCD Issuer ID
9D 52 E Invalid set MSM controls data date
9D 53 E Invalid MCD number
9D 54 E Reserved field error
9D 55 E Reserved field error
9D 56 E Reserved field error
9D 57 E Reserved field error
9D 60 E MAC verification failed
9D 61 E Maximum number of unblocks reached
9D 62 E Card was not blocked
9D 63 E Crypto functions not available
9D 64 E No application loaded
9E 00 PIN not installed
9E 04 PIN not succesfully verified, PIN not installed
9F 00 PIN blocked and Unblock Try Counter is 3
9F 04 PIN not succesfully verified, PIN blocked and Unblock Try Counter is 3
9x XX Application related status, (ISO 7816-3)