Closed vk2tds closed 7 months ago
Is the Inception behaviour of re-sending packets with the same encryption normal?
Regardless of whether there is a secure channel active, we definitely don't want the same messages that are being resent from either side to be registered as a valid packet. This becomes a security issue (reply-attack) when we have secure channel active (think: last card-read event resent by an attacker).
That's why these kind of protocols have sequence numbers in the first place; but SIA seems to have made some questionable decision regarding sequence numbers and how they can be repeated. Even so repeated sequence numbers have to be sent with the proper MAC chaining otherwise they would be rejected.
If the a message was totally lost (hence the MAC needed keep the SC going), the right thing for the CP/PD to do at this point is to discard the current SC session and start another one. Based on both the logs, this is what happens due to the NAK response from libosdp PD. Please reach out to the CP manufacturer to fix this issue: they cannot just resend a secure channel message when they think the PD did not respond to it.
Is the library when acting as a PD assuming that packet retries have new encryption because it is a new incoming packet?
Yes.
Thanks for this. I did reach out to the manufacturer and essentially their response was that they were implementing the specification.
I have looked into this more, and I think I have found a solution that I don't think is too much of a target for a reply-attack. It is not perfect, but works with what I have found in the field. It appears that at least one manufacturer has decided that a packet retry should use the same MAC. By my understanding, the MAC for a received packet is based on the last transmitted packet. A retry cannot be certain which transmission was lost so should use the last known good MAC. Well, that is my understanding. The old MAC is invalidated as soon as a new valid packet comes through, meaning that in normal circumstances, the MAC is invalidated in under a second.
So, what I have done to get this working firstly is to expand the osdp_secure_chanel structure with storage space for r_mac_backup[16].
struct osdp_secure_channel {
uint8_t scbk[16];
uint8_t s_enc[16];
uint8_t s_mac1[16];
uint8_t s_mac2[16];
uint8_t r_mac[16];
uint8_t r_mac_backup[16]; //vk2tds
uint8_t c_mac[16];
uint8_t cp_random[8];
uint8_t pd_random[8];
uint8_t pd_client_uid[8];
uint8_t cp_cryptogram[16];
uint8_t pd_cryptogram[16];
};
Next was to populate this. The place to do that was the aforementioned osdp_computer_mac()
function. Just before pd->sc.r_mac
is overwritten with a new value, we save a copy in case we need it. This might not be the most elegant, but it works.
/* N-1 blocks -- encrypted with SMAC-1 */
osdp_encrypt(pd->sc.s_mac1, iv, buf, pad_len - 16);
/* N-1 th block is the IV for N th block */
memcpy(iv, buf + pad_len - 32, 16);
}
/* N-th Block encrypted with SMAC-2 == MAC */
osdp_encrypt(pd->sc.s_mac2, iv, buf + pad_len - 16, 16);
if (!is_cmd){ //vk2tds
// r_mac is about to be updated. Save a copy
memcpy (pd->sc.r_mac_backup, pd->sc.r_mac, 16);
}
memcpy(is_cmd ? pd->sc.c_mac : pd->sc.r_mac, buf + pad_len - 16, 16);
Finally, we need to make a change to phy_check_packet()
in the file osdp_phy.c
. The change here is really simple. Whenever we have a sequence repeat packet, we overwrite the pd->sc.r_mac
with pd->sc.r_mac_backup
. We should probably be comparing the entire packet and making sure that it was identical to the previously sent one, but this works, at least for proof of concept.
LOG_INF("received a sequence repeat packet!");
memcpy (pd->sc.r_mac, pd->sc.r_mac_backup, 16); //vk2tds
And it works! Now, before overwriting the R_MAC, I should probably compare the total packet and not just the sequence number. That can be done later.
Thank you for the writeup. OSDP specification talks about sequence repeat and secure channel in two different places without any relation to one and other. Also, do you know why you are hitting this issue of CP/PD not receiving your messages? Is the channel so unstable?
The path between the Off The Shelf CP and the STM32 running LibOSDP as a PD is only about 2M. I am normally only seeing a lost packet about once or twice a day with two PD's on the RS-485 bus. Not exactly unstable, but it is annoying when the CP sends a Beep when the SC channel comes back online.
The second OSPD device is a commercial Wiegand to OSDP device, although running 'custom' protocol modifications...
Given that I am definitely sending the response to the first message, and this is getting lost, the options are:
The frequency of retransmissions does not seem to change if I add key-up time before and after the serial transmission to make sure that the RS485 transceiver switches from receive to transmit properly and vice versa. Sending is one of the easiest things to do. So I suspect that is not it. I have just unplugged the other OSDP device and will see if that affects things. This test will likely take days. Even so, I don't expect packet collisions to be the issue. That only leaves the firmware on the CP. I have my suspicions.
However, I suspect the CP
I have finally come back to working on an Arduino implementation of libosdp for a PD, and getting it to work with the InnerRange Inception. My issues with it turned out to be that the Inception didn't actually support OSDP despite being advertised as such. They have now resolved, although there are certain unusual 'features' like ignoring the capabilities data structure and encrypting regardless.
I mention this as the Inception may not be implementing OSDP in full accordance with the published specification, or may be implementing some strange behaviour.
Occasionally, at least once a day, I am getting an error saying that the PD has received a sequence repeat packet, and immediately after a message noting an invalid MAC and discarding the SC. As you can see from the comms logs below, the CP sends a packet, which the PD replies to and then the CP sends the exact same packet again.
When the identical packet is identified, the library identifies this, but then discards by noting an invalid MAC.
I have downloaded some logs from the Inception and they appear right at the bottom. I don't have much information on what the Inception logs are saying because they are designed for manufacturer use and are not normally available.
My thinking is:
I am guessing that repeat packets doesn't get tested much. My questions would be:
Any thoughts on this would be appreciated. Thanks.