nts: fix error response to NTS-KE request

When the request has an unrecognized critical record before the
NEXT_PROTOCOL and AEAD_ALGORITHM records, respond with error 0
(unrecognized critical record) instead of 1 (bad request).

When the request has multiple NEXT_PROTOCOL or AEAD_ALGORITHM records,
respond with error 1 (bad request).
This commit is contained in:
Miroslav Lichvar 2020-07-23 15:46:57 +02:00
parent cc20ead3dc
commit 72bf3d26eb
2 changed files with 41 additions and 14 deletions

View file

@ -330,6 +330,15 @@ prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_a
datum = htons(error); datum = htons(error);
if (!NKSN_AddRecord(session, 1, NKE_RECORD_ERROR, &datum, sizeof (datum))) if (!NKSN_AddRecord(session, 1, NKE_RECORD_ERROR, &datum, sizeof (datum)))
return 0; return 0;
} else if (next_protocol < 0) {
if (!NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, NULL, 0))
return 0;
} else if (aead_algorithm < 0) {
datum = htons(next_protocol);
if (!NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, &datum, sizeof (datum)))
return 0;
if (!NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, NULL, 0))
return 0;
} else { } else {
datum = htons(next_protocol); datum = htons(next_protocol);
if (!NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, &datum, sizeof (datum))) if (!NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, &datum, sizeof (datum)))
@ -376,6 +385,8 @@ prepare_response(NKSN_Instance session, int error, int next_protocol, int aead_a
static int static int
process_request(NKSN_Instance session) process_request(NKSN_Instance session)
{ {
int next_protocol_records = 0, aead_algorithm_records = 0;
int next_protocol_values = 0, aead_algorithm_values = 0;
int next_protocol = -1, aead_algorithm = -1, error = -1; int next_protocol = -1, aead_algorithm = -1, error = -1;
int i, critical, type, length; int i, critical, type, length;
uint16_t data[NKE_MAX_RECORD_BODY_LENGTH / sizeof (uint16_t)]; uint16_t data[NKE_MAX_RECORD_BODY_LENGTH / sizeof (uint16_t)];
@ -383,7 +394,7 @@ process_request(NKSN_Instance session)
assert(NKE_MAX_RECORD_BODY_LENGTH % sizeof (uint16_t) == 0); assert(NKE_MAX_RECORD_BODY_LENGTH % sizeof (uint16_t) == 0);
assert(sizeof (uint16_t) == 2); assert(sizeof (uint16_t) == 2);
while (error == -1) { while (error < 0) {
if (!NKSN_GetRecord(session, &critical, &type, &length, &data, sizeof (data))) if (!NKSN_GetRecord(session, &critical, &type, &length, &data, sizeof (data)))
break; break;
@ -393,7 +404,11 @@ process_request(NKSN_Instance session)
error = NKE_ERROR_BAD_REQUEST; error = NKE_ERROR_BAD_REQUEST;
break; break;
} }
next_protocol_records++;
for (i = 0; i < MIN(length, sizeof (data)) / 2; i++) { for (i = 0; i < MIN(length, sizeof (data)) / 2; i++) {
next_protocol_values++;
if (ntohs(data[i]) == NKE_NEXT_PROTOCOL_NTPV4) if (ntohs(data[i]) == NKE_NEXT_PROTOCOL_NTPV4)
next_protocol = NKE_NEXT_PROTOCOL_NTPV4; next_protocol = NKE_NEXT_PROTOCOL_NTPV4;
} }
@ -403,7 +418,11 @@ process_request(NKSN_Instance session)
error = NKE_ERROR_BAD_REQUEST; error = NKE_ERROR_BAD_REQUEST;
break; break;
} }
aead_algorithm_records++;
for (i = 0; i < MIN(length, sizeof (data)) / 2; i++) { for (i = 0; i < MIN(length, sizeof (data)) / 2; i++) {
aead_algorithm_values++;
if (ntohs(data[i]) == AEAD_AES_SIV_CMAC_256) if (ntohs(data[i]) == AEAD_AES_SIV_CMAC_256)
aead_algorithm = AEAD_AES_SIV_CMAC_256; aead_algorithm = AEAD_AES_SIV_CMAC_256;
} }
@ -419,8 +438,12 @@ process_request(NKSN_Instance session)
} }
} }
if (aead_algorithm < 0 || next_protocol < 0) if (error < 0) {
error = NKE_ERROR_BAD_REQUEST; if (next_protocol_records != 1 || next_protocol_values < 1 ||
(next_protocol == NKE_NEXT_PROTOCOL_NTPV4 &&
(aead_algorithm_records != 1 || aead_algorithm_values < 1)))
error = NKE_ERROR_BAD_REQUEST;
}
if (!prepare_response(session, error, next_protocol, aead_algorithm)) if (!prepare_response(session, error, next_protocol, aead_algorithm))
return 0; return 0;

View file

@ -50,7 +50,7 @@ prepare_request(NKSN_Instance session, int valid)
if (valid) if (valid)
index = -1; index = -1;
else else
index = random() % 7; index = random() % 9;
DEBUG_LOG("index=%d", index); DEBUG_LOG("index=%d", index);
NKSN_BeginMessage(session); NKSN_BeginMessage(session);
@ -61,30 +61,34 @@ prepare_request(NKSN_Instance session, int valid)
if (index != 0) { if (index != 0) {
memset(data, NKE_NEXT_PROTOCOL_NTPV4 + 1, sizeof (data)); memset(data, NKE_NEXT_PROTOCOL_NTPV4 + 1, sizeof (data));
data[0] = htons(NKE_NEXT_PROTOCOL_NTPV4);
if (index == 1) if (index == 1)
data[0] = htons(NKE_NEXT_PROTOCOL_NTPV4 + random() % 10 + 1); length = 0;
else else if (index == 2)
data[0] = htons(NKE_NEXT_PROTOCOL_NTPV4);
if (index == 2)
length = 3 + random() % 15 * 2; length = 3 + random() % 15 * 2;
else else
length = 2 + random() % 16 * 2; length = 2 + random() % 16 * 2;
TEST_CHECK(NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, data, length)); TEST_CHECK(NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, data, length));
} }
if (index != 3) { if (index == 3)
if (index == 4) TEST_CHECK(NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, data, length));
data[0] = htons(AEAD_AES_SIV_CMAC_256 + random() % 10 + 1);
else if (index != 4) {
data[0] = htons(AEAD_AES_SIV_CMAC_256); data[0] = htons(AEAD_AES_SIV_CMAC_256);
if (index == 5) if (index == 5)
length = 0;
else if (index == 6)
length = 3 + random() % 15 * 2; length = 3 + random() % 15 * 2;
else else
length = 2 + random() % 16 * 2; length = 2 + random() % 16 * 2;
TEST_CHECK(NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, data, length)); TEST_CHECK(NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, data, length));
} }
if (index == 6) { if (index == 7)
TEST_CHECK(NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, data, length));
if (index == 8) {
length = random() % (sizeof (data) + 1); length = random() % (sizeof (data) + 1);
TEST_CHECK(NKSN_AddRecord(session, 1, 1000 + random() % 1000, data, length)); TEST_CHECK(NKSN_AddRecord(session, 1, 1000 + random() % 1000, data, length));
} }