mirror of
https://github.com/FreeRTOS/FreeRTOS.git
synced 2025-06-23 09:27:46 +08:00
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.
This commit is contained in:
@ -31,13 +31,22 @@
|
|||||||
*
|
*
|
||||||
* This file contains the SNTP client (daemon) task as well as functionality for
|
* 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
|
* 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
|
* 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.
|
* from the system, refer to the SampleAppTask.c file in this project.
|
||||||
*
|
*
|
||||||
* !!! NOTE !!!
|
* This demo shows how the coreSNTP library can be used to communicate with SNTP/NTP
|
||||||
* This SNTP demo does not authenticate the server nor the client.
|
* servers in a mutually authenticated through the use of symmetric-key based AES-128-CMAC
|
||||||
* Hence, this demo should not be used as production ready code.
|
* 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. */
|
/* Standard includes. */
|
||||||
@ -70,6 +79,9 @@
|
|||||||
#include "core_pkcs11_config.h"
|
#include "core_pkcs11_config.h"
|
||||||
#include "core_pkcs11.h"
|
#include "core_pkcs11.h"
|
||||||
|
|
||||||
|
/* Backoff Algorithm include. */
|
||||||
|
#include "backoff_algorithm.h"
|
||||||
|
|
||||||
/*-----------------------------------------------------------*/
|
/*-----------------------------------------------------------*/
|
||||||
|
|
||||||
/* Compile time error for undefined configs. */
|
/* Compile time error for undefined configs. */
|
||||||
@ -170,6 +182,25 @@
|
|||||||
*/
|
*/
|
||||||
#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 );
|
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 )
|
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 )
|
void sntpTask( void * pParameters )
|
||||||
{
|
{
|
||||||
SntpContext_t clientContext;
|
SntpContext_t clientContext;
|
||||||
@ -1411,6 +1507,13 @@ void sntpTask( void * pParameters )
|
|||||||
* between client and server, if the server supports authentication. */
|
* between client and server, if the server supports authentication. */
|
||||||
static SntpAuthContext_t authContext;
|
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
|
/* Initialize the authentication context for information for the first time server and its
|
||||||
* keys configured in the demo. */
|
* keys configured in the demo. */
|
||||||
populateAuthContextForServer( pTimeServers[ 0 ], &authContext );
|
populateAuthContextForServer( pTimeServers[ 0 ], &authContext );
|
||||||
@ -1426,6 +1529,7 @@ void sntpTask( void * pParameters )
|
|||||||
if( initStatus == true )
|
if( initStatus == true )
|
||||||
{
|
{
|
||||||
SntpStatus_t status;
|
SntpStatus_t status;
|
||||||
|
bool backoffModeFlag = false;
|
||||||
|
|
||||||
/* Calculate Poll interval of SNTP client based on desired accuracy and clock tolerance of the system. */
|
/* Calculate Poll interval of SNTP client based on desired accuracy and clock tolerance of the system. */
|
||||||
status = Sntp_CalculatePollInterval( democonfigSYSTEM_CLOCK_TOLERANCE_PPM,
|
status = Sntp_CalculatePollInterval( democonfigSYSTEM_CLOCK_TOLERANCE_PPM,
|
||||||
@ -1433,7 +1537,7 @@ void sntpTask( void * pParameters )
|
|||||||
&systemClock.pollPeriod );
|
&systemClock.pollPeriod );
|
||||||
configASSERT( status == SntpSuccess );
|
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",
|
LogInfo( ( "Initialized SNTP Client context. Starting SNTP client loop to poll time every %lu seconds",
|
||||||
systemClock.pollPeriod ) );
|
systemClock.pollPeriod ) );
|
||||||
@ -1475,17 +1579,38 @@ void sntpTask( void * pParameters )
|
|||||||
* a single time server. */
|
* a single time server. */
|
||||||
if( ( status == SntpRejectedResponse ) && ( numOfServers == 1 ) )
|
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 ",
|
LogInfo( ( "The single configured time server, %s, rejected time request. Backing-off before ",
|
||||||
"next time poll....", strlen( pTimeServers[ 0 ] ) ) );
|
"next time poll....", strlen( pTimeServers[ 0 ] ) ) );
|
||||||
|
|
||||||
/* Add exponential back-off to polling period. */
|
/* 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. */
|
/* Wait for the increased poll interval before retrying request for time from server. */
|
||||||
vTaskDelay( pdMS_TO_TICKS( systemClock.pollPeriod * 1000 ) );
|
vTaskDelay( pdMS_TO_TICKS( systemClock.pollPeriod * 1000 ) );
|
||||||
}
|
}
|
||||||
else
|
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. */
|
/* Wait for the poll interval period before the next iteration of time synchronization. */
|
||||||
vTaskDelay( pdMS_TO_TICKS( systemClock.pollPeriod * 1000 ) );
|
vTaskDelay( pdMS_TO_TICKS( systemClock.pollPeriod * 1000 ) );
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,13 @@ extern void vLoggingPrintf( const char * pcFormatString,
|
|||||||
* It is RECOMMENDED to use an authentication mechanism for protecting devices against server spoofing
|
* It is RECOMMENDED to use an authentication mechanism for protecting devices against server spoofing
|
||||||
* attacks.
|
* 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
|
* @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
|
* 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
|
* not support authentication, then NULL should be used to indicate use of no authentication mechanism for the
|
||||||
|
@ -705,6 +705,7 @@ filteration
|
|||||||
findfirst
|
findfirst
|
||||||
findobjects
|
findobjects
|
||||||
fips
|
fips
|
||||||
|
firstbackoffattempt
|
||||||
fixme
|
fixme
|
||||||
flase
|
flase
|
||||||
flasg
|
flasg
|
||||||
@ -1226,6 +1227,7 @@ mingw
|
|||||||
minilistitem
|
minilistitem
|
||||||
minimise
|
minimise
|
||||||
minimised
|
minimised
|
||||||
|
minpollperiod
|
||||||
mips
|
mips
|
||||||
misc
|
misc
|
||||||
misra
|
misra
|
||||||
@ -1325,6 +1327,7 @@ nsec
|
|||||||
nt
|
nt
|
||||||
ntp
|
ntp
|
||||||
ntpdemo
|
ntpdemo
|
||||||
|
nts
|
||||||
nullptr
|
nullptr
|
||||||
num
|
num
|
||||||
numaker
|
numaker
|
||||||
@ -1611,6 +1614,7 @@ ppass
|
|||||||
ppassword
|
ppassword
|
||||||
ppc
|
ppc
|
||||||
ppcmessagetodisplay
|
ppcmessagetodisplay
|
||||||
|
ppollperiod
|
||||||
ppr
|
ppr
|
||||||
pprivatekey
|
pprivatekey
|
||||||
ppublishinfo
|
ppublishinfo
|
||||||
@ -2206,6 +2210,7 @@ shadownamelength
|
|||||||
shadowstatus
|
shadowstatus
|
||||||
shasum
|
shasum
|
||||||
shigherprioritytaskwoken
|
shigherprioritytaskwoken
|
||||||
|
shouldinitializecontext
|
||||||
shouldn
|
shouldn
|
||||||
shtml
|
shtml
|
||||||
sice
|
sice
|
||||||
|
Reference in New Issue
Block a user