how to create APDU (TLV) parser in C

前端 未结 2 975
终归单人心
终归单人心 2020-12-17 05:54

For example I have R-APDU like this

uchar rApdu[] = {0x6F, 0x35 ,0x84 ,0x08 ,0x45 ,0x4F ,0x50 ,
    0x43 ,0x43 ,0x41 ,0x52 ,0x44 ,0xA5 ,0x29 ,0x50 ,0x06 ,0x5         


        
相关标签:
2条回答
  • 2020-12-17 06:34

    To implement EMV TLV data parsing you need to follow ISO 8825-1 BER-TLV encoding rules, also known as ASN.1 Basic Encoding Rules (BER).

    To be short, to extract correct BER-TLV Value you need analyse Tag and Length bits to get its correct size.

    Then your sample buffer will be like this:

    tag: "6F"
    len: "35" #  // 53
    val:#"8408454F504343415244A5295006555A4B4152545F2D06757A7275656E87..0B0A"
    - x84:#"8408454F504343415244"
      - tag: "84"
      - len: "08" #  // 8
      - val: "454F504343415244"
    - xA5:#"A5295006555A4B4152545F2D06757A7275656E8701019F1101019F120655..0B0A"
      - tag: "A5"
      - len: "29" #  // 41
      - val:#"5006555A4B4152545F2D06757A7275656E8701019F1101019F1206555A4B..0B0A"
        - x50:#"5006555A4B415254"
          - tag: "50"
          - len: "06" #  // 6
          - val: "555A4B415254"
        - x5F2D:#"5F2D06757A7275656E"
          - tag: "5F2D"
          - len: "06" #  // 6
          - val: "757A7275656E"
        - x87:#"870101"
          - tag: "87"
          - len: "01" #  // 1
          - val: "01"
        - x9F11:#"9F110101"
          - tag: "9F11"
          - len: "01" #  // 1
          - val: "01"
        - x9F12:#"9F1206555A4B415254"
          - tag: "9F12"
          - len: "06" #  // 6
          - val: "555A4B415254"
        - xBF0C:#"BF0C059F4D020B0A"
          - tag: "BF0C"
          - len: "05" #  // 5
          - val:#"9F4D020B0A"
            - x9F4D:#"9F4D020B0A"
              - tag: "9F4D"
              - len: "02" #  // 2
              - val: "0B0A"
    

    Or, in case you wish to apply EMV analysis:

    # Cheef's parser.
    # lib   : "/lib/EMV/" - EMV - Integrated Circuit Card Specifications for Payment Systems
    # node  : "TLVs"
    
    TLVs:#"6F358408454F504343415244A5295006555A4B4152545F2D06757A727565..0B0A" # EMV, Tag + Length + Value (TLV) series
    - x6F:#"6F358408454F504343415244A5295006555A4B4152545F2D06757A727565..0B0A" # ISO 7816, Template, File Control Parameters and File Management Data (FCI)
      - tag: "6F"
      - len: "35" #  // 53
      - val:#"8408454F504343415244A5295006555A4B4152545F2D06757A7275656E87..0B0A"
        - x84:#"8408454F504343415244" # EMV, Dedicated File (DF) Name
          - tag: "84"
          - len: "08" #  // 8
          - val:#"454F504343415244" # Dedicated File (DF) Name.
            - RID: "454F504343" # Registered Application Provider Identifier (RID)
            - PIX: "415244" # Proprietary Application Identifier Extension (PIX)
        - xA5:#"A5295006555A4B4152545F2D06757A7275656E8701019F1101019F120655..0B0A" # EMV, Template, FCI A5
          - tag: "A5"
          - len: "29" #  // 41
          - val:#"5006555A4B4152545F2D06757A7275656E8701019F1101019F1206555A4B..0B0A"
            - x50:#"5006555A4B415254" # ISO 7816, Application Label
              - tag: "50"
              - len: "06" #  // 6
              - val: "555A4B415254" # Application Label. // UZKART
            - x5F2D:#"5F2D06757A7275656E" # ISO 7816, Language Preference
              - tag: "5F2D"
              - len: "06" #  // 6
              - val:#"757A7275656E" # Language Preference. // uzruen
                - A21: "uz" # ISO 639, Language Code (a2) // Uzbek
                - A22: "ru" # ISO 639, Language Code (a2) // Russian
                - A23: "en" # ISO 639, Language Code (a2) // English
            - x87:#"870101" # EMV, Application Priority Indicator
              - tag: "87"
              - len: "01" #  // 1
              - val:#"01" # Application Priority Indicator.
                - S01: "0" #  // Application may be selected without confirmation of cardholder
                - S02: "1" #  // No priority assigned
            - x9F11:#"9F110101" # EMV, Issuer Code Table Index
              - tag: "9F11"
              - len: "01" #  // 1
              - val: "01" # Issuer Code Table Index. // ISO 8859, Part 1
            - x9F12:#"9F1206555A4B415254" # EMV, Application Preferred Name
              - tag: "9F12"
              - len: "06" #  // 6
              - val: "555A4B415254" # Name, Application Preferred. // UZKART
            - xBF0C:#"BF0C059F4D020B0A" # EMV, FCI Issuer Discretionary Data
              - tag: "BF0C"
              - len: "05" #  // 5
              - val:#"9F4D020B0A" # FCI Issuer Discretionary Data.
                - x9F4D:#"9F4D020B0A" # EMV, Log Entry
                  - tag: "9F4D"
                  - len: "02" #  // 2
                  - val:#"0B0A" # Log Entry.
                    - B01: "0B" # SFI containing the cyclic transaction log file (binary) // 11
                    - B02: "0A" # Maximum number of records in the transaction log file (binary) // 10
    
    0 讨论(0)
  • I can provide the following code to parse BER-TLV:

    int parseTlv(const unsigned char *buffer, int length, void* ctx, int (*tagCallback)(void* ctx, int tag, int length, const unsigned char* value)) {
        while(length>0) {
            // Get tag
            int tag=*(buffer++);
            int tagLength,tmp;
            length--;
            if((tag&0x1F)==0x1F) {
                if((length--)==0) return -1;
                tag=(tag<<8)|*(buffer++);
                if((tag&0x80)==0x80) {
                    if((length--)==0) return -1;
                    tag=(tag<<8)|*(buffer++);
                    if((tag&0x80)==0x80) {
                        if((length--)==0) return -1;
                        tag=(tag<<8)|*(buffer++);
                        if((tag&0x80)==0x80) {
                            // Longer tags are NOT supported
                            return -1;
                        }
                    }
                }
            } else {
                if(tag==0) {
                    continue;
                }
            }
    
            // Get length
            if((length--)==0) return -1;
            tmp=*(buffer++);
            tagLength=0;
    
            switch(tmp) {
                case 0x84:
                    if((length--)==0) return -1;
                    tagLength=*(buffer++);
                    /* no break */
                case 0x83:
                    if((length--)==0) return -1;
                    tagLength=(tagLength<<8)|*(buffer++);
                    /* no break */
                case 0x82:
                    if((length--)==0) return -1;
                    tagLength=(tagLength<<8)|*(buffer++);
                    /* no break */
                case 0x81:
                    if((length--)==0) return -1;
                    tagLength=(tagLength<<8)|*(buffer++);
                    break;
                default:
                    if(tmp>=0x80) {
                        // Other 8x variants are NOT supported
                        return -1;
                    }
                    tagLength=tmp;
                    break;
            }
    
            // Check value
            if(tagLength>length) return -1;
    
            // Process tag
            if(tagCallback(ctx, tag, tagLength, buffer)<0) {
                return -1;
            }
            buffer+=tagLength;
            length-=tagLength;
        }
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题