Closed matt-treiber-compass-es closed 3 years ago
@matt-treiber-compass-es, when OSDP_FLAG_ENFORCE_SECURE
is requested, use of SCBK-D is not permitted (see include/osdp.h for other such restrictions). In fact, the log line that you pasted says exactly that: CHLNG failed. Set PD offline due to ENFORCE_SECURE
.
When you see a "due to ENFORCE_SECURE" failure, the CP/PD is doing something that we deem to be a protected action that needs to be under supervision. So, in this case, you should start the communication channel without OSDP_FLAG_ENFORCE_SECURE
to set the SCBK and once this is done, start passing OSDP_FLAG_ENFORCE_SECURE
in future (non-supervised) runs.
Another point to note: PD_FLAG_SC_USE_SCBKD
is an internal flag and using it may be as harmless as not doing anything or causing security issues (OSDP isn't super secure anyways; you wouldn't want to cut down any more limbs :D). So the general rule of thumb is: if it ain't on include/osdp.h
don't use it.
Let me know if that helps and feel free to reopen this issue if this did not fix your problem.
Hello, I am also trying to establish a secure communication with a HID reader. The reader is set up with a default key. What I want is to establish a secure channel using this default key. I tried to set up a secure channel more or less the same way @matt-treiber-compass-es tried. However after your explaining it is still not clear how to do it. For example we are doing:
osdp_pd_info_t pd_info[] = {
{
.baud_rate = 115200,
.address = 0,
.flags = OSDP_FLAG_ENFORCE_SECURE
...
cp.setup(1, pd_info, "Default Key I want to use in hex");
And I got the same errors described in this thread.
_So, in this case, you should start the communication channel without OSDP_FLAG_ENFORCE_SECURE to set the SCBK and once this is done, start passing OSDP_FLAG_ENFORCESECURE in future (non-supervised) runs.
Can you give some hints on how to set the keys and establish a SC following your explanation? Thanks
@bve-ape, you should NOT pass OSDP_FLAG_ENFORCE_SECURE
when you want to use SCB-D to setup the secure channel. So you should do this:
uint8_t my_pd_scbk[16] = { /* Put you key as 16 bytes */ };
osdp_pd_info_t pd_info[] = {
{
.baud_rate = 115200,
.address = 1,
.flags = 0,
.scbk = my_pd_scbk,
}
cp.setup(1, pd_info, NULL);
In the logs, you should see messages indicating that a secure channel was setup using SCBK-D and then a subsequent KEYSET was performed. After this, the PD is setup with my_pd_scbk
as SCBK. In the next runs, instead of .flags = 0
, you can pass .flags = OSDP_FLAG_ENFORCE_SECURE
.
Thanks for your insight. What is not clear is what you mean with In the next runs. Do I need to do another cp.setup ? Right now the code is doing one setup then setting callbacks, etc then doing some polling:
cp.set_event_callback(cp_event_callback);
cp.set_osdp_command_complete_callback(osdp_command_complete_callback);
..
cp.refresh();
usleep(1000); // sleep 1 milli second
Thank you very much
The PD has to be forced to enter the install-mode (to use SCBK-D) with some method such as by presenting config-card. During this time, CP must also be stared in a special mode where it does not pass the OSDP_FLAG_ENFORCE_SECURE
flag (this operation is insecure because it would start a secure channel with default keys).
After the SC was setup using SCBK-D and the SCBK was set to the PD (at this time the PD would be moved out of install-mode) it's generally a good practice to restart everything from scratch (ie., call cp.setup() again or just reboot the device) only this time you can start passing OSDP_FLAG_ENFORCE_SECURE
.
Another point to note:
OSDP_FLAG_INSTALL_MODE
is an internal flag and using it may be as harmless as not doing anything or causing security issues (OSDP isn't super secure anyways; you wouldn't want to cut down any more limbs :D). So the general rule of thumb is: if it ain't oninclude/osdp.h
don't use it.
Do you mean the flag PD_FLAG_SC_USE_SCBKD
?
In the code example above:
uint8_t my_pd_scbk[16] = { /* Put you key as 16 bytes */ };
osdp_pd_info_t pd_info[] = {
{
.baud_rate = 115200,
.address = 1,
.flags = 0,
.scbk = my_pd_scbk,
}
cp.setup(1, pd_info, NULL);
If a SCBK is passed to the CP setup, is that key used to decrypt the first PD cryptogram? I am passing the SCBK_D to use, but the library is still unable to decrypt:
.[0mOSDP: CP->PD[0]: Sent [zu] =>
0000 14 53 01 13 00 0e 03 11 01 76 03 4a 71 dd b9 af |.S.......v.Jq...|
000zu 44 ef b4 dd |D... |
OSDP: CP->PD[0]: Received [zu] =>
0000 16 53 81 2b 00 0e 03 12 01 76 00 11 12 4d 42 31 |.S.+.....v...MB1|
000zu 31 30 ec 1a 61 5c |10..a\ |
OSDP: CP->PD[0]: Received [zu] =>
0000 2c 53 81 2b 00 0e 03 12 01 76 00 11 12 4d 42 31 |.S.+.....v...MB1|
000zu 31 30 ec 1a 61 5c 42 4d 4a 49 a8 df b0 6b 34 b1 |10..a\BMJI...k4.|
000zu 2f 12 7a 00 47 a7 06 40 c6 8f 7b 50 |/.z.G..@..{P |
.[31mOSDP: ERROR: PD[0]: CP : Failed to verify PD cryptogram
.[0m.[33mOSDP: WARN : PD[0]: CP : SC Failed. Retry with SCBK-D
.[0mOSDP: CP->PD[0]: Sent [zu] =>
0000 14 53 01 13 00 0f 03 11 00 76 95 3d 41 2b 37 e1 |.S.......v.=A+7.|
000zu b1 41 c8 36 |.A.6 |
OSDP: CP->PD[0]: Received [zu] =>
0000 0d 53 81 0c 00 0f 03 12 00 41 06 b9 15 |.S.......A... |
.[33mOSDP: WARN : PD[0]: CP : PD replied with NAK(6) for CMD(76)
.[0m.[0mOSDP: DEBUG: PD[0]: CP : CMD(76) REPLY(41)
.[0m.[31mOSDP: ERROR: PD[0]: CP : CHLNG failed. Online without SC
Unfortunately, with this Veridt reader, it is NAKing all subsequent osdp_CHLNG commands.
If a SCBK is passed to the CP setup, is that key used to decrypt the first PD cryptogram?
Yes.
I am passing the SCBK_D to use, but the library is still unable to decrypt
The library will do this for you. You do not need to pass the SCBK-D. It will first try to setup a connection with the provided SCBK; if that fails, it attempts to setup a secure channel session with SCBK-D (make sure that the reader is in install-mode) and if that succeeds, the SCBK that you passed initially will be set to the device.
If this is not what you are seeing, please post the full logs to https://pastebin.com/ and link it here.
Note: You can disable colours in the log lines at configure time if you are not reading them on a terminal with:
cmake -DCONFIG_DISABLE_PRETTY_LOGGING=off ..
# (OR)
./configure.sh --no-colours
So, I have the following piece of code as you suggested:
uint8_t masterkey[] = "my key here";
osdp_pd_info_t pd_info[] = {
{
.baud_rate = 9600,
.address = 0,
.flags = 0,
.id = {},
...
.scbk = masterkey
}
};
....
cp.setup(1, pd_info, nullptr);
...
while loop {
cp.refresh()
}
For which I get the following output from the library:
OSDP: INFO : CP : CP setup complete
OSDP: DEBUG: PD[0]: CP : CMD(61) REPLY(45)
CMD: osdp_ID(0x61) completed
OSDP: DEBUG: PD[0]: CP : CMD(62) REPLY(46)
CMD: osdp_CAP(0x62) completed capabilities read
OSDP: ERROR: PD[0]: CP : Failed to verify PD cryptogram
OSDP: WARN : PD[0]: CP : SC Failed. Retry with SCBK-D
OSDP: WARN : PD[0]: CP : PD replied with NAK(6) for CMD(76)
OSDP: DEBUG: PD[0]: CP : CMD(76) REPLY(41)
CMD: osdp_CHLNG(0x76) completed
OSDP: ERROR: PD[0]: CP : CHLNG failed. Online without SC
Can you give us a pseudo code sample on how you would initialize a secure communication from a cp.setup to a cp.refresh ?
Thanks a lot
What you have there is a valid init sequence, with one minor comment: you shouldn't pass the master_key
in place of scbk
(see [1]). If you need more samples you can look at samples directory or have a look at the osdpctl directory (which implements LibOSDP fully). If these are not clear for you to setup the device, please open a separate ticket with what you feel is the gap, I'll address them.
Bases on the logs, it appears your PD is not in "install-mode". That is the only reason why it would respond with NACK(6)
(which translates to "Communication security criteria not met") as it didn't accept our attempt to start the secure channel with SCBK-D.
[1]: The distinction between a Master Key and SCBK is that the Master Key is common for all PDs connected to this CP and the SCBK is derived from this key. The SCBK (when passed via the osdp_pd_info_t
) has to be unique to each PD.
Another point to note:
OSDP_FLAG_INSTALL_MODE
is an internal flag and using it may be as harmless as not doing anything or causing security issues (OSDP isn't super secure anyways; you wouldn't want to cut down any more limbs :D). So the general rule of thumb is: if it ain't oninclude/osdp.h
don't use it.Do you mean the flag
PD_FLAG_SC_USE_SCBKD
?
Yes. I've updated the original comment with this correction.
@matt-treiber-compass-es, there was indeed an issue with the SC implementation. Update to the most recent master to get the fixes.
@bve-ape, thanks for your efforts in finding/fixing this bug.
First off, thanks for the help to @patrick-compass with porting to FreeRTOS on a Cortex M4 on Issue 40. We are able to talk to multiple readers on a channel and move readers to a new PD address and 115,200 as well as detect cards and key presses.
Now we are trying to get a secure channel established -- first with the default SCBK after which we can then issue a osdp_KEYSET command with a new SCBK. I am working off of the current master -- cdf4627.
Unfortunately, the library returns an error: "CP: Failed to verify PD cryptogram".
I have a Veridt reader in its default state which a Veridt engineer assures me I should be able to use the SCBK-D to initiate a secure channel. It is my understanding from working with Veridt, that the reader needs be informed to use the SCBK-D via the osdp_CHLNG command.
I am hoping that this is a usage error on my part.
Describe the bug I initiate a CP session and I set the OSDP_FLAG_ENFORCE_SECURE, OSDP_FLAG_INSTALL_MODE, and PD_FLAG_SC_USE_SCBKD flags in the PD info structure. I also set the
pd_info->scbk
to the SCBK-D, otherwise the session will fail and NULL is returned byosdp_cp_setup()
. My call toosdp_cp_setup()
gives NULL for themaster_key
as that is being deprecated by the spec.Communication with the reader starts successfully with CMD_ID and CMD_CAP commands, but verification of the PD cryptogram fails.
Expected behavior Secure Channel is established
Observed behavior
OSDP: ERROR: PD[0]: CP : Failed to verify PD cryptogram
Additional context
There is an issue with printf in the code handling the color coding, I apologize, but here is a debug output log:
In debugging this, I've found that in the
OSDP_CP_STATE_CAPDET
,PD_FLAG_SC_USE_SCBKD
is cleared and I'm not sure why. Because when the response arrives,osdp_compute_session_keys()
doesn't use the SCBK-D, but generates the SCBK withosdp_compute_scbk(pd, ctx->sc_master_key, pd->sc.scbk);
. However, If I force the used of SCBK-D inosdp_compute_session_keys()
, I get the same result with failing to verify PD cryptogram.However, if I comment out lines 928 and 929 of osdp_cp.c which clears the
PD_FLAG_SC_USE_SCBKD
, the reader responds with aNAK
, even if I also force a 0 in writing to theSMB[2]
byte incp_build_command()
:From issue 40:
Obviously, OpenSSL is not defined or used, so libOSDP is using hand written implementation of the above functions and I'm able to step through them.
Any help would be appreciated!