When reading BERTLV, when do you stop?

2.5k Views Asked by At

I have the following BERTLV: 61394F0BA00000030800001001234579074F05A000012345500E49442D4F6E65205049562042494F5F50107777772E6F626572746875722E636F6D7F66080202800002028000

I'm trying to parse this in a recursive way, so I am treating the first part as a TLV.

Tag: 0x61, Len: 0x39, Value: 4F0BA00000030800001001234579074F05A000012345500E49442D4F6E65205049562042494F5F50107777772E6F626572746875722E636F6D

Then I break it down further, and get

Tag: 0x4F, Len: 0x0B, Value: A000000308000010012345

Now, how do I stop? At this point, I know this value is the last leg of this TLV and is not another nested TLV.

2

There are 2 best solutions below

3
On BEST ANSWER

Ok after much digging, I found out what the simple TAG is actually more than just a number, the TAG itself actually encoded a brunch of information in there. I order to find out whether the TLV contains nested TLV so that my code would know when to continue processing and when to stop, I had to decode the TAG.

So the TAG contains 8 bits, and each one of them have special meaning:

TLV TAG and their bits meaning

The bit that I needed was B5 in order to determine whether the current TLV is Constructed or not... when is Constructed it means that current TLV consists of multiple TLV, so for my code, I am using this information to recursively dig in the nested TLV.

When the TLV is not Constructed that is my stopping case to bubble back up.

Here is my recursive function output by parsing the data and checking the bit B5 in TAG:

11:20:38.428 Parsing: 61394F0BA00000030800001000010079074F05A000000308500E49442D4F6E65205049562042494F5F50107777772E6F626572746875722E636F6D7F66080202800002028000
11:20:38.436 Constructed Data Object
11:20:38.437 Parsing: 4F0BA00000030800001000010079074F05A000000308500E49442D4F6E65205049562042494F5F50107777772E6F626572746875722E636F6D
11:20:38.437 Primitive Data Object
11:20:38.437 tag: 79, len: 11, value: A000000308000010000100
11:20:38.437 Constructed Data Object
11:20:38.437 Parsing: 4F05A000000308
11:20:38.437 Primitive Data Object
11:20:38.437 tag: 79, len: 5, value: A000000308
11:20:38.437 Primitive Data Object
11:20:38.437 tag: 80, len: 14, value: 49442D4F6E65205049562042494F
11:20:38.437 MultiByte tag
11:20:38.437 Primitive Data Object
11:20:38.437 tag: 24400, len: 16, value: 7777772E6F626572746875722E636F6D
11:20:38.438 MultiByte tag
11:20:38.438 Constructed Data Object
11:20:38.438 Parsing: 0202800002028000
11:20:38.438 Primitive Data Object
11:20:38.438 tag: 2, len: 2, value: 8000
11:20:38.438 Primitive Data Object
11:20:38.438 tag: 2, len: 2, value: 8000
5
On

Q: Now, how do I stop?

A: The TAG Length (0x0B) represented in HEX and show the amount of Bytes in the Value. Every Byte represented in your example as 2 (two) Hex characters. So the 0x0B which is 11 in decimal show you 11*2 = 22 characters in Value to use.

Here is parsing example of your BER-TLV buffer parsed by https://iso8583.info/lib/EMV/TLVs tool:

---
# Cheef's parser.
# Copyright (C) 2008-2017 Alexander Shevelev. https://iso8583.info/
# lib   : "/lib/EMV/" - Integrated Circuit Card Specifications for Payment Systems
# tool  : "TLVs"
# stat  : 40 nodes, 4 lookup tables, 25.00% passed (1/4)

TLVs:#"61394F0BA00000030800001001234579074F05A000012345500E49442D4F..8000" # EMV, Tag + Length + Value (TLV) series
- x61:#"61394F0BA00000030800001001234579074F05A000012345500E49442D4F..6F6D" # ISO 7816, Template, Application
  - tag: "61"
  - len: "39" #  // 57
  - val:#"4F0BA00000030800001001234579074F05A000012345500E49442D4F6E65..6F6D" # Template, Application.
    - x4F:#"4F0BA000000308000010012345" # ISO 7816, Application Identifier (AID), Card
      - tag: "4F"
      - len: "0B" #  // 11
      - val:#"A000000308000010012345" # AID, Card.
        - RID: "A000000308" # Registered Application Provider Identifier (RID) // National Institute of Standards and Technology
        - PIX: "000010012345" # Proprietary Application Identifier Extension (PIX)
    - x79:#"79074F05A000012345" # ISO 7816, Coexistent Tag Allocation Authority
      - tag: "79"
      - len: "07" #  // 7
      - val:#"4F05A000012345"
        - x4F:#"4F05A000012345" # ISO 7816, Application Identifier (AID), Card
          - tag: "4F"
          - len: "05" #  // 5
          - val:#"A000012345" # AID, Card.
            - RID: "A000012345" # Registered Application Provider Identifier (RID)
    - x50:#"500E49442D4F6E65205049562042494F" # ISO 7816, Application Label
      - tag: "50"
      - len: "0E" #  // 14
      - val: "49442D4F6E65205049562042494F" # Application Label. // ID-One PIV BIO
    - x5F50:#"5F50107777772E6F626572746875722E636F6D" # ISO 7816, Uniform resource locator (URL)
      - tag: "5F50"
      - len: "10" #  // 16
      - val: "7777772E6F626572746875722E636F6D" # URL. // www.oberthur.com
- x7F66:#"7F66080202800002028000"
  - tag: "7F66"
  - len: "08" #  // 8
  - val:#"0202800002028000"
    - x02:#"02028000"
      - tag: "02"
      - len: "02" #  // 2
      - val: "8000"
    - x02:#"02028000"
      - tag: "02"
      - len: "02" #  // 2
      - val: "8000"