Differences

This shows you the differences between two versions of the page.

Link to this comparison view

ac:laboratoare:09 [2024/12/02 08:31]
dimitrie.valu
ac:laboratoare:09 [2024/12/15 06:42] (current)
dimitrie.valu
Line 1: Line 1:
-===== Lab 09 - TOFU-based Authenticated Key Exchange ​=====+===== Lab 09 - EMV Basics ​=====
  
-In this labwe will implement Trust On First Use in a manner similar to that of SSH. We will base our implementation around ''​%%PyCryptodome%%'' ​you can find the relevant documentation [[https://​www.pycryptodome.org/​src/​api |here]].+We have presented in class the basic communication mechanisms in EMVthe protocol 
 +used in banking transactions. We have seen the low-level communication layer, 
 +as well as the higher layers of communication,​ including the format of commands (CAPDUs) 
 +and responses (RAPDUs)Furthermore,​ we have also seen an example of transaction.
  
-==== 0Init ====+Throughout this lab you'll have to analyze the transcript of a transaction,​ 
 +specifying what commands are being sent and what data is received from the card.
  
-Use these commands ​to generate a private key and a Diffie-Hellman parameter file:+For this, you should get the EMV specification for contact/​acceptance device (books 1-3) from [[http://​emvco.com]]:​ 
 +  * [[https://​www.emvco.com/​specifications/​emvlevel-1-specifications-for-payment-systems-emv-contact-interface-specification/​|Book 0 (contact specs)]] 
 +  * [[https://​www.emvco.com/​specifications/​book-1-application-independent-icc-to-terminal-interface-requirements-2/​|Book 1]] 
 +  * [[https://​www.emvco.com/​specifications/​book-2-security-and-key-management-2/​|Book 2]] 
 +  * [[https://​www.emvco.com/​specifications/​book-3-application-specification-2/​|Book 3]] 
 + 
 + 
 +==== 1. Answer-to-Reset (2p) ==== 
 + 
 +You are given the following ATR (each character represents a hexadecimal digit):
 <​code>​ <​code>​
-openssl genrsa -out private.pem 2048 +3B6500002063CB6600
-openssl dhparam -out dhparam.pem 2048+
 </​code>​ </​code>​
  
-The ''​%%dhparam%%''​ file will be used as a hardcoded ''​%%.pem%%''​ that contains ​the necessary Diffie-Hellman ​parameters ​to generate our DH keys. These values are generally decided upon by convention and are hardcoded - check [[https://​datatracker.ietf.org/​doc/​html/​rfc7919#​page-19 |RFC 7919]]. An example which can be found there is ''​%%ffdhe2048%%''​.+Decode it in order to understand the ATR parametersMention ​the available ​parameters.
  
-Create a Python environment or use an existing onethen install the required packages:+<note tip> 
 +See book 0 (contact specs)chapter "​Answer to Reset",​ section 8.2 (Characters Returned by ICC at Answer to Reset) 
 +</​note>​
  
-<​code ​bash+<​solution -hidden>​ 
-python3 ​-m venv create env +<​code>​ 
-source ./​env/​bin/​activate +ATR: 3B 65 00 00 20 63 CB 66 00 
-pip install ​--upgrade pip ++ TS = 3B --> Direct Convention 
-pip install pycryptodome pyasn1++ 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>​ </​code>​
 +</​solution>​
  
-==== 1. Implement DH + RSA signature ==== 
  
-Starting from {{:​ac:​laboratoare:​lab_tofu.zip |these files}}, solve the TODO 1 series in ''​%%dhe_server.py%%''​ and ''​%%dhe_client.py%%''​+==== 2Card verification method (2p) ====
  
-On the server sideyou should:+A card returns ​the following TLV as a response to a READ RECORD command 
 +(ignore the line breaksthis should ​be a single hexstring): 
 +<​code>​ 
 +70538D06910A8A0295058E0C0000000000000000410000008C219F02069F03069F1A02950 
 +55F2A029A039C019F37049F35019F45029F4C089F34039F561380000FFFFF000000000000 
 +00000000000000009F5501809000 
 +</​code>​
  
-    * Send the RSA public key to the client. +Find what are the cardholder verification methods allowed.
-    * Generate a DH key pair (use the data hardcoded in ''​%%dhparam.pem%%''​) and send the public key to the client. +
-    * Generate a signature over the RSA and DH public keys (concatenate and hash them, then sign using the RSA private key) and send it to the client. Use [[https://​pycryptodome.readthedocs.io/​en/​latest/​src/​signature/​pkcs1_v1_5.html |this]] as your guide. +
-    * Receive the client'​s DH public key and generate the shared DH secret. +
-    * Derive a symmetric key from the shared secret. Use [[https://​pycryptodome.readthedocs.io/​en/​latest/​src/​protocol/​kdf.html#​hkdf |HKDF]] for this.+
  
-On the client side, you should:+<note tip> 
 +Use [[https://​emvlab.org/​tlvutils/​|this]] tool to decode the TLV (remove the spaces from above). 
 +</​note>​
  
-    * Receive the RSA public key from the server. 
-    * Receive the server'​s DH public key. 
-    * Receive the server'​s signature over the RSA and DH public keys and [[https://​pycryptodome.readthedocs.io/​en/​latest/​src/​signature/​pkcs1_v1_5.html |verify]] it using the server'​s public key. 
-    * Generate a DH key pair and send the public key to the server. 
-    * Compute the shared DH secret. 
-    * Derive a symmetric key from the shared secret. 
  
-Generating a signature over the RSA and DH public keys is a way to authenticate the remote host. If the client successfully verifies this signature using the server'​s public key, then the server is authenticated unless the public key itself has been replaced by the attacker in a man in the middle attack. We will look at a way to (mostlysolve this issue in the next task.+<note tip> 
 +See the  EMV book 3 for "​Cardholder Verification Method ​(CVMList" ​in Section 10.5 and Appendix C3. 
 +</​note>​
  
-The symmetric key derived from the shared secret will be used to encrypt the communication between the client and server. Although we're stopping the tasks herethis key would be the one that you would use to encrypt and decrypt the communication between the client and server. If you want, you can check the [[https://​pycryptodome.readthedocs.io/​en/​latest/​src/​cipher/​aes.html |PyCryptodome documentation]] for more information on how to use AES. To see what ciphers SSH uses, run the following ​command:+<​solution -hidden>​ 
 +From the TLV decoder, you get the following ​Cardholder Verification Method (CVM) List (''​%%8E%%''​):
  
-<​code ​bash+<​code>​ 
-ssh -Q cipher+000000000000000041000000
 </​code>​ </​code>​
  
-==== 2. I hate TOFU ====+We have groups of 4 bytes prior to ''​%%0x41%%''​ - these represent two amount fields (''​%%X%%''​ and ''​%%Y%%''​). Not what this task is asking for.
  
-Now start solving ​the TODO 2 series by implementing Trust On First Use in ''​%%dhe_client.py%%''​. ​Do it as follows:+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 RuleIf you look at Appendix C3 of EMV Book 3, you can decode ​it to the following:
  
-    * Store the public key of the server in a file named ''​%%known_hosts%%''​ in the following format ​(the same way SSH does it):+<​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>​
  
-<​code ​text+Note that the following CV Rule that would be applied in the case of PIN failure is ''​%%0b00000000%%'',​ i.e. **Fail CVM processing**. 
-hostname1 public_key1 + 
-hostname2 public_key2 +The only cardholder verification method allowed is, hence, plaintext PIN verification. 
-...+</​solution>​ 
 + 
 +==== 3. Card verification method (2p) ==== 
 + 
 +A short part of the communication between terminal (T) and card (C) is as follows: 
 +<​code>​ 
 +T->C: 80CA9F1700 
 +C->T: 6C04 
 +T->C: 80CA9F1704 
 +C->T: CA9F1701069000
 </​code>​ </​code>​
  
-    * If the client already has a public key for the given IP of the server, check that the public key of the server matches the one that is stored (if it's a first connection ​i.e., **First Use** - just store the public key and **Trust** ​the host). +  - What is the command being sent by the terminal ? 
-    * If it matches, print a "​connection established"​ message and proceed to use that key for verification of the signature over the DH share of the server. +  - What is it asking for ? 
-    * If it doesn'​t match, print a suggestive error message and exit.+  ​What is the value obtained in the end for that item ?
  
-This is very similar ​to what SSH does when connecting ​to a server using a pair of public/private keys and is known as Trust On First Use (TOFU) authentication.+<note tip> 
 +See EMV book 3: 
 +  * section 6.3.5  for status bytes 
 +  * section 6.3 and 6.5 for commands 
 +</​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) ==== 
 + 
 +A short part of the communication between terminal (T) and card (C) is as follows: 
 +<​code>​ 
 +T->C: 0020008008241111FFFFFFFFFF 
 +C->T: 9000 
 +</​code>​ 
 + 
 +  - What is the command being sent by the terminal ? 
 +  - What is the data being sent by the terminal ? 
 +  - What is the response of the card? What does it mean ? 
 + 
 +<note tip> 
 +See EMV book 3: 
 +  * section 6.3.5  for status bytes 
 +  * section 6.3 and 6.5 for commands 
 +</​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) ==== 
 + 
 +A short part of the communication between terminal (T) and card (C) is as follows: 
 +<​code>​ 
 +T->C: 80AE80002B00000000000000000000000000008000000000000000000000000000003400000000000000000000410002 
 +C->T: 612B 
 +T->C: 00C000002B 
 +C->T: C077299F2701809F360201349F2608817C3AAB208BE0659F10120310A00006250400000000000000000000FF9000 
 +</​code>​ 
 + 
 +  - What is the command being sent by the terminal ? 
 +  - What is the data being sent by the terminal ? 
 +  - What is the response of the card? What does it mean ? 
 + 
 +<note tip> 
 +See EMV book 3: 
 +  * section 6.3.5  for status bytes 
 +  * section 6.3 and 6.5 for commands 
 +</​note>​ 
 + 
 +<​solution -hidden>​ 
 +''​%%T->​C:​ 80AE80002B00000000000000000000000000008000000000000000000000000000003400000000000000000000410002%%''​ 
 + 
 +Command APDU Format: ''​%%CLA INS P1 P2 Lc Data%%''​ 
 + 
 +**The terminal is sending a Generate Application Cryptogram ​(GEN ACcommand to request an ARQC (Authorisation Request Cryptogram) for transaction ​authentication.** 
 + 
 +<​code>​ 
 +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>​ 
 + 
 +''​%%C->​T:​ 612B%%''​ 
 + 
 +Status Bytes Format: ''​%%SW1 SW2%%''​ 
 + 
 +<​code>​ 
 +61 = Card has more data to send. 
 +2B = 43 bytes of data are available for retrieval. 
 +</​code>​ 
 + 
 +''​%%T->​C:​ 00C000002B%%''​ 
 + 
 +Command APDU Format: ''​%%CLA INS P1 P2 Le%%''​ 
 + 
 +**Here, the terminal is requesting 43 bytes of data from the card.** 
 + 
 +<​code>​ 
 +00 = ISO 7816 standard. 
 +C0 = GET RESPONSE. 
 +00 = RFU. 
 +00 = RFU. 
 +2B = 43 bytes. 
 +</​code>​ 
 + 
 +''​%%C->​T:​ C077299F2701809F360201349F2608817C3AAB208BE0659F10120310A00006250400000000000000000000FF9000%%''​ 
 + 
 +Response APDU Format: ''​%%Data SW1 SW2%%''​ 
 + 
 +<​code>​ 
 +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>​ 
 + 
 +**The response is concluded with 9000, meaning the operation was successful. This data will be sent to the issuer for further authentication.** 
 +</​solution>​ 
 +==== MAC generation (Bonus) (2p) ==== 
 + 
 +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>​
  
ac/laboratoare/09.1733121076.txt.gz · Last modified: 2024/12/02 08:31 by dimitrie.valu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0