Libreswan Documentation

Logo

Libreswan's Online Documentation

View the Project on GitHub libreswan/libreswan.github.io

Support
FAQ Common Error Messages
History
Implemented Standards
Kernel Support
HOWTO Additional ipsec.conf documentation
AWS Mesh
brendans Road Warrior Setup at Home
Configuration examples
Confuse !?@: github wiki
Enterprise cloud encryption
Entropy matters
EoIP shared ethernet LAN using IPsec
High Availability Fallover VPN in AWS
Host to host VPN
Host to host VPN with PSK
Libreswan as client to a Cisco ASA or VPN3000 server
Microsoft Azure configuration
Migrate from IKEv1 DPD to IKEv2 LIVENESS
Opportunistic IPsec
Opportunistic IPsec using LetsEncrypt
Pluto and DNSSEC
Read status output
Route based VPN
SElinux and Labeled IPsec VPN
Subnet extrusion
Subnet to subnet using NAT
Subnet to subnet VPN
Subnet to subnet VPN with PSK
Unauthenticated Opportunistic IPsec
Using Apache to serve PKCS
Using NSS Hardware Tokens
Using NSS with libreswan
VPN server for remote clients using IKEv2
VPN server for remote clients using IKEv2 split VPN
GSoC 2027 Code Project Ideas DRAFT
Contributor Guidance DRAFT
Completed Projects 2026 RFC 9593 Announcing Supported Authentication Methods in IKEv2
2026 Improve the ACQUIRE to IKE policy lookup
2026 Add HOST TO HOST Support on BSD
2021 RFC 8420 Add EdDSA Signature Authentication Support to IKEv2
2020 Session Resumption
2020 IKEv2 Interop testing with OpenBSD
2020 IKE Intermediate Exchange
2019 Libreswan Opportunistic IPsec using LetsEncrypt
2018 RSA PSS Support in compliance with RFC 7427 and RFC 8247
2018 RFC 7427 Add ECDSA Signature Authentication Support to IKEv2
2018 RFC 5685 Redirect Mechanism
2018 Managing Interface
2017 TCP encapsulation of IKE and IPsec
2017 RFC 7427 Add Signature Authentication Support to IKEv2
2017 Postquantum Preshared Keys
Presentations
IRC
Hacking Documentation
Git, GitHub, and Pull Requests
Merging GitHub Pull Requests
Programming Conventions
Testing Docker
KVM 1. Setup The Host
2. Configure Testing
3. Compile Libreswan
4. Test Libreswan
5. Accessing The Console
6. Maintenance and Internals
Bisecting
Debugging Pluto
Logging In Using SSH
Performance
Running A Custom Kernel
Running A Single Test
Running In The Background
Setup a Web Server
Testing Old Branches
Updating Test Results
Namespace Magic
Namespaces
Topology
Internals 3.14 X509
Benchmarking and Performance testing
Cipher suites and algorithm support
Cloud OE ideas
Compiling with AddressSanitizer
Compliance of RFC 7427 Signature Authentication in IKEv2
Coverity
Cryptographic Acceleration
Developer links strongswan android
Discouraged or forbidden C functions
IKEv2 Child SA
IKEv2 CP and EAP support
Introduction
Libreswan xfrm kernel support
Logging cleanup
New OE
Pluto
Pluto packet processing
Proposed ipsec ca command
Retransmit timings
Road Map
SAref code
Setting up system for debug logging
stf status
Testing 2017 Next Generation
Unbound
Uncrustify
Use Cases and Requirements document for ECC ECDSA support
Use Cases and Requirements document
XFRM Interface Development Notes
XFRM pCPU
XFRM pCPU RSS
Security Crypto boundary and certification
Libreswan and Heartbleed
Libreswan and TunnelCrack
Reporting a Vulnerability
Vulnerabilities
Meetups 2013 Helsinki
2014 San Francisco
2014 Toronto
2018 Toronto
Obsolete HOWTOs IKEv1 XAUTH with FreeOTP and FreeIPA
IKEv1 XAUTH with Google Authenticator One Time Passwords
Route based VPN using VTI
Testing Namespace
VPN server for remote clients using IKEv1 with L2TP
VPN server for remote clients using IKEv1 XAUTH with Certificates
VPN server for remote clients using IKEv1 XAUTH with PSK

The document describes the steps that a packet goes through when it is received by pluto. This is not a state machine, but rather a call graph, in general each run through the process causes a single state change.

The packet is received from the network and the origin and destination address and the ports of the packet are recorded. Based upon the destination port, a particular interface definition is chosen.

The packet is stored into an object called the “msg_digest”

A single common (statically allocated) msg_digest is used to receive all packets, if it needs to be saved (not the common case), it is copied.

process_packet() is the primary function which parses the incoming packet. In the diagram, this is why all other functions appear to be called from this function.

The first step is to take the packet apart. This is done by the in_struct() routine, which turns the wire format into a structure, found in md->hdr.

The first step is to look at the exchange type. Many exchange types are not supported. In general each type will cause a new state to be created when the msgid is different than a different code was done.

Each type will search for a state object that matches the set of cookies, and the message id. If no state object is found, a new one may be created.

If the state is not found by the message ID, then we look for state with a zero message ID. If that is found, then the state is adjusted to now be for this message ID.

Once we have a state object, it can determined what are valid transitions from this state to another state. The selection is typically based upon what payloads are present in the message. The transition microcode has a bit for each payload type, and based upon this we determine if there would be a valid state transition.

This microcode also then indicates things such as whether or not the message should be encrypted, and whether or not additional options payloads may appear.

The state may be suspended. This will occur if there is computation (such as a Diffie-Hellman exponentiation) occuring or a network lookup is occuring (DNS). If so, the packet will be dropped. Likely, it is a retransmission anyway.

Retransmissions are also detected — if we have already replied to this message, then we will have saved the outgoing packet, and it is simply resent.

The message may have been encrypted. The state transition may be valid only with an encrypted message. These two conditions are compared, and if they match, then the message is decrypted.

The resulting new data will have new payloads, and these will be de-marshalled.

Prior to losing track of the newly decrypted message, we calculate over the plaintext, which may be used later on to authenticate the message.

Some ordering of payloads is mandated, and without this ordering the message may not make sense. This is then checked.

The state transition microcode (“smc”) will have designated a particular function handle the state transition. The function will be passed a pointer to the pointer to the message digest, and a pointer to the microcode.

The reason a pointer to a pointer is passed is so that the state specific function can set the message digest to NULL. It will do this in situations where it needs to keep a copy of the message for later examination by a continuation function. Since the pointer will now be NULL, the enclosing read_packet() function will not free the message digest, and a new one will be allocated for the next packet.

State specific functions are named for the exchange type, and message number they expect. For instance, quick_inI1_outR1 is part of a QuickMode (aka “Phase 2”) exchange, and is called by the responder when it receives message I1 in order to prepare the R1 message

A typical IKEv1 negotiation looks like this:

     [[main_outI1|main_outI1]]
                       ------I1----->
                                       [[main_inI1_outR1|main_inI1_outR1]]
                       <-----R1------
     [[main_inR1_outI2|main_inR1_outI2]]
                       ------I2----->
                                       [[main_inI2_outR2|main_inI2_outR2]]
                       <-----R2------
     [[main_inR2_outI3|main_inR2_outI3]]
                       ------I3----->
                                       [[main_inI3_outR3|main_inI3_outR3]]
                       <-----R3------
     [[main_inR3|main_inR3]]
         |             PHASE 1 ESTABLISHED
         |
         V
     [[quick_outI1|quick_outI1]]
                       ------I1----->
                                      [[quick_inI1_outR1|quick_inI1_outR1]]
                       <-----R1------
     [[quick_inR1_outI2|quick_inR1_outI2]]
         |             ------I2----->
         |                            [[quick_inI2|quick_inI2]]
         |                                 |
         V                                 V
     PHASE 2 ESTABLISHED            PHASE 2 ESTABLISHED

Details about each state transition is covered in additional pages above.

The state specific function is expected to return one of the following returns of type stf_status (State Transition Function Status).

An ignore value means that this message should not cause any change to the current stat. No further processing is done.

A return of INLINE is a meta value, and means that the state transition has already been performed.

A return of SUSPEND means that the state transition function could not (yet) complete the state transition. A continuation function (to be called later) will likely complete the transition.

A return of FATAL means that something is wrong in the configuration of this connection pluto, and likely that it will be unable to continue processing.

An internal error means that a system wide resource is misconfigured, and it is likely that no connection will succeed.

A simple failure means that the message was not successfully processed. This could be due to inability to authenticate the message, mismatches in policy, etc. It may also be due to malicious corruption of the exchange.

The message could not be processed at this time because the system is too busy processing other (more important) messages. The message is dropped, and retransmission will take care of resending it.

The message was successfully processed, and the state should be advanced. The received message is record (in case it is retransmitted), and if this state requires a response, any response message will then be sent.

The send_packet() process actually transmits the reply. It uses the remote address and port that has been stored in the state structure, since the NAT-traversal code may have updated these values.

The state specific function, if it prepares a reply packet, may need to encrypt it. This is done in a single function.

Many state specific functions require that some work be done: this may involve one or more DNS or LDAP lookups to retrieve public keys, or may involve performing lengthy cryptographic operations. In this case, the state specific function will arrange to have the operation started. A continuation structure is created when the operation is started, and the state specific function will return STF_SUSPENDED.

When the asynchronous operation is completed, a continuation function (often called the _tail function) is called, it is provided with the continuation structure, and a reply message is fashioned. Typically, the continuation function will then call complete_state_transition() itself.