OSDP Secure Channel

OSDP uses AES, with key size of 128 bits (16 bytes). The Secure Channel (SC) session is initiated by the CP and either the CP or PD can invalidate an established session (PD by sending a NAK, and CP by starting a new SC handshake). This document tries to explain the secure channel workflow to enable application developers to better understand the failure logs emitted by LibOSDP and it’s reasons.

LibOSDP has a working implementation of the secure channel. Any CP/PD that uses this library will advertises this as an implicit capability. If for some reason (or for debugging) you don’t want to have secure communication, you can call osdp_pd_set_capabilities() after osdp_setup() to set the compliance level of OSDP_PD_CAP_COMMUNICATION_SECURITY to 0.

Secure Channel Session

A SC session is initiated with a handshake that involves 2 command-reply transactions between the CP and PD. A session once established can be kept active endlessly until either party decides to discard it or until a timeout (400ms) occurs.

The CP starts by sending CMD_CHLNG for which the PD replies with REPLY_CCRYPT. With this response the CP is able to authenticate the PD and also compute it’s session keys. Next, CP sends CMD_SCRYPT, which the PD will use to authenticate the CP and compute it’s session keys. If everything has gone as expected up to this pont, both CP and PD would have a working set of session keys (s-enc, s-mac1, and s-mac2). The final message of the handshake is the the REPLY_RMAC_I response from the PD. This reply has the initial reply MAC that the CP will use as the IV for encrypting it’s next command (MAC chaining).

The above process works in this flow if both the CP and PD have the same SCBK. If there is a mismatch, the CP will fail to verity PD’s authenticity when it receives REPLY_CCRYPT. At this point, LibOSDP will try to initiate a new SC handshake with SCBK-default instead to see if that works (it will if the PD was set to install-mode). If that too fails, the CP gives up and goes online without a secure session and retries once every 10 minutes.

Note: This is the default behavior, if you requested ENFORCE_SECURE, things change slightly (more on that later).

SCBK (Secure Channel Base Key)

This is the primary key that is used to derive the secure channel session keys. When the application wants to setup a CP or PD, it has to pass the SCBK in osdp_pd_info_t::scbk.

If osdp_pd_info_t::scbk is set to NULL,
  • In PD mode, the PD is forced into install mode.

  • In CP mode, LibOSDP will look for a master key. If that too doesn’t exits then the PD is setup with secure channel disabled.

Master Key (MK)

This a CP specific key that is used to derive the individual PD SCBKs. This can be passed to osdp_cp_setup(). The MK is common for all PD connected to this CP; on the other hand, the SCBK has to be unique to each PD.

Latest versions of the OSDP specification discourage the use of master key and recommend that the CP maintain the SCBKs directly. LibOSDP will print warning message if master key is used in any of the PDs.

Install Mode

The install-mode is provisioning-time, insecure mode that instructs the PD to uses SCBK-Default (hardcoded key specified by OSDP) and allows the CP to set a new SCBK. Once the PD receives a new SCBK, it automatically exits the install-mode so another SCBK key set is not possible.

This mode can be enabled by passing OSDP_FLAG_INSTALL_MODE in osdp_pd_info_t::flags. This flag should not be passed during normal operation of the PD.

Entering Install Mode

If you are building a PD as a product (in production), you’d have to come up with some method to force the PD to enter install-mode during provisioning time to allow the CP to set a new SCBK.

A very trivial method to do this is to have a pin-hole accessible tactile switch that can be pressed down while the PD reboots (like the WiFi router reset button). In your application, at boot, if you see this tactile switch pressed you should pass the OSDP_FLAG_INSTALL_MODE flag.

Of course, this is not a very secure way of doing this because an attacker who has physical access to the PD can do the same (see note on Enforce Secure). There are some other methods that makes it a little difficult for the attacker; for instance, HID has some special configuration cards that you can present to the RFID reader soon after boot to force the device into install-mode.


Enforce Secure is a flag that LibOSDP has introduced due to the insecure nature of the install-mode. A PD/CP can be instructed to operate with the some security consciousness, thereby not allowing some OSDP specified features such as the install-mode.

The following constraints are enforced when Enforce secure is enabled:
  • Secure Channel cannot be disabled

  • The CP/PD will not operate without a secure channel if setting one up failed.

  • Use of SCBK-Default is not allowed (ie., install-mode)

  • Disallow master key based SCBK derivation

When you see a “… due to ENFORCE_SECURE” failure log message, the CP/PD is doing something that LibOSDP deemed to be a protected action that needs to be performed under supervision.

Persistence of Keys

LibOSDP is not responsible for retaining the SCBK during power cycle of the CP or PD. It expects the application do this and give it the right SCBK/MK during osdp_cp/pd_setup().

In case of CP mode, it is the owner of the SCBK/MK (meaning the key originates here) so the CP app is already aware of the key. In PD mode, when the PD gets a new SCBK from the CP, the PD app gets a copy of this in the OSDP_CMD_KEYSET call back.