in SmartCard

Open Smart Card Shell Test on doemv.js – EMV DDA Test

Summary

Refer to dump.js and EMV SDA Test, continue to test on DDA. The DDA test result is successful.

DDA session contains a random number generated by the terminal, it is more secure than SDA.

I tested with below reader and expired credit card.
Reader

Credit card

Authentication procedure

DDA procedure

Retrieval of ICC Public Key

Before retrieve ICC Public key, you need to retrieve the CA key, refer to EMV SDA Test for retrieving CA key.

Retrieve CA key

Below screen shot is to retrieve the ICC PK by using the CA key.
Retrieve ICC PK

Dynamic Data Authentication

verify SDAD

The whole procedure APDU is as below,

Reset
00A404000E315041592E5359532E4444463031
6120
00C0000020
6F1E840E315041592E5359532E4444463031A50C8801015F2D02656E9F1101019000
00B2010C00
6C2B
00B2010C2B
702961274F07A0000000031010500B56495341204352454449549F120B56495341204352454449548701019000
00B2020C00
6A83
00A4040007A0000000031010
613A
00C000003A
6F388407A0000000031010A52D500B56495341204352454449548701019F38039F1A025F2D02656E9F120B56495341204352454449549F1101019000
80A800000483020276
6114
80C0000014
80127C00080202001001010010030400180102019000
00B2020C00
6C4F
00B2020C4F
704D57134147463002632848D17082010000032610000F5F201A58494F4E47204855494C494E20202020202020202020202020209F1F183030303030303030303030303030303332363120202020209000
00B2011400
6CB6
00B20114B6
7081B39081B06751D5FE4474C7A7F91D1C493991B7A1C487A406B2486573D2943A9EEDF15E3538CBB90191EAA8D34B46E7DD64B8A5926AFBB375BCB5F3EDDC7294EA34BBDF643DC3AA6EF8BF932A68846D0AEEADDD783A754C091B35807DD0CF9F42A3EE67909F7EB11555C6975D22065698E7D3B2F8FCF00B6B7397BDFCD75C601EE3AEC220CB06613A5E8ACE020DEA2510338EC2DD87F81EDB7B1FC3831FBABEB8ED2978F7010BAD8DEB8C397D8AC1512CB3F46D579000
00B2031400
6CF2
00B20314F2
7081EF8F01089224CCE4335A1A3CD7E4271A50B8D804D95ABA4E349811244D73336D196A6D969F25025B27D99F3201039F4681B025EBB698F660FB9E177F4A611E2FD4AB4C14A86A159E8838D10B6E47C99956D78C2E04C870F525227ABAA8D46BFE09CF46A372CD6FEBF8B59CA22FC646B6B38C1A061A5AF1E4D7556303EA5F7924C519D6D5EA5E10A25B6F9A4F4421081F4E9C7865F7ADEC183D39489C0B4A34E947C2D535426A7545EF4A2B9BF3A19DC1A07252F70A63E7A94A85C46FD55AFDB2348C402FA53905123A97A161F07D8E712576DCC15E92A10E93E504804E09629048AE9F4701039F49039F37049F4A01829000
00B2041400
6CB6
00B20414B6
7081B39381B0D025D46D7A68F3DBF8B7C303A59A8DF319F9E0ECBBC90DA96141D100C1F3B9B79F5893422A15CF70378737D3CC96DCFA6FFF8A99EB90CDFB292E451696EC776785F0F023CFE35F1350E081C7E444ADEA63E52B716BBDEFB9EA782812FA45622C13CD56EE213F5E29E7F0600D22F8331C8766C81BD6E6D613D06A462657890638FF1C9A630AC583C81FFAACEA11B9672342373F4AD214EF2B0E0448C3EF68183C7DA12FD4E656CAD7FB735CEF725E841C9000
00B2011C00
6C12
00B2011C12
70105A0841474630026328485F24031708319000
00B2021C00
6C81
00B2021C81
707F5F300202015F3401015F25031408019F420207029F4401028C159F02069F03069F1A0295055F2A029A039C019F37048D178A029F02069F03069F1A0295055F2A029A039C019F37049F0702FF008E0E00000000000000001E0302031F009F0802008C9F0D05F8709C88009F0E0500000000009F0F05F8F8DC98005F280207029000
00880000045B85F43A
6162
00C0000062
8060857BB70F0AA5420089B67C6AB97CC15483291B332AC53947F7E6965AD12A8C580DF368AA5C7BADF6D7A4F4FF4A81CDFA8C779E2DE53C73C22388268A0B1B2A0C807E00BC0950A5DE8A0242150EE15098FDAE96E43EC43A01821DF34AD0D2127B9000
0084000000
6C08
0084000008
D59472059BB097989000
80AE4000250000000000010000000000000000000000097809073021E30A111AD59472059BB09798DAC5
6700
80CA9F3600
6C05
80CA9F3605
9F360200769000

I made a few changes to the Javascript,

DataAuthentication.prototype.retrieveICCPublicKey = function(issuerPublicKeyModulus) {
    var issuerPublicKeyModulus =  issuerPublicKeyModulus;
    var key = new Key();
    key.setType(Key.PUBLIC);
    key.setComponent(Key.MODULUS, issuerPublicKeyModulus);
    key.setComponent(Key.EXPONENT, this.emv.cardDE[0x9F32]);
    var iccCert = this.emv.cardDE[0x9F46];

    // Step 1: ICC Public Key Certificate and Issuer Public Key Modulus have the same length
    assert(iccCert.length == issuerPublicKeyModulus.length);

    // Step 2: The Recovered Data Trailer is equal to 'BC'
    var decryptedICC = crypto.decrypt(key, Crypto.RSA, iccCert);
    assert(decryptedICC.byteAt(decryptedICC.length - 1) == 0xBC);

    // Step 3: The Recovered Data Header is equal to '6A'   
    assert(decryptedICC.byteAt(0) == 0x6A);

    // Step 4: The Certificate Format is equal to '04'  
    assert(decryptedICC.byteAt(1) == 0x04);

    // Step 5: Concatenation
    var list = decryptedICC.bytes(1, (decryptedICC.length - 22));
    var remainder = this.emv.cardDE[0x9F48];
    var exponent = this.emv.cardDE[0x9F47];
    //var remex = remainder.concat(exponent);  //2nd change, where is the 1st change?
    //list = list.concat(remex);    
    //change as below, as remainder is undefined. //2nd change
    list = list.concat(exponent);


    var daInput = this.emv.getDAInput();
    list = list.concat(daInput);

    var sdaTagList = this.emv.cardDE[0x9F4A];
    if(typeof(sdaTagList != "undefined")) {
        var value = new ByteBuffer();
        for(var i = 0; i < sdaTagList.length; i++) {
            var tag = sdaTagList.byteAt(i);         
            value = value.append(this.emv.cardDE[tag]);
        }
        value = value.toByteString();
        list = list.concat(value);
    }

    // Step 6: Generate hash from concatenation
    var hashConcat = this.crypto.digest(Crypto.SHA_1, list);    

    // Step 7: Compare recovered hash with generated hash
    var hashICC  = decryptedICC.bytes(decryptedICC.length - 21, 20);
    assert(hashConcat.equals(hashICC));

    // Step 8: Verify that the Issuer Identifier matches the lefmost 3-8 PAN digits 
    var pan = this.emv.cardDE[0x5A];    
    var panCert = decryptedICC.bytes(2, 10);

    var panCert = panCert.toString(HEX);
    var pan = pan.toString(HEX);
    for(var i = 0; i < 20; i++) {
        if(panCert.charAt(i) == 'F') {
            var panCert = panCert.substr(0, i);
            var pan = pan.substr(0, i);
        }
    }
    assert(pan == panCert);

    // Step 9: Verify that the last day of the month specified in the Certification Expiration Date is equal to or later than today's date.  

    // Step 10: Check the ICC Public Key Algorithm Indicator
    var pkAlgorithmIndicator = decryptedICC.byteAt(18);


    // Step 11: Concatenate the Leftmost Digits of the ICC Public Key and the ICC Public Key Remainder (if present) to obtain the ICC Public Key Modulus

    var modulus = key.getComponent(Key.MODULUS);
    var leftmostDigits = decryptedICC.bytes(21, (modulus.length - 42));
    //4th change
    //var iccPublicKeyModulus = leftmostDigits.concat(remainder);
    //return(iccPublicKeyModulus)
    return(leftmostDigits)
}   

/**
 * Generation and verification of the dynamic signature.
 * A successfully retrieval of the ICC Public Key is required.
 *
 * @param {Key} key the ICC Public Key
*/
DataAuthentication.prototype.dynamicDataAuthentication = function(iccPublicKeyModulus) {
    var iccPublicKeyModulus = iccPublicKeyModulus;

    //added for testing, added, otherwise, fail. 2018.9.30, 5th change.
    var iccPublicKeyModulus = iccPublicKeyModulus.bytes(0, (iccPublicKeyModulus.length - 38));

    var Data = crypto.generateRandom(4);
    var internalAuthenticate = card.sendApdu(0x00, 0x88, 0x00, 0x00, Data, 0x00);
    //var asn = new ASN1(internalAuthenticate);  //3rd change
    //var tag = asn.find(0x9F4B);
    //var SDAD = tag.value;
    var SDAD  = internalAuthenticate.bytes(2,internalAuthenticate.length - 2);

    var picKey = new Key();
    picKey.setType(Key.PUBLIC);
    picKey.setComponent(Key.MODULUS, iccPublicKeyModulus);
    picKey.setComponent(Key.EXPONENT, this.emv.cardDE[0x9F47]);
    var decryptedSDAD = crypto.decrypt(picKey, Crypto.RSA, SDAD);
    // Step 1: SDAD and ICC Public Key Modulus have the same length
    assert(SDAD.length == iccPublicKeyModulus.length);

    // Step 2: The Recovered Data Trailer is equal to 'BC'
    assert(decryptedSDAD.byteAt(decryptedSDAD.length - 1) == 0xBC);

    // Step 3: The Recovered Data Header is equal to '6A'
    assert(decryptedSDAD.byteAt(0) == 0x6A);

    // Step 4: The Signed Data Format is equal to '05'
    assert(decryptedSDAD.byteAt(1) == 0x05);

    // Step 5: Concatenation of Signed Data Format, Hash Algorithm Indicator, ICC Dynamic Data Length, ICC Dynamic Data, Pad Pattern, random number
    var LDD = decryptedSDAD.byteAt(3);
    var list = decryptedSDAD.bytes(1, 3 + LDD + decryptedSDAD.length - LDD - 25);
    list = list.concat(Data);

    // Step 6: Genereate hash from concatenation
    var hashConcat = this.crypto.digest(Crypto.SHA_1, list);

    // Step 7: Compare recovered hash with generated hash
    var hashSDAD = decryptedSDAD.bytes(decryptedSDAD.length - 21, 20);
    assert(hashConcat.equals(hashSDAD));
    print("<-----------------------------DDA was successful------------------------------>\n");
}

The Javascript output is as below,


Application Primary Account Number (PAN) Sequence Number: 01 Application Usage Control: FF00 Byte 1: Valid at terminals other than ATMs Valid at ATMs Valid for international services Valid for domestic services Valid for international goods Valid for domestic goods Valid for international cash transactions Valid for domestic cash transactions Byte 2: Application Version Number: 008C Issuer Action Code - Default: F8709C8800 Byte 1: Offline data authentication was not performed (b8) SDA failed (b7) ICC data missing (b6) Card appears on terminal exception file (b5) DDA failed (b4) Byte 2: Expired application (b7) Application not yet effective (b6) Requested service not allowed for card product (b5) Byte 3: Cardholder verification was not successful (b8) PIN entry required and PIN pad not present or not working (b5) PIN entry required, PIN pad present, but PIN was not entered (b4) Online PIN entered (b3) Byte 4: Transaction exceeds floor limit (b8) Merchant forced transaction online (b4) Byte 5: Issuer Action Code - Denial: 0000000000 Byte 1: Byte 2: Byte 3: Byte 4: Byte 5: Issuer Action Code - Online: F8F8DC9800 Byte 1: Offline data authentication was not performed (b8) SDA failed (b7) ICC data missing (b6) Card appears on terminal exception file (b5) DDA failed (b4) Byte 2: ICC and terminal have different application versions (b8) Expired application (b7) Application not yet effective (b6) Requested service not allowed for card product (b5) New card (b4) Byte 3: Cardholder verification was not successful (b8) Unrecognised CVM (b7) PIN entry required and PIN pad not present or not working (b5) PIN entry required, PIN pad present, but PIN was not entered (b4) Online PIN entered (b3) Byte 4: Transaction exceeds floor limit (b8) Transaction selected randomly for online processing (b5) Merchant forced transaction online (b4) Byte 5: Unknown Class: 9f11 Unknown Class: 9f12 Track 1 Discretionary Data: 303030303030303030303030303030333236312020202020 Issuer Public Key Exponent: 03 Processing Options Data Object List (PDOL): 9F1A02 9f1a - 2 - Terminal Country Code Application Currency Code: 0702 Application Currency Exponent: 02 ICC Public Key Certificate: 25EBB698F660FB9E177F4A611E2FD4AB4C14A86A159E8838D10B6E47C99956D78C2E04C870F525227ABAA8D46BFE09CF46A372CD6FEBF8B59CA22FC646B6B38C1A061A5AF1E4D7556303EA5F7924C519D6D5EA5E10A25B6F9A4F4421081F4E9C7865F7ADEC183D39489C0B4A34E947C2D535426A7545EF4A2B9BF3A19DC1A07252F70A63E7A94A85C46FD55AFDB2348C402FA53905123A97A161F07D8E712576DCC15E92A10E93E504804E09629048AE ICC Public Key Exponent: 03 Dynamic Data Authentication Data Object List (DDOL): 9F3704 9f37 - 4 - Unpredictable Number Static Data Authentication Tag List: 82 ------------------------------------------------------------------------------> <-----------------------------SDA was successful------------------------------> <-----------------------------DDA was successful------------------------------>

Reference

Open Smart Card Shell Test on doemv.js – EMV SDA Test
Open Smart Card Shell Test on dump.js
www.openscdp.org: Dynamic Data Authentication
BP-Tools – Cryptographic Calculator

Write a Comment

Comment