References


Card info




Serbian eVRC ATR

3B DB 96 00 80 B1 FE 45 1F 83 00 31 C0 64 1A 18 01 00 0F 90 00 52

Serbian Car registration ID card / Serbian Electronic Vehicle Registration card
http://ludovic.rousseau.free.fr/softwares/pcsc-tools/smartcard_list.txt


Serbian eVRC AID value

A0 00 00 00 77 01 08 00 07 00 00 FE 00 00 AD F2

Application must be selected explicitly.


Files

EF.Registration_A (D0 01)
EF.Registration_B (D0 01)  
EF.Registration_C (D0 21)  

Raw digital signature is in the file named after same pattern with first digit E, while X.509v3 certificates are starting with first digit C.

Custom file EF.Registration_D (D0 31) does not have digital signature and contains eVRC serial number.

Custom extensions:
C1: ograničenje promene vlasnika,
C2: JMBG vlasnika,
C3: JMBG korisnika,
C4: nosivost vozila,
C5: godina proizvodnje,
C9: serijski broj saobraćajne dozvole


APDU Commands




SELECT output

SELECT returns FCP when used with P1=02 and P2=04

       length       fd byte    name          shortEF  sec attr   lifecycle
62 16  80 02 (3k)   82 01 01   83 02 D0 01   88 00    A1 04 ..   8A 01 05  
62 16  80 02 (2k)   82 01 01   83 02 D0 11   88 00    A1 04 ..   8A 01 05  
62 16  80 02 (1k)   82 01 01   83 02 D0 21   88 00    A1 04 ..   8A 01 05  
62 16  80 02 (1k)   82 01 01   83 02 D0 31   88 00    A1 04 ..   8A 01 05  


READ BINARY output

Command:

                  /- offset object (54) with 2 bytes offset
                  |     /- offset 0x00E4=228 bytes  
>  00 B1 00 00 04 54 02 00 E4 00  
                              \- Le (all up to 256)  
                                 try with Le = 00 00 for up to 65536

Each reply begins with:

/- discretionary data object (53)
|  /- nested object 81  
|  |  /- length in bytes up to 0xE4=228 bytes (inc zero padding)  
53 81 xx

The first reply continues as:

/- nesting 4F (aid), len 18 bytes
|      /- aid, len 16 bytes  
78 12  4F 10 A0 00 00 00 77 01 08 00 07 00 00 FE 00 00 AD F2

And based on a selected file continues as:

                 /- nesting part 1 mandatory data, len 312 bytes
                 |   /- >0x7F, len in next 0x82-0x80=2b, 312 = 0x0138  
01=              71  82 01 38    80 03 123     9F33 10 REPUBLIKA...  
                                  \- version   \- issuing state  
                                                  0x9F (0b1001 1111) has bits  
                                                  1-5 all 1, so tag continues  
                                                  until a byte with a leading  
                                                  bit set to 0 which the next  
                                                  0x33 (0b0011 0011).  

                 /- nesting part 1 optional data, len 46 bytes  
                 |  /- if 0x7F or smaller, it is actual length  
11=              72 2E           80 03 123     98 09 MOTORCIKL...  
                                  \- version   \- vehicle cat.  

                 /- nesting part 1 optional data, len 29 bytes  
21=              72 1D           80 03 123     C2 0D 20029...  
                                  \- version   \- owner JMBG    

                 /- nesting part 1 optional data, len 21 bytes  
31=              72 15           80 03 123     C9 0E 672     
                                  \- version   \- eVRC serial number

The best hack may be to skip the first 3 bytes (53 81 xx) and continue reading tags nested under application specific tags 71, 72, 73 and 74 up to the final length where there are no more tags.

Note that there are nested tags, for example A1 len > A9 len > 83/84/85. TLV parser need to be smart enough to handle this. A basic naive implementation can go into every A* tag, and add use full tag path as a tag label. This will give tag A1:A9:83 which should be unique. The only exception is 4F inside 78, but we can start reading after the fixed size AID and continue until there are no more tag (skipping zero padding).