diff --git a/scapy/layers/ipsec.py b/scapy/layers/ipsec.py
index f45fa49c15996270c4887d2c69f7939c0aac2fad..b609b9473c81424bba202a26a473982ca6bb5d09 100644
--- a/scapy/layers/ipsec.py
+++ b/scapy/layers/ipsec.py
@@ -40,6 +40,7 @@ True
 """
 
 import socket
+import struct
 from Crypto.Util.number import GCD as gcd
 
 from scapy.data import IP_PROTOS
@@ -169,7 +170,7 @@ class CryptAlgo(object):
     IPSec encryption algorithm
     """
 
-    def __init__(self, name, cipher, mode, block_size=None, iv_size=None, key_size=None):
+    def __init__(self, name, cipher, mode, block_size=None, iv_size=None, key_size=None, icv_size=None):
         """
         @param name: the name of this encryption algorithm
         @param cipher: a Cipher module
@@ -185,6 +186,11 @@ class CryptAlgo(object):
         self.name = name
         self.cipher = cipher
         self.mode = mode
+        self.icv_size = icv_size
+        self.is_aead = (hasattr(self.cipher, 'MODE_GCM') and
+                        self.mode == self.cipher.MODE_GCM) or \
+                        (hasattr(self.cipher, 'MODE_CCM') and
+                        self.mode == self.cipher.MODE_CCM)
 
         if block_size is not None:
             self.block_size = block_size
@@ -232,8 +238,7 @@ class CryptAlgo(object):
         @return:    an initialized cipher object for this algo
         """
         if (hasattr(self.cipher, 'MODE_CTR') and self.mode == self.cipher.MODE_CTR
-            or hasattr(self.cipher, 'MODE_GCM') and self.mode == self.cipher.MODE_GCM
-            or hasattr(self.cipher, 'MODE_CCM') and self.mode == self.cipher.MODE_CCM):
+            or self.is_aead):
             # in counter mode, the "iv" must be incremented for each block
             # it is calculated like this:
             # +---------+------------------+---------+
@@ -252,8 +257,7 @@ class CryptAlgo(object):
             #                              <--------->
             #                               nonce_size
             cipher_key, nonce = key[:-nonce_size], key[-nonce_size:]
-            if (hasattr(self.cipher, 'MODE_GCM') and self.mode == self.cipher.MODE_GCM
-            or  hasattr(self.cipher, 'MODE_CCM') and self.mode == self.cipher.MODE_CCM):
+            if self.is_aead:
                 return self.cipher.new(cipher_key, self.mode, nonce + iv,
                                        counter=Counter.new(4 * 8, prefix=nonce + iv))
 
@@ -307,7 +311,13 @@ class CryptAlgo(object):
         if self.cipher:
             self.check_key(key)
             cipher = self.new_cipher(key, esp.iv)
-            data = cipher.encrypt(data)
+
+            if self.is_aead:
+                cipher.update(struct.pack('!LL', esp.spi, esp.seq))
+                data = cipher.encrypt(data)
+                data += cipher.digest()[:self.icv_size]
+            else:
+                data = cipher.encrypt(data)
 
         return ESP(spi=esp.spi, seq=esp.seq, data=esp.iv + data)
 
@@ -323,12 +333,19 @@ class CryptAlgo(object):
         """
         self.check_key(key)
 
+        if self.cipher and self.is_aead:
+            icv_size = self.icv_size
+
         iv = esp.data[:self.iv_size]
         data = esp.data[self.iv_size:len(esp.data) - icv_size]
         icv = esp.data[len(esp.data) - icv_size:]
 
         if self.cipher:
             cipher = self.new_cipher(key, iv)
+
+            if self.is_aead:
+                cipher.update(struct.pack('!LL', esp.spi, esp.seq))
+
             data = cipher.decrypt(data)
 
         # extract padlen and nh
@@ -373,12 +390,14 @@ if AES:
                                            cipher=AES,
                                            mode=AES.MODE_GCM,
                                            iv_size=8,
+                                           icv_size=8,
                                            key_size=(16 + 4, 24 + 4, 32 + 4))
     if hasattr(AES, "MODE_CCM"):
         CRYPT_ALGOS['AES-CCM'] = CryptAlgo('AES-CCM',
                                            cipher=AES,
                                            mode=AES.MODE_CCM,
                                            iv_size=8,
+                                           icv_size=8,
                                            key_size=(16 + 4, 24 + 4, 32 + 4))
 if DES:
     CRYPT_ALGOS['DES'] = CryptAlgo('DES',