19bool in_range(
const uint8_t *addr,
const uint8_t *lo,
const uint8_t *hi, uint8_t len)
21 return memcmp(addr, lo, len) >= 0 && memcmp(addr, hi, len) <= 0;
23bool port_in(uint16_t p, uint16_t lo, uint16_t hi)
25 return p >= lo && p <= hi;
31void pc_ipsec_spd_init(IpsecSpd *spd)
40bool pc_ipsec_spd_add(IpsecSpd *spd,
const IpsecSelector *sel, IpsecAction action, uint32_t sa_spi)
42 if (!spd || !sel || spd->count >= PC_IPSEC_SPD_MAX)
46 IpsecPolicy *p = &spd->entries[spd->count];
49 p->sa_spi = (action == IpsecAction::PROTECT) ? sa_spi : 0;
54bool pc_ipsec_selector_match(
const IpsecSelector *sel,
const IpsecFlow *flow)
56 if (!sel || !flow || !flow->src || !flow->dst)
60 if (sel->addr_len != flow->addr_len)
64 if (sel->addr_len != 4 && sel->addr_len != 16)
68 if (sel->ip_protocol != 0 && sel->ip_protocol != flow->ip_protocol)
72 if (!in_range(flow->src, sel->src_lo, sel->src_hi, sel->addr_len))
76 if (!in_range(flow->dst, sel->dst_lo, sel->dst_hi, sel->addr_len))
80 if (!port_in(flow->src_port, sel->src_port_lo, sel->src_port_hi))
84 if (!port_in(flow->dst_port, sel->dst_port_lo, sel->dst_port_hi))
91const IpsecPolicy *pc_ipsec_spd_lookup(
const IpsecSpd *spd,
const IpsecFlow *flow)
97 for (
size_t i = 0; i < spd->count; i++)
99 if (pc_ipsec_selector_match(&spd->entries[i].sel, flow))
101 return &spd->entries[i];
107bool pc_ipsec_selector_from_ts(IpsecSelector *out,
const IkeTrafficSelector *ts_src,
const IkeTrafficSelector *ts_dst)
109 if (!out || !ts_src || !ts_dst)
113 if (ts_src->ts_type != ts_dst->ts_type)
117 if (ts_src->addr_len != ts_dst->addr_len || (ts_src->addr_len != 4 && ts_src->addr_len != 16))
121 if (!ts_src->start_addr || !ts_src->end_addr || !ts_dst->start_addr || !ts_dst->end_addr)
126 if (ts_src->ip_protocol != 0 && ts_dst->ip_protocol != 0 && ts_src->ip_protocol != ts_dst->ip_protocol)
131 memset(out, 0,
sizeof(*out));
132 uint8_t len = (uint8_t)ts_src->addr_len;
134 out->ip_protocol = ts_src->ip_protocol ? ts_src->ip_protocol : ts_dst->ip_protocol;
135 memcpy(out->src_lo, ts_src->start_addr, len);
136 memcpy(out->src_hi, ts_src->end_addr, len);
137 memcpy(out->dst_lo, ts_dst->start_addr, len);
138 memcpy(out->dst_hi, ts_dst->end_addr, len);
139 out->src_port_lo = ts_src->start_port;
140 out->src_port_hi = ts_src->end_port;
141 out->dst_port_lo = ts_dst->start_port;
142 out->dst_port_hi = ts_dst->end_port;
148void pc_ipsec_sad_init(IpsecSad *sad)
155 for (
size_t i = 0; i < PC_IPSEC_SAD_MAX; i++)
157 sad->entries[i].valid =
false;
161IpsecSaEntry *pc_ipsec_sad_add(IpsecSad *sad, uint32_t spi,
const uint8_t *dst, uint8_t addr_len,
162 const uint8_t key[PC_ESP_KEY_LEN],
const uint8_t salt[PC_ESP_SALT_LEN],
bool inbound)
164 if (!sad || !dst || !key || !salt || (addr_len != 4 && addr_len != 16))
168 if (pc_ipsec_sad_find(sad, spi))
172 IpsecSaEntry *e =
nullptr;
173 for (
size_t i = 0; i < PC_IPSEC_SAD_MAX; i++)
175 if (!sad->entries[i].valid)
177 e = &sad->entries[i];
186 memset(e, 0,
sizeof(*e));
188 e->addr_len = addr_len;
189 memcpy(e->dst, dst, addr_len);
190 memcpy(e->key, key, PC_ESP_KEY_LEN);
191 memcpy(e->salt, salt, PC_ESP_SALT_LEN);
193 e->inbound = inbound;
196 pc_esp_replay_init(&e->replay);
203IpsecSaEntry *pc_ipsec_sad_find(IpsecSad *sad, uint32_t spi)
209 for (
size_t i = 0; i < PC_IPSEC_SAD_MAX; i++)
211 if (sad->entries[i].valid && sad->entries[i].spi == spi)
213 return &sad->entries[i];
219bool pc_ipsec_sad_remove(IpsecSad *sad, uint32_t spi)
221 IpsecSaEntry *e = pc_ipsec_sad_find(sad, spi);
226 memset(e, 0,
sizeof(*e));
235bool pc_ipsec_sad_next_seq(IpsecSaEntry *sa, uint32_t *seq_out)
241 if (sa->seq == 0xFFFFFFFFu)
IPsec Security Policy Database (SPD) + Security Association Database (SAD) - RFC 4301.