Skip to content

Commit

Permalink
Fix handling of empty SCS17/SCS18 messages
Browse files Browse the repository at this point in the history
Add a flag to allow for non-compliant messages for SCS17/SCS18 messages.  Some
OSDP implementations will send an SCS17/SCS18 message with no data when in
secure mode.  This is not correct according to the standard.  If this message
is received with libosdp, the current behavior is to drop the message and
print an error.

This patch adds a new flag, FLAG_ALLOW_EMPTY_ENCRYPTED_DATA_BLOCK to allow for
non-standard behavior of an empty data block with SCS17/SCS18.  This is only
when libosdp is used as a PD.
  • Loading branch information
Robert Middleton committed Nov 11, 2024
1 parent 0a87d4f commit 23c30f3
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 3 deletions.
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,8 +162,7 @@ is how you can run them:
```sh
mkdir build && cd build
cmake ..
make python_install
make check
make check-ut
```

To add new tests for the feature you are working one, see the other tests in
Expand Down
11 changes: 11 additions & 0 deletions include/osdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,17 @@ extern "C" {
*/
#define OSDP_FLAG_CAPTURE_PACKETS 0x00100000

/**
* @brief Allow an empty encrypted data block(SCS_17 and SCS_18 packets).
* This is non-conforming to the standard. If there is no data to be
* transferred, the CP should instead use the SCS_15/SCS_16 messages.
* Some OSDP implementations are buggy and send a 0-length data block with
* the SCS_17 and SCS_18 messages, this flag accepts that buggy behavior.
*
* @note this is a PD mode only flag
*/
#define OSDP_FLAG_ALLOW_EMPTY_ENCRYPTED_DATA_BLOCK 0x00200000

/**
* @brief Various PD capability function codes.
*/
Expand Down
1 change: 1 addition & 0 deletions python/osdp/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class LibFlag:
IgnoreUnsolicited = osdp_sys.FLAG_IGN_UNSOLICITED
EnableNotification = osdp_sys.FLAG_ENABLE_NOTIFICATION
CapturePackets = osdp_sys.FLAG_CAPTURE_PACKETS
AllowEmptySCS17_SCS18 = osdp_sys.FLAG_ALLOW_EMPTY_SCS17_SCS18

class LogLevel:
Emergency = osdp_sys.LOG_EMERG
Expand Down
1 change: 1 addition & 0 deletions python/osdp_sys/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ void pyosdp_add_module_constants(PyObject *module)
ADD_CONST("FLAG_IGN_UNSOLICITED", OSDP_FLAG_IGN_UNSOLICITED);
ADD_CONST("FLAG_ENABLE_NOTIFICATION", OSDP_FLAG_ENABLE_NOTIFICATION);
ADD_CONST("FLAG_CAPTURE_PACKETS", OSDP_FLAG_CAPTURE_PACKETS);
ADD_CONST("FLAG_ALLOW_EMPTY_ENCRYPTED_DATA_BLOCK", OSDP_FLAG_ALLOW_EMPTY_ENCRYPTED_DATA_BLOCK);

ADD_CONST("LOG_EMERG", OSDP_LOG_EMERG);
ADD_CONST("LOG_ALERT", OSDP_LOG_ALERT);
Expand Down
12 changes: 12 additions & 0 deletions src/osdp_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@
#define LOG_ERR(...) __logger_log(&pd->logger, LOG_ERR, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_INF(...) __logger_log(&pd->logger, LOG_INFO, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_WRN(...) __logger_log(&pd->logger, LOG_WARNING,__FILE__, __LINE__, __VA_ARGS__)
#define LOG_WRN_ONCE(...) \
do {\
static int warned = 0; \
if(!warned) { \
__logger_log(&pd->logger, LOG_WARNING,__FILE__, __LINE__, __VA_ARGS__);\
warned = 1;\
}\
}while(0)
#define LOG_NOT(...) __logger_log(&pd->logger, LOG_NOTICE, __FILE__, __LINE__, __VA_ARGS__)
#define LOG_DBG(...) __logger_log(&pd->logger, LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)

Expand Down Expand Up @@ -581,4 +589,8 @@ static inline bool is_packet_trace_enabled(struct osdp_pd *pd) {
IS_ENABLED(CONFIG_OSDP_PACKET_TRACE));
}

static inline bool sc_allow_empty_encrypted_data_block(struct osdp_pd *pd) {
return ISSET_FLAG(pd, OSDP_FLAG_ALLOW_EMPTY_ENCRYPTED_DATA_BLOCK);
}

#endif /* _OSDP_COMMON_H_ */
2 changes: 1 addition & 1 deletion src/osdp_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ int osdp_phy_decode_packet(struct osdp_pd *pd, uint8_t **pkt_start)
* used SCS_15/SCS_16 but we will be tolerant
* towards those faulty implementations.
*/
LOG_INF("Received encrypted data block with 0 "
LOG_WRN_ONCE("Received encrypted data block with 0 "
"length; tolerating non-conformance!");
}
len += 1; /* put back cmd/reply ID */
Expand Down
4 changes: 4 additions & 0 deletions src/osdp_sc.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ int osdp_decrypt_data(struct osdp_pd *pd, int is_cmd, uint8_t *data, int length)
return -1;
}

if (allow_scs17_scs18_empty(pd) && length == 0) {
return 0;
}

memcpy(iv, is_cmd ? pd->sc.r_mac : pd->sc.c_mac, 16);
for (i = 0; i < 16; i++) {
iv[i] = ~iv[i];
Expand Down

0 comments on commit 23c30f3

Please sign in to comment.