[Git][NTPsec/ntpsec][master] 3 commits: Add unresolved issues section to nts.adoc.

Eric S. Raymond gitlab at mg.gitlab.com
Wed Feb 6 02:13:04 UTC 2019


Eric S. Raymond pushed to branch master at NTPsec / ntpsec


Commits:
b20431c8 by James Browning at 2019-02-05T18:00:15Z
Add unresolved issues section to nts.adoc.

- - - - -
79491d27 by James Browning at 2019-02-05T18:24:52Z
nts_lib foundation

- - - - -
033d512f by James Browning at 2019-02-05T20:05:56Z
NTS records handling 1

- - - - -


7 changed files:

- devel/nts.adoc
- + include/nts_lib.h
- + ntpd/nts_lib.c
- ntpd/wscript
- tests/common/tests_main.c
- + tests/ntpd/nts_lib.c
- tests/wscript


Changes:

=====================================
devel/nts.adoc
=====================================
@@ -569,6 +569,12 @@ the hexadecimal timestamps and such.
 ...
 ----
 
+== Unresolved issues for the next RFC revision
+
+The binary KE request-response format is unfortunate for all the usual
+reasons (endianness issues etc). At the expected transaction volume,
+the encode/decode overhead shouldn't be an issue.
+
 == Martin Langer's notes == 
 
 um... maybe the first hint... The current OpenSSL version doesn't


=====================================
include/nts_lib.h
=====================================
@@ -0,0 +1,110 @@
+#ifndef GUARD_NTS_LIB_H
+#define GUARD_NTS_LIB_H
+
+#include <linux/types.h>
+#include <openssl/evp.h>
+#include <stdbool.h>
+
+typedef struct {
+  void *key_c2s;
+  void *key_s2c;
+  void *nonce;
+  char *plaintext;
+  void *ciphertext;
+  char *cookie;
+  void *iv;
+  void *bit; // pointer for mempcpy, upf
+  __u8 addr_peer[16];
+
+  int tally;
+
+  __u16 size_iv;
+  __u16 size_key_csc;
+  __u16 size_nonce;
+  __u16 size_ciphertext;
+  __u16 size_plaintext;
+  __u16 nts_algo;
+  __u16 cookie_key_id;
+  __u16 recipe;
+  __u16 countdown;
+  __u16 now; // network order word
+} cookie_bits;
+
+typedef struct {
+  __u8 *next;
+  __u8 *record;
+  __u8 *body;
+  __u8 *bit; // pointer for mempcpy, upf
+
+  __u16 body_length;
+  __u16 record_type;
+  __u16 record_length;
+  __u16 now; // network order word
+  bool critical;
+} record_bits;
+
+enum record_type {
+  end_of_message = 0,
+  next_protocol_negotiation = 1,
+  error = 2,
+  warning = 3,
+  algorithm_negotiation = 4,
+  new_cookie = 5,
+  server_negotiation = 6,
+  port_negotiation = 7
+};
+
+enum errors_type {
+  unrecognized_critical_section = 0,
+  bad_request = 1
+};
+
+enum aead_ciphers {
+  AEAD_AES_128_GCM = 1,
+  AEAD_AES_256_GCM = 2,
+  AEAD_AES_128_CCM = 3,
+  AEAD_AES_256_CCM = 4,
+
+  AEAD_AES_128_GCM_8 = 5,
+  AEAD_AES_256_GCM_8 = 6,
+  AEAD_AES_128_GCM_12 = 7,
+  AEAD_AES_256_GCM_12 = 8,
+
+  AEAD_AES_128_CCM_SHORT = 9,
+  AEAD_AES_256_CCM_SHORT = 10,
+  AEAD_AES_128_CCM_SHORT_8 = 11,
+  AEAD_AES_256_CCM_SHORT_8 = 12,
+  AEAD_AES_128_CCM_SHORT_12 = 13,
+  AEAD_AES_256_CCM_SHORT_12 = 14,
+
+  AEAD_AES_SIV_CMAC_256 = 15,
+  AEAD_AES_SIV_CMAC_384 = 16,
+  AEAD_AES_SIV_CMAC_512 = 17,
+
+  AEAD_AES_128_CCM_8 = 18,
+  AEAD_AES_256_CCM_8 = 19,
+
+  AEAD_AES_128_OCB_TAGLEN128 = 20,
+  AEAD_AES_128_OCB_TAGLEN96 = 21,
+  AEAD_AES_128_OCB_TAGLEN64 = 22,
+  AEAD_AES_192_OCB_TAGLEN128 = 23,
+  AEAD_AES_192_OCB_TAGLEN96 = 24,
+  AEAD_AES_192_OCB_TAGLEN64 = 25,
+  AEAD_AES_256_OCB_TAGLEN128 = 26,
+  AEAD_AES_256_OCB_TAGLEN96 = 27,
+  AEAD_AES_256_OCB_TAGLEN64 = 28,
+
+  AEAD_CHACHA20_POLY1305 = 29
+};
+
+extern __u8 *upf(void *src, void *dest, size_t n);
+
+extern int nts_record_form(record_bits *in);
+extern int nts_record_parse(record_bits *in);
+
+extern int nts_cookie_prep(cookie_bits *input);
+extern int nts_cookie_clean(cookie_bits *a);
+extern int nts_cookie_plaintext_parse(cookie_bits *out);
+extern int nts_cookie_plaintext_form(cookie_bits *in);
+
+#endif // GUARD_NTS_LIB_H
\ No newline at end of file


=====================================
ntpd/nts_lib.c
=====================================
@@ -0,0 +1,114 @@
+#include "nts_lib.h"
+#include "config.h"
+#include "nts_lib.h"
+#include "ntp_types.h"
+#include "ntpd.h"
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <string.h>
+
+// a binary unpack function it should sort of reverse mempcpy
+__u8 *upf(void *src, void *dest, size_t n) {
+  (void)memcpy(dest, src, n);
+  return (__u8 *)src + n;
+}
+
+/* parse an NTS record to retrieve the body, body_length and record_type
+ *
+ * Assumes the record field is set to an appropriate value.
+ *
+ * sets the record_length, record_type and body fields
+ *
+ * returns 0 on success
+ */
+int nts_record_parse(record_bits *in) {
+  in->bit = upf(in->record, &in->now, sizeof(__u16));
+
+  if (0x80 & in->record[0]) {
+     in->critical = true;
+     in->now &= htons(~0x8000);
+  }
+  in->record_type = ntohs(in->now);
+
+  in->bit = upf(in->bit, &in->now, sizeof(__u16));
+  in->body_length = ntohs(in->now);
+  if (0 != in->body_length) {
+    in->body = in->bit;
+    in->bit += in->body_length;
+  } else {
+    in->body = NULL;
+  }
+  return 0;
+}
+
+/* form an NTS record
+ *
+ * Assumes the record_length, record_type and body fields are set to appropriate
+ * values
+ *
+ * sets the record_length and record fields.
+ *
+ * returns 0 on success
+ * returns 1 on memory allcation failure;
+ */
+int nts_record_form(record_bits *in) {
+  in->record_length = (4 + in->body_length);
+  in->record = malloc(in->record_length);
+  if (NULL == in->record) {
+    return 1;
+  }
+  in->now = htons(in->record_type);
+  if (in->critical) {
+    in->now |= htons(0x8000);
+  }
+  in->bit = mempcpy(in->record, &in->now, sizeof(__u16));
+  in->now = htons(in->body_length);
+  in->bit = mempcpy(in->bit, &in->now, sizeof(__u16));
+  if (0 < in->body_length) {
+    in->bit = mempcpy(in->bit, in->body, in->body_length);
+  }
+  return 0;
+}
+
+// Allocate & initialize structure & fields for NTS cookie generation/parsing
+int nts_cookie_prep(cookie_bits *input) {
+  UNUSED_ARG(input);
+  return 0;
+}
+
+// Free (most) storage used by NTS cookie generation/parsing routines
+int nts_cookie_clean(cookie_bits *a) {
+  UNUSED_ARG(a);
+  return 0;
+}
+
+/* Parse the plaintext to retrieve the AEAD algorithm to use when processing,
+ * the c2s key used to decipher the AEAF extension from the client and the
+ * s2c key used to encipher the AEAF extension returned to the client.
+ *
+ * Assumes the plaintext and recipe fields are set.
+ *
+ * Sets the key_c2s, key_s2c and size_key_csc fields
+ * optionally sets fields addr_peer and countdown
+ *
+ * returns number of bytes remaining in the plaintext (should be 0)
+ */
+int nts_cookie_plaintext_parse(cookie_bits *out) {
+  UNUSED_ARG(out);
+  return 0;
+}
+
+/* Form the cookie plaintext from the AEAD algorithm number, the c2s key and
+ * the sc key extracted during the NTS-KE session.
+ *
+ * Assumes the key_c2s, key_s2c, recipe and size_key_csc fields are set
+ * optionally uses fields addr_peer and countdown
+ *
+ * sets the plaintext and size_plaintext fields.
+ *
+ * returns 0 on success
+ */
+int nts_cookie_plaintext_form(cookie_bits *in) {
+  UNUSED_ARG(in);
+  return 0;
+}


=====================================
ntpd/wscript
=====================================
@@ -57,6 +57,7 @@ def build(ctx):
         "ntp_restrict.c",
         "ntp_util.c",
         "nts.c",
+        "nts_lib.c",
     ]
 
     ctx(


=====================================
tests/common/tests_main.c
=====================================
@@ -73,6 +73,7 @@ static void RunAllTests(void)
 	RUN_TEST_GROUP(leapsec);
 	RUN_TEST_GROUP(hackrestrict);
 	RUN_TEST_GROUP(recvbuff);
+	RUN_TEST_GROUP(nts_lib);
 #endif
 
 }


=====================================
tests/ntpd/nts_lib.c
=====================================
@@ -0,0 +1,293 @@
+#include "nts_lib.h"
+#include "unity.h"
+#include "unity_fixture.h"
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+TEST_GROUP(nts_lib);
+
+TEST_SETUP(nts_lib) {}
+
+TEST_TEAR_DOWN(nts_lib) {}
+
+TEST(nts_lib, record_decode_null) {
+  __u8 expected[4] = {0x80, 0, 0, 0};
+  record_bits *record;
+
+  record = calloc(1, sizeof(record_bits));
+  if (NULL == record) {
+    TEST_FAIL_MESSAGE("record malloc");
+    return;
+  }
+  record->record = malloc(4);
+  if (NULL == record->record) {
+    TEST_FAIL_MESSAGE("record value malloc");
+    return;
+  }
+  memcpy(record->record, expected, 4);
+  record->record_length = 4;
+
+  nts_record_parse(record);
+
+  TEST_ASSERT_TRUE(record->critical);
+  TEST_ASSERT_EQUAL_INT16(0, record->record_type);
+  TEST_ASSERT_EQUAL_INT16(0, record->body_length);
+  TEST_ASSERT_NULL(record->body);
+  record->body = NULL;
+
+  free(record->record);
+  free(record);
+}
+
+TEST(nts_lib, record_decode_u16) {
+  __u8 expected[6] = {0, port_negotiation, 0, 2, 0, 123};
+  record_bits *record;
+  int lints[1];
+
+  record = calloc(1, sizeof(record_bits));
+  if (NULL == record) {
+    TEST_FAIL_MESSAGE("record malloc");
+    return;
+  }
+  record->record = malloc(6);
+  if (NULL == record->record) {
+    TEST_FAIL_MESSAGE("record value malloc");
+    return;
+  }
+  memcpy(record->record, expected, 6);
+  record->record_length = 6;
+
+  nts_record_parse(record);
+  if (record->body_length & 1) {
+    TEST_FAIL_MESSAGE("odd byte out");
+  }
+  memcpy(lints, record->body, 2);
+
+  TEST_ASSERT_FALSE(record->critical);
+  TEST_ASSERT_EQUAL_INT16(port_negotiation, record->record_type);
+  TEST_ASSERT_EQUAL_INT16(2, record->body_length);
+  TEST_ASSERT_NOT_NULL(record->body);
+
+  TEST_ASSERT_EQUAL_INT16(123, ntohs(lints[0]));
+  record->body = NULL;
+
+  free(record->record);
+  free(record);
+}
+
+TEST(nts_lib, record_decode_u16s) {
+  __u8 expected[8] = {0, algorithm_negotiation, 0, 4,
+                      0, AEAD_AES_SIV_CMAC_512, 0, AEAD_CHACHA20_POLY1305};
+  record_bits *record;
+  int lints[2];
+  void *there;
+
+  record = calloc(1, sizeof(record_bits));
+  if (NULL == record) {
+    TEST_FAIL_MESSAGE("record malloc");
+    return;
+  }
+  record->record = malloc(8);
+  if (NULL == record->record) {
+    TEST_FAIL_MESSAGE("record value malloc");
+    return;
+  }
+  memcpy(record->record, expected, 8);
+  record->record_length = 8;
+
+  nts_record_parse(record);
+  there = record->body;
+  if (record->body_length & 1) {
+    TEST_FAIL_MESSAGE("odd byte out");
+  }
+  for (int count = 0; (count * 2) < record->body_length; count++) {
+    there = upf(there, &lints[count], 2);
+  }
+
+  TEST_ASSERT_FALSE(record->critical);
+  TEST_ASSERT_EQUAL_INT16(algorithm_negotiation, record->record_type);
+  TEST_ASSERT_EQUAL_INT16(4, record->body_length);
+  TEST_ASSERT_NOT_NULL(record->body);
+
+  TEST_ASSERT_EQUAL_INT16(AEAD_AES_SIV_CMAC_512, ntohs(lints[0]));
+  TEST_ASSERT_EQUAL_INT16(AEAD_CHACHA20_POLY1305, ntohs(lints[1]));
+  record->body = NULL;
+
+  free(record->record);
+  free(record);
+}
+
+TEST(nts_lib, record_decode_text) {
+  record_bits *record;
+  const char *expserv = "asus.internal.jamesb192.com";
+  __u8 expected[31] = {0,   server_negotiation,
+                       0,   27,
+                       'a', 's', 'u', 's', '.', 'i', 'n', 't', 'e',
+                       'r', 'n', 'a', 'l', '.', 'j', 'a', 'm', 'e',
+                       's', 'b', '1', '9', '2', '.', 'c', 'o', 'm'
+                      };
+  record = calloc(1, sizeof(record_bits));
+  if (NULL == record) {
+    TEST_FAIL_MESSAGE("record malloc");
+    return;
+  }
+  record->record = malloc(31);
+  if (NULL == record->record) {
+    TEST_FAIL_MESSAGE("record value malloc");
+    return;
+  }
+  memcpy(record->record, expected, 31);
+  record->record_length = 31;
+
+  nts_record_parse(record);
+
+  TEST_ASSERT_FALSE(record->critical);
+  TEST_ASSERT_EQUAL_INT16(server_negotiation, record->record_type);
+  TEST_ASSERT_EQUAL_INT16(27, record->body_length);
+  TEST_ASSERT_NOT_NULL(record->body);
+
+  TEST_ASSERT_EQUAL_STRING_LEN(expserv, record->body, 27);
+  record->body = NULL;
+
+  free(record->record);
+  free(record);
+}
+
+TEST(nts_lib, record_encode_null) {
+  __u8 expected[4] = {0x80, end_of_message, 0, 0};
+  record_bits *record;
+
+  record = calloc(1, sizeof(record_bits));
+  if (NULL == record) {
+    TEST_FAIL_MESSAGE("record malloc");
+    return;
+  }
+  record->critical = true;
+  record->body_length = 0;
+  record->record_type = end_of_message;
+
+  nts_record_form(record);
+
+  TEST_ASSERT_EQUAL_UINT16(4, record->record_length);
+  TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, record->record, 4);
+
+  free(record->body);
+  free(record);
+}
+TEST(nts_lib, record_encode_u16) {
+  __u8 expected[6] = {0, port_negotiation, 0, 2, 0, 123};
+  __u16 exp_port = htons(123);
+  record_bits *record;
+
+  record = calloc(1, sizeof(record_bits));
+  if (NULL == record) {
+    TEST_FAIL_MESSAGE("record malloc");
+    return;
+  }
+  record->critical = false;
+  record->body_length = 2;
+  record->record_type = port_negotiation;
+  record->body = malloc(2);
+  if (NULL == record->body) {
+    TEST_FAIL_MESSAGE("body malloc");
+    return;
+  }
+  memcpy(record->body, &exp_port, 2);
+
+  nts_record_form(record);
+
+  TEST_ASSERT_EQUAL_UINT16(6, record->record_length);
+  TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, record->record, 6);
+
+  free(record->body);
+  free(record);
+}
+
+TEST(nts_lib, record_encode_u16s) {
+  __u8 expected[8] = {0, algorithm_negotiation, 0, 4, 0, 2, 0, 4};
+  __u16 exp_algos[2] = {htons(2), htons(4)};
+  record_bits *record;
+
+  record = calloc(1, sizeof(record_bits));
+  if (NULL == record) {
+    TEST_FAIL_MESSAGE("record malloc");
+    return;
+  }
+  record->critical = false;
+  record->body_length = 4;
+  record->record_type = algorithm_negotiation;
+  record->body = malloc(4);
+  if (NULL == record->body) {
+    TEST_FAIL_MESSAGE("body malloc");
+    return;
+  }
+  memcpy(record->body, &exp_algos, 4);
+
+  nts_record_form(record);
+
+  TEST_ASSERT_EQUAL_UINT16(8, record->record_length);
+  TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, record->record, 8);
+
+  free(record->body);
+  free(record);
+}
+
+TEST(nts_lib, record_encode_text) {
+  const char *expserv = "asus.internal.jamesb192.com";
+  __u8 expected[31] = {  0,  server_negotiation,
+                         0,  27,
+                       'a', 's', 'u', 's', '.', 'i', 'n', 't', 'e',
+                       'r', 'n', 'a', 'l', '.', 'j', 'a', 'm', 'e',
+                       's', 'b', '1', '9', '2', '.', 'c', 'o', 'm'
+                      };
+  record_bits *record;
+
+  record = calloc(1, sizeof(record_bits));
+  if (NULL == record) {
+    TEST_FAIL_MESSAGE("record malloc");
+    return;
+  }
+  record->critical = false;
+  record->body_length = 27;
+  record->record_type = server_negotiation;
+  record->body = malloc(27);
+  if (NULL == record->body) {
+    TEST_FAIL_MESSAGE("body calloc");
+    return;
+  }
+  memcpy(record->body, expserv, 27);
+
+  nts_record_form(record);
+
+  TEST_ASSERT_EQUAL_UINT16(31, record->record_length);
+  TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, record->record, 31);
+
+  free(record->body);
+  free(record);
+}
+
+/*TEST(nts_lib, existance) {
+  TEST_ASSERT_NOT_NULL(upf);
+  TEST_ASSERT_NOT_NULL(nts_record_form)
+  TEST_ASSERT_NOT_NULL(nts_record_parse)
+  TEST_ASSERT_NOT_NULL(nts_cookie_prep);
+  TEST_ASSERT_NOT_NULL(nts_cookie_clean);
+  TEST_ASSERT_NOT_NULL(nts_cookie_plaintext_parse);
+  TEST_ASSERT_NOT_NULL(nts_cookie_plaintext_form);
+}*/
+
+TEST_GROUP_RUNNER(nts_lib) {
+//  RUN_TEST_CASE(nts_lib, existance);
+
+  RUN_TEST_CASE(nts_lib, record_decode_null);
+  RUN_TEST_CASE(nts_lib, record_decode_u16);
+  RUN_TEST_CASE(nts_lib, record_decode_u16s);
+  RUN_TEST_CASE(nts_lib, record_decode_text);
+
+  RUN_TEST_CASE(nts_lib, record_encode_null);
+  RUN_TEST_CASE(nts_lib, record_encode_u16);
+  RUN_TEST_CASE(nts_lib, record_encode_u16s);
+  RUN_TEST_CASE(nts_lib, record_encode_text);
+}


=====================================
tests/wscript
=====================================
@@ -101,6 +101,7 @@ def build(ctx):
         "ntpd/leapsec.c",
         "ntpd/restrict.c",
         "ntpd/recvbuff.c",
+        "ntpd/nts_lib.c"
     ] + common_source
 
     ctx.ntp_test(



View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/52536ed60e319a5c3918b4cf1eef3df21788ec86...033d512f8a56d5234f162bb4d0a58b21fb55a532

-- 
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/compare/52536ed60e319a5c3918b4cf1eef3df21788ec86...033d512f8a56d5234f162bb4d0a58b21fb55a532
You're receiving this email because of your account on gitlab.com.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20190206/83d7d99d/attachment-0001.html>


More information about the vc mailing list