From c4f26e26332dd1cc0017e7bc2a49f1ffe67b32c7 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Thu, 16 Nov 2023 16:19:34 -0500 Subject: [PATCH] Fix #2467, message integrity API Adds two new APIs to the MSG module related to integrity: CFE_MSG_OriginationAction CFE_MSG_VerificationAction These should perform all calculations/updates on origination and all verifcation/checks at termination of the message path, respectively. The specific set of actions depends on how the user has implemented their particular MSG module. By default, the traditional CFE encapsulation sets a checksum on commands and a timestamp on TLM, and no verification at the receiver. --- modules/core_api/fsw/inc/cfe_msg.h | 73 +++++++++------ modules/core_api/fsw/inc/cfe_sb.h | 35 ++++--- .../core_api/ut-stubs/src/cfe_msg_handlers.c | 32 +++++++ modules/core_api/ut-stubs/src/cfe_msg_stubs.c | 49 +++++++--- modules/core_api/ut-stubs/src/cfe_sb_stubs.c | 8 +- modules/msg/CMakeLists.txt | 2 +- modules/msg/fsw/src/cfe_msg_init.c | 31 ------- modules/msg/fsw/src/cfe_msg_integrity.c | 76 ++++++++++++++++ modules/msg/ut-coverage/CMakeLists.txt | 2 +- modules/msg/ut-coverage/msg_UT.c | 4 +- modules/msg/ut-coverage/test_cfe_msg_init.c | 37 -------- modules/msg/ut-coverage/test_cfe_msg_init.h | 2 +- .../msg/ut-coverage/test_cfe_msg_integrity.c | 91 +++++++++++++++++++ modules/msg/ut-coverage/test_cfe_msg_verify.h | 2 +- modules/sb/fsw/inc/cfe_sb_eventids.h | 25 +++++ modules/sb/fsw/src/cfe_sb_api.c | 9 +- modules/sb/ut-coverage/sb_UT.c | 18 ++-- 17 files changed, 354 insertions(+), 142 deletions(-) create mode 100644 modules/msg/fsw/src/cfe_msg_integrity.c create mode 100644 modules/msg/ut-coverage/test_cfe_msg_integrity.c diff --git a/modules/core_api/fsw/inc/cfe_msg.h b/modules/core_api/fsw/inc/cfe_msg.h index ccd43bdb7..7a25771f2 100644 --- a/modules/core_api/fsw/inc/cfe_msg.h +++ b/modules/core_api/fsw/inc/cfe_msg.h @@ -60,30 +60,6 @@ */ CFE_Status_t CFE_MSG_Init(CFE_MSG_Message_t *MsgPtr, CFE_SB_MsgId_t MsgId, CFE_MSG_Size_t Size); -/*****************************************************************************/ -/** - * \brief Set/compute all dynamically-updated headers on a message - * - * \par Description - * This routine updates all dynamic header fields on a message, and is typically - * invoked via SB just prior to broadcasting the message. Dynamic headers include - * are values that should be computed/updated per message, including: - * - the sequence number - * - the timestamp, if present - * - any error control or checksum fields, if present - * - * The MSG module implementation determines which header fields meet this criteria - * and how they should be computed. - * - * \param[inout] MsgPtr A pointer to the buffer that contains the message @nonnull. - * \param[in] SeqCnt The current sequence number from the message route - * - * \return Execution status, see \ref CFEReturnCodes - * \retval #CFE_SUCCESS \copybrief CFE_SUCCESS - * \retval #CFE_MSG_BAD_ARGUMENT \copybrief CFE_MSG_BAD_ARGUMENT - */ -CFE_Status_t CFE_MSG_UpdateHeader(CFE_MSG_Message_t *MsgPtr, CFE_MSG_SequenceCount_t SeqCnt); - /**\}*/ /** \defgroup CFEAPIMSGHeaderPri cFE Message Primary Header APIs @@ -725,12 +701,44 @@ CFE_Status_t CFE_MSG_GetTypeFromMsgId(CFE_SB_MsgId_t MsgId, CFE_MSG_Type_t *Type /**\}*/ -/** \defgroup CFEAPIMSGMsgVerify cFE Message Checking APIs +/** \defgroup CFEAPIMSGMsgIntegrity cFE Message Integrity APIs * \{ */ + /*****************************************************************************/ /** - * \brief Checks message headers against expected values + * \brief Perform any necessary actions on a newly-created message, prior to sending + * + * \par Description + * This routine updates and/or appends any necessary fields on a message, is + * invoked via SB just prior to broadcasting the message. The actions include + * updating any values that should be computed/updated per message, including: + * - setting the sequence number + * - updating the timestamp, if present + * - computing any error control or checksum fields, if present + * + * The MSG module implementation determines which header fields meet this criteria + * and how they should be computed. + * + * The BufferSize parameter indicates the allocation size message of the buffer that + * holds the message (i.e. the message envelope size). In some implementations, the + * allocated buffer may include extra space in order to append a CRC or digital signature. + * + * \sa CFE_MSG_VerificationAction + * + * \param[inout] MsgPtr A pointer to the buffer that contains the message @nonnull. + * \param[in] BufferSize The size of the buffer encapsulating the message + * \param[out] IsAcceptable Output variable to be set, indicates message acceptability @nonnull + * + * \return Execution status, see \ref CFEReturnCodes + * \retval #CFE_SUCCESS \copybrief CFE_SUCCESS + * \retval #CFE_MSG_BAD_ARGUMENT \copybrief CFE_MSG_BAD_ARGUMENT + */ +CFE_Status_t CFE_MSG_OriginationAction(CFE_MSG_Message_t *MsgPtr, size_t BufferSize, bool *IsAcceptable); + +/*****************************************************************************/ +/** + * \brief Checks message integrity/acceptability * * \par Description * This routine validates that any error-control field(s) in the message header @@ -740,14 +748,23 @@ CFE_Status_t CFE_MSG_GetTypeFromMsgId(CFE_SB_MsgId_t MsgId, CFE_MSG_Type_t *Type * and may be a no-op if no error checking is implemented. In that case, it * will always output "true". * + * \note Due to the fact that software bus uses a multicast architecture, this function + * must not modify the message, as the buffer may be shared among multiple receivers. + * This should generally be the inverse of CFE_MSG_OriginationAction(), but on the + * origination side it may update header fields and/or modify the message, on + * the verification/receive side it must only check those fields, not modify them. + * + * \sa CFE_MSG_OriginationAction + * * \param[in] MsgPtr Message Pointer @nonnull - * \param[out] VerifyStatus Output variable to be set to verification result @nonnull + * \param[in] BufferSize The size of the buffer encapsulating the message + * \param[out] IsAcceptable Output variable to be set, indicates message acceptability @nonnull * * \return Execution status, see \ref CFEReturnCodes * \retval #CFE_SUCCESS \copybrief CFE_SUCCESS * \retval #CFE_MSG_BAD_ARGUMENT \copybrief CFE_MSG_BAD_ARGUMENT */ -CFE_Status_t CFE_MSG_Verify(const CFE_MSG_Message_t *MsgPtr, bool *VerifyStatus); +CFE_Status_t CFE_MSG_VerificationAction(const CFE_MSG_Message_t *MsgPtr, size_t BufferSize, bool *IsAcceptable); /**\}*/ diff --git a/modules/core_api/fsw/inc/cfe_sb.h b/modules/core_api/fsw/inc/cfe_sb.h index a670d0120..d08b5aca5 100644 --- a/modules/core_api/fsw/inc/cfe_sb.h +++ b/modules/core_api/fsw/inc/cfe_sb.h @@ -402,9 +402,15 @@ CFE_Status_t CFE_SB_UnsubscribeLocal(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeI ** software bus will read the message ID from the message header to ** determine which pipes should receive the message. ** -** In general, the "UpdateHeader" parameter should be passed as "true" -** if the message was newly constructed by the sender and is being sent -** for the first time. When forwarding a message that originated from +** The IsOrigination parameter should be passed as "true" if the message was +** newly constructed by the sender and is being sent for the first time. This +** enables the message origination actions as determined by the CFE MSG module, +** which may include (but not limited to): +** - Updating sequence number +** - Updating timestamp +** - Calcualating a CRC, checksum, or other message error control field +** +** Conversely, when forwarding a message that originated from ** an external entity (e.g. messages passing through CI or SBN), the ** parameter should be passed as "false" to not overwrite existing data. ** @@ -421,7 +427,7 @@ CFE_Status_t CFE_SB_UnsubscribeLocal(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeI ** ** \param[in] MsgPtr A pointer to the message to be sent @nonnull. This must point ** to the first byte of the message header. -** \param[in] UpdateHeader Update the headers of the message +** \param[in] IsOrigination Update the headers of the message ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS @@ -429,7 +435,7 @@ CFE_Status_t CFE_SB_UnsubscribeLocal(CFE_SB_MsgId_t MsgId, CFE_SB_PipeId_t PipeI ** \retval #CFE_SB_MSG_TOO_BIG \copybrief CFE_SB_MSG_TOO_BIG ** \retval #CFE_SB_BUF_ALOC_ERR \covtest \copybrief CFE_SB_BUF_ALOC_ERR **/ -CFE_Status_t CFE_SB_TransmitMsg(const CFE_MSG_Message_t *MsgPtr, bool UpdateHeader); +CFE_Status_t CFE_SB_TransmitMsg(const CFE_MSG_Message_t *MsgPtr, bool IsOrigination); /*****************************************************************************/ /** @@ -471,6 +477,7 @@ CFE_Status_t CFE_SB_TransmitMsg(const CFE_MSG_Message_t *MsgPtr, bool UpdateHead ** \retval #CFE_SB_NO_MESSAGE \copybrief CFE_SB_NO_MESSAGE **/ CFE_Status_t CFE_SB_ReceiveBuffer(CFE_SB_Buffer_t **BufPtr, CFE_SB_PipeId_t PipeId, int32 TimeOut); + /** @} */ /** @defgroup CFEAPISBZeroCopy cFE Zero Copy APIs @@ -544,9 +551,15 @@ CFE_Status_t CFE_SB_ReleaseMessageBuffer(CFE_SB_Buffer_t *BufPtr); ** internal buffer. The "zero copy" interface can be used to improve ** performance in high-rate, high-volume software bus traffic. ** -** In general, the "UpdateHeader" parameter should be passed as "true" -** if the message was newly constructed by the sender and is being sent -** for the first time. When forwarding a message that originated from +** The IsOrigination parameter should be passed as "true" if the message was +** newly constructed by the sender and is being sent for the first time. This +** enables the message origination actions as determined by the CFE MSG module, +** which may include (but not limited to): +** - Updating sequence number +** - Updating timestamp +** - Calcualating a CRC, checksum, or other message error control field +** +** Conversely, when forwarding a message that originated from ** an external entity (e.g. messages passing through CI or SBN), the ** parameter should be passed as "false" to not overwrite existing data. ** @@ -567,15 +580,15 @@ CFE_Status_t CFE_SB_ReleaseMessageBuffer(CFE_SB_Buffer_t *BufPtr); ** -# This function will increment and apply the internally tracked ** sequence counter if set to do so. ** -** \param[in] BufPtr A pointer to the buffer to be sent @nonnull. -** \param[in] UpdateHeader Update the headers of the message +** \param[in] BufPtr A pointer to the buffer to be sent @nonnull. +** \param[in] IsOrigination Update applicable header field(s) of a newly constructed message ** ** \return Execution status, see \ref CFEReturnCodes ** \retval #CFE_SUCCESS \copybrief CFE_SUCCESS ** \retval #CFE_SB_BAD_ARGUMENT \copybrief CFE_SB_BAD_ARGUMENT ** \retval #CFE_SB_MSG_TOO_BIG \copybrief CFE_SB_MSG_TOO_BIG **/ -CFE_Status_t CFE_SB_TransmitBuffer(CFE_SB_Buffer_t *BufPtr, bool UpdateHeader); +CFE_Status_t CFE_SB_TransmitBuffer(CFE_SB_Buffer_t *BufPtr, bool IsOrigination); /** @} */ diff --git a/modules/core_api/ut-stubs/src/cfe_msg_handlers.c b/modules/core_api/ut-stubs/src/cfe_msg_handlers.c index fee87345c..e9228a998 100644 --- a/modules/core_api/ut-stubs/src/cfe_msg_handlers.c +++ b/modules/core_api/ut-stubs/src/cfe_msg_handlers.c @@ -376,3 +376,35 @@ void UT_DefaultHandler_CFE_MSG_GetNextSequenceCount(void *UserObj, UT_EntryKey_t UT_Stub_SetReturnValue(FuncKey, return_value); } + +/*------------------------------------------------------------ + * + * Default handler for CFE_MSG_OriginationAction coverage stub function + * + *------------------------------------------------------------*/ +void UT_DefaultHandler_CFE_MSG_OriginationAction(void *UserObj, UT_EntryKey_t FuncKey, const UT_StubContext_t *Context) +{ + bool *IsAcceptable = UT_Hook_GetArgValueByName(Context, "IsAcceptable", bool *); + + /* by default just always return true -- a UT case that needs something else can override this handler */ + if (IsAcceptable != NULL) + { + *IsAcceptable = true; + } +} + +/*------------------------------------------------------------ + * + * Default handler for CFE_MSG_VerificationAction coverage stub function + * + *------------------------------------------------------------*/ +void UT_DefaultHandler_CFE_MSG_VerificationAction(void *UserObj, UT_EntryKey_t FuncKey, const UT_StubContext_t *Context) +{ + bool *IsAcceptable = UT_Hook_GetArgValueByName(Context, "IsAcceptable", bool *); + + /* by default just always return true -- a UT case that needs something else can override this handler */ + if (IsAcceptable != NULL) + { + *IsAcceptable = true; + } +} diff --git a/modules/core_api/ut-stubs/src/cfe_msg_stubs.c b/modules/core_api/ut-stubs/src/cfe_msg_stubs.c index 066f8e8d1..ea39c87b3 100644 --- a/modules/core_api/ut-stubs/src/cfe_msg_stubs.c +++ b/modules/core_api/ut-stubs/src/cfe_msg_stubs.c @@ -42,7 +42,9 @@ void UT_DefaultHandler_CFE_MSG_GetSubsystem(void *, UT_EntryKey_t, const UT_Stub void UT_DefaultHandler_CFE_MSG_GetSystem(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_MSG_GetType(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_MSG_GetTypeFromMsgId(void *, UT_EntryKey_t, const UT_StubContext_t *); +void UT_DefaultHandler_CFE_MSG_OriginationAction(void *, UT_EntryKey_t, const UT_StubContext_t *); void UT_DefaultHandler_CFE_MSG_ValidateChecksum(void *, UT_EntryKey_t, const UT_StubContext_t *); +void UT_DefaultHandler_CFE_MSG_VerificationAction(void *, UT_EntryKey_t, const UT_StubContext_t *); /* * ---------------------------------------------------- @@ -366,6 +368,24 @@ CFE_Status_t CFE_MSG_Init(CFE_MSG_Message_t *MsgPtr, CFE_SB_MsgId_t MsgId, CFE_M return UT_GenStub_GetReturnValue(CFE_MSG_Init, CFE_Status_t); } +/* + * ---------------------------------------------------- + * Generated stub function for CFE_MSG_OriginationAction() + * ---------------------------------------------------- + */ +CFE_Status_t CFE_MSG_OriginationAction(CFE_MSG_Message_t *MsgPtr, size_t BufferSize, bool *IsAcceptable) +{ + UT_GenStub_SetupReturnBuffer(CFE_MSG_OriginationAction, CFE_Status_t); + + UT_GenStub_AddParam(CFE_MSG_OriginationAction, CFE_MSG_Message_t *, MsgPtr); + UT_GenStub_AddParam(CFE_MSG_OriginationAction, size_t, BufferSize); + UT_GenStub_AddParam(CFE_MSG_OriginationAction, bool *, IsAcceptable); + + UT_GenStub_Execute(CFE_MSG_OriginationAction, Basic, UT_DefaultHandler_CFE_MSG_OriginationAction); + + return UT_GenStub_GetReturnValue(CFE_MSG_OriginationAction, CFE_Status_t); +} + /* * ---------------------------------------------------- * Generated stub function for CFE_MSG_SetApId() @@ -623,34 +643,35 @@ CFE_Status_t CFE_MSG_SetType(CFE_MSG_Message_t *MsgPtr, CFE_MSG_Type_t Type) /* * ---------------------------------------------------- - * Generated stub function for CFE_MSG_UpdateHeader() + * Generated stub function for CFE_MSG_ValidateChecksum() * ---------------------------------------------------- */ -CFE_Status_t CFE_MSG_UpdateHeader(CFE_MSG_Message_t *MsgPtr, CFE_MSG_SequenceCount_t SeqCnt) +CFE_Status_t CFE_MSG_ValidateChecksum(const CFE_MSG_Message_t *MsgPtr, bool *IsValid) { - UT_GenStub_SetupReturnBuffer(CFE_MSG_UpdateHeader, CFE_Status_t); + UT_GenStub_SetupReturnBuffer(CFE_MSG_ValidateChecksum, CFE_Status_t); - UT_GenStub_AddParam(CFE_MSG_UpdateHeader, CFE_MSG_Message_t *, MsgPtr); - UT_GenStub_AddParam(CFE_MSG_UpdateHeader, CFE_MSG_SequenceCount_t, SeqCnt); + UT_GenStub_AddParam(CFE_MSG_ValidateChecksum, const CFE_MSG_Message_t *, MsgPtr); + UT_GenStub_AddParam(CFE_MSG_ValidateChecksum, bool *, IsValid); - UT_GenStub_Execute(CFE_MSG_UpdateHeader, Basic, NULL); + UT_GenStub_Execute(CFE_MSG_ValidateChecksum, Basic, UT_DefaultHandler_CFE_MSG_ValidateChecksum); - return UT_GenStub_GetReturnValue(CFE_MSG_UpdateHeader, CFE_Status_t); + return UT_GenStub_GetReturnValue(CFE_MSG_ValidateChecksum, CFE_Status_t); } /* * ---------------------------------------------------- - * Generated stub function for CFE_MSG_ValidateChecksum() + * Generated stub function for CFE_MSG_VerificationAction() * ---------------------------------------------------- */ -CFE_Status_t CFE_MSG_ValidateChecksum(const CFE_MSG_Message_t *MsgPtr, bool *IsValid) +CFE_Status_t CFE_MSG_VerificationAction(const CFE_MSG_Message_t *MsgPtr, size_t BufferSize, bool *IsAcceptable) { - UT_GenStub_SetupReturnBuffer(CFE_MSG_ValidateChecksum, CFE_Status_t); + UT_GenStub_SetupReturnBuffer(CFE_MSG_VerificationAction, CFE_Status_t); - UT_GenStub_AddParam(CFE_MSG_ValidateChecksum, const CFE_MSG_Message_t *, MsgPtr); - UT_GenStub_AddParam(CFE_MSG_ValidateChecksum, bool *, IsValid); + UT_GenStub_AddParam(CFE_MSG_VerificationAction, const CFE_MSG_Message_t *, MsgPtr); + UT_GenStub_AddParam(CFE_MSG_VerificationAction, size_t, BufferSize); + UT_GenStub_AddParam(CFE_MSG_VerificationAction, bool *, IsAcceptable); - UT_GenStub_Execute(CFE_MSG_ValidateChecksum, Basic, UT_DefaultHandler_CFE_MSG_ValidateChecksum); + UT_GenStub_Execute(CFE_MSG_VerificationAction, Basic, UT_DefaultHandler_CFE_MSG_VerificationAction); - return UT_GenStub_GetReturnValue(CFE_MSG_ValidateChecksum, CFE_Status_t); + return UT_GenStub_GetReturnValue(CFE_MSG_VerificationAction, CFE_Status_t); } diff --git a/modules/core_api/ut-stubs/src/cfe_sb_stubs.c b/modules/core_api/ut-stubs/src/cfe_sb_stubs.c index 3f541d54c..369394492 100644 --- a/modules/core_api/ut-stubs/src/cfe_sb_stubs.c +++ b/modules/core_api/ut-stubs/src/cfe_sb_stubs.c @@ -384,12 +384,12 @@ void CFE_SB_TimeStampMsg(CFE_MSG_Message_t *MsgPtr) * Generated stub function for CFE_SB_TransmitBuffer() * ---------------------------------------------------- */ -CFE_Status_t CFE_SB_TransmitBuffer(CFE_SB_Buffer_t *BufPtr, bool UpdateHeader) +CFE_Status_t CFE_SB_TransmitBuffer(CFE_SB_Buffer_t *BufPtr, bool IsOrigination) { UT_GenStub_SetupReturnBuffer(CFE_SB_TransmitBuffer, CFE_Status_t); UT_GenStub_AddParam(CFE_SB_TransmitBuffer, CFE_SB_Buffer_t *, BufPtr); - UT_GenStub_AddParam(CFE_SB_TransmitBuffer, bool, UpdateHeader); + UT_GenStub_AddParam(CFE_SB_TransmitBuffer, bool, IsOrigination); UT_GenStub_Execute(CFE_SB_TransmitBuffer, Basic, UT_DefaultHandler_CFE_SB_TransmitBuffer); @@ -401,12 +401,12 @@ CFE_Status_t CFE_SB_TransmitBuffer(CFE_SB_Buffer_t *BufPtr, bool UpdateHeader) * Generated stub function for CFE_SB_TransmitMsg() * ---------------------------------------------------- */ -CFE_Status_t CFE_SB_TransmitMsg(const CFE_MSG_Message_t *MsgPtr, bool UpdateHeader) +CFE_Status_t CFE_SB_TransmitMsg(const CFE_MSG_Message_t *MsgPtr, bool IsOrigination) { UT_GenStub_SetupReturnBuffer(CFE_SB_TransmitMsg, CFE_Status_t); UT_GenStub_AddParam(CFE_SB_TransmitMsg, const CFE_MSG_Message_t *, MsgPtr); - UT_GenStub_AddParam(CFE_SB_TransmitMsg, bool, UpdateHeader); + UT_GenStub_AddParam(CFE_SB_TransmitMsg, bool, IsOrigination); UT_GenStub_Execute(CFE_SB_TransmitMsg, Basic, UT_DefaultHandler_CFE_SB_TransmitMsg); diff --git a/modules/msg/CMakeLists.txt b/modules/msg/CMakeLists.txt index 4cc69762c..c4af293b0 100644 --- a/modules/msg/CMakeLists.txt +++ b/modules/msg/CMakeLists.txt @@ -18,7 +18,7 @@ set(${DEP}_SRC fsw/src/cfe_msg_ccsdspri.c fsw/src/cfe_msg_init.c - fsw/src/cfe_msg_verify.c + fsw/src/cfe_msg_integrity.c fsw/src/cfe_msg_msgid_shared.c fsw/src/cfe_msg_sechdr_checksum.c fsw/src/cfe_msg_sechdr_fc.c diff --git a/modules/msg/fsw/src/cfe_msg_init.c b/modules/msg/fsw/src/cfe_msg_init.c index ab988f4bb..d67fc643d 100644 --- a/modules/msg/fsw/src/cfe_msg_init.c +++ b/modules/msg/fsw/src/cfe_msg_init.c @@ -53,34 +53,3 @@ CFE_Status_t CFE_MSG_Init(CFE_MSG_Message_t *MsgPtr, CFE_SB_MsgId_t MsgId, CFE_M return status; } - -/*---------------------------------------------------------------- - * - * Implemented per public API - * See description in header file for argument/return detail - * - *-----------------------------------------------------------------*/ -CFE_Status_t CFE_MSG_UpdateHeader(CFE_MSG_Message_t *MsgPtr, CFE_MSG_SequenceCount_t SeqCnt) -{ - if (MsgPtr == NULL) - { - return CFE_MSG_BAD_ARGUMENT; - } - - /* Sequence count is in the basic CCSDS Primary Hdr, so all msgs have it */ - CFE_MSG_SetSequenceCount(MsgPtr, SeqCnt); - - /* - * TLM packets have a timestamp in the secondary header. - * This may fail if this is not a TLM packet (that is OK) - */ - CFE_MSG_SetMsgTime(MsgPtr, CFE_TIME_GetTime()); - - /* - * CMD packets have a checksum in the secondary header. - * This may fail if this is not a CMD packet (that is OK) - */ - CFE_MSG_GenerateChecksum(MsgPtr); - - return CFE_SUCCESS; -} \ No newline at end of file diff --git a/modules/msg/fsw/src/cfe_msg_integrity.c b/modules/msg/fsw/src/cfe_msg_integrity.c new file mode 100644 index 000000000..bf1c61bd0 --- /dev/null +++ b/modules/msg/fsw/src/cfe_msg_integrity.c @@ -0,0 +1,76 @@ +/************************************************************************ + * NASA Docket No. GSC-18,719-1, and identified as “core Flight System: Bootes” + * + * Copyright (c) 2020 United States Government as represented by the + * Administrator of the National Aeronautics and Space Administration. + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ************************************************************************/ + +#include "cfe_msg.h" +#include "cfe_msg_priv.h" +#include "cfe_msg_defaults.h" +#include "cfe_time.h" + +/*---------------------------------------------------------------- + * + * Implemented per public API + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +CFE_Status_t CFE_MSG_OriginationAction(CFE_MSG_Message_t *MsgPtr, size_t BufferSize, bool *IsAcceptable) +{ + if (MsgPtr == NULL || IsAcceptable == NULL) + { + return CFE_MSG_BAD_ARGUMENT; + } + + /* + * TLM packets have a timestamp in the secondary header. + * This may fail if this is not a TLM packet (that is OK) + */ + CFE_MSG_SetMsgTime(MsgPtr, CFE_TIME_GetTime()); + + /* + * CMD packets have a checksum in the secondary header. + * This may fail if this is not a CMD packet (that is OK) + */ + CFE_MSG_GenerateChecksum(MsgPtr); + + /* This implementation permits all outgoing messages */ + *IsAcceptable = true; + + return CFE_SUCCESS; +} +/*---------------------------------------------------------------- + * + * Implemented per public API + * See description in header file for argument/return detail + * + *-----------------------------------------------------------------*/ +CFE_Status_t CFE_MSG_VerificationAction(const CFE_MSG_Message_t *MsgPtr, size_t BufferSize, bool *IsAcceptable) +{ + if (MsgPtr == NULL || IsAcceptable == NULL) + { + return CFE_MSG_BAD_ARGUMENT; + } + + /* + * In the default implementation, there is not anything to check here. + * + * This is mainly a hook for user expansion, in case a custom implementation + * has message verification capability. + */ + *IsAcceptable = true; + + return CFE_SUCCESS; +} \ No newline at end of file diff --git a/modules/msg/ut-coverage/CMakeLists.txt b/modules/msg/ut-coverage/CMakeLists.txt index dd2c3bad1..a2c5eed17 100644 --- a/modules/msg/ut-coverage/CMakeLists.txt +++ b/modules/msg/ut-coverage/CMakeLists.txt @@ -18,7 +18,7 @@ set (ut_${DEP}_tests test_msg_not.c test_msg_pri_not.c test_cfe_msg_init.c - test_cfe_msg_verify.c + test_cfe_msg_integrity.c test_cfe_msg_ccsdspri.c test_cfe_msg_msgid_shared.c test_cfe_msg_checksum.c diff --git a/modules/msg/ut-coverage/msg_UT.c b/modules/msg/ut-coverage/msg_UT.c index 0ad1b30bb..48d8f9259 100644 --- a/modules/msg/ut-coverage/msg_UT.c +++ b/modules/msg/ut-coverage/msg_UT.c @@ -44,11 +44,11 @@ void UtTest_Setup(void) UtPrintf("Message header coverage test..."); UT_ADD_TEST(Test_MSG_Init); - UT_ADD_TEST(Test_MSG_UpdateHeader); + UT_ADD_TEST(Test_MSG_OriginationAction); Test_MSG_CCSDSPri(); Test_MSG_CCSDSExt(); Test_MSG_MsgId_Shared(); - UT_ADD_TEST(Test_MSG_Verify); + UT_ADD_TEST(Test_MSG_VerificationAction); UT_ADD_TEST(Test_MSG_MsgId); UT_ADD_TEST(Test_MSG_Checksum); UT_ADD_TEST(Test_MSG_FcnCode); diff --git a/modules/msg/ut-coverage/test_cfe_msg_init.c b/modules/msg/ut-coverage/test_cfe_msg_init.c index a707c3618..a072566ae 100644 --- a/modules/msg/ut-coverage/test_cfe_msg_init.c +++ b/modules/msg/ut-coverage/test_cfe_msg_init.c @@ -124,40 +124,3 @@ void Test_MSG_Init(void) UtAssert_UINT32_EQ(Test_MSG_Pri_NotZero(CFE_MSG_PTR(cmd)) & ~MSG_HDRVER_FLAG, MSG_APID_FLAG | MSG_HASSEC_FLAG | MSG_TYPE_FLAG | MSG_LENGTH_FLAG | MSG_SEGMENT_FLAG); } - -/* - * Test MSG Update Header - */ -void Test_MSG_UpdateHeader(void) -{ - union - { - CFE_MSG_Message_t msg; - CFE_MSG_CommandHeader_t cmd; - CFE_MSG_TelemetryHeader_t tlm; - - } LocalBuf; - CFE_MSG_SequenceCount_t SeqCnt; - CFE_MSG_SequenceCount_t CheckCnt; - - memset(&LocalBuf, 0, sizeof(LocalBuf)); - SeqCnt = 1; - CheckCnt = 0; - - /* bad buffer */ - UtAssert_INT32_EQ(CFE_MSG_UpdateHeader(NULL, SeqCnt), CFE_MSG_BAD_ARGUMENT); - - /* nominal, cmd */ - CFE_MSG_SetType(&LocalBuf.msg, CFE_MSG_Type_Cmd); - CFE_UtAssert_SUCCESS(CFE_MSG_UpdateHeader(&LocalBuf.msg, SeqCnt)); - CFE_MSG_GetSequenceCount(&LocalBuf.msg, &CheckCnt); - UtAssert_UINT32_EQ(CheckCnt, SeqCnt); - ++SeqCnt; - - /* nominal, tlm */ - CFE_MSG_SetType(&LocalBuf.msg, CFE_MSG_Type_Tlm); - CFE_UtAssert_SUCCESS(CFE_MSG_UpdateHeader(&LocalBuf.msg, SeqCnt)); - CFE_MSG_GetSequenceCount(&LocalBuf.msg, &CheckCnt); - UtAssert_UINT32_EQ(CheckCnt, SeqCnt); - ++SeqCnt; -} diff --git a/modules/msg/ut-coverage/test_cfe_msg_init.h b/modules/msg/ut-coverage/test_cfe_msg_init.h index 3c5b25f62..6e465b03d 100644 --- a/modules/msg/ut-coverage/test_cfe_msg_init.h +++ b/modules/msg/ut-coverage/test_cfe_msg_init.h @@ -33,6 +33,6 @@ */ /* Test extended header mission functionality */ void Test_MSG_Init(void); -void Test_MSG_UpdateHeader(void); +void Test_MSG_OriginationAction(void); #endif /* TEST_CFE_MSG_INIT_H */ diff --git a/modules/msg/ut-coverage/test_cfe_msg_integrity.c b/modules/msg/ut-coverage/test_cfe_msg_integrity.c new file mode 100644 index 000000000..bc3aa7311 --- /dev/null +++ b/modules/msg/ut-coverage/test_cfe_msg_integrity.c @@ -0,0 +1,91 @@ +/************************************************************************ + * NASA Docket No. GSC-18,719-1, and identified as “core Flight System: Bootes” + * + * Copyright (c) 2020 United States Government as represented by the + * Administrator of the National Aeronautics and Space Administration. + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ************************************************************************/ + +/* + * Test message verify + */ + +/* + * Includes + */ +#include "utassert.h" +#include "ut_support.h" +#include "cfe_msg.h" +#include "test_cfe_msg_verify.h" +#include "cfe_error.h" +#include "cfe_msg_defaults.h" + +#include + +/* + * Test MSG integrity origination action(s) + */ +void Test_MSG_OriginationAction(void) +{ + union + { + CFE_MSG_Message_t msg; + CFE_MSG_CommandHeader_t cmd; + CFE_MSG_TelemetryHeader_t tlm; + + } LocalBuf; + bool IsAcceptable; + + memset(&LocalBuf, 0, sizeof(LocalBuf)); + + /* bad buffer */ + UtAssert_INT32_EQ(CFE_MSG_OriginationAction(NULL, sizeof(LocalBuf), &IsAcceptable), CFE_MSG_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_MSG_OriginationAction(&LocalBuf.msg, sizeof(LocalBuf), NULL), CFE_MSG_BAD_ARGUMENT); + + /* nominal, cmd */ + IsAcceptable = false; + CFE_MSG_SetType(&LocalBuf.msg, CFE_MSG_Type_Cmd); + CFE_UtAssert_SUCCESS(CFE_MSG_OriginationAction(&LocalBuf.msg, sizeof(LocalBuf), &IsAcceptable)); + UtAssert_BOOL_TRUE(IsAcceptable); + + /* nominal, tlm */ + IsAcceptable = false; + CFE_MSG_SetType(&LocalBuf.msg, CFE_MSG_Type_Tlm); + CFE_UtAssert_SUCCESS(CFE_MSG_OriginationAction(&LocalBuf.msg, sizeof(LocalBuf), &IsAcceptable)); + UtAssert_BOOL_TRUE(IsAcceptable); +} + +/* + * Test MSG integrity verification action(s) + */ +void Test_MSG_VerificationAction(void) +{ + union + { + CFE_MSG_Message_t msg; + CFE_MSG_CommandHeader_t cmd; + CFE_MSG_TelemetryHeader_t tlm; + } LocalBuf; + bool IsAcceptable; + + memset(&LocalBuf, 0, sizeof(LocalBuf)); + + /* bad buffer */ + UtAssert_INT32_EQ(CFE_MSG_VerificationAction(NULL, sizeof(LocalBuf), &IsAcceptable), CFE_MSG_BAD_ARGUMENT); + UtAssert_INT32_EQ(CFE_MSG_VerificationAction(&LocalBuf.msg, sizeof(LocalBuf), NULL), CFE_MSG_BAD_ARGUMENT); + + /* nominal */ + IsAcceptable = false; + CFE_UtAssert_SUCCESS(CFE_MSG_VerificationAction(&LocalBuf.msg, sizeof(LocalBuf), &IsAcceptable)); + UtAssert_BOOL_TRUE(IsAcceptable); +} diff --git a/modules/msg/ut-coverage/test_cfe_msg_verify.h b/modules/msg/ut-coverage/test_cfe_msg_verify.h index f017560e2..024412ea4 100644 --- a/modules/msg/ut-coverage/test_cfe_msg_verify.h +++ b/modules/msg/ut-coverage/test_cfe_msg_verify.h @@ -31,6 +31,6 @@ /* * Functions */ -void Test_MSG_Verify(void); +void Test_MSG_VerificationAction(void); #endif /* TEST_CFE_MSG_VERIFY_H */ diff --git a/modules/sb/fsw/inc/cfe_sb_eventids.h b/modules/sb/fsw/inc/cfe_sb_eventids.h index 326542f9c..0f59304a2 100644 --- a/modules/sb/fsw/inc/cfe_sb_eventids.h +++ b/modules/sb/fsw/inc/cfe_sb_eventids.h @@ -759,6 +759,31 @@ * #CFE_SB_CreatePipe API failure due to no free queues. */ #define CFE_SB_CR_PIPE_NO_FREE_EID 70 + +/** + * \brief SB integrity actions on transmit message failure event + * + * \par Type: ERROR + * + * \par Cause: + * + * A CFE SB transmit transaction has rejected a message due + * to failure of the associated message integrity action(s). + */ +#define CFE_SB_SEND_MESSAGE_INTEGRITY_FAIL_EID 71 + +/** + * \brief SB validation of received message failure event + * + * \par Type: ERROR + * + * \par Cause: + * + * A CFE SB receive transaction has rejected a message due + * to failure of the associated message integrity action(s). + */ +#define CFE_SB_RCV_MESSAGE_INTEGRITY_FAIL_EID 72 + /**\}*/ #endif /* CFE_SB_EVENTS_H */ diff --git a/modules/sb/fsw/src/cfe_sb_api.c b/modules/sb/fsw/src/cfe_sb_api.c index b4747f452..a2f4f3f5b 100644 --- a/modules/sb/fsw/src/cfe_sb_api.c +++ b/modules/sb/fsw/src/cfe_sb_api.c @@ -123,7 +123,8 @@ CFE_Status_t CFE_SB_CreatePipe(CFE_SB_PipeId_t *PipeIdPtr, uint16 Depth, const c CFE_ES_GetTaskID(&TskId); /* check input parameters */ - if ((PipeIdPtr == NULL) || (Depth > OS_QUEUE_MAX_DEPTH) || (Depth == 0) || (PipeName != NULL && PipeName[0] == '\0')) + if ((PipeIdPtr == NULL) || (Depth > OS_QUEUE_MAX_DEPTH) || (Depth == 0) || + (PipeName != NULL && PipeName[0] == '\0')) { PendingEventId = CFE_SB_CR_PIPE_BAD_ARG_EID; Status = CFE_SB_BAD_ARGUMENT; @@ -1535,8 +1536,10 @@ void CFE_SB_BroadcastBufferToRoute(CFE_SB_BufferD_t *BufDscPtr, CFE_SBR_RouteId_ uint32 i; char FullName[(OS_MAX_API_NAME * 2)]; char PipeName[OS_MAX_API_NAME]; + bool IsAcceptable; SBSndErr.EvtsToSnd = 0; + IsAcceptable = true; /* get app id for loopback testing */ CFE_ES_GetAppID(&AppId); @@ -1555,8 +1558,10 @@ void CFE_SB_BroadcastBufferToRoute(CFE_SB_BufferD_t *BufDscPtr, CFE_SBR_RouteId_ { CFE_SBR_IncrementSequenceCounter(RouteId); + CFE_MSG_SetSequenceCount(&BufDscPtr->Content.Msg, CFE_SBR_GetSequenceCounter(RouteId)); + /* Update all MSG headers based on the current sequence */ - CFE_MSG_UpdateHeader(&BufDscPtr->Content.Msg, CFE_SBR_GetSequenceCounter(RouteId)); + CFE_MSG_OriginationAction(&BufDscPtr->Content.Msg, BufDscPtr->ContentSize, &IsAcceptable); /* Clear the flag, just in case */ BufDscPtr->NeedsUpdate = false; diff --git a/modules/sb/ut-coverage/sb_UT.c b/modules/sb/ut-coverage/sb_UT.c index b31faa4e5..92436bdf3 100644 --- a/modules/sb/ut-coverage/sb_UT.c +++ b/modules/sb/ut-coverage/sb_UT.c @@ -3015,8 +3015,8 @@ void Test_TransmitMsg_UpdateHeader(void) memset(&TlmPkt, 0, sizeof(TlmPkt)); - /* Set up hook for checking CFE_MSG_UpdateHeader calls */ - UT_SetHookFunction(UT_KEY(CFE_MSG_UpdateHeader), UT_CheckSetSequenceCount, &SeqCnt); + /* Set up hook for checking CFE_MSG_OriginationAction calls */ + UT_SetHookFunction(UT_KEY(CFE_MSG_OriginationAction), UT_CheckSetSequenceCount, &SeqCnt); CFE_UtAssert_SETUP(CFE_SB_CreatePipe(&PipeId, PipeDepth, "SeqCntTestPipe")); CFE_UtAssert_SETUP(CFE_SB_Subscribe(MsgId, PipeId)); @@ -3029,7 +3029,7 @@ void Test_TransmitMsg_UpdateHeader(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &Type, sizeof(Type), false); CFE_UtAssert_SETUP(CFE_SB_TransmitMsg(CFE_MSG_PTR(TlmPkt.TelemetryHeader), true)); - UtAssert_STUB_COUNT(CFE_MSG_UpdateHeader, 1); + UtAssert_STUB_COUNT(CFE_MSG_OriginationAction, 1); UtAssert_STUB_COUNT(CFE_MSG_GetNextSequenceCount, 1); UtAssert_INT32_EQ(SeqCnt, SeqCntExpected); @@ -3040,7 +3040,7 @@ void Test_TransmitMsg_UpdateHeader(void) /* Assert sequence count wasn't set */ UtAssert_STUB_COUNT(CFE_MSG_GetNextSequenceCount, 1); - UtAssert_STUB_COUNT(CFE_MSG_UpdateHeader, 1); + UtAssert_STUB_COUNT(CFE_MSG_OriginationAction, 1); SeqCntExpected = 2; UT_SetDefaultReturnValue(UT_KEY(CFE_MSG_GetNextSequenceCount), SeqCntExpected); @@ -3049,7 +3049,7 @@ void Test_TransmitMsg_UpdateHeader(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &Type, sizeof(Type), false); CFE_UtAssert_SUCCESS(CFE_SB_TransmitMsg(CFE_MSG_PTR(TlmPkt.TelemetryHeader), true)); UtAssert_INT32_EQ(SeqCnt, SeqCntExpected); - UtAssert_STUB_COUNT(CFE_MSG_UpdateHeader, 2); + UtAssert_STUB_COUNT(CFE_MSG_OriginationAction, 2); UtAssert_STUB_COUNT(CFE_MSG_GetNextSequenceCount, 2); CFE_UtAssert_EVENTCOUNT(2); @@ -3063,7 +3063,7 @@ void Test_TransmitMsg_UpdateHeader(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetSize), &Size, sizeof(Size), false); UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &Type, sizeof(Type), false); CFE_UtAssert_SETUP(CFE_SB_TransmitMsg(CFE_MSG_PTR(TlmPkt.TelemetryHeader), true)); /* increment to 3 */ - UtAssert_STUB_COUNT(CFE_MSG_UpdateHeader, 3); + UtAssert_STUB_COUNT(CFE_MSG_OriginationAction, 3); UtAssert_STUB_COUNT(CFE_MSG_GetNextSequenceCount, 3); CFE_UtAssert_SETUP(CFE_SB_Subscribe(MsgId, PipeId)); /* resubscribe so we can receive a msg */ @@ -3075,7 +3075,7 @@ void Test_TransmitMsg_UpdateHeader(void) UT_SetDataBuffer(UT_KEY(CFE_MSG_GetType), &Type, sizeof(Type), false); CFE_UtAssert_SETUP(CFE_SB_TransmitMsg(CFE_MSG_PTR(TlmPkt.TelemetryHeader), true)); /* increment to 4 */ UtAssert_INT32_EQ(SeqCnt, SeqCntExpected); - UtAssert_STUB_COUNT(CFE_MSG_UpdateHeader, 4); + UtAssert_STUB_COUNT(CFE_MSG_OriginationAction, 4); UtAssert_STUB_COUNT(CFE_MSG_GetNextSequenceCount, 4); CFE_UtAssert_TEARDOWN(CFE_SB_DeletePipe(PipeId)); @@ -3326,8 +3326,8 @@ void Test_TransmitBuffer_IncrementSeqCnt(void) CFE_MSG_Size_t Size = sizeof(SB_UT_Test_Tlm_t); CFE_MSG_Type_t Type = CFE_MSG_Type_Tlm; - /* Set up hook for checking CFE_MSG_UpdateHeader calls */ - UT_SetHookFunction(UT_KEY(CFE_MSG_UpdateHeader), UT_CheckSetSequenceCount, &SeqCnt); + /* Set up hook for checking CFE_MSG_OriginationAction calls */ + UT_SetHookFunction(UT_KEY(CFE_MSG_OriginationAction), UT_CheckSetSequenceCount, &SeqCnt); CFE_UtAssert_SETUP(CFE_SB_CreatePipe(&PipeId, PipeDepth, "ZeroCpyTestPipe"));