User Tools

Site Tools


mywiki:linux:ipsec

IPSec Implementation in Linux

Reference ipsec_xfrm

IPSEC Basic

Security Scheme Difference
IPSEC Security scheme operating in the Internet Layer of the Internet Protocol Suite
TLS/SSH Security scheme operating in the upper layers of the TCP/IP model, like transport layer
IPSEC Protocol Note
AH (Authentication Header) provides source authentication & data integrity for IP datagrams. But it is not designed to provide confidentiality.
ESP(Encapsulating Security Payload) provides source authentication, data integrity, and confidentiality.
IPSEC Mode Protocol Note
Transport AH only the payload of the IP packet is usually authenticated
ESP only the payload of the IP packet is usually encrypted and/or authenticated
Tunnel Mode AH the entire IP packet is authenticated
ESP the entire IP packet is encrypted and/or authenticated

Terms

SP(Security policy) a rule which decides whether a given flow needs to go for IPSec processing or not
SA(Security Association) a bundle of algorithms and parameters (such as keys) that is being used to encrypt and authenticate a particular flow in one direction. IPsec uses the Security Parameter Index (SPI: an index to the security association database - SADB), along with the destination address in a packet header, which together uniquely identify a security association for that packet.

Limux Implementation

XFRM_MSG_NEWSA To add a new SA to SAD
XFRM_MSG_DELSA To delete a new SA to SAD
XFRM_MSG_GETSA To get a new SA to SAD
XFRM_MSG_FLUSHSA To flush SAD
XFRM_MSG_NEWPOLICY To add a new policy to SPD
XFRM_MSG_DELPOLICY To delete a new policy to SPD
XFRM_MSG_GETPOLICY To get a new policy to SPD
XFRM_MSG_FLUSHPOLICY To flush SPD

IPSec framework in kernel

ESP Protocol net/ipv4/esp4.c, net/ipv6/esp6.c
AH Protocol net/ipv4/ah4.c, net/ipv6/ah6.c
XFRM framework net/ipv4/xfrm4_policy.c and net/ipv6/xfrm6_policy.c
XFRM initialization xfrm4_init() and xfrm6_init().

Kernel Terms

aalg Authentication algo pointer
ealg Encryption algo pointer
calg Compression algo pointer
aead Authentication Encryption with Associated Data pointer Note: if (aead == NULL); then only authentication without any encryption
encap Data for encapsulator, ie, for special UDP Encapsulation only draft-ietf-ipsec-udp-encaps-06

Kernel cryptography

acrypto asynchronous crypto
cryptd
pcrypto for multicore environment

Algo: DES, 3DES, AES, RC5, IDEA, 3-IDEA, CAST, BLOWFISH etc…

two IPSec stacks:

native netkey stack syncronous
traditional KLIPS stack asynchronous

To start with, the core object of xfrm is the 'xfrm' member of 'struct net'. i.e each network namespace has got a separate xfrm object. This object will be reffered to access the hash tables (remeber hash tables :) ) of SPD and SAD. Also holds the state garbage collector (state_gc_work)

Data structures

The building block of SPD (Policy Database) is struct xfrm_policy.

/* ################################################# */

struct xfrm_policy {

#ifdef CONFIG_NET_NS
                struct net                            *xp_net;
#endif
                struct hlist_node              bydst;
                struct hlist_node              byidx;
                /* This lock only affects elements except for entry. */
                rwlock_t                              lock;
                atomic_t                              refcnt;
                struct timer_list                timer;
                struct flow_cache_object flo;
                atomic_t                              genid;
                u32                                         priority;
                u32                                         index;
                struct xfrm_mark             mark;
                struct xfrm_selector       selector;
                struct xfrm_lifetime_cfg lft;
                struct xfrm_lifetime_cur curlft;
                struct xfrm_policy_walk_entry walk;
                struct xfrm_policy_queue polq;
                u8                                           type;
                u8                                           action;
                u8                                           flags;
                u8                                           xfrm_nr;
                u16                                         family;
                struct xfrm_sec_ctx        *security;
                struct xfrm_tmpl              xfrm_vec[XFRM_MAX_DEPTH];
};




Important Fields:

                                - refcnt is to hold the reference to the policy.

                                - which embedded xfrm_selector object to hold the source and destination IP addresses, source and destination ports, protocol, interface index etc. xfrm_selector_match() API checks if the given packet matches with the XFRM selector.

                                - lft:  is the policy lifetime

                                - timer: to handle the policy expiry

                                - polq: is a queue to push the packets when there are no states associated with this policy.

                                - action: this field decides the fate of the traffic. (XFRM_POLICY_ALLOW and XFRM_POLICY_BLOCK)

                                - family (v4 or v6, as mentioned this structure is common for all protocols)           

The building block of SAD (Association Database) is struct xfrm_state

/* Full description of state of transformer. */

struct xfrm_state {

#ifdef CONFIG_NET_NS
                struct net                            *xs_net;
#endif
                union {
                                struct hlist_node              gclist;
                                struct hlist_node              bydst;
                };
                struct hlist_node              bysrc;
                struct hlist_node              byspi;
                atomic_t                              refcnt;
                spinlock_t                           lock;
                struct xfrm_id                   id;
                struct xfrm_selector       sel;

                /* Key manager bits */

                struct xfrm_state_walk km;

                /* Parameters of this state. */

                struct {
                                u32                         reqid;
                                u8                           mode;
                                u8                           replay_window;
                                u8                           aalgo, ealgo, calgo;
                                u8                           flags;
                                u16                         family;
                                xfrm_address_t               saddr;
                                int                           header_len;
                                int                           trailer_len;
                                u32                         extra_flags;
                } props;

                struct xfrm_lifetime_cfg lft;

                /* Data for transformer */
                struct xfrm_algo_auth   *aalg;
                struct xfrm_algo               *ealg;
                struct xfrm_algo               *calg;
                struct xfrm_algo_aead  *aead;

                /* Data for encapsulator */

                struct xfrm_encap_tmpl               *encap;

                --------------         

               -------------------

                /* data for replay detection */

                struct xfrm_replay_state replay;

                struct xfrm_replay_state_esn *replay_esn;

                struct xfrm_replay_state preplay;

                struct xfrm_replay_state_esn *preplay_esn;

                struct xfrm_replay          *repl;

                u32                                         replay_maxage;

                u32                                         replay_maxdiff;

                struct timer_list                rtimer;

                /* Statistics */

                struct xfrm_stats             stats;

                struct xfrm_lifetime_cur curlft;

                struct tasklet_hrtimer    mtimer;

                /* Last used time */

                unsigned long                    lastused;

                ---------------------------

                ----------------------------

                /* Private data of this transformer, format is opaque,

                 * interpreted by xfrm_type methods. */
                void                                       *data;

}

IPSec kernel APIs

Xfrm_lookup() xfrm lookup(SPD and SAD) method
Xfrm_input() xfrm processing for an ingress packet
Xfrm_output() xfrm processing for an egress packet
Xfrm4_rcv() IPv4 specific Rx method
Xfrm6_rcv() IPv6 specific Rx method
Esp_input() ESP processing for an ingress packet
Esp_output() ESP processing for an egress packet
Ah_input() AH processing for an ingress packet
Ah_output() AH processing for an egress packet
xfrm_policy_alloc() allocates an SPD object
Xfrm_policy_destroy() frees an SPD object
xfrm_ policy_lookup SPD lookup
xfrm_policy_byid() SPD lookup based on id
Xfrm_policy_insert() Add an entry to SPD
Xfrm_Policy_delete() remove an entry from SPD
Xfrm_bundle_create() creates a xfrm bundle
Xfrm_policy_delete() releases the resources of a policy object
Xfrm_state_add() add an entry to SAD
Xfrm_state_delete() free and SAD object
xfrm_state_alloc() allocate an SAD object
xfrm_state_lookup_byaddr() src address based SAD lookup
xfrm_state_find() SAD look up based on dst
xfrm_state_lookup() SAD lookup based on spi

IPSec SA initialize

It is initialized by API: static int esp_init_state(struct xfrm_state *x), which is defined in file:

  • net/ipv4/esp4.c
  • net/ipv6/esp6.c

IPSec Tx steps

For better understanding I have divided the IPSec transmission process in 7 stepes as below

Step-1: Transport_layer_sendmsg() 

Does TCP/UDP specific jobs are done here before going for route lookup

Step-2: ip_route_output_slow() 

Xfrm_lookup()

Step-3: ip_local_output()

Step-4: ip_local_out()

 LOCAL_OUT netfilter applies here.

Calls skb->dst->output(), which is xfrm4_output in case of ipv4 and xfrm6_output in the case of ipv6

Step-5: xfrm4_output/xfrm6_output

Step-6: esp_output()/ah_output()

Step-7: ip_output()

Step-8: dev_queue_xmit()

Egress QoS comes here.

Step-9: dev->ndo_start_xmit() 

IPSec Rx steps

For better understanding I have divided the IPSec reception process in 7 stepes, they are below

Step-1: netif_receive_skb()

Step-2: ip_rcv()

Netfilter PRE_ROUTING applies here.

Step-3: ip_receive_finish

Calls ip_route_input_noref(). Which finds the route entry and set dst->output for local delivery, forwarding etc. But IPSec applies on the end systems ONLY. So we bothr if it is set for local delivery

Step-4: ip_local_deliver

LOCAL_IN Netfilter part here.

Step-5: ip_local_deliver_finish()

Based on the protocol field of  ip header (IPPROTO_AH, IPPROTO_ESP),  packet will be given to xfrm4_rcv() function

Step-6:  xfrm4_rcv()

Step-7: xfrm_input()

Calls xfrm_state_lookup()

calls esp_input()/ah_input()

Once again applies the PRE_ROUTING Netfilter, but now  for the decapsulated packet

Step-8: xfrm4_rcv_encap_finish()

Will do the route lookup again for the decapsulated packet using ip_route_input_noref(). Again route lookup should decide for local_delivery.

Step-9: ip_local_delivery()

again the LOCAL_IN Netfilter for decapsulated packet

now the protocol field will be TCP/UDP and the packet flows in the native reception methods of TCP/UDP and delivers to the socket

Step-10: transport_layer_rcvmsg()

-to userspace
mywiki/linux/ipsec.txt · Last modified: by 127.0.0.1