diff --git a/doc/chronyc.adoc b/doc/chronyc.adoc index 9f4e804..57300ee 100644 --- a/doc/chronyc.adoc +++ b/doc/chronyc.adoc @@ -610,6 +610,7 @@ be reported: * 13: AES128 * 14: AES256 * 15: AEAD-AES-SIV-CMAC-256 +* 30: AEAD-AES-128-GCM-SIV *KLen*::: This column shows the length of the key in bits. *Last*::: diff --git a/nts_ke_client.c b/nts_ke_client.c index 2ad8106..3891f71 100644 --- a/nts_ke_client.c +++ b/nts_ke_client.c @@ -102,16 +102,22 @@ static int prepare_request(NKC_Instance inst) { NKSN_Instance session = inst->session; - uint16_t datum; + uint16_t data[2]; + int length; NKSN_BeginMessage(session); - datum = htons(NKE_NEXT_PROTOCOL_NTPV4); - if (!NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, &datum, sizeof (datum))) + data[0] = htons(NKE_NEXT_PROTOCOL_NTPV4); + if (!NKSN_AddRecord(session, 1, NKE_RECORD_NEXT_PROTOCOL, data, sizeof (data[0]))) return 0; - datum = htons(AEAD_AES_SIV_CMAC_256); - if (!NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, &datum, sizeof (datum))) + length = 0; + if (SIV_GetKeyLength(AEAD_AES_128_GCM_SIV) > 0) + data[length++] = htons(AEAD_AES_128_GCM_SIV); + if (SIV_GetKeyLength(AEAD_AES_SIV_CMAC_256) > 0) + data[length++] = htons(AEAD_AES_SIV_CMAC_256); + if (!NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, data, + length * sizeof (data[0]))) return 0; if (!NKSN_EndMessage(session)) @@ -159,12 +165,14 @@ process_response(NKC_Instance inst) next_protocol = NKE_NEXT_PROTOCOL_NTPV4; break; case NKE_RECORD_AEAD_ALGORITHM: - if (length != 2 || ntohs(data[0]) != AEAD_AES_SIV_CMAC_256) { + if (length != 2 || (ntohs(data[0]) != AEAD_AES_SIV_CMAC_256 && + ntohs(data[0]) != AEAD_AES_128_GCM_SIV) || + SIV_GetKeyLength(ntohs(data[0])) <= 0) { DEBUG_LOG("Unexpected NTS-KE AEAD algorithm"); error = 1; break; } - aead_algorithm = AEAD_AES_SIV_CMAC_256; + aead_algorithm = ntohs(data[0]); inst->context.algorithm = aead_algorithm; break; case NKE_RECORD_ERROR: @@ -236,7 +244,7 @@ process_response(NKC_Instance inst) if (error || inst->num_cookies == 0 || next_protocol != NKE_NEXT_PROTOCOL_NTPV4 || - aead_algorithm != AEAD_AES_SIV_CMAC_256) + aead_algorithm < 0) return 0; return 1; diff --git a/test/unit/nts_ke_client.c b/test/unit/nts_ke_client.c index 72690bf..3100d1d 100644 --- a/test/unit/nts_ke_client.c +++ b/test/unit/nts_ke_client.c @@ -64,9 +64,12 @@ prepare_response(NKSN_Instance session, int valid) if (index != 5) { if (index == 6) - data[0] = htons(AEAD_AES_SIV_CMAC_256 + random() % 10 + 1); + do { + data[0] = htons(random() % 100); + } while (SIV_GetKeyLength(ntohs(data[0])) > 0); else - data[0] = htons(AEAD_AES_SIV_CMAC_256); + data[0] = htons(random() % 2 && SIV_GetKeyLength(AEAD_AES_128_GCM_SIV) > 0 ? + AEAD_AES_128_GCM_SIV : AEAD_AES_SIV_CMAC_256); if (index == 7) length = 3 + random() % 10; TEST_CHECK(NKSN_AddRecord(session, 1, NKE_RECORD_AEAD_ALGORITHM, data, length)); diff --git a/test/unit/nts_ntp_client.c b/test/unit/nts_ntp_client.c index c14fd41..7953413 100644 --- a/test/unit/nts_ntp_client.c +++ b/test/unit/nts_ntp_client.c @@ -50,7 +50,10 @@ get_nts_data(NKC_Instance inst, NKE_Context *context, if (random() % 2) return 0; - context->algorithm = AEAD_AES_SIV_CMAC_256; + do { + context->algorithm = AEAD_AES_SIV_CMAC_256 + random() % + (AEAD_AES_256_GCM_SIV - AEAD_AES_SIV_CMAC_256 + 10); + } while (SIV_GetKeyLength(context->algorithm) <= 0); context->c2s.length = SIV_GetKeyLength(context->algorithm); UTI_GetRandomBytes(context->c2s.key, context->c2s.length); @@ -75,9 +78,9 @@ static int get_request(NNC_Instance inst) { unsigned char nonce[NTS_MIN_UNPADDED_NONCE_LENGTH], uniq_id[NTS_MIN_UNIQ_ID_LENGTH]; + int nonce_length, expected_length, req_cookies; NTP_PacketInfo info; NTP_Packet packet; - int expected_length, req_cookies; memset(&packet, 0, sizeof (packet)); memset(&info, 0, sizeof (info)); @@ -100,6 +103,17 @@ get_request(NNC_Instance inst) TEST_CHECK(inst->num_cookies > 0); TEST_CHECK(inst->siv); + switch (inst->context.algorithm) { + case AEAD_AES_SIV_CMAC_256: + nonce_length = 16; + break; + case AEAD_AES_128_GCM_SIV: + nonce_length = 12; + break; + default: + assert(0); + } + memcpy(nonce, inst->nonce, sizeof (nonce)); memcpy(uniq_id, inst->uniq_id, sizeof (uniq_id)); TEST_CHECK(NNC_PrepareForAuth(inst)); @@ -111,9 +125,10 @@ get_request(NNC_Instance inst) (inst->cookies[inst->cookie_index].length + 4)); expected_length = info.length + 4 + sizeof (inst->uniq_id) + req_cookies * (4 + inst->cookies[inst->cookie_index].length) + - 4 + 4 + sizeof (inst->nonce) + SIV_GetTagLength(inst->siv); - DEBUG_LOG("length=%d cookie_length=%d expected_length=%d", - info.length, inst->cookies[inst->cookie_index].length, expected_length); + 4 + 4 + nonce_length + SIV_GetTagLength(inst->siv); + DEBUG_LOG("algo=%d length=%d cookie_length=%d expected_length=%d", + (int)inst->context.algorithm, info.length, + inst->cookies[inst->cookie_index].length, expected_length); if (info.length % 4 == 0 && info.length >= NTP_HEADER_LENGTH && inst->cookies[inst->cookie_index].length % 4 == 0 && @@ -162,7 +177,10 @@ prepare_response(NNC_Instance inst, NTP_Packet *packet, NTP_PacketInfo *info, in return; } - nonce_length = random() % (sizeof (nonce)) + 1; + nonce_length = SIV_GetMinNonceLength(inst->siv) + random() % + (MIN(SIV_GetMaxNonceLength(inst->siv), sizeof (nonce)) - + SIV_GetMinNonceLength(inst->siv) + 1); + assert(nonce_length >= 1 && nonce_length <= sizeof (nonce)); do { cookie_length = random() % (sizeof (cookie) + 1);