diff --git a/README.md b/README.md index ef9a38e..217b139 100644 --- a/README.md +++ b/README.md @@ -168,8 +168,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 diff --git a/include/osdp.h b/include/osdp.h index 3651b44..9992ee9 100644 --- a/include/osdp.h +++ b/include/osdp.h @@ -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. */ diff --git a/python/osdp/constants.py b/python/osdp/constants.py index 4d0c583..2e38df2 100644 --- a/python/osdp/constants.py +++ b/python/osdp/constants.py @@ -12,6 +12,7 @@ class LibFlag: IgnoreUnsolicited = osdp_sys.FLAG_IGN_UNSOLICITED EnableNotification = osdp_sys.FLAG_ENABLE_NOTIFICATION CapturePackets = osdp_sys.FLAG_CAPTURE_PACKETS + AllowEmptyEncryptedDataBlock = osdp_sys.FLAG_ALLOW_EMPTY_ENCRYPTED_DATA_BLOCK class LogLevel: Emergency = osdp_sys.LOG_EMERG diff --git a/python/osdp_sys/module.c b/python/osdp_sys/module.c index 7d935ed..b5d365e 100644 --- a/python/osdp_sys/module.c +++ b/python/osdp_sys/module.c @@ -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); diff --git a/src/osdp_common.h b/src/osdp_common.h index 2bd43cf..f296f5f 100644 --- a/src/osdp_common.h +++ b/src/osdp_common.h @@ -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__) @@ -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_ */ diff --git a/src/osdp_phy.c b/src/osdp_phy.c index 2274500..1d6bc04 100644 --- a/src/osdp_phy.c +++ b/src/osdp_phy.c @@ -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 */ diff --git a/src/osdp_sc.c b/src/osdp_sc.c index 35b448d..a695157 100644 --- a/src/osdp_sc.c +++ b/src/osdp_sc.c @@ -139,6 +139,10 @@ int osdp_decrypt_data(struct osdp_pd *pd, int is_cmd, uint8_t *data, int length) return -1; } + if (sc_allow_empty_encrypted_data_block(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];