nts: refactor NTS context

Add a context structure for the algorithm and keys established by
NTS-KE. Modify the client to save the context and reset the SIV key to
the C2S/S2C key before each request/response instead of keeping two SIV
instances.

This will make it easier for the server to support different algorithms
and allow the client to save the context with cookies to disk.
This commit is contained in:
Miroslav Lichvar 2020-03-30 18:06:57 +02:00
parent 5296858411
commit adcf073484
10 changed files with 121 additions and 91 deletions

View file

@ -65,6 +65,12 @@ typedef struct {
unsigned char key[NKE_MAX_KEY_LENGTH]; unsigned char key[NKE_MAX_KEY_LENGTH];
} NKE_Key; } NKE_Key;
typedef struct {
SIV_Algorithm algorithm;
NKE_Key c2s;
NKE_Key s2c;
} NKE_Context;
typedef struct { typedef struct {
int length; int length;
unsigned char cookie[NKE_MAX_COOKIE_LENGTH]; unsigned char cookie[NKE_MAX_COOKIE_LENGTH];

View file

@ -49,8 +49,7 @@ struct NKC_Instance_Record {
int got_response; int got_response;
int resolving_name; int resolving_name;
SIV_Algorithm siv_algorithm; NKE_Context context;
NKE_Key c2s, s2c;
NKE_Cookie cookies[NKE_MAX_COOKIES]; NKE_Cookie cookies[NKE_MAX_COOKIES];
int num_cookies; int num_cookies;
char server_name[NKE_MAX_RECORD_BODY_LENGTH + 1]; char server_name[NKE_MAX_RECORD_BODY_LENGTH + 1];
@ -156,7 +155,7 @@ process_response(NKC_Instance inst)
break; break;
} }
aead_algorithm = AEAD_AES_SIV_CMAC_256; aead_algorithm = AEAD_AES_SIV_CMAC_256;
inst->siv_algorithm = aead_algorithm; inst->context.algorithm = aead_algorithm;
break; break;
case NKE_RECORD_ERROR: case NKE_RECORD_ERROR:
if (length == 2) if (length == 2)
@ -237,7 +236,8 @@ handle_message(void *arg)
return 0; return 0;
} }
if (!NKSN_GetKeys(inst->session, inst->siv_algorithm, &inst->c2s, &inst->s2c)) if (!NKSN_GetKeys(inst->session, inst->context.algorithm,
&inst->context.c2s, &inst->context.s2c))
return 0; return 0;
if (inst->server_name[0] != '\0') { if (inst->server_name[0] != '\0') {
@ -371,8 +371,7 @@ NKC_IsActive(NKC_Instance inst)
/* ================================================== */ /* ================================================== */
int int
NKC_GetNtsData(NKC_Instance inst, NKC_GetNtsData(NKC_Instance inst, NKE_Context *context,
SIV_Algorithm *siv_algorithm, NKE_Key *c2s, NKE_Key *s2c,
NKE_Cookie *cookies, int *num_cookies, int max_cookies, NKE_Cookie *cookies, int *num_cookies, int max_cookies,
IPSockAddr *ntp_address) IPSockAddr *ntp_address)
{ {
@ -381,9 +380,7 @@ NKC_GetNtsData(NKC_Instance inst,
if (!inst->got_response || inst->resolving_name) if (!inst->got_response || inst->resolving_name)
return 0; return 0;
*siv_algorithm = inst->siv_algorithm; *context = inst->context;
*c2s = inst->c2s;
*s2c = inst->s2c;
for (i = 0; i < inst->num_cookies && i < max_cookies; i++) for (i = 0; i < inst->num_cookies && i < max_cookies; i++)
cookies[i] = inst->cookies[i]; cookies[i] = inst->cookies[i];

View file

@ -50,8 +50,7 @@ extern int NKC_Start(NKC_Instance inst);
extern int NKC_IsActive(NKC_Instance inst); extern int NKC_IsActive(NKC_Instance inst);
/* Get the NTS data if the session was successful */ /* Get the NTS data if the session was successful */
extern int NKC_GetNtsData(NKC_Instance inst, extern int NKC_GetNtsData(NKC_Instance inst, NKE_Context *context,
SIV_Algorithm *siv_algorithm, NKE_Key *c2s, NKE_Key *s2c,
NKE_Cookie *cookies, int *num_cookies, int max_cookies, NKE_Cookie *cookies, int *num_cookies, int max_cookies,
IPSockAddr *ntp_address); IPSockAddr *ntp_address);

View file

@ -293,8 +293,8 @@ helper_signal(int x)
static int static int
prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_algorithm) prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_algorithm)
{ {
NKE_Context context;
NKE_Cookie cookie; NKE_Cookie cookie;
NKE_Key c2s, s2c;
uint16_t datum; uint16_t datum;
int i; int i;
@ -329,11 +329,13 @@ prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_a
return 0; return 0;
} }
if (!NKSN_GetKeys(session, aead_algorithm, &c2s, &s2c)) context.algorithm = aead_algorithm;
if (!NKSN_GetKeys(session, aead_algorithm, &context.c2s, &context.s2c))
return 0; return 0;
for (i = 0; i < NKE_MAX_COOKIES; i++) { for (i = 0; i < NKE_MAX_COOKIES; i++) {
if (!NKS_GenerateCookie(&c2s, &s2c, &cookie)) if (!NKS_GenerateCookie(&context, &cookie))
return 0; return 0;
if (!NKSN_AddRecord(session, 0, NKE_RECORD_COOKIE, cookie.cookie, cookie.length)) if (!NKSN_AddRecord(session, 0, NKE_RECORD_COOKIE, cookie.cookie, cookie.length))
return 0; return 0;
@ -679,7 +681,7 @@ NKS_Finalise(void)
/* A server cookie consists of key ID, nonce, and encrypted C2S+S2C keys */ /* A server cookie consists of key ID, nonce, and encrypted C2S+S2C keys */
int int
NKS_GenerateCookie(NKE_Key *c2s, NKE_Key *s2c, NKE_Cookie *cookie) NKS_GenerateCookie(NKE_Context *context, NKE_Cookie *cookie)
{ {
unsigned char plaintext[2 * NKE_MAX_KEY_LENGTH], *ciphertext; unsigned char plaintext[2 * NKE_MAX_KEY_LENGTH], *ciphertext;
int plaintext_length, tag_length; int plaintext_length, tag_length;
@ -691,8 +693,14 @@ NKS_GenerateCookie(NKE_Key *c2s, NKE_Key *s2c, NKE_Cookie *cookie)
return 0; return 0;
} }
if (c2s->length < 0 || c2s->length > NKE_MAX_KEY_LENGTH || /* The algorithm is hardcoded for now */
s2c->length < 0 || s2c->length > NKE_MAX_KEY_LENGTH) { if (context->algorithm != AEAD_AES_SIV_CMAC_256) {
DEBUG_LOG("Unexpected SIV algorithm");
return 0;
}
if (context->c2s.length < 0 || context->c2s.length > NKE_MAX_KEY_LENGTH ||
context->s2c.length < 0 || context->s2c.length > NKE_MAX_KEY_LENGTH) {
DEBUG_LOG("Invalid key length"); DEBUG_LOG("Invalid key length");
return 0; return 0;
} }
@ -705,10 +713,10 @@ NKS_GenerateCookie(NKE_Key *c2s, NKE_Key *s2c, NKE_Cookie *cookie)
header->key_id = key->id; header->key_id = key->id;
UTI_GetRandomBytes(header->nonce, sizeof (header->nonce)); UTI_GetRandomBytes(header->nonce, sizeof (header->nonce));
plaintext_length = c2s->length + s2c->length; plaintext_length = context->c2s.length + context->s2c.length;
assert(plaintext_length <= sizeof (plaintext)); assert(plaintext_length <= sizeof (plaintext));
memcpy(plaintext, c2s->key, c2s->length); memcpy(plaintext, context->c2s.key, context->c2s.length);
memcpy(plaintext + c2s->length, s2c->key, s2c->length); memcpy(plaintext + context->c2s.length, context->s2c.key, context->s2c.length);
tag_length = SIV_GetTagLength(key->siv); tag_length = SIV_GetTagLength(key->siv);
cookie->length = sizeof (*header) + plaintext_length + tag_length; cookie->length = sizeof (*header) + plaintext_length + tag_length;
@ -729,7 +737,7 @@ NKS_GenerateCookie(NKE_Key *c2s, NKE_Key *s2c, NKE_Cookie *cookie)
/* ================================================== */ /* ================================================== */
int int
NKS_DecodeCookie(NKE_Cookie *cookie, NKE_Key *c2s, NKE_Key *s2c) NKS_DecodeCookie(NKE_Cookie *cookie, NKE_Context *context)
{ {
unsigned char plaintext[2 * NKE_MAX_KEY_LENGTH], *ciphertext; unsigned char plaintext[2 * NKE_MAX_KEY_LENGTH], *ciphertext;
int ciphertext_length, plaintext_length, tag_length; int ciphertext_length, plaintext_length, tag_length;
@ -776,12 +784,14 @@ NKS_DecodeCookie(NKE_Cookie *cookie, NKE_Key *c2s, NKE_Key *s2c)
return 0; return 0;
} }
c2s->length = plaintext_length / 2; context->algorithm = AEAD_AES_SIV_CMAC_256;
s2c->length = plaintext_length / 2;
assert(c2s->length <= sizeof (c2s->key));
memcpy(c2s->key, plaintext, c2s->length); context->c2s.length = plaintext_length / 2;
memcpy(s2c->key, plaintext + c2s->length, s2c->length); context->s2c.length = plaintext_length / 2;
assert(context->c2s.length <= sizeof (context->c2s.key));
memcpy(context->c2s.key, plaintext, context->c2s.length);
memcpy(context->s2c.key, plaintext + context->c2s.length, context->s2c.length);
return 1; return 1;
} }

View file

@ -33,10 +33,10 @@
extern void NKS_Initialise(int scfilter_level); extern void NKS_Initialise(int scfilter_level);
extern void NKS_Finalise(void); extern void NKS_Finalise(void);
/* Generate a new NTS cookie containing the C2S and S2C keys */ /* Generate an NTS cookie with a given context */
extern int NKS_GenerateCookie(NKE_Key *c2s, NKE_Key *s2c, NKE_Cookie *cookie); extern int NKS_GenerateCookie(NKE_Context *context, NKE_Cookie *cookie);
/* Validate a cookie and extract the C2S and S2C keys */ /* Validate a cookie and decode the context */
extern int NKS_DecodeCookie(NKE_Cookie *cookie, NKE_Key *c2s, NKE_Key *s2c); extern int NKS_DecodeCookie(NKE_Cookie *cookie, NKE_Context *context);
#endif #endif

View file

@ -49,13 +49,14 @@ struct NNC_Instance_Record {
const IPSockAddr *ntp_address; const IPSockAddr *ntp_address;
IPSockAddr nts_address; IPSockAddr nts_address;
char *name; char *name;
SIV_Instance siv_c2s;
SIV_Instance siv_s2c;
NKC_Instance nke; NKC_Instance nke;
SIV_Instance siv;
int nke_attempts; int nke_attempts;
double next_nke_attempt; double next_nke_attempt;
double last_nke_success; double last_nke_success;
NKE_Context context;
NKE_Cookie cookies[NTS_MAX_COOKIES]; NKE_Cookie cookies[NTS_MAX_COOKIES];
int num_cookies; int num_cookies;
int cookie_index; int cookie_index;
@ -73,6 +74,8 @@ reset_instance(NNC_Instance inst)
inst->nke_attempts = 0; inst->nke_attempts = 0;
inst->next_nke_attempt = 0.0; inst->next_nke_attempt = 0.0;
inst->last_nke_success = 0.0; inst->last_nke_success = 0.0;
memset(&inst->context, 0, sizeof (inst->context));
inst->num_cookies = 0; inst->num_cookies = 0;
inst->cookie_index = 0; inst->cookie_index = 0;
inst->nak_response = 0; inst->nak_response = 0;
@ -93,8 +96,7 @@ NNC_CreateInstance(IPSockAddr *nts_address, const char *name, const IPSockAddr *
inst->ntp_address = ntp_address; inst->ntp_address = ntp_address;
inst->nts_address = *nts_address; inst->nts_address = *nts_address;
inst->name = name ? Strdup(name) : NULL; inst->name = name ? Strdup(name) : NULL;
inst->siv_c2s = NULL; inst->siv = NULL;
inst->siv_s2c = NULL;
inst->nke = NULL; inst->nke = NULL;
reset_instance(inst); reset_instance(inst);
@ -109,10 +111,8 @@ NNC_DestroyInstance(NNC_Instance inst)
{ {
if (inst->nke) if (inst->nke)
NKC_DestroyInstance(inst->nke); NKC_DestroyInstance(inst->nke);
if (inst->siv_c2s) if (inst->siv)
SIV_DestroyInstance(inst->siv_c2s); SIV_DestroyInstance(inst->siv);
if (inst->siv_s2c)
SIV_DestroyInstance(inst->siv_s2c);
Free(inst->name); Free(inst->name);
Free(inst); Free(inst);
@ -187,8 +187,6 @@ static int
get_nke_data(NNC_Instance inst) get_nke_data(NNC_Instance inst)
{ {
NTP_Remote_Address ntp_address; NTP_Remote_Address ntp_address;
SIV_Algorithm siv;
NKE_Key c2s, s2c;
double now; double now;
int got_data; int got_data;
@ -223,7 +221,7 @@ get_nke_data(NNC_Instance inst)
if (NKC_IsActive(inst->nke)) if (NKC_IsActive(inst->nke))
return 0; return 0;
got_data = NKC_GetNtsData(inst->nke, &siv, &c2s, &s2c, got_data = NKC_GetNtsData(inst->nke, &inst->context,
inst->cookies, &inst->num_cookies, NTS_MAX_COOKIES, inst->cookies, &inst->num_cookies, NTS_MAX_COOKIES,
&ntp_address); &ntp_address);
@ -240,17 +238,12 @@ get_nke_data(NNC_Instance inst)
inst->cookie_index = 0; inst->cookie_index = 0;
if (inst->siv_c2s) if (inst->siv)
SIV_DestroyInstance(inst->siv_c2s); SIV_DestroyInstance(inst->siv);
if (inst->siv_s2c)
SIV_DestroyInstance(inst->siv_s2c);
inst->siv_c2s = SIV_CreateInstance(siv); inst->siv = SIV_CreateInstance(inst->context.algorithm);
inst->siv_s2c = SIV_CreateInstance(siv);
if (!inst->siv_c2s || !inst->siv_s2c || if (!inst->siv) {
!SIV_SetKey(inst->siv_c2s, c2s.key, c2s.length) ||
!SIV_SetKey(inst->siv_s2c, s2c.key, s2c.length)) {
DEBUG_LOG("Could not initialise SIV"); DEBUG_LOG("Could not initialise SIV");
inst->num_cookies = 0; inst->num_cookies = 0;
return 0; return 0;
@ -273,6 +266,11 @@ NNC_PrepareForAuth(NNC_Instance inst)
return 0; return 0;
} }
if (!SIV_SetKey(inst->siv, inst->context.c2s.key, inst->context.c2s.length)) {
DEBUG_LOG("Could not set SIV key");
return 0;
}
UTI_GetRandomBytes(&inst->uniq_id, sizeof (inst->uniq_id)); UTI_GetRandomBytes(&inst->uniq_id, sizeof (inst->uniq_id));
UTI_GetRandomBytes(&inst->nonce, sizeof (inst->nonce)); UTI_GetRandomBytes(&inst->nonce, sizeof (inst->nonce));
@ -289,7 +287,7 @@ NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
int i, req_cookies; int i, req_cookies;
void *ef_body; void *ef_body;
if (inst->num_cookies == 0 || !inst->siv_c2s) if (inst->num_cookies == 0 || !inst->siv)
return 0; return 0;
if (info->mode != MODE_CLIENT) if (info->mode != MODE_CLIENT)
@ -314,7 +312,7 @@ NNC_GenerateRequestAuth(NNC_Instance inst, NTP_Packet *packet,
memset(ef_body, 0, cookie->length); memset(ef_body, 0, cookie->length);
} }
if (!NNA_GenerateAuthEF(packet, info, inst->siv_c2s, inst->nonce, sizeof (inst->nonce), if (!NNA_GenerateAuthEF(packet, info, inst->siv, inst->nonce, sizeof (inst->nonce),
(const unsigned char *)"", 0, NTP_MAX_V4_MAC_LENGTH + 4)) (const unsigned char *)"", 0, NTP_MAX_V4_MAC_LENGTH + 4))
return 0; return 0;
@ -384,8 +382,11 @@ NNC_CheckResponseAuth(NNC_Instance inst, NTP_Packet *packet,
if (inst->ok_response) if (inst->ok_response)
return 0; return 0;
if (!inst->siv_s2c) if (!inst->siv ||
!SIV_SetKey(inst->siv, inst->context.s2c.key, inst->context.s2c.length)) {
DEBUG_LOG("Could not set SIV key");
return 0; return 0;
}
for (parsed = NTP_HEADER_LENGTH; parsed < info->length; parsed += ef_length) { for (parsed = NTP_HEADER_LENGTH; parsed < info->length; parsed += ef_length) {
if (!NEF_ParseField(packet, info->length, parsed, if (!NEF_ParseField(packet, info->length, parsed,
@ -410,7 +411,7 @@ NNC_CheckResponseAuth(NNC_Instance inst, NTP_Packet *packet,
return 0; return 0;
} }
if (!NNA_DecryptAuthEF(packet, info, inst->siv_s2c, parsed, if (!NNA_DecryptAuthEF(packet, info, inst->siv, parsed,
plaintext, sizeof (plaintext), &plaintext_length)) plaintext, sizeof (plaintext), &plaintext_length))
return 0; return 0;

View file

@ -41,6 +41,8 @@
#include "siv.h" #include "siv.h"
#include "util.h" #include "util.h"
#define SERVER_SIV AEAD_AES_SIV_CMAC_256
struct NtsServer { struct NtsServer {
SIV_Instance siv; SIV_Instance siv;
unsigned char nonce[NTS_MIN_UNPADDED_NONCE_LENGTH]; unsigned char nonce[NTS_MIN_UNPADDED_NONCE_LENGTH];
@ -64,7 +66,7 @@ NNS_Initialise(void)
} }
server = Malloc(sizeof (struct NtsServer)); server = Malloc(sizeof (struct NtsServer));
server->siv = SIV_CreateInstance(AEAD_AES_SIV_CMAC_256); server->siv = SIV_CreateInstance(SERVER_SIV);
} }
/* ================================================== */ /* ================================================== */
@ -88,8 +90,8 @@ NNS_CheckRequestAuth(NTP_Packet *packet, NTP_PacketInfo *info, uint32_t *kod)
int ef_type, ef_body_length, ef_length, has_uniq_id = 0, has_auth = 0, has_cookie = 0; int ef_type, ef_body_length, ef_length, has_uniq_id = 0, has_auth = 0, has_cookie = 0;
int i, plaintext_length, parsed, requested_cookies, cookie_length = -1, auth_start = 0; int i, plaintext_length, parsed, requested_cookies, cookie_length = -1, auth_start = 0;
unsigned char plaintext[NTP_MAX_EXTENSIONS_LENGTH]; unsigned char plaintext[NTP_MAX_EXTENSIONS_LENGTH];
NKE_Context context;
NKE_Cookie cookie; NKE_Cookie cookie;
NKE_Key c2s, s2c;
void *ef_body; void *ef_body;
if (!server) if (!server)
@ -144,12 +146,17 @@ NNS_CheckRequestAuth(NTP_Packet *packet, NTP_PacketInfo *info, uint32_t *kod)
return 0; return 0;
} }
if (!NKS_DecodeCookie(&cookie, &c2s, &s2c)) { if (!NKS_DecodeCookie(&cookie, &context)) {
*kod = NTP_KOD_NTS_NAK; *kod = NTP_KOD_NTS_NAK;
return 0; return 0;
} }
if (!SIV_SetKey(server->siv, c2s.key, c2s.length)) { if (context.algorithm != SERVER_SIV) {
DEBUG_LOG("Unexpected SIV");
return 0;
}
if (!SIV_SetKey(server->siv, context.c2s.key, context.c2s.length)) {
DEBUG_LOG("Could not set C2S key"); DEBUG_LOG("Could not set C2S key");
return 0; return 0;
} }
@ -178,7 +185,7 @@ NNS_CheckRequestAuth(NTP_Packet *packet, NTP_PacketInfo *info, uint32_t *kod)
} }
} }
if (!SIV_SetKey(server->siv, s2c.key, s2c.length)) { if (!SIV_SetKey(server->siv, context.s2c.key, context.s2c.length)) {
DEBUG_LOG("Could not set S2C key"); DEBUG_LOG("Could not set S2C key");
return 0; return 0;
} }
@ -187,7 +194,7 @@ NNS_CheckRequestAuth(NTP_Packet *packet, NTP_PacketInfo *info, uint32_t *kod)
server->num_cookies = MIN(NTS_MAX_COOKIES, requested_cookies); server->num_cookies = MIN(NTS_MAX_COOKIES, requested_cookies);
for (i = 0; i < server->num_cookies; i++) for (i = 0; i < server->num_cookies; i++)
if (!NKS_GenerateCookie(&c2s, &s2c, &server->cookies[i])) if (!NKS_GenerateCookie(&context, &server->cookies[i]))
return 0; return 0;
return 1; return 1;

View file

@ -132,8 +132,8 @@ void
test_unit(void) test_unit(void)
{ {
NKSN_Instance session; NKSN_Instance session;
NKE_Context context, context2;
NKE_Cookie cookie; NKE_Cookie cookie;
NKE_Key c2s, s2c, c2s2, s2c2;
int i, valid, l; int i, valid, l;
uint32_t sum, sum2; uint32_t sum, sum2;
@ -167,14 +167,16 @@ test_unit(void)
for (i = 0; i < 10000; i++) { for (i = 0; i < 10000; i++) {
get_keys(session, AEAD_AES_SIV_CMAC_256, &c2s, &s2c); context.algorithm = AEAD_AES_SIV_CMAC_256;
get_keys(session, context.algorithm, &context.c2s, &context.s2c);
memset(&cookie, 0, sizeof (cookie)); memset(&cookie, 0, sizeof (cookie));
TEST_CHECK(NKS_GenerateCookie(&c2s, &s2c, &cookie)); TEST_CHECK(NKS_GenerateCookie(&context, &cookie));
TEST_CHECK(NKS_DecodeCookie(&cookie, &c2s2, &s2c2)); TEST_CHECK(NKS_DecodeCookie(&cookie, &context2));
TEST_CHECK(c2s.length == c2s2.length); TEST_CHECK(context.algorithm == context2.algorithm);
TEST_CHECK(s2c.length == s2c2.length); TEST_CHECK(context.c2s.length == context2.c2s.length);
TEST_CHECK(memcmp(c2s.key, c2s2.key, c2s.length) == 0); TEST_CHECK(context.s2c.length == context2.s2c.length);
TEST_CHECK(memcmp(s2c.key, s2c2.key, s2c.length) == 0); TEST_CHECK(memcmp(context.c2s.key, context2.c2s.key, context.c2s.length) == 0);
TEST_CHECK(memcmp(context.s2c.key, context2.s2c.key, context.s2c.length) == 0);
if (random() % 4) { if (random() % 4) {
cookie.cookie[random() % (cookie.length)]++; cookie.cookie[random() % (cookie.length)]++;
@ -185,7 +187,7 @@ test_unit(void)
while (l == cookie.length) while (l == cookie.length)
cookie.length = random() % (sizeof (cookie.cookie) + 1); cookie.length = random() % (sizeof (cookie.cookie) + 1);
} }
TEST_CHECK(!NKS_DecodeCookie(&cookie, &c2s2, &s2c2)); TEST_CHECK(!NKS_DecodeCookie(&cookie, &context2));
} }
unlink("ntskeys"); unlink("ntskeys");

View file

@ -32,27 +32,29 @@
#define NKC_Start(inst) (random() % 2) #define NKC_Start(inst) (random() % 2)
#define NKC_IsActive(inst) (random() % 2) #define NKC_IsActive(inst) (random() % 2)
static int get_nts_data(NKC_Instance inst, SIV_Algorithm *siv_algorithm, NKE_Key *c2s, NKE_Key *s2c, static int get_nts_data(NKC_Instance inst, NKE_Context *context,
NKE_Cookie *cookies, int *num_cookies, int max_cookies, IPSockAddr *ntp_address); NKE_Cookie *cookies, int *num_cookies, int max_cookies,
IPSockAddr *ntp_address);
#define NKC_GetNtsData get_nts_data #define NKC_GetNtsData get_nts_data
#include <nts_ntp_client.c> #include <nts_ntp_client.c>
static int static int
get_nts_data(NKC_Instance inst, SIV_Algorithm *siv_algorithm, NKE_Key *c2s, NKE_Key *s2c, get_nts_data(NKC_Instance inst, NKE_Context *context,
NKE_Cookie *cookies, int *num_cookies, int max_cookies, IPSockAddr *ntp_address) NKE_Cookie *cookies, int *num_cookies, int max_cookies,
IPSockAddr *ntp_address)
{ {
int i; int i;
if (random() % 2) if (random() % 2)
return 0; return 0;
*siv_algorithm = AEAD_AES_SIV_CMAC_256; context->algorithm = AEAD_AES_SIV_CMAC_256;
c2s->length = SIV_GetKeyLength(*siv_algorithm); context->c2s.length = SIV_GetKeyLength(context->algorithm);
UTI_GetRandomBytes(c2s->key, c2s->length); UTI_GetRandomBytes(context->c2s.key, context->c2s.length);
s2c->length = SIV_GetKeyLength(*siv_algorithm); context->s2c.length = SIV_GetKeyLength(context->algorithm);
UTI_GetRandomBytes(s2c->key, s2c->length); UTI_GetRandomBytes(context->s2c.key, context->s2c.length);
*num_cookies = random() % max_cookies + 1; *num_cookies = random() % max_cookies + 1;
for (i = 0; i < *num_cookies; i++) { for (i = 0; i < *num_cookies; i++) {
@ -89,8 +91,7 @@ get_request(NNC_Instance inst)
} }
TEST_CHECK(inst->num_cookies > 0); TEST_CHECK(inst->num_cookies > 0);
TEST_CHECK(inst->siv_c2s); TEST_CHECK(inst->siv);
TEST_CHECK(inst->siv_s2c);
memcpy(nonce, inst->nonce, sizeof (nonce)); memcpy(nonce, inst->nonce, sizeof (nonce));
memcpy(uniq_id, inst->uniq_id, sizeof (uniq_id)); memcpy(uniq_id, inst->uniq_id, sizeof (uniq_id));
@ -103,7 +104,7 @@ get_request(NNC_Instance inst)
(inst->cookies[inst->cookie_index].length + 4)); (inst->cookies[inst->cookie_index].length + 4));
expected_length = info.length + 4 + sizeof (inst->uniq_id) + expected_length = info.length + 4 + sizeof (inst->uniq_id) +
req_cookies * (4 + inst->cookies[inst->cookie_index].length) + req_cookies * (4 + inst->cookies[inst->cookie_index].length) +
4 + 4 + sizeof (inst->nonce) + SIV_GetTagLength(inst->siv_c2s); 4 + 4 + sizeof (inst->nonce) + SIV_GetTagLength(inst->siv);
DEBUG_LOG("length=%d cookie_length=%d expected_length=%d", DEBUG_LOG("length=%d cookie_length=%d expected_length=%d",
info.length, inst->cookies[inst->cookie_index].length, expected_length); info.length, inst->cookies[inst->cookie_index].length, expected_length);
@ -126,6 +127,7 @@ prepare_response(NNC_Instance inst, NTP_Packet *packet, NTP_PacketInfo *info, in
unsigned char cookie[508], plaintext[512], nonce[512]; unsigned char cookie[508], plaintext[512], nonce[512];
int nonce_length, cookie_length, plaintext_length, min_auth_length; int nonce_length, cookie_length, plaintext_length, min_auth_length;
int index, auth_start; int index, auth_start;
SIV_Instance siv;
memset(packet, 0, sizeof (*packet)); memset(packet, 0, sizeof (*packet));
packet->lvm = NTP_LVM(0, 4, MODE_SERVER); packet->lvm = NTP_LVM(0, 4, MODE_SERVER);
@ -175,10 +177,15 @@ prepare_response(NNC_Instance inst, NTP_Packet *packet, NTP_PacketInfo *info, in
TEST_CHECK(NEF_SetField(plaintext, sizeof (plaintext), 0, NTP_EF_NTS_COOKIE, TEST_CHECK(NEF_SetField(plaintext, sizeof (plaintext), 0, NTP_EF_NTS_COOKIE,
cookie, cookie_length, &plaintext_length)); cookie, cookie_length, &plaintext_length));
auth_start = info->length; auth_start = info->length;
if (index != 4) if (index != 4) {
TEST_CHECK(NNA_GenerateAuthEF(packet, info, inst->siv_s2c, siv = SIV_CreateInstance(inst->context.algorithm);
TEST_CHECK(siv);
TEST_CHECK(SIV_SetKey(siv, inst->context.s2c.key, inst->context.s2c.length));
TEST_CHECK(NNA_GenerateAuthEF(packet, info, siv,
nonce, nonce_length, plaintext, plaintext_length, nonce, nonce_length, plaintext, plaintext_length,
min_auth_length)); min_auth_length));
SIV_DestroyInstance(siv);
}
if (index == 5) if (index == 5)
((unsigned char *)packet)[auth_start + 8]++; ((unsigned char *)packet)[auth_start + 8]++;
} }

View file

@ -32,17 +32,18 @@ static void
prepare_request(NTP_Packet *packet, NTP_PacketInfo *info, int valid, int nak) prepare_request(NTP_Packet *packet, NTP_PacketInfo *info, int valid, int nak)
{ {
unsigned char uniq_id[NTS_MIN_UNIQ_ID_LENGTH], nonce[NTS_MIN_UNPADDED_NONCE_LENGTH]; unsigned char uniq_id[NTS_MIN_UNIQ_ID_LENGTH], nonce[NTS_MIN_UNPADDED_NONCE_LENGTH];
NKE_Key c2s, s2c;
SIV_Instance siv; SIV_Instance siv;
NKE_Context context;
NKE_Cookie cookie; NKE_Cookie cookie;
int i, index, cookie_start, auth_start; int i, index, cookie_start, auth_start;
c2s.length = SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256); context.algorithm = SERVER_SIV;
UTI_GetRandomBytes(&c2s.key, c2s.length); context.c2s.length = SIV_GetKeyLength(context.algorithm);
s2c.length = SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256); UTI_GetRandomBytes(&context.c2s.key, context.c2s.length);
UTI_GetRandomBytes(&s2c.key, s2c.length); context.s2c.length = SIV_GetKeyLength(context.algorithm);
UTI_GetRandomBytes(&context.s2c.key, context.s2c.length);
TEST_CHECK(NKS_GenerateCookie(&c2s, &s2c, &cookie)); TEST_CHECK(NKS_GenerateCookie(&context, &cookie));
UTI_GetRandomBytes(uniq_id, sizeof (uniq_id)); UTI_GetRandomBytes(uniq_id, sizeof (uniq_id));
UTI_GetRandomBytes(nonce, sizeof (nonce)); UTI_GetRandomBytes(nonce, sizeof (nonce));
@ -78,8 +79,8 @@ prepare_request(NTP_Packet *packet, NTP_PacketInfo *info, int valid, int nak)
auth_start = info->length; auth_start = info->length;
if (index != 2) { if (index != 2) {
siv = SIV_CreateInstance(AEAD_AES_SIV_CMAC_256); siv = SIV_CreateInstance(context.algorithm);
TEST_CHECK(SIV_SetKey(siv, c2s.key, c2s.length)); TEST_CHECK(SIV_SetKey(siv, context.c2s.key, context.c2s.length));
TEST_CHECK(NNA_GenerateAuthEF(packet, info, siv, nonce, sizeof (nonce), TEST_CHECK(NNA_GenerateAuthEF(packet, info, siv, nonce, sizeof (nonce),
(const unsigned char *)"", 0, 0)); (const unsigned char *)"", 0, 0));
SIV_DestroyInstance(siv); SIV_DestroyInstance(siv);