19#define PC_NATD_INPUT_MAX (PC_IKE_SPI_LEN + PC_IKE_SPI_LEN + 16 + 2)
22size_t natd_input(uint8_t *buf,
const uint8_t *init_spi,
const uint8_t *resp_spi,
const uint8_t *ip,
size_t ip_len,
25 if (!init_spi || !resp_spi || !ip || (ip_len != 4 && ip_len != 16))
30 memcpy(buf + n, init_spi, PC_IKE_SPI_LEN);
32 memcpy(buf + n, resp_spi, PC_IKE_SPI_LEN);
34 memcpy(buf + n, ip, ip_len);
36 buf[n++] = (uint8_t)(port >> 8);
37 buf[n++] = (uint8_t)port;
42size_t pc_ike_natd_hash(
const uint8_t init_spi[PC_IKE_SPI_LEN],
const uint8_t resp_spi[PC_IKE_SPI_LEN],
43 const uint8_t *ip,
size_t ip_len, uint16_t port, uint8_t out[PC_IKE_NATD_HASH_LEN])
49 uint8_t in[PC_NATD_INPUT_MAX];
50 size_t n = natd_input(in, init_spi, resp_spi, ip, ip_len, port);
56 return PC_IKE_NATD_HASH_LEN;
59size_t pc_ike_natd_source_build(uint8_t *buf,
size_t cap, IkePayloadType next_payload,
60 const uint8_t init_spi[PC_IKE_SPI_LEN],
const uint8_t resp_spi[PC_IKE_SPI_LEN],
61 const uint8_t *src_ip,
size_t ip_len, uint16_t src_port)
63 uint8_t hash[PC_IKE_NATD_HASH_LEN];
64 if (pc_ike_natd_hash(init_spi, resp_spi, src_ip, ip_len, src_port, hash) == 0)
68 return pc_ike_notify_build(buf, cap, next_payload, IkeProtocol::IKE_PROTO_NONE,
nullptr, 0,
69 PC_IKE_N_NAT_DETECTION_SOURCE_IP, hash, PC_IKE_NATD_HASH_LEN);
72size_t pc_ike_natd_dest_build(uint8_t *buf,
size_t cap, IkePayloadType next_payload,
73 const uint8_t init_spi[PC_IKE_SPI_LEN],
const uint8_t resp_spi[PC_IKE_SPI_LEN],
74 const uint8_t *dst_ip,
size_t ip_len, uint16_t dst_port)
76 uint8_t hash[PC_IKE_NATD_HASH_LEN];
77 if (pc_ike_natd_hash(init_spi, resp_spi, dst_ip, ip_len, dst_port, hash) == 0)
81 return pc_ike_notify_build(buf, cap, next_payload, IkeProtocol::IKE_PROTO_NONE,
nullptr, 0,
82 PC_IKE_N_NAT_DETECTION_DESTINATION_IP, hash, PC_IKE_NATD_HASH_LEN);
85bool pc_ike_natd_match(
const uint8_t init_spi[PC_IKE_SPI_LEN],
const uint8_t resp_spi[PC_IKE_SPI_LEN],
86 const uint8_t *ip,
size_t ip_len, uint16_t port,
const uint8_t *hash)
92 uint8_t expect[PC_IKE_NATD_HASH_LEN];
93 if (pc_ike_natd_hash(init_spi, resp_spi, ip, ip_len, port, expect) == 0)
97 return memcmp(expect, hash, PC_IKE_NATD_HASH_LEN) == 0;
100bool pc_ike_natd_peer_behind_nat(
const uint8_t init_spi[PC_IKE_SPI_LEN],
const uint8_t resp_spi[PC_IKE_SPI_LEN],
101 const uint8_t *observed_src_ip,
size_t ip_len, uint16_t observed_src_port,
102 const uint8_t *received_source_hash)
104 return !pc_ike_natd_match(init_spi, resp_spi, observed_src_ip, ip_len, observed_src_port, received_source_hash);
107bool pc_ike_natd_self_behind_nat(
const uint8_t init_spi[PC_IKE_SPI_LEN],
const uint8_t resp_spi[PC_IKE_SPI_LEN],
108 const uint8_t *local_ip,
size_t ip_len, uint16_t local_port,
109 const uint8_t *received_dest_hash)
111 return !pc_ike_natd_match(init_spi, resp_spi, local_ip, ip_len, local_port, received_dest_hash);
114bool pc_natt_is_keepalive(
const uint8_t *p,
size_t len)
116 return p && len == 1 && p[0] == PC_NATT_KEEPALIVE_BYTE;
119bool pc_natt_is_ike(
const uint8_t *p,
size_t len)
121 if (!p || len < PC_NATT_NON_ESP_MARKER_LEN)
126 return p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0;
IKEv2 NAT traversal - NAT detection (RFC 7296 §2.23) + UDP-encapsulation demux (RFC 3948).
PC_CRYPTO_HOT void pc_sha1(const uint8_t *data, size_t len, uint8_t digest[PC_SHA1_DIGEST_LEN])
Compute a SHA-1 digest over an arbitrary byte buffer.
SHA-1 (FIPS 180-4) - one-shot digest.