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.
pull/645/head^2
Archit Aggarwal 4 years ago committed by GitHub
parent e38c279b22
commit b550e6090d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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 ) );
}

@ -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

@ -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

Loading…
Cancel
Save