COTAG RFID analysis and proxmark COTAG demodulation implementation

published:

tags: [ #RFID, #COTAG ]

There was one RFID tech that had kept intriguing me over the years -- and that was COTAG. Especially since the company I work for uses it for garage door entrance. Researching history, some individuals from the proxmark community have already done some excellent work in terms of COTAG research. But surprisingly to me, things have never fully evolved, so strange. Proxmark iceman fork has had some kind of COTAG support for a long time, but very limited, and frankly, mostly not working, at least when I tried to use it.

So that kept occupying my mind, thus one day I finally started to deep-dive myself into it. I got hold of two COTAG readers, and a bunch of active and passive cards.

  • COTAG is unusual RFID technology in a sense, quick summary:
    • it does not operate on "standard" or common 125 kHz, but on 132 kHz
    • 132 kHz is input signal (carrier for the tag), the tag output is half of that: 66 kHz
    • COTAG card needs start pulse sequence to respond
    • There are active and passive cards.
    • It has very slow data rate: RF/768, Manchester
Data plot from lf cotag reader for an active COTAG card

The first problem to solve was the same as others have already stumbled upon: the minimum number of samples to read for at least 1 full COTAG card read is really high for COTAG: due to its very slow data rate of RF/768, it well-exceeds the normal proxmark device memory limit: 40000 samples.

  • But looking at proxmark code I realized that after a recent real-time sampling mode support -- this should no longer be a problem at all! So the first thing to start my experiments with was to quickly hack-patch the code to use realtime sampling mode for COTAG.

The next huge factor was: The original COTAG support code, after sending a COTAG start sequence at 132 kHz, switched divisor to 66 kHz with field on, not sure why? When I did sniffing (with an SDR) of a COTAG card with an actual original COTAG reader: after the card woke up, the reader switched from sending start sequence to outputting the carrier at the same frequency (i.e. 132 kHz), and the tag started outputting at exactly half of that. So I started getting some results when in the code I kept the field on at the same frequency (132 kHz).

The next huge factor to get better results was when I started to use custom bigger antennas, more tuned down towards (not necessarily exactly or close to) 66 kHz. With original proxmark antennas I could mostly read just active cards, and even with those the coupling was poor (even slight change in tag position would possibly yield very different results). With the original antenna I couldn't read passive cards at all.

  • I experimented with both rdv4 and proxmark-easy and their original antennas.
  • Surprisingly, pm3-easy antenna was better.
  • rdv4 original antenna was very poor with both passive and active cards.
  • rdv4 with a larger LF antenna (tuned to 134 kHz though) could get a strong signal trace for active cards only, but with lots of strange glitches and thus demodulation was not reliable. For passive cards that antenna was useless though.
rdv4 with larger LF antenna for COTAG pm3-easy with Aliexpress RFID antenna
  • Then I started winding my own, larger 12cm diameter antenna. And experimenting. So far the results make sense: The lower I got in resonant frequency, the better results I was having.

Bellow is my custom built antenna I used with proxmark for COTAG to get any decent results, especially with passive cards.

76 turns, 12 cm diameter:

Reading COTAG with larger custom antenna on pm3-easy
[=] -------- LF Antenna ----------
[+] 125,00 kHz ...........  3,52 V
[+] 134,83 kHz ...........  3,25 V
[+] 67,04 kHz ........... 33,77 V
[+] 67,42 kHz optimal.... 33,97 V
[+]
[+] Approx. Q factor measurement
[+] Frequency bandwidth... 8,9
[+] Peak voltage.......... 9,9
[+] LF antenna............ ok

With a better antenna the COTAG dumps were getting very clean and strong, also card position and orientation was much less of a factor with a better antenna (still was though). Example of a good COTAG passive card dump:

Data plot from lf cotag reader for a passive COTAG card

And as soon as I was getting some good COTAG samples I started analysing the dumps, first by demodulating "by hand", then starting building demodulation code.

The result is the following pull request with my reimplementation of proxmark COTAG support: https://github.com/RfidResearchGroup/proxmark3/pull/3373. Complete reimplementation of "lf cotag reader" and "lf cotag demod".

My analysis of my COTAG card dumps:

  • The repeating sequence is always 128 bits (or 128x768==98304 samples)
  • If we reverse those 128 data bits, it is clear that the last 24 bit are the card number. When I convert those 24-bits to hex/dec it always matches the number printed on the card (or read by an official COTAG reader).
  • The reversed data bits obviously start with some kind of a preamble: lots of leading zeros, then some pattern. With my COTAG cards collection I was able to identify 3 different types of COTAG preambles: 1 for active cards, 2 for passive cards:
  • There may be other types of COTAG preambles out there. My analysis is based on my collection of approx. 30 active COTAG cards (bought from ebay) and 20 passive COTAG cards (10 IB-958 passive COTAG cards, 10 IB-0968/bewator passive cards)
  • For other bits, I have not yet been able to identify their meaning. At some point I thought I had identified the parity bit, but later on that theory collapsed for me with some additional data dumps from other cards.

Some of the COTAG tag dumps on which I have identified what preambles could be:

active COTAG cards:

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0000 0101 1110 0011 0001 1000   (active 385816)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000 0010 0111 1011 0000 0100 1000 1110 0000 0000 0000 0000 0000 0110 0001 0100   (active 1556)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000 0010 0111 1011 0000 0100 1000 1110 0000 0000 0000 0000 0000 0110 0001 0101   (active 1557)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000 0010 0111 1011 0000 0100 1000 1110 0000 0000 0000 0000 0000 0110 0001 0110   (active 1558)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000 0010 0111 1011 0000 0100 1000 1110 0000 0000 0000 0000 0000 0110 0001 0111   (active 1559)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000 0010 0111 1011 0000 0100 1000 1110 0000 0000 0000 0000 0000 0110 0001 1001   (active 1561)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000 0001 1010 0100 0000 0011 1110 1000 0000 0000 <  redacted                 >   (active)

assuming thus COTAG preamble for active cards:

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 1000

passive COTAG cards:

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0100 1100 1010 1011 1100 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 0101   (passive bewator IB-0968 01576805)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0110 1100 1010 1011 0000 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 1001   (passive bewator IB-0968 01576809)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0100 1100 1010 1011 0101 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 1100   (passive bewator IB-0968 01576812)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0101 1100 1011 1011 0100 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 1101   (passive bewator IB-0968 01576813)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0110 1100 1010 1011 1111 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 0110   (passive bewator IB-0968 01576806)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 1100 1011 1011 0111 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 1110   (passive bewator IB-0968 01576814)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0111 1100 1011 1011 1110 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 0111   (passive bewator IB-0968 01576807)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0111 1100 1011 1011 0001 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 1000   (passive bewator IB-0968 01576808)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0101 1100 1011 1011 0010 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 1011   (passive bewator IB-0968 01576811)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0100 1100 1010 1011 0011 0000 0000 0000 0000 1000 0000 0001 1000 0000 1111 0110 1010   (passive bewator IB-0968 01576810)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0110 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1000 1000   (passive IB-958 02402440)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0111 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1001 0001   (passive IB-958 02402449)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0111 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1000 1001   (passive IB-958 02402441)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0111 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1000 1010   (passive IB-958 02402442)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0100 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1000 1011   (passive IB-958 02402443)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0111 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1000 1100   (passive IB-958 02402444)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0100 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1000 1101   (passive IB-958 02402445)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0100 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1000 1110   (passive IB-958 02402446)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0101 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1000 1111   (passive IB-958 02402447)
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 0110 1000 0010 0100 1110 0000 0000 0000 0000 1000 0000 0010 0100 1010 1000 1001 0000   (passive IB-958 02402448)

Assuming thus 2 types of preamble for passive cards:

0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001 0000 01
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 01

There may be other types of COTAG preamble out there.