I am trying to establish a secure channel SCP02
with a smart card using python. My smartcard is connected to the terminal using a serial port and I use pySerial
to send APDUs.
I send commands SELECT ISD
, INITIALIZE UPDATE
correctly, and next I try to do EXTERNAL AUTHENTICATE
as the python code below:
import serial
from serial.serialutil import EIGHTBITS, PARITY_NONE, STOPBITS_ONE, XON
import exchangeApdu
import numpy as np
from Crypto.Cipher import DES, DES3
CARD_KEY = [0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F]
ZERO_IV_8 = [0X00, 0X00, 0x00, 0x00, 0X00, 0X00, 0x00, 0x00]
serialObj = serial.Serial( port = 'COM3', \
baudrate = 115200, \
parity = PARITY_NONE, \
bytesize = EIGHTBITS, \
stopbits = STOPBITS_ONE, \
timeout = 0.1, \
xonxoff = True, \
rtscts = True, \
inter_byte_timeout = None, \
dsrdtr = True )
if(serialObj.is_open):
serialObj.close()
serialObj.open()
# Select ISD
select_apdu = [0x00, 0xA4, 0x04, 0x00, 0x00]
response = exchangeApdu.exchange(serialObj, select_apdu)
print('Select ISD: ' + response.hex())
# Initialize Update
host_challenge = np.random.bytes(8)
initialize_update_apdu = [0x80, 0x50, 0x00, 0x00, 0x08] + list(host_challenge)
response = exchangeApdu.exchange(serialObj, initialize_update_apdu)
print('Initialize Update: ' + response.hex())
key_derivation_data = list(response[:10])
key_information = list(response[10:12])
sequence_counter = list(response[12:14])
card_challenge = list(response[14:20])
card_cryptogram = list(response[20:28])
derivation_data = [0X01, 0X82] + sequence_counter + \
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
encryptor = DES3.new(bytes(CARD_KEY), DES3.MODE_CBC, bytes(ZERO_IV_8))
S_ENC = encryptor.encrypt(bytes(derivation_data))
derivation_data = [0X01, 0X01] + sequence_counter + \
[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
encryptor = DES3.new(bytes(CARD_KEY), DES3.MODE_CBC, bytes(ZERO_IV_8))
S_MAC = encryptor.encrypt(bytes(derivation_data))
# External Authenticate
PADDING_DES = [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
host_auth_data = sequence_counter + card_challenge + list(host_challenge) + PADDING_DES
card_auth_data = list(host_challenge) + sequence_counter + card_challenge + PADDING_DES
encryptor = DES3.new(bytes(S_ENC), DES3.MODE_CBC, bytes(ZERO_IV_8))
host_cryptogram = list(bytes((encryptor.encrypt(bytes(host_auth_data)))[-8:]))
encryptor = DES3.new(bytes(S_ENC), DES3.MODE_CBC, bytes(ZERO_IV_8))
card_cryptogram = list(bytes((encryptor.encrypt(bytes(card_auth_data)))[-8:]))
external_auth_apdu = [0x84, 0x82, 0x00, 0x00, 0x10] + list(host_cryptogram)
external_auth_apdu_padded = external_auth_apdu + [0x80, 0x00, 0x00]
cipher = DES.new(bytes(list(S_MAC[:8])), DES3.MODE_CBC, bytes(ZERO_IV_8))
step1 = cipher.encrypt(bytes(external_auth_apdu_padded))
cipher = DES.new(bytes(list(S_MAC[8:16])), DES3.MODE_ECB)
step2 = cipher.decrypt(step1[-8:])
cipher = DES.new(bytes(list(S_MAC[:8])), DES3.MODE_ECB)
apdu_mac = list(bytes(cipher.encrypt(step2[-8:])))
external_auth_apdu = external_auth_apdu + apdu_mac
response = exchangeApdu.exchange(serialObj, external_auth_apdu)
print('External Authenticate: ' + response.hex())
serialObj.close()
The "exchangeApdu" is a class in which I have handled APDUs like 61xx and 6Cxx. This is the output for this code:
Select ISD: 6f108408a000000151000000a5049f6501ff9000
Initialize Update: 000081210103b49d856dff02004eecc2acd14944a54f9790521d203b9000
External Authenticate: 6982
Smartcard rejects the channel sending back 6982
on the serial port. I have checked whole the procedure uwing online cryptography tools and I am quite sure the cryptographic part is completely doing right.
I have also checked this procedure using a usb smartcard reader and again correctly working and I get 9000
.
Again I checked this on a smartcard simulator, namely JCIDE, and again 9000
.
Thus I'm sure about the procedure correctness.
I have used a serial port monitoring application on Win10 to check the correctness of APDUs on the serial port and there is no error. I think there must be a problem with the smartcard itself but I cannot guess what it is!
Does anyone have any idea where the problem rises?
I found the roblem. Byte array is not delivered to the card correctly, hence the error 6982. This refers to ISO7816 standard which needs bytes sent to the card by a specific delay. I put delays between bytes and now everything is working correctly.