summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArchit Aggarwal <architag@amazon.com>2021-07-15 15:21:29 -0700
committerGitHub <noreply@github.com>2021-07-15 15:21:29 -0700
commitb550e6090d26a19dc72b390f64e7b6573c214ef1 (patch)
tree4e1fcd1f6295d137d07ec200ac4cff918197a688
parente38c279b22002e7dc788079eefb951db09f29a7e (diff)
downloadfreertos-git-b550e6090d26a19dc72b390f64e7b6573c214ef1.tar.gz
Add note in coreSNTP demo about Network Time Security (NTS) (#648)
This PR makes the following changes in the coreSNTP demo: To suggest the most secure way of using SNTP communication, we are adding a documentation note about the Network Time Security in the SNTP demo. Hygiene update of using the FreeRTOS/backoffAlgorithm utility library for calculating time polling period interval backoff when time requests are rejected by a time server.
-rwxr-xr-xFreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/DemoTasks/SNTPClientTask.c149
-rwxr-xr-xFreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/demo_config.h7
-rw-r--r--lexicon.txt5
3 files changed, 149 insertions, 12 deletions
diff --git a/FreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/DemoTasks/SNTPClientTask.c b/FreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/DemoTasks/SNTPClientTask.c
index 7a84f56de..a3497d463 100755
--- a/FreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/DemoTasks/SNTPClientTask.c
+++ b/FreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/DemoTasks/SNTPClientTask.c
@@ -31,13 +31,22 @@
*
* This file contains the SNTP client (daemon) task as well as functionality for
* maintaining wall-clock or UTC time in RAM. The SNTP client periodically synchronizes
- * system clock with an SNTP/NTP servers. Any other task running an application in the
+ * system clock with SNTP/NTP server(s). Any other task running an application in the
* system can query the system time. For an example of an application task querying time
* from the system, refer to the SampleAppTask.c file in this project.
*
- * !!! NOTE !!!
- * This SNTP demo does not authenticate the server nor the client.
- * Hence, this demo should not be used as production ready code.
+ * This demo shows how the coreSNTP library can be used to communicate with SNTP/NTP
+ * servers in a mutually authenticated through the use of symmetric-key based AES-128-CMAC
+ * algorithm. To run this demo with an SNTP/NTP server in authenticated mode, the AES-128-CMAC
+ * symmetric key needs to be pre-shared between the client (i.e. this demo) and the server.
+ *
+ * !!!Note!!!:
+ * Even though this demo shows the use of AES-128-CMAC, a symmetric-key cryptographic based
+ * solution, for authenticating SNTP communication between the demo (SNTP client) and
+ * SNTP/NTP server, we instead RECOMMEND that production devices use the most secure authentication
+ * mechanism alternative available with the Network Time Security (NTS) protocol, an asymmetric-key
+ * cryptographic protocol. For more information, refer to the NTS specification here:
+ * https://datatracker.ietf.org/doc/html/rfc8915
*/
/* Standard includes. */
@@ -70,6 +79,9 @@
#include "core_pkcs11_config.h"
#include "core_pkcs11.h"
+/* Backoff Algorithm include. */
+#include "backoff_algorithm.h"
+
/*-----------------------------------------------------------*/
/* Compile time error for undefined configs. */
@@ -120,7 +132,7 @@
* @note The size of the buffer MUST be large enough to hold an entire SNTP packet, which includes the standard SNTP
* packet data of 48 bytes and authentication data for security mechanism, if used, in communication with time server.
*/
-#define SNTP_CONTEXT_NETWORK_BUFFER_SIZE ( SNTP_PACKET_BASE_SIZE )
+#define SNTP_CONTEXT_NETWORK_BUFFER_SIZE ( SNTP_PACKET_BASE_SIZE )
/**
* @brief The constant for storing the number of milliseconds per FreeRTOS tick in the system.
@@ -129,13 +141,13 @@
* internet time or UTC time. Thus, the actual time duration value per tick of the system will be
* larger from the perspective of internet time.
*/
-#define MILLISECONDS_PER_TICK ( 1000 / configTICK_RATE_HZ )
+#define MILLISECONDS_PER_TICK ( 1000 / configTICK_RATE_HZ )
/**
* @brief The fixed size of the key for the AES-128-CMAC algorithm used for authenticating communication
* between the time server and the client.
*/
-#define AES_CMAC_AUTHENTICATION_KEY_SIZE ( 16 )
+#define AES_CMAC_AUTHENTICATION_KEY_SIZE ( 16 )
/**
* @brief The size of the "Key Identifier" field in the SNTP packet when symmetric key authentication mode as
@@ -147,7 +159,7 @@
* @note This demo uses the "Key Identifier" field to communicate with time servers that support authentication mechanism.
* This field is stored with the Key ID of the AES-128-CMAC based authentication key stored in the time server.
*/
-#define SNTP_PACKET_SYMMETRIC_KEY_ID_LENGTH 4
+#define SNTP_PACKET_SYMMETRIC_KEY_ID_LENGTH 4
/**
* @brief The offset for the starting byte of the "Key Identifier" field in an SNTPv4/NTPv4 packet.
@@ -156,7 +168,7 @@
* For more information of the SNTP packet format, refer to the SNTPv4 specification
* https://datatracker.ietf.org/doc/html/rfc4330#page-8
*/
-#define SNTP_PACKET_SYMMETRIC_KEY_ID_OFFSET SNTP_PACKET_BASE_SIZE
+#define SNTP_PACKET_SYMMETRIC_KEY_ID_OFFSET SNTP_PACKET_BASE_SIZE
/**
* @brief The total size of an SNTP packet (which remains same for both client request and server response in SNTP communication)
@@ -168,7 +180,26 @@
* For more information of the SNTP packet format, refer to the SNTPv4 specification
* https://datatracker.ietf.org/doc/html/rfc4330#page-8
*/
-#define SNTP_PACKET_AUTHENTICATED_MODE_SIZE ( SNTP_PACKET_BASE_SIZE + SNTP_PACKET_SYMMETRIC_KEY_ID_LENGTH + pkcs11AES_CMAC_SIGNATURE_LENGTH )
+#define SNTP_PACKET_AUTHENTICATED_MODE_SIZE ( SNTP_PACKET_BASE_SIZE + SNTP_PACKET_SYMMETRIC_KEY_ID_LENGTH + pkcs11AES_CMAC_SIGNATURE_LENGTH )
+
+/**
+ * @brief The maximum poll period that the SNTP client can use as back-off on receiving a rejection from a time server.
+ *
+ * @note This demo performs back-off in polling rate from time server ONLY for the case when a single time server being
+ * is configured through the democonfigLIST_OF_TIME_SERVERS macro.
+ * This is because when more than one time server is configured, the coreSNTP library automatically handles the case
+ * of server rejection of time request by rotating to the next configured server for subsequent time polling requests.
+ */
+#define SNTP_DEMO_POLL_MAX_BACKOFF_DELAY_SEC UINT16_MAX
+
+/**
+ * @brief The maximum number of times of retrying time requests at exponentially backed-off polling frequency
+ * from a server that rejects time requests.
+ *
+ * @note This macro is only relevant for the case when a single time server is configured in
+ * the demo through, democonfigLIST_OF_TIME_SERVERS.
+ */
+#define SNTP_DEMO_MAX_SERVER_BACKOFF_RETRIES 10
/*-----------------------------------------------------------*/
@@ -593,6 +624,31 @@ static bool createUdpSocket( Socket_t * pSocket );
*/
static void closeUdpSocket( Socket_t * pSocket );
+/**
+ * @brief Utility to calculate new poll period with exponential backoff and jitter
+ * algorithm.
+ *
+ * @note The demo applies time polling frequency backoff only when a single time server
+ * is configured, through the democonfigLIST_OF_SERVERS macro, and the single server
+ * rejects time requests.
+ *
+ * @param[in, out] pContext The context representing the back-off parameters. This
+ * context is initialized by the function whenever the caller indicates it with the
+ * @p shouldInitializeContext flag.
+ * @param[in] shouldInitializeContext Flag to indicate if the passed context should be
+ * initialized to start a new sequence of backed-off time request retries.
+ * @param[in] minPollPeriod The minimum poll period
+ * @param[in] pPollPeriod The new calculated poll period.
+ *
+ * @return Return #true if a new poll interval is calculated to retry time request
+ * from the server; #false otherwise to indicate exhaustion of time request retry attempts
+ * with the server.
+ */
+static bool calculateBackoffForNextPoll( BackoffAlgorithmContext_t * pContext,
+ bool shouldInitializeContext,
+ uint32_t minPollPeriod,
+ uint32_t * pPollPeriod );
+
/*------------------------------------------------------------------------------*/
static uint32_t translateYearToUnixSeconds( uint16_t year )
@@ -1379,6 +1435,46 @@ static void closeUdpSocket( Socket_t * pSocket )
/*-----------------------------------------------------------*/
+static bool calculateBackoffForNextPoll( BackoffAlgorithmContext_t * pBackoffContext,
+ bool shouldInitializeContext,
+ uint32_t minPollPeriod,
+ uint32_t * pPollPeriod )
+{
+ uint16_t newPollPeriod = 0U;
+ BackoffAlgorithmStatus_t status;
+
+ configASSERT( pBackoffContext != NULL );
+ configASSERT( pPollPeriod != NULL );
+
+ if( shouldInitializeContext == true )
+ {
+ /* Initialize reconnect attempts and interval.*/
+ BackoffAlgorithm_InitializeParams( &pBackoffContext,
+ minPollPeriod,
+ SNTP_DEMO_POLL_MAX_BACKOFF_DELAY_SEC,
+ SNTP_DEMO_MAX_SERVER_BACKOFF_RETRIES );
+ }
+
+ /* Generate a random number and calculate the new backoff poll period to wait before the next
+ * time poll attempt. */
+ status = BackoffAlgorithm_GetNextBackoff( &pBackoffContext, generateRandomNumber(), &newPollPeriod );
+
+ if( status == BackoffAlgorithmRetriesExhausted )
+ {
+ LogError( ( "All backed-off attempts of polling time server have expired: MaxAttempts=%d",
+ SNTP_DEMO_MAX_SERVER_BACKOFF_RETRIES ) );
+ }
+ else
+ {
+ /* Store the calculated backoff period as the new poll period. */
+ *pPollPeriod = newPollPeriod;
+ }
+
+ return( status == BackoffAlgorithmSuccess );
+}
+
+/*-----------------------------------------------------------*/
+
void sntpTask( void * pParameters )
{
SntpContext_t clientContext;
@@ -1411,6 +1507,13 @@ void sntpTask( void * pParameters )
* between client and server, if the server supports authentication. */
static SntpAuthContext_t authContext;
+ /* Context used for calculating backoff that is applied to polling interval when the configured
+ * time server rejects time request.
+ * Note: Backoff is applied to polling interval ONLY when a single server is configured in the demo
+ * because in the case of multiple server configurations, the coreSNTP library handles server
+ * rejection by rotating server. */
+ static BackoffAlgorithmContext_t backoffContext;
+
/* Initialize the authentication context for information for the first time server and its
* keys configured in the demo. */
populateAuthContextForServer( pTimeServers[ 0 ], &authContext );
@@ -1426,6 +1529,7 @@ void sntpTask( void * pParameters )
if( initStatus == true )
{
SntpStatus_t status;
+ bool backoffModeFlag = false;
/* Calculate Poll interval of SNTP client based on desired accuracy and clock tolerance of the system. */
status = Sntp_CalculatePollInterval( democonfigSYSTEM_CLOCK_TOLERANCE_PPM,
@@ -1433,7 +1537,7 @@ void sntpTask( void * pParameters )
&systemClock.pollPeriod );
configASSERT( status == SntpSuccess );
- LogDebug( ( "SNTP client polling interval calculated as %lus", systemClock.pollPeriod ) );
+ LogDebug( ( "Minimum SNTP client polling interval calculated as %lus", systemClock.pollPeriod ) );
LogInfo( ( "Initialized SNTP Client context. Starting SNTP client loop to poll time every %lu seconds",
systemClock.pollPeriod ) );
@@ -1475,17 +1579,38 @@ void sntpTask( void * pParameters )
* a single time server. */
if( ( status == SntpRejectedResponse ) && ( numOfServers == 1 ) )
{
+ bool backoffStatus = false;
+
+ /* Determine if this is the first back-off attempt we are making since the most recent server rejection
+ * for time request. */
+ bool firstBackoffAttempt = false;
+
+ if( backoffModeFlag == false )
+ {
+ firstBackoffAttempt = true;
+
+ /* Set the flag to indicate we are in back-off retry mode for requesting time from the server. */
+ backoffModeFlag = true;
+ }
+
LogInfo( ( "The single configured time server, %s, rejected time request. Backing-off before ",
"next time poll....", strlen( pTimeServers[ 0 ] ) ) );
/* Add exponential back-off to polling period. */
- systemClock.pollPeriod *= 2;
+ backoffStatus = calculateBackoffForNextPoll( &backoffContext,
+ firstBackoffAttempt,
+ systemClock.pollPeriod,
+ &systemClock.pollPeriod );
+ configASSERT( backoffStatus == true );
/* Wait for the increased poll interval before retrying request for time from server. */
vTaskDelay( pdMS_TO_TICKS( systemClock.pollPeriod * 1000 ) );
}
else
{
+ /* Reset flag to indicate that we are not backing-off for the next time poll. */
+ backoffModeFlag = false;
+
/* Wait for the poll interval period before the next iteration of time synchronization. */
vTaskDelay( pdMS_TO_TICKS( systemClock.pollPeriod * 1000 ) );
}
diff --git a/FreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/demo_config.h b/FreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/demo_config.h
index b3fd9a058..3f62b4dc9 100755
--- a/FreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/demo_config.h
+++ b/FreeRTOS-Plus/Demo/coreSNTP_Windows_Simulator/demo_config.h
@@ -109,6 +109,13 @@ extern void vLoggingPrintf( const char * pcFormatString,
* It is RECOMMENDED to use an authentication mechanism for protecting devices against server spoofing
* attacks.
*
+ * @note Even though this demo shows the use of AES-128-CMAC, a symmetric-key cryptographic based
+ * solution, for authenticating SNTP communication between the demo (SNTP client) and
+ * SNTP/NTP server, we instead RECOMMEND that production devices use the most secure authentication
+ * mechanism alternative available with the Network Time Security (NTS) protocol, an asymmetric-key
+ * cryptographic protocol. For more information, refer to the NTS specification here:
+ * https://datatracker.ietf.org/doc/html/rfc8915
+ *
* @note Please provide the 128-bit keys as comma separated list of hexadecimal strings in the order matching
* the list of time servers configured in democonfigLIST_OF_TIME_SERVERS configuration. If a time server does
* not support authentication, then NULL should be used to indicate use of no authentication mechanism for the
diff --git a/lexicon.txt b/lexicon.txt
index 887e1f091..2db8f8a84 100644
--- a/lexicon.txt
+++ b/lexicon.txt
@@ -705,6 +705,7 @@ filteration
findfirst
findobjects
fips
+firstbackoffattempt
fixme
flase
flasg
@@ -1226,6 +1227,7 @@ mingw
minilistitem
minimise
minimised
+minpollperiod
mips
misc
misra
@@ -1325,6 +1327,7 @@ nsec
nt
ntp
ntpdemo
+nts
nullptr
num
numaker
@@ -1611,6 +1614,7 @@ ppass
ppassword
ppc
ppcmessagetodisplay
+ppollperiod
ppr
pprivatekey
ppublishinfo
@@ -2206,6 +2210,7 @@ shadownamelength
shadowstatus
shasum
shigherprioritytaskwoken
+shouldinitializecontext
shouldn
shtml
sice