'Why Smart Card answers 6982 to EXTERNAL AUTHENTICATE while all calculations are correct?
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?
Solution 1:[1]
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.
Solution 2:[2]
You can use the working Test Vectors from the GlobalPlatform library and test if your executed crypto logic is really working. It could also be that your card is using some key derivation scheme, i.e. the keys you are using cannot be used directly.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | MJay |
| Solution 2 | k_o_ |
