Reputation: 23
Thanks to these informations I'm able to calculate EXTERNAL_AUTHENTICATE_data but how exactly can I calculate MAC ?
I know that my default C-MAC key is [40 41 ... 4F]. I have tried to encrypt [84 82 00 00 10]+EXTERNAL_AUTHENTIFICATE apdu with it using 3DES in CBC mode but it doesn't give the MAC value I expect.
With the help of this tutorial, these are the steps I followed to "Calculate C-MAC" :
1 - I take the apdu with EXTERNAL_AUTHENTICATE_data : 8482000010448126B770B27702
2 - I pad this apdu : 8482000010448126B770B27702800000
3 - I encrypt the data with the first 8 bytes of S-MAC key : single DES in CBC mode (key : D1C28C601652A477 / IV : 00 00 00 00 00 00 00 00) result => 25F7DC3B1FEE1B9018CCD8E66A69B560
4 - I encrypt this with the last 8 bytes of S-MAC key : 3DES in EBC mode (key : 0D67AD82D2D2E1C4) result => 11E1B058F0EB6910196A68BF1FBA97AA
Or the result I except is D770D0A0001B05AA
Did I do the retail MAC wrong ?
Upvotes: 2
Views: 704
Reputation: 6126
I've developed a Python class for the SCP02. The MAC-related secions may answer your question:
from Crypto.Cipher import DES3,DES
ZERO_IV_8 = b"\x00\x00\x00\x00\x00\x00\x00\x00"
last_mac = None
def pad_80(data_list):
reminder = len(data_list) % 8
if reminder != 0:
return data_list + [0x80,] + [0x00 for i in range(8 - reminder - 1)]
else:
return data_list + [0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
def calc_mac(command):
padded_command = self.pad_80(command)
mac_in = bytes.fromhex(toHexString(padded_command).replace(" ", ""))
iv = ZERO_IV_8
if last_mac != None:
cipher = DES.new(session_mac[:8], DES3.MODE_ECB)
iv = cipher.encrypt(last_mac)
cipher = DES.new(session_mac[:8], DES3.MODE_CBC, iv)
step1 = cipher.encrypt(mac_in)
cipher = DES.new(session_mac[8:16], DES3.MODE_ECB)
step2 = cipher.decrypt(step1[-8:])
cipher = DES.new(session_mac[:8], DES3.MODE_ECB)
mac = list(bytes(cipher.encrypt(step2[-8:])))
last_mac = bytes.fromhex(toHexString(mac).replace(" ", ""))
return mac
The variable session_mac
is a 16-bytes byte strings which contains session MAC key. You also need to keep the calculated MAC in a variable (in my case last_mac
) to use it as IV for next command MAC calculation.
The calc_mac
function input (command) is a list of numbers as the APDU Command. You need to fix CLA and LC values before MAC calculation.
Upvotes: 2
Reputation: 94038
I see two mistakes:
As for the last point, it performs DES encrypt with single key given, decrypt with single key given and a final encrypt again. So two of these operations are cancelling each other out. This is deliberate in the design of triple 3DES to make a single HW implementation be able to do both.
I think this is mentioned in the earlier question, but beware, MAC generally uses bit padding: a byte with 0x80
always padded, with as many 0x00
bytes to reach the next block boundary.
Note that Bouncy Castle contains Retail MAC.
Upvotes: 1