APDU FF 88 00 gives incorrect length - rfid

I have some PC/SC code that has encoded thousands of MIFARE cards. I now have a HID OMNIKEY 5127 CK reader and I cannot get it to authenticate. For a standard 1K MIFARE card I load the transport key with:
FF 82 20 00 06 FF FF FF FF FF FF
which succeeds and then to authenticate against the first block:
FF 88 00 00 60 00
and it gives 67 00. Has anyone else seen this?

The AUTHENTICATE command (CLA=FF, INS=88) has been declared obsolete in the PC/SC specification, so it might not be supported by that reader. You could instead try the GENERAL AUTHENTICATE command:
+-----+-----+----+----+----+---------+---------+----------+------+
| CLA | INS | P1 | P2 | Lc | Version | Address | Key type | Key# |
+-----+-----+----+----+----+---------+---------+----------+------+
| FF | 86 | 00 | 00 | 05 | 01 | 00 00 | 60 | 00 |
+-----+-----+----+----+----+---------+---------+----------+------+
The relevant part of the PC/SC specification is "Part3. Requirements for PC-Connected Interface Devices" (get it here).

Related

Why RDATA in EDNS(0) resource record has 1 octet?

I want to understand why EDNS(0) resource records contains an extra octet? I read RFC 6891 and RFC 1035. It says nothing about case when RDLENGHT == 0 but RDATA == "\0".
To test this here python code
import binascii
import socket
def send_udp_message(message, address, port):
"""send_udp_message sends a message to UDP server
message should be a hexadecimal encoded string
"""
message = message.replace(" ", "").replace("\n", "")
server_address = (address, port)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
sock.sendto(binascii.unhexlify(message), server_address)
data, _ = sock.recvfrom(4096)
finally:
sock.close()
return binascii.hexlify(data).decode("utf-8")
def format_hex(hex):
"""format_hex returns a pretty version of a hex string"""
octets = [hex[i:i+2] for i in range(0, len(hex), 2)]
pairs = [" ".join(octets[i:i+2]) for i in range(0, len(octets), 2)]
return "\n".join(pairs)
message = "AA AA 01 00 00 01 00 00 00 00 00 01 " \
"07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 "
# EDNS(0) resource record
message += "00 00 " # NAME
message += "29 00 " # TYPE
message += "FF 00 00 80 " # TTL
message += "00 00 " # RDLENGTH
# message += "00" # RDATA
response = send_udp_message(message, "8.8.8.8", 53)
print(format_hex(response))
Dns query returns here error. But if uncomment RDATA line it returns success.
You misread section §6.1.2 of RFC 6891, so the RFCs are not "lies".
It says:
+------------+--------------+------------------------------+
| Field Name | Field Type | Description |
+------------+--------------+------------------------------+
| NAME | domain name | MUST be 0 (root domain) |
| TYPE | u_int16_t | OPT (41) |
| CLASS | u_int16_t | requestor's UDP payload size |
| TTL | u_int32_t | extended RCODE and flags |
| RDLEN | u_int16_t | length of all RDATA |
| RDATA | octet stream | {attribute,value} pairs |
+------------+--------------+------------------------------+
so 6 pieces of information while your code has only 5 pieces:
# EDNS(0) resource record
message += "00 00 " # NAME
message += "29 00 " # TYPE
message += "FF 00 00 80 " # TTL
message += "00 00 " # RDLENGTH
# message += "00" # RDATA
You are missing the CLASS between TYPE and TTL, hence things are not interpreted the way you think they are.
You are also misreading how the bytes work for the name.
It is not:
00 00 NAME
29 00 TYPE
FF 00 00 80 TTL
00 00 RDLENGTH
but really:
00 NAME (root domain per EDNS(0) specification, which is a sole zero)
00 29 TYPE (41, per specification)
00 FF CLASS (255, considered as payload)
00 00 80 00 TTL, read as 00 = EXTENDED-CODE, 00 = VERSION (mandatory), 80 = DO set plus everything else 0 as the final 00 byte, per specification
00 RDLENGTH
and the final item RDLENGTH is then not properly formatted per the RFC 1035 specification as it is 2 bytes (16 bits).
Once you comment your last line, RDLENGTH becomes 00 00 and then is valid.
And there is indeed no RDATA part in your message.
What you believe being a 00 value in RDATA is in fact the last byte of RDLENGTH but you did not parse the stream correctly.
Had you used dnspython as advised to you, you would have seen the problem immediately with the proper mapping of fields:
In [1]: import dns
In [2]: import dns.message
In [10]: stream = 'AA AA 01 00 00 01 00 00 00 00 00 01 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 00 00 29 00 FF 00 00 80 00 00 00'
In [11]: data=''.join(chr(int(x, base=16)) for x in stream.split(' '))
In [12]: m = dns.message.from_wire(data)
In [13]: print m
id 43690
opcode QUERY
rcode NOERROR
flags RD
edns 0
eflags DO
payload 255
;QUESTION
example.com. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
Had you wanted to do that you could have simulated the expected bytes stream that way:
(starting from your message)
In [31]: m = dns.message.from_wire(data)
In [32]: print m
id 43690
opcode QUERY
rcode NOERROR
flags RD
edns 0
eflags DO
payload 255
;QUESTION
example.com. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
(creating a new one to look like yours)
In [39]: mm = dns.message.make_query('example.com.', 'A', use_edns=0, payload=255, want_dnssec=True)
In [40]: mm.id=43690
In [41]: print mm
id 43690
opcode QUERY
rcode NOERROR
flags RD
edns 0
eflags DO
payload 255
;QUESTION
example.com. IN A
;ANSWER
;AUTHORITY
;ADDITIONAL
(now looking at its wire representation)
In [46]: print ' '.join(hex(ord(d)) for d in mm.to_wire())
0xaa 0xaa 0x1 0x0 0x0 0x1 0x0 0x0 0x0 0x0 0x0 0x1 0x7 0x65 0x78 0x61 0x6d 0x70 0x6c 0x65 0x3 0x63 0x6f 0x6d 0x0 0x0 0x1 0x0 0x1 0x0 0x0 0x29 0x0 0xff 0x0 0x0 0x80 0x0 0x0 0x0
Comparing with your bytestream:
dnspython: AA AA 01 00 00 01 00 00 00 00 00 01 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 00 00 29 00 FF 00 00 80 00 00 00
you: AA AA 01 00 00 01 00 00 00 00 00 01 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 01 00 01 00 00 29 00 FF 00 00 80 00 00
Note the missing final 00 being in your commented line.
This shows that existing good libraries, as dnspython is, really help sometimes better understanding RFCs or other specifications. And in the world of DNS there are many RFCs, sometimes conflicting between each other, with ambiguous parts, etc. So using existing libraries for tests and/or studying their source code really helps, if you want this advice.

Linux BlueZ custom Manufacturing Scan Response Data

I have a custom GATT Server working as a plugin using BlueZ 4.101 on Linux. I am now trying to set custom Scan Response advertising data. I am using LightBlue on iOS to debug my GATT Server and advertising parameters. I tried the following code, and LightBlue can see the Advertising Payload and Device Name, but not the Scan Response data. How do I set custom Scan Response data with BlueZ?
# BLE Name
echo "<GATT SERVER> Setting BLE Advertising Name..."
btmgmt -i $BLUETOOTH_DEVICE name "My-Test-Device"
echo "<GATT SERVER> Starting BLE Advertising..."
hciconfig $BLUETOOTH_DEVICE leadv
# Adv Packet
echo "<GATT SERVER> Setting BLE Advertising Packets..."
hcitool -i hci0 cmd 0x08 0x0008 15 02 01 06 11 06 fa d8 43 31 14 09 0c ba e1 14 82 25 11 48 96 16
# | | | | | | -----------------------------------------------
# | | | | | | |
# | | | | | | +---- device state service UUID
# | | | | | |
# | | | | | +- Incomplete List of 128-bit Service Class UUIDs
# | | | | |
# | | | | +- Num bytes in -----------------------------------+
# | | | |
# | | | +- LE General Discoverable Mode, BR/EDR
# | | |
# | | +- Flags AD type
# | |
# | +nBytes+
# |
# +- Num bytes in -----------------------------------------------+
# Scan Response
echo "<GATT SERVER> Setting BLE Scan Response..."
hcitool -i hci0 cmd 0x08 0x0009 02 01 06 1A FF 02 5E 03 02 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Your command to set discovery response does not make any sense. Here is an exemple :
hcitool -i hci0 cmd 0x08 0x0009 14 13 09 74 68 65 20 70 69
hcitool -i hci0 cmd 0x08 0x0009 : set discovery response
14 : total payload length
13 : info payload length
09 : info type == name
74 68 65 20 70 69 : info payload => the name in ascii. here "the pi"
Please note that this won't work if you device is not connectable.

A little Game/Quiz: Do you see my values? (Interpreting Hex-Values)

Okay I need some Help... I got a bluetooth-le-weight-scale. I can connect my Raspberry Pi to this scale and get some data. But its not easy for me to read my values in this hex-salad.
After every measurement I get two lines of Information, which should contain my values
(I simulated all measurements ... Person 5 is just me pushing my hands on the scale .. Person 2 + 3 is me wearing socks on the scale, so no need to give me some medical advices if you find some unrealistic values :D )
Scale: starts with 5.0kg(officaly, but i can see a 4.9 as starting point), Max 180kg (this could be just a safety note. its a glass-scale), d = 100g
what I noted from the Display:
# | Person | m kg| Fat % | TbW % | Mus % | Bone kg | kcal | BMI
1 | 5 |13,3 | 5 | 72,7 | 60,1 | 0,8 | 1056 | 13,3
2 | 3 |73,6 | 26,3 | 51,1 | 34,2 | 3,5 | 2428 | 24,3
3 | 2 |76,8 | 18,5 | 61,1 | 41,9 | 3,4 | 2741 | 24,8
4 | 5 |15,0 | 5 | 70,3 | 58,4 | 0,9 | 1092 | 15,0
5 | 6 | 5,1 | 5 | 73 | 66,5 | 0,5 | 881 | 5,1
What I received via Bluetooth:
# | handle | Byte 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
-----------------------------------------------------------------------------
1 | 0x001b | value: 1d 32 05 00 fe 0f 13 11 11 01 12 00 ff 05 09 00 00 00 00
1 | 0x001e | value: 6f 0f 13 11 11 05 20 04 32 f0 d7 f2 59 f2 08 f0 00 00 00
-----------------------------------------------------------------------------
2 | 0x001b | value: 1d c0 1c 00 fe 45 06 00 00 7a 13 00 ff 03 09 00 00 00 00
2 | 0x001e | value: 6f 45 06 00 00 03 7c 09 07 f1 ff f1 56 f1 23 f0 00 00 00
-----------------------------------------------------------------------------
3 | 0x001b | value: 1d 00 1e 00 fe 37 01 00 00 d7 12 00 ff 02 09 00 00 00 00
3 | 0x001e | value: 6f 37 01 00 00 02 b5 0a b9 f0 63 f2 a3 f1 22 f0 00 00 00
-----------------------------------------------------------------------------
4 | 0x001b | value: 1d dc 05 00 fe 80 14 11 11 83 18 00 ff 05 09 00 00 00 00
4 | 0x001e | value: 6f 80 14 11 11 05 44 04 32 f0 bf f2 48 f2 09 f0 00 00 00
-----------------------------------------------------------------------------
5 | 0x001b | value: 1d fe 01 00 fe 5c 15 11 11 ac 16 00 ff 06 09 00 00 00 00
5 | 0x001e | value: 6f 5c 15 11 11 06 71 03 32 f0 da f2 99 f2 05 f0 00 00 00
Note:
Each time before receiving the values, I have to send my scale a Unix-timestamp.. most of the times, I had just send 1111111111 or 0000000000 or something like that.. but I did not note what I send.. sorry..
there is always another incoming line where I spotted the user values, that are stored in the scale. So I think these are unimportant but maybe I'm wrong
P2, male, Height: 176cm, Age: 34
P3, female, Height: 174cm, Age: 23
P5, male, Height: 100cm, Age: 10
so maybe someone could tell me, like where I can find the Information that represents my weight. I just have spotted the person numbers
thanks for helping & greetings from germany
ok ok.. I solved it...
0x1b:
weight: byte: 1 & 2
timestamp: byte 5-8
person: byte 13
0x1e:
timestamp: byte 1-4
person: 5
kcal: 6 & 7
fat: 8 & 9
tbw: 10 & 11
muscle: 12 & 13
bone: 14 & 15
To add some more details:
values decode as unsigned integers, little endian. For some obscure reason the 2 byte (short) integers have a most significant nibble as 0xf.
Transmission starts off with indication 0x25 which contains the programmed properties of the person detected (i.e. weight is within +/- 2 kg of last measurement).
0x25:
person: byte 2
gender: byte 4 (1=male, 2=female)
age: byte 5
size: byte 6
activity: byte 8 (0=normal, 3=high)

Cannot ungzip : Minimum header length is 10 bytes

I have a problem with my website, which is completely gzipped:
http://goout.cz/cs/fotoreporty/
The page can be easily shown in Chrome, but in Safari it never loads (and I suppose in other browsers as well. When I try:
curl -v http://goout.cz/cs/fotoreporty/ | gzip -d
I am getting expected results. But validation on
http://validator.w3.org/check?uri=http%3A%2F%2Fgoout.cz%2Fcs%2Ffotoreporty%2F#fatal-errors
yields:
The error was: Can't gunzip content: Header Error: Minimum header size is 10 bytes
What is wrong with the gzip format? How can I solve it? Thanks.
EDIT:
The gzip header seems to me okay to me:
$ curl http://goout.cz/cs/ | head -1 | hexdump | head -1
0000000 1f 8b 08 00 00 00 00 00 00 00 ed 5d cd 73 db 38
$ curl http://goout.cz/cs/fotoreporty/ | head -1 | hexdump | head -1
0000000 1f 8b 08 00 00 00 00 00 00 00 ed 7d cf 73 e3 46

Buffer inspection tool for Node.js

Do you know of any good Buffer inspection library for Node.js?
It would be pretty useful to print out a Buffer along with its utf8 content.
Example:
Byte | HEX | UTF-8 | Name
-----+-----+-------+-----------
0 | 48 | H | UPPER H
1 | 65 | e | LOWER E
2 | 6c | l | LOWER L
3 | 6c | l | LOWER L
4 | 6f | o | LOWER O
5 | 20 | | WHITESPACE
6 | 57 | W | UPPER W
7 | 6f | o | LOWER O
8 | 72 | r | LOWER R
9 | 6c | l | LOWER L
10 | 64 | d | LOWER D
Yesterday I made a simple module called hex. It's like the hxd program. No config necessary, easy to use, for debugging purposes.
var hex = require("hex");
hex(buffer);
Output:
Offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
000000 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000010 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000020 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000030 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ
000040 54 41 47 42 72 65 61 6B 69 6E 67 20 54 68 65 20 TAGBreaking The
000050 4C 61 77 00 00 00 00 00 00 00 00 00 00 00 00 00 Law.............
000060 00 4A 75 64 61 73 20 50 72 69 65 73 74 00 00 00 .Judas Priest...
000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 ...............B
000080 72 69 74 69 73 68 20 53 74 65 65 6C 00 00 00 00 ritish Steel....
000090 00 00 00 00 00 00 00 00 00 00 00 00 00 31 39 38 .............198
0000A0 30 47 72 65 61 74 20 73 6F 6E 67 21 00 00 00 00 0Great song!....
0000B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 33 89 ..............3.

Resources