This shows you the differences between two versions of the page.
|
ac:laboratoare:09 [2024/12/12 02:25] dimitrie.valu [Lab 09 - EMV Basics] |
ac:laboratoare:09 [2025/11/20 11:37] (current) marios.choudary |
||
|---|---|---|---|
| Line 28: | Line 28: | ||
| See book 0 (contact specs), chapter "Answer to Reset", section 8.2 (Characters Returned by ICC at Answer to Reset) | See book 0 (contact specs), chapter "Answer to Reset", section 8.2 (Characters Returned by ICC at Answer to Reset) | ||
| </note> | </note> | ||
| + | |||
| + | <solution -hidden> | ||
| + | <code> | ||
| + | ATR: 3B 65 00 00 20 63 CB 66 00 | ||
| + | + TS = 3B --> Direct Convention | ||
| + | + T0 = 65, Y(1): 0110, K: 5 (historical bytes) | ||
| + | TB(1) = 00 --> VPP is not electrically connected | ||
| + | TC(1) = 00 --> Extra guard time: 0 | ||
| + | + Historical bytes: 20 63 CB 68 00 | ||
| + | Category indicator byte: 20 (proprietary format) | ||
| + | </code> | ||
| + | </solution> | ||
| + | |||
| ==== 2. Card verification method (2p) ==== | ==== 2. Card verification method (2p) ==== | ||
| Line 50: | Line 63: | ||
| </note> | </note> | ||
| + | <solution -hidden> | ||
| + | From the TLV decoder, you get the following Cardholder Verification Method (CVM) List (''%%8E%%''): | ||
| + | |||
| + | <code> | ||
| + | 000000000000000041000000 | ||
| + | </code> | ||
| + | |||
| + | We have 2 groups of 4 bytes prior to ''%%0x41%%'' - these represent two amount fields (''%%X%%'' and ''%%Y%%''). Not what this task is asking for. | ||
| + | |||
| + | Beyond the two amount fields, we have a variable-length Cardholder Verification Rules (CV Rules) field. Each CV Rule describes a CVM and the conditions under which it should be applied. We only have ''%%0x41%%'' as a CV Rule. If you look at Appendix C3 of EMV Book 3, you can decode it to the following: | ||
| + | |||
| + | <code> | ||
| + | bin(0x41) = 0b01000001 | ||
| + | 0 = RFU (Reserved for Future Use) | ||
| + | 1 = Apply succeeding CV Rule if this CVM is unsuccessful | ||
| + | 000001 = Plaintext PIN verification performed by ICC | ||
| + | </code> | ||
| + | |||
| + | Note that the following CV Rule that would be applied in the case of PIN failure is ''%%0b00000000%%'', i.e. **Fail CVM processing**. | ||
| + | |||
| + | The only cardholder verification method allowed is, hence, plaintext PIN verification. | ||
| + | </solution> | ||
| ==== 3. Card verification method (2p) ==== | ==== 3. Card verification method (2p) ==== | ||
| Line 71: | Line 106: | ||
| </note> | </note> | ||
| + | <solution -hidden> | ||
| + | ''%%T->C: 80CA9F1700%%'' | ||
| + | |||
| + | Command APDU Format: ''%%CLA INS P1 P2 Le%%'' | ||
| + | |||
| + | <code> | ||
| + | 80 = (CLA) (class) proprietary class of commands, not ISO 7816-standard. | ||
| + | CA = (INS) (instruction) GET DATA. | ||
| + | From here, we know to look into Book 3, 6.5.7 - GET DATA Command-Response APDUs. | ||
| + | |||
| + | 9F17 = (P1+P2) (parameters 1/2) Tag of data that the terminal is requesting. | ||
| + | In this case, it's PIN Try Counter. | ||
| + | |||
| + | 00 = (Le) Length of command data, 0=no data is being sent with this command. | ||
| + | </code> | ||
| + | |||
| + | ''%%C->T: 6C04%%'' | ||
| + | |||
| + | Status Bytes Format: ''%%SW1 SW2%%'' (Status Bytes 1 and 2) | ||
| + | |||
| + | <code> | ||
| + | 6C = (SW1) Wrong length Le. | ||
| + | 04 = (SW2) The correct, exact length. | ||
| + | </code> | ||
| + | |||
| + | ''%%T->C: 80CA9F1704%%'' | ||
| + | |||
| + | Command APDU Format: ''%%CLA INS P1 P2 Le%%'' | ||
| + | |||
| + | <code> | ||
| + | Same as the first command, but with a correct length: | ||
| + | 04 = (Le) Length of command data, i.e. PIN is 4-bytes long. | ||
| + | </code> | ||
| + | |||
| + | ''%%C->T: CA9F1701069000%%'' | ||
| + | |||
| + | Response APDU Format: ''%%Data SW1 SW2%%'' | ||
| + | |||
| + | <code> | ||
| + | CA = Echo of the INS byte (GET DATA). | ||
| + | 9F17 = The tag for the data object being returned (PIN Try Counter). | ||
| + | 01 = Length of the value being returned, in bytes. | ||
| + | 06 = Value of the data object (i.e. 6 remaining PIN attempts). | ||
| + | 9000 = Operation successful. | ||
| + | </code> | ||
| + | |||
| + | </solution> | ||
| ==== 4. Card-holder verification (2p) ==== | ==== 4. Card-holder verification (2p) ==== | ||
| Line 89: | Line 171: | ||
| * section 6.3 and 6.5 for commands | * section 6.3 and 6.5 for commands | ||
| </note> | </note> | ||
| + | |||
| + | <solution -hidden> | ||
| + | ''%%T->C: 0020008008241111FFFFFFFFFF%%'' | ||
| + | |||
| + | Command APDU Format: ''%%CLA INS P1 P2 Lc Data%%'' | ||
| + | |||
| + | <code> | ||
| + | 00 = (CLA) ISO 7816 class of instructions for standard commands. | ||
| + | 20 = (INS) VERIFY. Used for Cardholder Verification, such as PIN verification | ||
| + | 00 = (P1) PIN verification applies to the currently selected application. | ||
| + | 80 = (P2) Specifies the PIN type and format (plaintext data for 80). | ||
| + | 08 = (Lc) (Length of data) Data field is 8 bytes long. | ||
| + | |||
| + | 241111FFFFFFFFFF = (Data) Of which: | ||
| + | 241111 = The PIN to be verified. | ||
| + | FFFFFFFFFF = Padding (used to fill until 8 bytes). | ||
| + | </code> | ||
| + | |||
| + | ''%%C->T: 9000%%'' | ||
| + | |||
| + | Status Bytes Format: ''%%SW1 SW2%%'' | ||
| + | |||
| + | <code> | ||
| + | 90 = Operation successful. | ||
| + | 00 = No additional information. | ||
| + | </code> | ||
| + | |||
| + | **The card successfully verified the PIN sent by the terminal.** | ||
| + | </solution> | ||
| ==== 5. Transaction authentication (2p) ==== | ==== 5. Transaction authentication (2p) ==== | ||
| Line 110: | Line 221: | ||
| </note> | </note> | ||
| - | ==== MAC generation (Bonus) (2p) ==== | + | <solution -hidden> |
| + | ''%%T->C: 80AE80002B00000000000000000000000000008000000000000000000000000000003400000000000000000000410002%%'' | ||
| + | |||
| + | Command APDU Format: ''%%CLA INS P1 P2 Lc Data%%'' | ||
| + | |||
| + | **The terminal is sending a Generate Application Cryptogram (GEN AC) command to request an ARQC (Authorisation Request Cryptogram) for transaction authentication.** | ||
| - | Say you know the card's master key to be: | ||
| <code> | <code> | ||
| - | 79610497EFCB67E5546EF8CEBCB05D85 | + | 80 = (CLA) Proprietary command. |
| + | AE = (INS) GEN AC (Generate Application Cryptogram). This is used for transaction authentication. | ||
| + | It requests the card to generate a cryptogram to verify the integrity of the transaction. | ||
| + | |||
| + | 80 = (P1) Terminal is requesting an Authorisation Request Cryptogram (ARQC). | ||
| + | 00 = (P2) RFU. | ||
| + | 2B = (Lc) (Length of Data) 43 bytes. | ||
| + | |||
| + | The data itself follows. It is broken into: | ||
| + | 000000000000 = Amount Authorized | ||
| + | 000000000000 = Amount Other | ||
| + | |||
| + | 0800 = Terminal Country Code | ||
| + | 0000 = Transaction Currency Code | ||
| + | 000000 = Transaction Date | ||
| + | 34 = Transaction Type | ||
| + | |||
| + | 0000000000000000 = Unpredictable Number (randomly generated) | ||
| + | 410002 = Data Authentication Code (ARQC input) | ||
| </code> | </code> | ||
| - | Can you regenerate the cryptogram (MAC) from the information obtained in the previous exercises ? | + | ''%%C->T: 612B%%'' |
| - | You know the encryption algorithm is 3DES. | + | Status Bytes Format: ''%%SW1 SW2%%'' |
| - | Besides the data from previous exercises, you are also given the | + | <code> |
| - | Application Interchange Profile is 0x1000. | + | 61 = Card has more data to send. |
| + | 2B = 43 bytes of data are available for retrieval. | ||
| + | </code> | ||
| - | <note tip> | + | ''%%T->C: 00C000002B%%'' |
| - | See EMV book 2, section 8.1. | + | |
| - | </note> | + | |
| - | <hidden> | + | Command APDU Format: ''%%CLA INS P1 P2 Le%%'' |
| - | ==== Getting data from your card ==== | + | |
| - | First, get pyscard from | + | **Here, the terminal is requesting 43 bytes of data from the card.** |
| - | [[https://pypi.python.org/pypi/pyscard|here]]. | + | |
| - | Then, install pyscard (check the readme). Do the following (as root): | ||
| - | * Install pcsclite-dev: | ||
| <code> | <code> | ||
| - | sudo apt-get install libpcsclite-dev | + | 00 = ISO 7816 standard. |
| + | C0 = GET RESPONSE. | ||
| + | 00 = RFU. | ||
| + | 00 = RFU. | ||
| + | 2B = 43 bytes. | ||
| </code> | </code> | ||
| - | * Only if the above doesn't work, then install these packages: | + | |
| + | ''%%C->T: C077299F2701809F360201349F2608817C3AAB208BE0659F10120310A00006250400000000000000000000FF9000%%'' | ||
| + | |||
| + | Response APDU Format: ''%%Data SW1 SW2%%'' | ||
| <code> | <code> | ||
| - | #apt-get install swig libudev-dev git autoconf libtool libsystemd-dev flex | + | Data is broken into: |
| + | C0 = Proprietary or issuer-specific data. | ||
| + | 7729 = Template for cryptogram-related data (EMV tag 77). | ||
| + | |||
| + | Following data is TLV-encoded: | ||
| + | 9F27 = Cryptogram Information Data (CID). | ||
| + | 01 = Length of CID data. | ||
| + | 80 = Cryptogram type: ARQC (Authorisation Request Cryptogram). | ||
| + | |||
| + | 9F36 = Application Transaction Counter (ATC). | ||
| + | 02 = ATC value length. | ||
| + | 0134 = ATC value (Counter = 308). | ||
| + | |||
| + | 9F26 = Application Cryptogram. | ||
| + | 08 = Length of cryptogram. | ||
| + | 817C3AAB208BE065 = The actual cryptogram generated by the card. | ||
| + | |||
| + | 9F10 = Issuer Application Data (IAD). | ||
| + | 12 = Length of IAD. | ||
| + | 0310A00006250400000000000000000000FF = Encrypted issuer-specific data (used for ARQC verification). | ||
| + | |||
| + | 9000 = Operation successful, no more information. | ||
| </code> | </code> | ||
| - | * Get and install Pyscard from [[https://pypi.python.org/pypi/pyscard|here]] | + | |
| + | **The response is concluded with 9000, meaning the operation was successful. This data will be sent to the issuer for further authentication.** | ||
| + | </solution> | ||
| + | |||
| + | ==== Bonus 1: Get data from your card (or other card) (2 points) ==== | ||
| + | |||
| + | === First install some tools to work with a smartcard reader ==== | ||
| + | |||
| + | Do the following on Linux (this is for Ubuntu/Debian -- you might need root access): | ||
| + | |||
| + | * Install these packages: | ||
| <code> | <code> | ||
| - | #python setup.py build_ext install | + | sudo apt install libpcsclite-dev swig libpcsc-perl pcsc-tools python3-dev libudev-dev python3-pyscard python3-pyserial |
| </code> | </code> | ||
| - | * Install Pyserial | + | |
| + | Note: on some distributions the python3-pyserial package is python3-serial. | ||
| + | |||
| + | If this doesn't work, then get ''%%Pyserial%%'' from [[https://pypi.python.org/pypi/pyserial#downloads|here]] | ||
| + | |||
| + | * Install ''%%pcsc%%'' related libs: | ||
| <code> | <code> | ||
| - | #sudo pip install pyserial | + | sudo apt install libusb-dev libccid pcscd libpcsclite1 |
| </code> | </code> | ||
| - | If this doesn't work, then get pyserial from [[https://pypi.python.org/pypi/pyserial#downloads|here]] | + | |
| - | * Install pcsc related libs: | + | * You might also want to install these additional card tools: |
| <code> | <code> | ||
| - | sudo apt-get install libusb-dev libusb++-0.1-4v5 libccid pcscd libpcsclite1 | + | sudo apt install libpcsc-perl pcsc-tools |
| </code> | </code> | ||
| - | * Only if desired, additional tools can be installed from here: | + | |
| + | On Arch Linux, get the following packages (reference [[https://wiki.archlinux.org/title/Smartcards |the Arch wiki]] if you need to): | ||
| <code> | <code> | ||
| - | #apt-get install libpcsc-perl | + | yay -S swig flex libusb ccid pcsclite pcsc-perl pcsc-tools python-pyscard python-pyserial |
| - | #apt-get install pcsc-tools | + | |
| </code> | </code> | ||
| - | See details [[http://support.gemalto.com/fileadmin/user_upload/IAM/FAQ/How_to_install_the_PC-Link_reader_on_Linux.pdf|here]]. | ||
| + | You may need to start the ''%%pcscd%%'' daemon: | ||
| + | <code> | ||
| + | systemctl start pcscd.service | ||
| + | </code> | ||
| - | Files for accessing card data [[https://ocw.cs.pub.ro/courses/_media/ac/laboratoare/sclink.zip|here]]. | + | See details [[http://www.audentia-gestion.fr/GEMALTO/PDF/How_to_install_the_PC-Link_reader_on_Linux.pdf |here]]. |
| - | </hidden> | + | |
| + | For Windows drivers you can check [[https://supportportal.gemalto.com/csm/?id=kb_article_view&sys_kb_id=0adc96844f350700873b69d18110c76a&sysparm_article=KB0016522|here]]. However, we recommend using Linux, as the instructions below apply for the Linux installation. | ||
| + | |||
| + | For Mac OS, things should work by just installing pcsc_tools through mac ports or brew: | ||
| + | <code> | ||
| + | sudo port install pcsc-tools swig py-pyscard py-serial | ||
| + | </code> | ||
| + | |||
| + | |||
| + | === Get basic information about your card === | ||
| + | |||
| + | Try this with your card in the smartcard reader: | ||
| + | |||
| + | <code> | ||
| + | pcsc_scan | ||
| + | </code> | ||
| + | |||
| + | This should show you the ATR and some applications on the card. | ||
| + | |||
| + | What is the ATR from your card ? | ||
| + | |||
| + | === Use a terminal emulator to interact with your card === | ||
| + | |||
| + | Start with files for accessing the card data in {{:ac:laboratoare:lab_emv_py3.zip|this}} archive. | ||
| + | |||
| + | Create a file named ''%%terminal.txt%%'' that will be populated as mentioned below (perhaps already included in the zip file). | ||
| + | This file should end with a line containing the string ''%%0000000000%%''. | ||
| + | |||
| + | After updating this file (see below), we can run the terminal in this manner: | ||
| + | |||
| + | <code> | ||
| + | python3 sclink.py --scterminal terminal.txt gg | ||
| + | </code> | ||
| + | |||
| + | |||
| + | === Select financial app === | ||
| + | |||
| + | We shall now first select the main financial application on the card via the general ''%%1PAY.SYS.DDF01%%'' file available on some EMV cards followed by the selection of the Application ID. See [[https://www.emvco.com/specifications/book-1-application-independent-icc-to-terminal-interface-requirements-2/ |EMV Book 1]], sections 11.3 and 12 for details. | ||
| + | |||
| + | <note> | ||
| + | Newer EMV cards may not support the ''%%1PAY.SYS.DDF01%%'' selection method described below, but you may need to use the Application ID list method or some other variant, as explained in the [[https://www.emvco.com/specifications/book-1-application-independent-icc-to-terminal-interface-requirements-2/ |EMV Book 1]], chapter 12. | ||
| + | </note> | ||
| + | |||
| + | In summary, the main steps are these: | ||
| + | |||
| + | - Send the first ''%%SELECT%%'' command with ''%%1PAY.SYS.DDF01%%'': ''%%00A404000E315041592E5359532E4444463031%%'' | ||
| + | - Decode the response using [[http://www.emvlab.org|emvlab]]. Use the SFI response (e.g. ''%%01%%'', concatenated with the record number encoded in the last 3 bits): ''%%(SFI << 3) | REC_NUM%%''. E.g. If ''%%SFI=01%%'' and ''%%REC_NUM=1%%'', we get the Reference Control parameter (P2) ''%%0x0C%%'' for the ''%%READ RECORD%%'' command, leading to the ''%%READ RECORD%%'' command ''%%00B2010C00%%''. | ||
| + | - Check the available apps by sending ''%%READ RECORD%%'' commands of the form ''%%00B2010C00%%'', ''%%00B2020C00%%'', etc. Check the responses by decoding them with [[http://www.emvlab.org|emvlab]] | ||
| + | - Eventually select one of them using ''%%SELECT%%'', e.g. | ||
| + | * Select particular app: ''%%00A4040007XXXXXXXXXXXXXX%%'' (replace the X values based on the Application ID response to the ''%%00B2XXX%%'' command above). | ||
| + | E.g. to get something like ''%%00A4040007A0000000041010%%'' (if the application has 7 bytes -- 14 hex characters for the Application ID). | ||
| + | * ''%%00A4040007A0000000041010%%'' (this must be updated for your card, based on the response to the ''%%00B2XXX%%'' command above). | ||
| + | * Start transaction with ''%%GET PROCESSING OPTS%%'': ''%%80A80000028300%%'' | ||
| + | |||
| + | Now your ''%%terminal.txt%%'' file should look something like this (but again, replace the Application ID with the correct one and also use the correct ''%%READ RECORD%%'' commands -- from your trials). | ||
| + | |||
| + | <code - terminal.txt> | ||
| + | 00A404000E315041592E5359532E4444463031 | ||
| + | 00B2010C00 | ||
| + | 00A4040007A0000000041010 | ||
| + | 80A80000028300 | ||
| + | 0000000000 | ||
| + | </code> | ||
| + | |||
| + | As mentioned above, now run this terminal emulator with the following code: | ||
| + | |||
| + | <code> | ||
| + | python3 sclink.py --scterminal terminal.txt gg | ||
| + | </code> | ||
| + | |||
| + | What applications do you see on the card ? | ||
| + | |||
| + | Are you able to start communication ? | ||
| + | |||
| + | ==== Bonus 2: MAC generation (2 points) ==== | ||
| + | |||
| + | Say you know the card's master key to be: | ||
| + | <code> | ||
| + | 79610497EFCB67E5546EF8CEBCB05D85 | ||
| + | </code> | ||
| + | |||
| + | Can you regenerate the cryptogram (MAC) from the information obtained in the previous exercises ? | ||
| + | |||
| + | You know the encryption algorithm is 3DES. | ||
| + | |||
| + | Besides the data from previous exercises, you are also given the | ||
| + | Application Interchange Profile is 0x1000. | ||
| + | |||
| + | <note tip> | ||
| + | See EMV book 2, section 8.1. | ||
| + | </note> | ||
| + | |||
| + | <solution -hidden> | ||
| + | We should allow students to select the data somewhat arbitrarily as it's not **entirely** provided in the exercises above, as per the minimum spec mentioned in EMV Book 2, page 87, section 8.1.1, table 28. | ||
| + | |||
| + | <code python> | ||
| + | from Crypto.Cipher import DES3 | ||
| + | from Crypto.Util.Padding import pad | ||
| + | |||
| + | master_key = bytes.fromhex("79610497EFCB67E5546EF8CEBCB05D85") | ||
| + | aip = bytes.fromhex("1000") | ||
| + | |||
| + | # concatenation of amount authorised and amount other, | ||
| + | # terminal country code, transaction currency code, | ||
| + | # transaction date, transaction type, | ||
| + | # unpredictable number, given AIP and the ATC | ||
| + | # we aren't given the terminal verification results, | ||
| + | # so I assumed that it's gonna be 5 * b'00' | ||
| + | transaction_data = bytes.fromhex( | ||
| + | "00000000000000000000000008000000000000000000000034000000000000000010000134" | ||
| + | ) # from task 5 | ||
| + | |||
| + | # 3DES block size is 8 bytes | ||
| + | padded_data = pad(transaction_data, 8) | ||
| + | |||
| + | # 3DES encryption | ||
| + | cipher = DES3.new(master_key, DES3.MODE_ECB) | ||
| + | mac = cipher.encrypt(padded_data) | ||
| + | |||
| + | mac = mac.hex() | ||
| + | print(mac) | ||
| + | </code> | ||
| + | </solution> | ||