Issue #3072

Windows 10: setting WFP SA SPI fails with error 0x80320014

Added by Valtteri Vuorikoski over 1 year ago. Updated over 1 year ago.

Affected version:


When attempting to establish an IPv6 transport mode SA (as initiator) on Windows 10 Pro build 17763 and strongSwan 4.8.0, WFP SA configuration fails:

16[IKE] IKE_SA test[1] established between 2001:<omitted>:1[CN=foo]...2001:<omitted>:2[CN=bar]
16[IKE] scheduling rekeying in 14359s
16[IKE] maximum IKE_SA lifetime 15799s
16[CFG] selected proposal: ESP:AES_CBC_128/HMAC_SHA2_256_128/NO_EXT_SEQ
16[KNL] setting WFP SA SPI failed: 0x80320014
16[IKE] unable to install IPsec policies (SPD) in kernel
16[IKE] failed to establish CHILD_SA, keeping IKE_SA

Config is as follows:

connections {
    niemivalas {
        version = 2

        local_addrs = %any
        remote_addrs = 2001:<omitted>:2

        proposals = aes128-sha256-modp2048
        mobike = no
        dpd_delay = 60s
        rekey_time = 4h

        local {
            certs = server.crt
            auth = pubkey

        remote {
            id = %any
            cacerts = ca.crt
            auth = pubkey

        children {
            transport {
                esp_proposals = aes128-sha256
                mode = transport
                start_action = start

The other end is strongSwan 4.5.2 running on Linux. Essentially the same configuration works with IKEEXT as well as with Linux and macOS hosts running strongSwan. Patch for issue has been applied to resolve error 0x80320035. I spent a while staring at SPI numbers used by IKEEXT and couldn't see any other obvious structure than the one described in that ticket.

Same issue occurs with both strongSwan cross-compiled on Ubuntu 18.04 as well as native compilation with MSYS2 (latest mingw64), both using 64-bit gcc.

Code 0x80320014 is FWP_E_INCOMPATIBLE_LAYER which makes it sound like the SA selector is not matching the SP installed earlier by install_sp(). I checked find_callout() return values and it seemed to be returning proper layers viz. those for in+outbound IPv6 transport mode. SPI number generated by get_spi() also looked reasonable. I'm pretty much out of ideas at this point.

(As an aside, ipsecdump.exe messes up the byte order on IPv6 addresses.)


#1 Updated by Tobias Brunner over 1 year ago

  • Status changed from New to Feedback

Yeah, no idea either.

#2 Updated by Valtteri Vuorikoski over 1 year ago

Actually I need to try this with IPv4 later this week. One thing that just occurred to me:

install_sas() calls hosts2traffic() which does byte-order conversion on the IPv6 addresses with host2address() to configure the SA endpoints in the IPSEC_TRAFFIC1 structure.

install_sp() calls ts2condition() which does this:

                cond->matchType = FWP_MATCH_EQUAL;
                switch (ts->get_type(ts))
                        case TS_IPV4_ADDR_RANGE:
                                cond->conditionValue.type = FWP_UINT32;
                                cond->conditionValue.uint32 = untoh32(from);
                        case TS_IPV6_ADDR_RANGE:
                                cond->conditionValue.type = FWP_BYTE_ARRAY16_TYPE;
                                cond->conditionValue.byteArray16 = addr = malloc(sizeof(*addr));
                                memcpy(addr, from, sizeof(*addr));
                                return FALSE;

So v4 address is converted to host byte order but v6 address is memcpy'd directly into the FWPM_FILTER_CONDITION structure. In another place (install_sas) v6 addresses are also run through byte-order conversion. Is the right thing happening here?

#3 Updated by Tobias Brunner over 1 year ago

Is the right thing happening here?

I don't know, but given the name of the type and union member I'd say yes, a byte array is a byte array.

#4 Updated by Valtteri Vuorikoski over 1 year ago

Yep, verified that Windows-created filters have FWP_BYTE_ARRAY16_TYPE in big-endian format (the ipsecdump.exe display bug is caused by print_host() thinking that it's little-endian). That makes hosts2traffic() a bit fishy (it reverses the order), but anyway testing reveals that changing things there doesn't resolve the original error.

IPv4 transport mode works fine, so this problem is limited to IPv6 transport mode (tunnel mode not tested). I might continue digging later this week, but so far it seems that everything is being set up almost identically to IKEEXT.

Also available in: Atom PDF