[Git][NTPsec/ntpsec][master] 2 commits: libntp: make the ntp_endian helpers static inline
Gary E. Miller (@garyedmundsmiller)
gitlab at mg.gitlab.com
Thu Oct 15 20:06:13 UTC 2026
Gary E. Miller pushed to branch master at NTPsec / ntpsec
Commits:
5c8ae355 by Matt Selsky at 2026-10-15T02:10:37-04:00
libntp: make the ntp_endian helpers static inline
ntp_be16dec(), ntp_be32dec(), and ntp_be64dec() were out-of-line
functions in libntp, so every use was a call. As static inline functions
in ntp_endian.h, GCC and Clang compile each to a single load plus a byte
swap at -O2, the same code as memcpy() followed by ntohs(), ntohl(), or
be64toh().
pure is dropped since the compiler now sees the bodies.
The parameters are now uint8_t pointers, which every caller passes, so
the helpers need no local cast.
- - - - -
8d8ce136 by Matt Selsky at 2026-10-15T02:10:38-04:00
nts: read and write wire uint16s bytewise
The NTS wire helpers read and wrote 16-bit fields through a uint16_t
pointer cast of a byte buffer. NTS-KE record bodies can be any length,
so after an odd-length record (an unknown non-critical record from a
client, or an NTPv4 Server Negotiation hostname from a server) the next
header starts at an odd offset and the load is misaligned. Likewise, the
client echoes cookies of whatever length the NTS-KE server sent, so an
odd-length cookie misaligns every field the client writes after it.
That is undefined behavior. x86 and modern ARM usually tolerate it, but
strict-alignment CPUs such as SPARC raise SIGBUS, so there any client
could crash the NTS-KE server, and an NTS-KE server could crash its
clients.
Use ntp_be16dec() and a new inline ntp_be16enc() from ntp_endian.h in
find_end_marker(), ke_next_record(), ex_next_record(), next_uint16(),
append_header(), and append_uint16(). <arpa/inet.h> is no longer needed.
UBSan reported the misaligned load in ke_next_record() from test_ntpd.
- - - - -
5 changed files:
- include/ntp_endian.h
- − libntp/ntp_endian.c
- libntp/wscript
- ntpd/nts.c
- tests/libntp/ntp_endian.c
Changes:
=====================================
include/ntp_endian.h
=====================================
@@ -4,15 +4,29 @@
* SPDX-License-Identifier: BSD-2-Clause
*
* These are portable reimplementations of what BSD provides
- * in <sys/endian.h>.
+ * in <sys/endian.h>, but using uint8_t instead of void *.
*/
#ifndef GUARD_NTP_ENDIAN_H
#define GUARD_NTP_ENDIAN_H
#include <stdint.h>
-uint16_t ntp_be16dec(const void *buf) __attribute__((pure));
-uint32_t ntp_be32dec(const void *buf) __attribute__((pure));
-uint64_t ntp_be64dec(const void *buf) __attribute__((pure));
+static inline uint16_t ntp_be16dec(const uint8_t *buf) {
+ return (uint16_t)(((uint16_t)buf[0] << 8) | buf[1]);
+}
+
+static inline uint32_t ntp_be32dec(const uint8_t *buf) {
+ return ((uint32_t)buf[0] << 24) | ((uint32_t)buf[1] << 16) |
+ ((uint32_t)buf[2] << 8) | buf[3];
+}
+
+static inline uint64_t ntp_be64dec(const uint8_t *buf) {
+ return ((uint64_t)ntp_be32dec(buf) << 32) | ntp_be32dec(buf + 4);
+}
+
+static inline void ntp_be16enc(uint8_t *buf, uint16_t v) {
+ buf[0] = (uint8_t)(v >> 8);
+ buf[1] = (uint8_t)v;
+}
#endif
=====================================
libntp/ntp_endian.c deleted
=====================================
@@ -1,37 +0,0 @@
-/* ntp_endian.c - BSD-style big-endian encoding/decoding functions
- *
- * Copyright the NTPsec project contributors
- * SPDX-License-Identifier: BSD-2-Clause
- *
- * These are portable reimplementations of what BSD provides
- * in <sys/endian.h>.
- */
-
-#include <stdint.h>
-#include "ntp_endian.h"
-
-uint16_t ntp_be16dec(const void *buf) {
- const uint8_t *b = (const uint8_t*)buf;
- return ((uint16_t)(b[0]) << 8) +
- (uint16_t)(b[1]);
-}
-
-uint32_t ntp_be32dec(const void *buf) {
- const uint8_t *b = (const uint8_t*)buf;
- return ((uint32_t)(b[0]) << 24) +
- ((uint32_t)(b[1]) << 16) +
- ((uint32_t)(b[2]) << 8) +
- (uint32_t)(b[3]);
-}
-
-uint64_t ntp_be64dec(const void *buf) {
- const uint8_t *b = (const uint8_t*)buf;
- return ((uint64_t)(b[0]) << 56) +
- ((uint64_t)(b[1]) << 48) +
- ((uint64_t)(b[2]) << 40) +
- ((uint64_t)(b[3]) << 32) +
- ((uint64_t)(b[4]) << 24) +
- ((uint64_t)(b[5]) << 16) +
- ((uint64_t)(b[6]) << 8) +
- (uint64_t)(b[7]);
-}
=====================================
libntp/wscript
=====================================
@@ -22,7 +22,6 @@ def build(ctx):
"isc_net.c",
"macencrypt.c",
"md5.c",
- "ntp_endian.c",
"numtoa.c",
"refidsmear.c",
"socket.c",
=====================================
ntpd/nts.c
=====================================
@@ -20,9 +20,9 @@
#include <sys/stat.h>
#include <unistd.h>
-#include <arpa/inet.h>
#include <openssl/err.h>
+#include "ntp_endian.h"
#include "ntp_types.h"
#include "ntp_stdlib.h"
#include "ntpd.h"
@@ -292,9 +292,8 @@ bool nts_load_certificate(SSL_CTX *ctx) {
// scan partial(?) buffer for end marker
static bool find_end_marker(uint8_t *buff, int bytes) {
while (NTS_KE_HDR_LNG<=bytes) {
- uint16_t *buff16 = (uint16_t *)buff;
- uint16_t type = ntohs(*buff16++) & ~NTS_CRITICAL;
- uint16_t length = ntohs(*buff16++);
+ uint16_t type = ntp_be16dec(buff) & ~NTS_CRITICAL;
+ uint16_t length = ntp_be16dec(buff + NTS_KE_U16_LNG);
if (NTS_KE_HDR_LNG + length > bytes) return false;
if (nts_end_of_message == type) return true;
buff += NTS_KE_HDR_LNG + length;
@@ -446,21 +445,19 @@ void ex_append_header(BufCtl* buf, uint16_t type, uint16_t length) {
}
void append_header(BufCtl* buf, uint16_t type, uint16_t length) {
- uint16_t * ptr = (uint16_t *)buf->next;
if (NTS_KE_HDR_LNG > buf->left)
return;
- *ptr++ = htons(type);
- *ptr++ = htons(length);
+ ntp_be16enc(buf->next, type);
+ ntp_be16enc(buf->next + NTS_KE_U16_LNG, length);
buf->next += NTS_KE_HDR_LNG;
buf->left -= NTS_KE_HDR_LNG;
// leaves buf pointing to where data will go
}
void append_uint16(BufCtl* buf, uint16_t data) {
- uint16_t * ptr = (uint16_t *)buf->next;
if (NTS_KE_U16_LNG > buf->left)
return;
- *ptr++ = htons(data);
+ ntp_be16enc(buf->next, data);
buf->next += NTS_KE_U16_LNG;
buf->left -= NTS_KE_U16_LNG;
}
@@ -475,18 +472,16 @@ void append_bytes(BufCtl* buf, uint8_t *data, int length) {
// Reads type and length of the next record, and moves cursor to the data
uint16_t ke_next_record(BufCtl* buf, int *length) {
- uint16_t *ptr = (uint16_t *)buf->next;
- uint16_t type = ntohs(*ptr++);
- *length = ntohs(*ptr++);
+ uint16_t type = ntp_be16dec(buf->next);
+ *length = ntp_be16dec(buf->next + NTS_KE_U16_LNG);
buf->next += NTS_KE_HDR_LNG;
buf->left -= NTS_KE_HDR_LNG;
return type;
}
uint16_t ex_next_record(BufCtl* buf, int *length) {
- uint16_t *ptr = (uint16_t *)buf->next;
- uint16_t type = ntohs(*ptr++);
- *length = ntohs(*ptr++)-NTS_KE_HDR_LNG;
+ uint16_t type = ntp_be16dec(buf->next);
+ *length = ntp_be16dec(buf->next + NTS_KE_U16_LNG) - NTS_KE_HDR_LNG;
buf->next += NTS_KE_HDR_LNG;
buf->left -= NTS_KE_HDR_LNG;
return type;
@@ -494,8 +489,7 @@ uint16_t ex_next_record(BufCtl* buf, int *length) {
// Reads a uint16 from the record and advances to the next data
uint16_t next_uint16(BufCtl* buf) {
- uint16_t *ptr = (uint16_t *)buf->next;
- uint16_t data = ntohs(*ptr++);
+ uint16_t data = ntp_be16dec(buf->next);
buf->next += NTS_KE_U16_LNG;
buf->left -= NTS_KE_U16_LNG;
return data;
=====================================
tests/libntp/ntp_endian.c
=====================================
@@ -14,19 +14,19 @@ TEST_TEAR_DOWN(endian) {}
TEST(endian, Bit16) {
uint8_t buffer[2] = {0x22, 0x11};
- TEST_ASSERT_EQUAL(0x2211, ntp_be16dec((void *)buffer));
+ TEST_ASSERT_EQUAL(0x2211, ntp_be16dec(buffer));
}
TEST(endian, Bit32) {
uint8_t buffer[4] = {0x44, 0x33, 0x22, 0x11};
- TEST_ASSERT_EQUAL(0x44332211, ntp_be32dec((void *)buffer));
+ TEST_ASSERT_EQUAL(0x44332211, ntp_be32dec(buffer));
}
TEST(endian, Bit64) {
uint8_t buffer[8] = {0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11};
- TEST_ASSERT_EQUAL(0x8877665544332211, ntp_be64dec((void *)buffer));
+ TEST_ASSERT_EQUAL(0x8877665544332211, ntp_be64dec(buffer));
}
TEST_GROUP_RUNNER(endian) {
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/97be66b43ed90d64c1eb314fd91638fb78f05b5e...8d8ce13660c82cee2e8d5dafa557eb894e83b54c
--
View it on GitLab: https://gitlab.com/NTPsec/ntpsec/-/compare/97be66b43ed90d64c1eb314fd91638fb78f05b5e...8d8ce13660c82cee2e8d5dafa557eb894e83b54c
You're receiving this email because of your account on gitlab.com. Manage all notifications: https://gitlab.com/-/profile/notifications | Help: https://gitlab.com/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.ntpsec.org/pipermail/vc/attachments/20261015/1dd0b4c2/attachment-0001.htm>
More information about the vc
mailing list