[Pkg-swan-devel] [strongswan] 01/12: Imported Upstream version 5.3.1

Yves-Alexis Perez corsac at moszumanska.debian.org
Mon Jun 8 14:51:55 UTC 2015


This is an automated email from the git hooks/post-receive script.

corsac pushed a commit to branch master
in repository strongswan.

commit fc556ec2bc92a9d476c11406fad2c33db8bf7cb0
Author: Yves-Alexis Perez <corsac at debian.org>
Date:   Mon Jun 1 14:46:30 2015 +0200

    Imported Upstream version 5.3.1
---
 Android.common.mk                                  |    2 +-
 Doxyfile.in                                        |    4 +-
 Makefile.am                                        |    6 +-
 Makefile.in                                        |    6 +-
 NEWS                                               |   16 +
 conf/Makefile.am                                   |    1 +
 conf/Makefile.in                                   |    1 +
 conf/options/imv_policy_manager.conf               |   18 +
 conf/options/imv_policy_manager.opt                |   13 +
 conf/plugins/kernel-netlink.conf                   |    3 +
 conf/plugins/kernel-netlink.opt                    |    3 +
 conf/strongswan.conf.5.main                        |   22 +
 config.h.in                                        |    3 +
 configure                                          |  182 +-
 configure.ac                                       |   41 +-
 init/Makefile.am                                   |    2 +
 init/Makefile.in                                   |    2 +-
 man/ipsec.conf.5.in                                |    2 +-
 scripts/Makefile.am                                |    4 +-
 scripts/Makefile.in                                |   20 +-
 scripts/crypt_burn.c                               |  264 ++-
 scripts/timeattack.c                               |  418 ++++
 src/charon-nm/charon-nm.c                          |    3 +
 src/charon-tkm/src/tkm/tkm_id_manager.c            |    2 -
 src/charon-tkm/src/tkm/tkm_kernel_ipsec.c          |   17 +-
 src/charon-tkm/src/tkm/tkm_kernel_sad.c            |   89 +-
 src/charon-tkm/src/tkm/tkm_kernel_sad.h            |   21 +-
 src/charon-tkm/src/tkm/tkm_keymat.c                |   15 +-
 src/charon-tkm/src/tkm/tkm_listener.c              |    9 +
 src/charon-tkm/src/tkm/tkm_nonceg.c                |   53 +-
 src/charon-tkm/src/tkm/tkm_nonceg.h                |    8 -
 src/charon-tkm/tests/kernel_sad_tests.c            |   48 +-
 src/charon-tkm/tests/keymat_tests.c                |    2 +-
 src/charon-tkm/tests/nonceg_tests.c                |    1 -
 src/ipsec/_ipsec.8                                 |    2 +-
 src/libcharon/bus/bus.c                            |   34 +-
 src/libcharon/bus/bus.h                            |   13 +-
 src/libcharon/bus/listeners/listener.h             |   17 +-
 src/libcharon/encoding/message.c                   |   66 +-
 .../encoding/payloads/encrypted_payload.c          |    5 +
 src/libcharon/encoding/payloads/payload.c          |    2 +
 src/libcharon/encoding/payloads/payload.h          |    7 +-
 src/libcharon/encoding/payloads/unknown_payload.c  |    8 +
 src/libcharon/encoding/payloads/unknown_payload.h  |    8 +
 src/libcharon/network/receiver.c                   |    2 +-
 src/libcharon/plugins/eap_aka/eap_aka_server.c     |    5 +-
 .../plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c     |    3 +-
 .../plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c |    3 +-
 src/libcharon/plugins/eap_md5/eap_md5.c            |    3 +-
 src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c  |    7 +-
 .../plugins/eap_radius/eap_radius_accounting.c     |  390 +++-
 src/libcharon/plugins/eap_sim/eap_sim_peer.c       |    3 +-
 src/libcharon/plugins/eap_sim/eap_sim_server.c     |    3 +-
 .../plugins/eap_sim_file/eap_sim_file_card.c       |    3 +-
 src/libcharon/plugins/ha/ha_cache.c                |   12 +-
 src/libcharon/plugins/ha/ha_cache.h                |    3 +-
 src/libcharon/plugins/ha/ha_plugin.c               |  128 +-
 src/libcharon/plugins/vici/libvici.h               |   29 +-
 src/libcharon/plugins/vici/python/Makefile.am      |   12 +-
 src/libcharon/plugins/vici/python/Makefile.in      |   17 +-
 src/libcharon/plugins/vici/ruby/Makefile.am        |    4 +-
 src/libcharon/plugins/vici/ruby/Makefile.in        |   14 +-
 src/libcharon/plugins/vici/vici_config.c           |   37 +
 src/libcharon/plugins/vici/vici_dispatcher.c       |   41 +
 src/libcharon/plugins/vici/vici_dispatcher.h       |   33 +
 src/libcharon/plugins/vici/vici_plugin.c           |   24 +
 src/libcharon/plugins/vici/vici_query.c            |   85 +
 src/libcharon/plugins/vici/vici_query.h            |   28 +
 src/libcharon/plugins/vici/vici_socket.c           |   46 +-
 .../plugins/xauth_generic/xauth_generic.c          |    2 +-
 src/libcharon/processing/jobs/adopt_children_job.c |   20 +-
 src/libcharon/sa/ike_sa_manager.c                  |    4 +-
 .../sa/ikev1/authenticators/psk_v1_authenticator.c |    2 +-
 src/libcharon/sa/ikev1/task_manager_v1.c           |    5 +
 .../sa/ikev2/authenticators/eap_authenticator.c    |    2 +-
 .../sa/ikev2/authenticators/psk_authenticator.c    |    2 +-
 src/libcharon/sa/ikev2/keymat_v2.c                 |   15 +-
 src/libcharon/sa/ikev2/task_manager_v2.c           |   18 +-
 src/libcharon/sa/ikev2/tasks/child_create.c        |   43 +-
 src/libcharon/sa/ikev2/tasks/ike_init.c            |   53 +-
 src/libcharon/sa/ikev2/tasks/ike_mobike.c          |    2 +-
 src/libcharon/sa/ikev2/tasks/ike_vendor.c          |   10 +
 .../plugins/kernel_netlink/kernel_netlink_ipsec.c  |    2 +-
 .../plugins/kernel_netlink/kernel_netlink_net.c    |   24 +
 .../plugins/kernel_netlink/kernel_netlink_shared.c |   18 +-
 src/libhydra/plugins/kernel_netlink/tests.c        |    2 -
 src/libimcv/ietf/ietf_attr_attr_request.c          |   27 +-
 src/libimcv/ietf/ietf_attr_fwd_enabled.h           |    2 +-
 src/libimcv/ietf/ietf_attr_numeric_version.h       |    2 +-
 src/libimcv/ietf/ietf_attr_op_status.h             |    2 +-
 src/libimcv/imc/imc_os_info.c                      |    4 +-
 src/libimcv/imv/imv_policy_manager.c               |   22 +-
 src/libimcv/pa_tnc/pa_tnc_msg.c                    |    9 +-
 src/libimcv/plugins/imc_os/imc_os.c                |    6 +-
 .../imv_attestation/imv_attestation_process.c      |    7 +-
 src/libimcv/pts/components/ita/ita_comp_ima.c      |    9 +-
 src/libimcv/pts/components/ita/ita_comp_tboot.c    |    3 +-
 src/libimcv/pts/components/ita/ita_comp_tgrub.c    |    2 +-
 src/libimcv/pts/pts_database.c                     |    4 +-
 src/libimcv/pts/pts_file_meas.c                    |    8 +-
 src/libipsec/esp_context.c                         |    9 +-
 src/libipsec/ipsec_sa_mgr.c                        |    2 +-
 src/libpttls/sasl/sasl_plain/sasl_plain.c          |    2 +-
 src/libradius/radius_message.c                     |    2 +-
 src/libradius/radius_socket.c                      |  104 +-
 src/libsimaka/Makefile.am                          |    4 +
 src/libsimaka/Makefile.in                          |   11 +-
 src/libstrongswan/Android.mk                       |    9 +-
 src/libstrongswan/Makefile.am                      |   23 +-
 src/libstrongswan/Makefile.in                      |  286 +--
 src/libstrongswan/asn1/asn1.c                      |    4 +
 src/libstrongswan/crypto/aead.c                    |    4 +-
 src/libstrongswan/crypto/aead.h                    |    3 +-
 src/libstrongswan/crypto/crypto_factory.c          |  182 +-
 src/libstrongswan/crypto/crypto_factory.h          |   21 +-
 src/libstrongswan/crypto/crypto_tester.c           |  193 +-
 src/libstrongswan/crypto/crypto_tester.h           |   41 +
 src/libstrongswan/crypto/diffie_hellman.h          |   12 +
 src/libstrongswan/crypto/iv/iv_gen.c               |   61 +
 src/libstrongswan/crypto/iv/iv_gen.h               |    8 +
 src/libstrongswan/crypto/iv/iv_gen_seq.c           |   24 +
 src/libstrongswan/crypto/iv/iv_gen_seq.h           |    3 +
 src/libstrongswan/crypto/signers/mac_signer.c      |    3 +-
 src/libstrongswan/crypto/transform.c               |   32 +
 src/libstrongswan/crypto/transform.h               |    8 +
 src/libstrongswan/plugins/aesni/Makefile.am        |   26 +
 .../plugins/aesni}/Makefile.in                     |  155 +-
 src/libstrongswan/plugins/aesni/aesni_cbc.c        |  671 ++++++
 src/libstrongswan/plugins/aesni/aesni_cbc.h        |   48 +
 src/libstrongswan/plugins/aesni/aesni_ccm.c        |  914 ++++++++
 src/libstrongswan/plugins/aesni/aesni_ccm.h        |   50 +
 src/libstrongswan/plugins/aesni/aesni_cmac.c       |  371 ++++
 src/libstrongswan/plugins/aesni/aesni_cmac.h       |   52 +
 src/libstrongswan/plugins/aesni/aesni_ctr.c        |  643 ++++++
 src/libstrongswan/plugins/aesni/aesni_ctr.h        |   48 +
 src/libstrongswan/plugins/aesni/aesni_gcm.c        | 1447 +++++++++++++
 src/libstrongswan/plugins/aesni/aesni_gcm.h        |   50 +
 src/libstrongswan/plugins/aesni/aesni_key.c        |  301 +++
 src/libstrongswan/plugins/aesni/aesni_key.h        |   65 +
 src/libstrongswan/plugins/aesni/aesni_plugin.c     |  125 ++
 .../iv_gen_seq.h => plugins/aesni/aesni_plugin.h}  |   32 +-
 src/libstrongswan/plugins/aesni/aesni_xcbc.c       |  367 ++++
 src/libstrongswan/plugins/aesni/aesni_xcbc.h       |   52 +
 src/libstrongswan/plugins/af_alg/af_alg_signer.c   |    2 +-
 src/libstrongswan/plugins/ccm/ccm_aead.c           |    2 +-
 src/libstrongswan/plugins/fips_prf/fips_prf.c      |    2 -
 src/libstrongswan/plugins/gcm/gcm_aead.c           |    2 +-
 src/libstrongswan/plugins/gcrypt/gcrypt_dh.c       |   19 +
 src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c   |    3 +
 src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c |   10 +
 src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c |    5 +-
 .../plugins/openssl/openssl_crypter.c              |    2 +
 .../plugins/openssl/openssl_diffie_hellman.c       |   13 +
 .../plugins/openssl/openssl_ec_diffie_hellman.c    |   44 +
 src/libstrongswan/plugins/openssl/openssl_hmac.c   |   22 +-
 src/libstrongswan/plugins/openssl/openssl_pkcs7.c  |    2 +-
 .../plugins/openssl/openssl_rsa_public_key.c       |    2 +-
 src/libstrongswan/plugins/padlock/padlock_plugin.c |   97 +-
 src/libstrongswan/plugins/pkcs12/pkcs12_decode.c   |    2 +-
 .../plugins/pkcs7/pkcs7_signed_data.c              |    2 +-
 src/libstrongswan/plugins/plugin_feature.c         |    2 +
 src/libstrongswan/plugins/rdrand/rdrand_plugin.c   |   55 +-
 src/libstrongswan/plugins/sqlite/sqlite_database.c |   27 +-
 src/libstrongswan/plugins/sqlite/sqlite_plugin.c   |    9 +-
 src/libstrongswan/plugins/test_vectors/Makefile.am |    4 +
 src/libstrongswan/plugins/test_vectors/Makefile.in |   19 +-
 .../plugins/test_vectors/test_vectors.h            |   32 +
 .../plugins/test_vectors/test_vectors/aes_ccm.c    |   79 +
 .../plugins/test_vectors/test_vectors/aes_gcm.c    |  150 ++
 .../plugins/test_vectors/test_vectors/ecp.c        |  134 ++
 .../plugins/test_vectors/test_vectors/ecpbp.c      |  113 +
 .../plugins/test_vectors/test_vectors/modp.c       |  731 +++++++
 .../plugins/test_vectors/test_vectors/modpsub.c    |  164 ++
 .../plugins/test_vectors/test_vectors_plugin.c     |   29 +-
 src/libstrongswan/tests/suites/test_chunk.c        |   27 +
 src/libstrongswan/tests/suites/test_enum.c         |   10 +
 src/libstrongswan/tests/suites/test_threading.c    |   31 +
 src/libstrongswan/tests/suites/test_utils.c        |   86 +
 src/libstrongswan/tests/suites/test_vectors.c      |   34 +-
 src/libstrongswan/tests/test_runner.c              |   22 +-
 src/libstrongswan/tests/test_runner.h              |    4 +
 src/libstrongswan/tests/test_suite.h               |    6 +-
 src/libstrongswan/tests/tests.c                    |    3 +-
 src/libstrongswan/threading/thread.c               |   39 +-
 src/libstrongswan/threading/thread.h               |   10 +
 src/libstrongswan/threading/windows/thread.c       |   20 +
 src/libstrongswan/utils/chunk.h                    |   13 +
 src/libstrongswan/utils/cpu_feature.c              |  158 ++
 src/libstrongswan/utils/cpu_feature.h              |   62 +
 src/libstrongswan/utils/enum.c                     |    6 +-
 src/libstrongswan/utils/leak_detective.c           |    5 +-
 src/libstrongswan/utils/utils.c                    |  739 +------
 src/libstrongswan/utils/utils.h                    |  895 +-------
 src/libstrongswan/utils/utils/align.c              |   62 +
 src/libstrongswan/utils/utils/align.h              |   86 +
 src/libstrongswan/utils/utils/atomics.c            |  112 +
 src/libstrongswan/utils/utils/atomics.h            |  130 ++
 src/libstrongswan/utils/utils/byteorder.h          |  161 ++
 src/libstrongswan/utils/utils/memory.c             |  237 +++
 src/libstrongswan/utils/utils/memory.h             |  183 ++
 src/libstrongswan/utils/utils/object.h             |  126 ++
 src/libstrongswan/utils/utils/path.c               |  168 ++
 src/libstrongswan/utils/utils/path.h               |   77 +
 .../iv/iv_gen_seq.h => utils/utils/status.c}       |   42 +-
 src/libstrongswan/utils/utils/status.h             |   72 +
 src/libstrongswan/utils/utils/strerror.h           |    3 +-
 src/libstrongswan/utils/utils/string.c             |   91 +
 src/libstrongswan/utils/utils/string.h             |  103 +
 src/libstrongswan/utils/utils/time.c               |  143 ++
 src/libstrongswan/utils/utils/time.h               |   91 +
 src/libstrongswan/utils/utils/tty.c                |   86 +
 src/libstrongswan/utils/utils/tty.h                |   65 +
 src/libstrongswan/utils/utils/types.h              |   87 +
 src/libtls/tls_peer.c                              |    9 +-
 src/libtls/tls_server.c                            |    2 +-
 src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c |    2 +-
 .../plugins/tnccs_20/messages/pb_tnc_msg.h         |    2 +-
 src/starter/Android.mk                             |    2 +-
 src/starter/Makefile.am                            |    4 -
 src/starter/Makefile.in                            |    7 +-
 src/starter/confread.c                             |   23 -
 src/starter/confread.h                             |    1 -
 src/starter/starter.c                              |    9 +-
 src/starter/starterstroke.c                        |  308 +--
 src/stroke/stroke.c                                |  281 +--
 src/stroke/stroke_msg.h                            |   18 +-
 src/swanctl/command.c                              |   45 +-
 src/swanctl/command.h                              |    2 +-
 src/swanctl/commands/list_sas.c                    |   86 +-
 testing/config/kernel/config-4.0                   | 2202 ++++++++++++++++++++
 .../hosts/winnetou/etc/openssl/research/index.txt  |    3 +-
 .../winnetou/etc/openssl/research/index.txt.old    |    3 +-
 .../winnetou/etc/openssl/research/newcerts/0B.pem  |   25 +
 testing/hosts/winnetou/etc/openssl/research/serial |    2 +-
 .../hosts/winnetou/etc/openssl/research/serial.old |    2 +-
 testing/hosts/winnetou/etc/openssl/sales/index.txt |    3 +-
 .../hosts/winnetou/etc/openssl/sales/index.txt.old |    3 +-
 .../winnetou/etc/openssl/sales/newcerts/09.pem     |   24 +
 testing/hosts/winnetou/etc/openssl/sales/serial    |    2 +-
 .../hosts/winnetou/etc/openssl/sales/serial.old    |    2 +-
 testing/scripts/build-baseimage                    |    4 +-
 testing/scripts/build-guestkernel                  |    2 +-
 testing/scripts/recipes/005_anet.mk                |    2 +-
 testing/scripts/recipes/006_tkm-rpc.mk             |    2 +-
 testing/scripts/recipes/010_tkm.mk                 |    2 +-
 testing/scripts/recipes/012_openssl.mk             |    2 +-
 testing/testing.conf                               |    8 +-
 testing/tests/af-alg/rw-cert/pretest.dat           |    2 +-
 testing/tests/gcrypt-ikev2/rw-cert/pretest.dat     |    2 +-
 testing/tests/ha/active-passive/description.txt    |    8 +
 testing/tests/ha/active-passive/evaltest.dat       |   32 +
 .../ha/active-passive/hosts/alice/etc/ipsec.conf   |   19 +
 .../hosts/alice/etc/ipsec.d/certs/marsCert.pem     |   25 +
 .../hosts/alice/etc/ipsec.d/private/marsKey.pem    |   27 +
 .../active-passive/hosts/alice/etc/ipsec.secrets   |    3 +
 .../active-passive/hosts/alice/etc/iptables.rules  |   57 +
 .../active-passive/hosts/alice/etc/strongswan.conf |   16 +
 .../ha/active-passive/hosts/carol/etc/ipsec.conf   |   20 +
 .../active-passive/hosts/carol/etc/strongswan.conf |    5 +
 .../ha/active-passive/hosts/dave/etc/ipsec.conf    |   20 +
 .../active-passive/hosts/dave/etc/strongswan.conf  |    6 +
 .../ha/active-passive/hosts/moon/etc/ipsec.conf    |   19 +
 .../hosts/moon/etc/ipsec.d/certs/marsCert.pem      |   25 +
 .../hosts/moon/etc/ipsec.d/private/marsKey.pem     |   27 +
 .../ha/active-passive/hosts/moon/etc/ipsec.secrets |    3 +
 .../active-passive/hosts/moon/etc/iptables.rules   |   57 +
 .../active-passive/hosts/moon/etc/strongswan.conf  |   15 +
 testing/tests/ha/active-passive/posttest.dat       |   15 +
 testing/tests/ha/active-passive/pretest.dat        |   21 +
 .../active-passive}/test.conf                      |   13 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 .../hosts/carol/etc/ipsec.d/certs/carolCert.pem    |   34 +-
 .../hosts/carol/etc/ipsec.d/private/carolKey.pem   |   50 +-
 .../hosts/dave/etc/ipsec.d/certs/daveCert.pem      |   32 +-
 .../hosts/dave/etc/ipsec.d/private/daveKey.pem     |   50 +-
 testing/tests/ikev2/rw-cert/pretest.dat            |    2 +-
 testing/tests/openssl-ikev2/rw-cert/pretest.dat    |    2 +-
 .../tests/openssl-ikev2/rw-suite-b-128/pretest.dat |    2 +-
 .../tests/openssl-ikev2/rw-suite-b-192/pretest.dat |    2 +-
 testing/tests/pfkey/rw-cert/pretest.dat            |    2 +-
 .../hosts/carol/etc/ipsec.d/data.sql               |    7 +-
 .../carol/etc/ipsec.d/{data.sql => data.sql~}      |    8 +-
 .../multi-level-ca/hosts/dave/etc/ipsec.d/data.sql |    6 +-
 .../hosts/dave/etc/ipsec.d/{data.sql => data.sql~} |    7 +-
 testing/tests/sql/rw-cert/pretest.dat              |    2 +-
 testing/tests/tkm/host2host-initiator/evaltest.dat |    4 +-
 testing/tests/tkm/host2host-responder/evaltest.dat |    2 +-
 testing/tests/tkm/host2host-xfrmproxy/evaltest.dat |    2 +-
 testing/tests/tkm/multiple-clients/evaltest.dat    |    4 +-
 testing/tests/tkm/net2net-initiator/evaltest.dat   |    2 +-
 testing/tests/tkm/net2net-xfrmproxy/evaltest.dat   |    2 +-
 testing/tests/tkm/xfrmproxy-expire/evaltest.dat    |    4 +-
 testing/tests/tnc/tnccs-11-fhh/description.txt     |    2 +-
 .../tnc/tnccs-11-radius-block/description.txt      |    4 +-
 .../tests/tnc/tnccs-11-radius-pts/description.txt  |    2 +-
 testing/tests/tnc/tnccs-11-radius/description.txt  |    2 +-
 .../tests/tnc/tnccs-11-supplicant/description.txt  |    2 +-
 testing/tests/tnc/tnccs-20-fhh/description.txt     |    4 +-
 testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat |    4 +
 .../hosts/alice/etc/iptables.rules                 |    6 +-
 .../hosts/alice/etc/strongswan.conf                |    5 +
 .../etc/{strongswan.conf => strongswan.conf~}      |    5 +
 .../tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.conf  |    3 +
 .../hosts/moon/etc/ipsec.secrets                   |    3 +
 .../hosts/moon/etc/strongswan.conf                 |    3 +
 testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf    |    2 +-
 341 files changed, 16718 insertions(+), 3853 deletions(-)

diff --git a/Android.common.mk b/Android.common.mk
index d33062a..f75efed 100644
--- a/Android.common.mk
+++ b/Android.common.mk
@@ -26,5 +26,5 @@ add_plugin_subdirs = $(if $(call plugin_enabled,$(1)), \
               )
 
 # strongSwan version, replaced by top Makefile
-strongswan_VERSION := "5.3.0"
+strongswan_VERSION := "5.3.1"
 
diff --git a/Doxyfile.in b/Doxyfile.in
index eaf02d7..7608ffe 100644
--- a/Doxyfile.in
+++ b/Doxyfile.in
@@ -416,7 +416,7 @@ EXTRACT_PACKAGE        = NO
 # included in the documentation.
 # The default value is: NO.
 
-EXTRACT_STATIC         = NO
+EXTRACT_STATIC         = YES
 
 # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
 # locally in source files will be included in the documentation. If set to NO
@@ -683,7 +683,7 @@ CITE_BIB_FILES         =
 # messages are off.
 # The default value is: NO.
 
-QUIET                  = NO
+QUIET                  = YES
 
 # The WARNINGS tag can be used to turn on/off the warning messages that are
 # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
diff --git a/Makefile.am b/Makefile.am
index bea4ba7..898b262 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -38,7 +38,9 @@ Doxyfile :	Doxyfile.in
 		$(srcdir)/$@.in > $@
 
 apidoc :	Doxyfile
-		doxygen
+		@test -d apidoc || doxygen
+		@! find Doxyfile $(top_srcdir)/src/ \( -name '*.h' -o -name '*.md' \) -newer apidoc | \
+			grep -q '' || doxygen && touch apidoc
 
 cov-reset-common:
 		@rm -rf $(top_builddir)/coverage
@@ -75,4 +77,4 @@ clean-local: cov-reset-common
 		@find $(top_builddir)/src $(top_builddir)/scripts -name "*.gcno" -delete
 		@rm -rf apidoc
 
-.PHONY: cov-reset-common cov-reset cov-report coverage
+.PHONY: cov-reset-common cov-reset cov-report coverage apidoc
diff --git a/Makefile.in b/Makefile.in
index e10818f..22286fe 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1000,7 +1000,9 @@ Doxyfile :	Doxyfile.in
 		$(srcdir)/$@.in > $@
 
 apidoc :	Doxyfile
-		doxygen
+		@test -d apidoc || doxygen
+		@! find Doxyfile $(top_srcdir)/src/ \( -name '*.h' -o -name '*.md' \) -newer apidoc | \
+			grep -q '' || doxygen && touch apidoc
 
 cov-reset-common:
 		@rm -rf $(top_builddir)/coverage
@@ -1034,7 +1036,7 @@ clean-local: cov-reset-common
 		@find $(top_builddir)/src $(top_builddir)/scripts -name "*.gcno" -delete
 		@rm -rf apidoc
 
-.PHONY: cov-reset-common cov-reset cov-report coverage
+.PHONY: cov-reset-common cov-reset cov-report coverage apidoc
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/NEWS b/NEWS
index 81a7fc5..b2e8cb2 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,19 @@
+strongswan-5.3.1
+----------------
+
+- Fixed a denial-of-service and potential remote code execution vulnerability
+  triggered by IKEv1/IKEv2 messages that contain payloads for the respective
+  other IKE version. Such payload are treated specially since 5.2.2 but because
+  they were still identified by their original payload type they were used as
+  such in some places causing invalid function pointer dereferences.
+  The vulnerability has been registered as CVE-2015-3991.
+
+- The new aesni plugin provides CBC, CTR, XCBC, CMAC, CCM and GCM crypto
+  primitives for AES-128/192/256. The plugin requires AES-NI and PCLMULQDQ
+  instructions and works on both x86 and x64 architectures. It provides
+  superior crypto performance in userland without any external libraries.
+
+
 strongswan-5.3.0
 ----------------
 
diff --git a/conf/Makefile.am b/conf/Makefile.am
index f10af25..7cee0cb 100644
--- a/conf/Makefile.am
+++ b/conf/Makefile.am
@@ -14,6 +14,7 @@ options = \
 	options/charon-logging.opt \
 	options/charon-systemd.opt \
 	options/imcv.opt \
+	options/imv_policy_manager.opt \
 	options/manager.opt \
 	options/medsrv.opt \
 	options/pacman.opt \
diff --git a/conf/Makefile.in b/conf/Makefile.in
index 4b39140..fb3082b 100644
--- a/conf/Makefile.in
+++ b/conf/Makefile.in
@@ -396,6 +396,7 @@ options = \
 	options/charon-logging.opt \
 	options/charon-systemd.opt \
 	options/imcv.opt \
+	options/imv_policy_manager.opt \
 	options/manager.opt \
 	options/medsrv.opt \
 	options/pacman.opt \
diff --git a/conf/options/imv_policy_manager.conf b/conf/options/imv_policy_manager.conf
new file mode 100644
index 0000000..8979b28
--- /dev/null
+++ b/conf/options/imv_policy_manager.conf
@@ -0,0 +1,18 @@
+imv_policy_manager {
+
+    # Shell command to be executed with recommendation allow.
+    # command_allow =
+
+    # Shell command to be executed with all other recommendations.
+    # command_block =
+
+    # Database URI for the database that stores the package information. If it
+    # contains a password, make sure to adjust the permissions of the config
+    # file accordingly.
+    # database =
+
+    # Plugins to load in IMV policy manager.
+    # load = sqlite
+
+}
+
diff --git a/conf/options/imv_policy_manager.opt b/conf/options/imv_policy_manager.opt
new file mode 100644
index 0000000..6ed0efc
--- /dev/null
+++ b/conf/options/imv_policy_manager.opt
@@ -0,0 +1,13 @@
+imv_policy_manager.database =
+	Database URI for the database that stores the package information. If it
+	contains a password, make sure to adjust the permissions of the config file
+	accordingly.
+
+imv_policy_manager.load = sqlite
+	Plugins to load in IMV policy manager.
+
+imv_policy_manager.command_allow =
+	Shell command to be executed with recommendation allow.
+
+imv_policy_manager.command_block =
+	Shell command to be executed with all other recommendations. 
diff --git a/conf/plugins/kernel-netlink.conf b/conf/plugins/kernel-netlink.conf
index 723bf0a..6ea341f 100644
--- a/conf/plugins/kernel-netlink.conf
+++ b/conf/plugins/kernel-netlink.conf
@@ -1,5 +1,8 @@
 kernel-netlink {
 
+    # Buffer size for received Netlink messages.
+    # buflen = 4096
+
     # Firewall mark to set on the routing rule that directs traffic to our
     # routing table.
     # fwmark =
diff --git a/conf/plugins/kernel-netlink.opt b/conf/plugins/kernel-netlink.opt
index 800ba20..4338a5f 100644
--- a/conf/plugins/kernel-netlink.opt
+++ b/conf/plugins/kernel-netlink.opt
@@ -1,3 +1,6 @@
+charon.plugins.kernel-netlink.buflen = 4096
+	Buffer size for received Netlink messages.
+
 charon.plugins.kernel-netlink.fwmark =
 	Firewall mark to set on the routing rule that directs traffic to our routing
 	table.
diff --git a/conf/strongswan.conf.5.main b/conf/strongswan.conf.5.main
index b6db9c9..b81b58c 100644
--- a/conf/strongswan.conf.5.main
+++ b/conf/strongswan.conf.5.main
@@ -853,6 +853,10 @@ plugins can be used
 to circumvent that problem.
 
 .TP
+.BR charon.plugins.kernel-netlink.buflen " [4096]"
+Buffer size for received Netlink messages.
+
+.TP
 .BR charon.plugins.kernel-netlink.fwmark " []"
 Firewall mark to set on the routing rule that directs traffic to our routing
 table. The format is [!]mark[/mask], where the optional exclamation mark inverts
@@ -1661,6 +1665,24 @@ Specifies the default loglevel to be used for subsystems for which no specific
 loglevel is defined.
 
 .TP
+.BR imv_policy_manager.command_allow " []"
+Shell command to be executed with recommendation allow.
+
+.TP
+.BR imv_policy_manager.command_block " []"
+Shell command to be executed with all other recommendations.
+
+.TP
+.BR imv_policy_manager.database " []"
+Database URI for the database that stores the package information. If it
+contains a password, make sure to adjust the permissions of the config file
+accordingly.
+
+.TP
+.BR imv_policy_manager.load " [sqlite]"
+Plugins to load in IMV policy manager.
+
+.TP
 .BR libimcv.debug_level " [1]"
 Debug level for a stand\-alone
 .RI "" "libimcv" ""
diff --git a/config.h.in b/config.h.in
index ad095d0..7633409 100644
--- a/config.h.in
+++ b/config.h.in
@@ -97,6 +97,9 @@
 /* have struct in6_pktinfo.ipi6_ifindex */
 #undef HAVE_IN6_PKTINFO
 
+/* have __int128 type support */
+#undef HAVE_INT128
+
 /* Define to 1 if you have the <inttypes.h> header file. */
 #undef HAVE_INTTYPES_H
 
diff --git a/configure b/configure
index 811e452..a7e5faa 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for strongSwan 5.3.0.
+# Generated by GNU Autoconf 2.69 for strongSwan 5.3.1.
 #
 #
 # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -587,8 +587,8 @@ MAKEFLAGS=
 # Identity of this package.
 PACKAGE_NAME='strongSwan'
 PACKAGE_TARNAME='strongswan'
-PACKAGE_VERSION='5.3.0'
-PACKAGE_STRING='strongSwan 5.3.0'
+PACKAGE_VERSION='5.3.1'
+PACKAGE_STRING='strongSwan 5.3.1'
 PACKAGE_BUGREPORT=''
 PACKAGE_URL=''
 
@@ -963,6 +963,8 @@ USE_NONCE_FALSE
 USE_NONCE_TRUE
 USE_RANDOM_FALSE
 USE_RANDOM_TRUE
+USE_AESNI_FALSE
+USE_AESNI_TRUE
 USE_RDRAND_FALSE
 USE_RDRAND_TRUE
 USE_GMP_FALSE
@@ -1015,9 +1017,13 @@ attest_plugins
 pool_plugins
 starter_plugins
 charon_plugins
+PYTHON_EGGS_INSTALL_FALSE
+PYTHON_EGGS_INSTALL_TRUE
 PY_TEST
 PYTHONEGGINSTALLDIR
 EASY_INSTALL
+RUBY_GEMS_INSTALL_FALSE
+RUBY_GEMS_INSTALL_TRUE
 RUBYGEMDIR
 GEM
 COVERAGE_LDFLAGS
@@ -1281,6 +1287,7 @@ enable_padlock
 enable_random
 enable_rc2
 enable_rdrand
+enable_aesni
 enable_sha1
 enable_sha2
 enable_xcbc
@@ -1417,7 +1424,9 @@ enable_load_warning
 enable_mediation
 enable_unwind_backtraces
 enable_ruby_gems
+enable_ruby_gems_install
 enable_python_eggs
+enable_python_eggs_install
 enable_coverage
 enable_leak_detective
 enable_lock_profiler
@@ -2009,7 +2018,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures strongSwan 5.3.0 to adapt to many kinds of systems.
+\`configure' configures strongSwan 5.3.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -2079,7 +2088,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of strongSwan 5.3.0:";;
+     short | recursive ) echo "Configuration of strongSwan 5.3.1:";;
    esac
   cat <<\_ACEOF
 
@@ -2112,6 +2121,7 @@ Optional Features:
   --disable-random        disable RNG implementation on top of /dev/(u)random.
   --disable-rc2           disable RC2 software implementation plugin.
   --enable-rdrand         enable Intel RDRAND random generator plugin.
+  --enable-aesni          enable Intel AES-NI crypto plugin.
   --disable-sha1          disable SHA1 software implementation plugin.
   --disable-sha2          disable SHA256/SHA384/SHA512 software implementation
                           plugin.
@@ -2293,8 +2303,12 @@ Optional Features:
   --enable-unwind-backtraces
                           use libunwind to create backtraces for memory leaks
                           and segfaults.
-  --enable-ruby-gems      enable installation of provided ruby gems.
-  --enable-python-eggs    enable installation of provided python eggs.
+  --enable-ruby-gems      enable build of provided ruby gems.
+  --enable-ruby-gems-install
+                          enable installation of provided ruby gems.
+  --enable-python-eggs    enable build of provided python eggs.
+  --enable-python-eggs-install
+                          enable installation of provided python eggs.
   --enable-coverage       enable lcov coverage report generation.
   --enable-leak-detective enable malloc hooks to find memory leaks.
   --enable-lock-profiler  enable lock/mutex profiling code.
@@ -2512,7 +2526,7 @@ fi
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-strongSwan configure 5.3.0
+strongSwan configure 5.3.1
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -3034,7 +3048,7 @@ cat >config.log <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by strongSwan $as_me 5.3.0, which was
+It was created by strongSwan $as_me 5.3.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -3897,7 +3911,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE='strongswan'
- VERSION='5.3.0'
+ VERSION='5.3.1'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -5102,6 +5116,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" rdrand"
 
+# Check whether --enable-aesni was given.
+if test "${enable_aesni+set}" = set; then :
+  enableval=$enable_aesni; aesni_given=true
+		if test x$enableval = xyes; then
+			aesni=true
+		 else
+			aesni=false
+		fi
+else
+  aesni=false
+		aesni_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" aesni"
+
 # Check whether --enable-sha1 was given.
 if test "${enable_sha1+set}" = set; then :
   enableval=$enable_sha1; sha1_given=true
@@ -7289,6 +7319,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" ruby_gems"
 
+# Check whether --enable-ruby-gems-install was given.
+if test "${enable_ruby_gems_install+set}" = set; then :
+  enableval=$enable_ruby_gems_install; ruby_gems_install_given=true
+		if test x$enableval = xyes; then
+			ruby_gems_install=true
+		 else
+			ruby_gems_install=false
+		fi
+else
+  ruby_gems_install=false
+		ruby_gems_install_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" ruby_gems_install"
+
 # Check whether --enable-python-eggs was given.
 if test "${enable_python_eggs+set}" = set; then :
   enableval=$enable_python_eggs; python_eggs_given=true
@@ -7305,6 +7351,22 @@ fi
 
 	disabled_by_default=${disabled_by_default}" python_eggs"
 
+# Check whether --enable-python-eggs-install was given.
+if test "${enable_python_eggs_install+set}" = set; then :
+  enableval=$enable_python_eggs_install; python_eggs_install_given=true
+		if test x$enableval = xyes; then
+			python_eggs_install=true
+		 else
+			python_eggs_install=false
+		fi
+else
+  python_eggs_install=false
+		python_eggs_install_given=false
+
+fi
+
+	disabled_by_default=${disabled_by_default}" python_eggs_install"
+
 # compile options
 # Check whether --enable-coverage was given.
 if test "${enable_coverage+set}" = set; then :
@@ -17175,6 +17237,14 @@ if test x$medcli = xtrue; then
 	mediation=true
 fi
 
+if test x$ruby_gems_install = xtrue; then
+	ruby_gems=true
+fi
+
+if test x$python_eggs_install = xtrue; then
+	python_eggs=true
+fi
+
 # ===========================================
 #  check required libraries and header files
 # ===========================================
@@ -18437,6 +18507,33 @@ $as_echo "no" >&6; }
 fi
 rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for __int128" >&5
+$as_echo_n "checking for __int128... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <sys/types.h>
+int
+main ()
+{
+__int128 x = 0;
+		  return x;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; };
+
+$as_echo "#define HAVE_INT128 /**/" >>confdefs.h
+
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC __sync operations" >&5
 $as_echo_n "checking for GCC __sync operations... " >&6; }
 if test "$cross_compiling" = yes; then :
@@ -21529,9 +21626,18 @@ fi
 	RUBYGEMDIR="$rubygemdir"
 
 fi
+ if test "x$ruby_gems_install" = xtrue; then
+  RUBY_GEMS_INSTALL_TRUE=
+  RUBY_GEMS_INSTALL_FALSE='#'
+else
+  RUBY_GEMS_INSTALL_TRUE='#'
+  RUBY_GEMS_INSTALL_FALSE=
+fi
+
 
 if test x$python_eggs = xtrue; then
-	# Extract the first word of "easy_install", so it can be a program name with args.
+	if test x$python_eggs_install = xtrue; then
+		# Extract the first word of "easy_install", so it can be a program name with args.
 set dummy easy_install; ac_word=$2
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
 $as_echo_n "checking for $ac_word... " >&6; }
@@ -21572,8 +21678,9 @@ $as_echo "no" >&6; }
 fi
 
 
-	if test x$EASY_INSTALL = x; then
-		as_fn_error $? "Python easy_install not found" "$LINENO" 5
+		if test x$EASY_INSTALL = x; then
+			as_fn_error $? "Python easy_install not found" "$LINENO" 5
+		fi
 	fi
 	if test "x$pythoneggdir" = "xmain site-packages directory"; then
 		PYTHONEGGINSTALLDIR=""
@@ -21624,6 +21731,14 @@ fi
 
 
 fi
+ if test "x$python_eggs_install" = xtrue; then
+  PYTHON_EGGS_INSTALL_TRUE=
+  PYTHON_EGGS_INSTALL_FALSE='#'
+else
+  PYTHON_EGGS_INSTALL_TRUE='#'
+  PYTHON_EGGS_INSTALL_FALSE=
+fi
+
 
 # ===============================================
 #  collect plugin list for strongSwan components
@@ -21690,6 +21805,20 @@ if test x$pkcs11 = xtrue; then
 
 	fi
 
+if test x$aesni = xtrue; then
+		s_plugins=${s_plugins}" aesni"
+		charon_plugins=${charon_plugins}" aesni"
+		scepclient_plugins=${scepclient_plugins}" aesni"
+		pki_plugins=${pki_plugins}" aesni"
+		scripts_plugins=${scripts_plugins}" aesni"
+		medsrv_plugins=${medsrv_plugins}" aesni"
+		attest_plugins=${attest_plugins}" aesni"
+		nm_plugins=${nm_plugins}" aesni"
+		cmd_plugins=${cmd_plugins}" aesni"
+		aikgen_plugins=${aikgen_plugins}" aesni"
+
+	fi
+
 if test x$aes = xtrue; then
 		s_plugins=${s_plugins}" aes"
 		charon_plugins=${charon_plugins}" aes"
@@ -22817,6 +22946,14 @@ else
   USE_RDRAND_FALSE=
 fi
 
+ if test x$aesni = xtrue; then
+  USE_AESNI_TRUE=
+  USE_AESNI_FALSE='#'
+else
+  USE_AESNI_TRUE='#'
+  USE_AESNI_FALSE=
+fi
+
  if test x$random = xtrue; then
   USE_RANDOM_TRUE=
   USE_RANDOM_FALSE='#'
@@ -24229,7 +24366,7 @@ fi
 #  build Makefiles
 # =================
 
-ac_config_files="$ac_config_files Makefile conf/Makefile man/Makefile init/Makefile init/systemd/Makefile init/systemd-swanctl/Makefile src/Makefile src/include/Makefile src/libstrongswan/Makefile src/libstrongswan/plugins/aes/Makefile src/libstrongswan/plugins/cmac/Makefile src/libstrongswan/plugins/des/Makefile src/libstrongswan/plugins/blowfish/Makefile src/libstrongswan/plugins/rc2/Makefile src/libstrongswan/plugins/md4/Makefile src/libstrongswan/plugins/md5/Makefile src/libstrongswa [...]
+ac_config_files="$ac_config_files Makefile conf/Makefile man/Makefile init/Makefile init/systemd/Makefile init/systemd-swanctl/Makefile src/Makefile src/include/Makefile src/libstrongswan/Makefile src/libstrongswan/plugins/aes/Makefile src/libstrongswan/plugins/cmac/Makefile src/libstrongswan/plugins/des/Makefile src/libstrongswan/plugins/blowfish/Makefile src/libstrongswan/plugins/rc2/Makefile src/libstrongswan/plugins/md4/Makefile src/libstrongswan/plugins/md5/Makefile src/libstrongswa [...]
 
 
 # =================
@@ -24385,6 +24522,14 @@ if test -z "${USE_DEV_HEADERS_TRUE}" && test -z "${USE_DEV_HEADERS_FALSE}"; then
   as_fn_error $? "conditional \"USE_DEV_HEADERS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${RUBY_GEMS_INSTALL_TRUE}" && test -z "${RUBY_GEMS_INSTALL_FALSE}"; then
+  as_fn_error $? "conditional \"RUBY_GEMS_INSTALL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
+if test -z "${PYTHON_EGGS_INSTALL_TRUE}" && test -z "${PYTHON_EGGS_INSTALL_FALSE}"; then
+  as_fn_error $? "conditional \"PYTHON_EGGS_INSTALL\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_TEST_VECTORS_TRUE}" && test -z "${USE_TEST_VECTORS_FALSE}"; then
   as_fn_error $? "conditional \"USE_TEST_VECTORS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -24457,6 +24602,10 @@ if test -z "${USE_RDRAND_TRUE}" && test -z "${USE_RDRAND_FALSE}"; then
   as_fn_error $? "conditional \"USE_RDRAND\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${USE_AESNI_TRUE}" && test -z "${USE_AESNI_FALSE}"; then
+  as_fn_error $? "conditional \"USE_AESNI\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${USE_RANDOM_TRUE}" && test -z "${USE_RANDOM_FALSE}"; then
   as_fn_error $? "conditional \"USE_RANDOM\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -25514,7 +25663,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by strongSwan $as_me 5.3.0, which was
+This file was extended by strongSwan $as_me 5.3.1, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -25580,7 +25729,7 @@ _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-strongSwan config.status 5.3.0
+strongSwan config.status 5.3.1
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
@@ -26010,6 +26159,7 @@ do
     "src/libstrongswan/plugins/fips_prf/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/fips_prf/Makefile" ;;
     "src/libstrongswan/plugins/gmp/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/gmp/Makefile" ;;
     "src/libstrongswan/plugins/rdrand/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/rdrand/Makefile" ;;
+    "src/libstrongswan/plugins/aesni/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/aesni/Makefile" ;;
     "src/libstrongswan/plugins/random/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/random/Makefile" ;;
     "src/libstrongswan/plugins/nonce/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/nonce/Makefile" ;;
     "src/libstrongswan/plugins/hmac/Makefile") CONFIG_FILES="$CONFIG_FILES src/libstrongswan/plugins/hmac/Makefile" ;;
diff --git a/configure.ac b/configure.ac
index 73c2884..d8278db 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@
 #  initialize & set some vars
 # ============================
 
-AC_INIT([strongSwan],[5.3.0])
+AC_INIT([strongSwan],[5.3.1])
 AM_INIT_AUTOMAKE(m4_esyscmd([
 	echo tar-ustar
 	echo subdir-objects
@@ -144,6 +144,7 @@ ARG_ENABL_SET([padlock],        [enables VIA Padlock crypto plugin.])
 ARG_DISBL_SET([random],         [disable RNG implementation on top of /dev/(u)random.])
 ARG_DISBL_SET([rc2],            [disable RC2 software implementation plugin.])
 ARG_ENABL_SET([rdrand],         [enable Intel RDRAND random generator plugin.])
+ARG_ENABL_SET([aesni],          [enable Intel AES-NI crypto plugin.])
 ARG_DISBL_SET([sha1],           [disable SHA1 software implementation plugin.])
 ARG_DISBL_SET([sha2],           [disable SHA256/SHA384/SHA512 software implementation plugin.])
 ARG_DISBL_SET([xcbc],           [disable xcbc crypto implementation plugin.])
@@ -290,8 +291,10 @@ ARG_ENABL_SET([integrity-test], [enable integrity testing of libstrongswan and p
 ARG_DISBL_SET([load-warning],   [disable the charon plugin load option warning in starter.])
 ARG_ENABL_SET([mediation],      [enable IKEv2 Mediation Extension.])
 ARG_ENABL_SET([unwind-backtraces],[use libunwind to create backtraces for memory leaks and segfaults.])
-ARG_ENABL_SET([ruby-gems],      [enable installation of provided ruby gems.])
-ARG_ENABL_SET([python-eggs],    [enable installation of provided python eggs.])
+ARG_ENABL_SET([ruby-gems],      [enable build of provided ruby gems.])
+ARG_ENABL_SET([ruby-gems-install],[enable installation of provided ruby gems.])
+ARG_ENABL_SET([python-eggs],    [enable build of provided python eggs.])
+ARG_ENABL_SET([python-eggs-install],[enable installation of provided python eggs.])
 # compile options
 ARG_ENABL_SET([coverage],       [enable lcov coverage report generation.])
 ARG_ENABL_SET([leak-detective], [enable malloc hooks to find memory leaks.])
@@ -432,6 +435,14 @@ if test x$medcli = xtrue; then
 	mediation=true
 fi
 
+if test x$ruby_gems_install = xtrue; then
+	ruby_gems=true
+fi
+
+if test x$python_eggs_install = xtrue; then
+	python_eggs=true
+fi
+
 # ===========================================
 #  check required libraries and header files
 # ===========================================
@@ -697,6 +708,17 @@ AC_COMPILE_IFELSE(
 	[AC_MSG_RESULT([no])]
 )
 
+AC_MSG_CHECKING([for __int128])
+AC_COMPILE_IFELSE(
+	[AC_LANG_PROGRAM(
+		[[#include <sys/types.h>]],
+		[[__int128 x = 0;
+		  return x;]])],
+	[AC_MSG_RESULT([yes]);
+	 AC_DEFINE([HAVE_INT128], [], [have __int128 type support])],
+	[AC_MSG_RESULT([no])]
+)
+
 AC_MSG_CHECKING([for GCC __sync operations])
 AC_RUN_IFELSE([AC_LANG_SOURCE(
 	[[
@@ -1187,11 +1209,14 @@ if test x$ruby_gems = xtrue; then
 	fi
 	AC_SUBST(RUBYGEMDIR, "$rubygemdir")
 fi
+AM_CONDITIONAL(RUBY_GEMS_INSTALL, [test "x$ruby_gems_install" = xtrue])
 
 if test x$python_eggs = xtrue; then
-	AC_PATH_PROG([EASY_INSTALL], [easy_install], [], [$PATH:/bin:/usr/bin:/usr/local/bin])
-	if test x$EASY_INSTALL = x; then
-		AC_MSG_ERROR(Python easy_install not found)
+	if test x$python_eggs_install = xtrue; then
+		AC_PATH_PROG([EASY_INSTALL], [easy_install], [], [$PATH:/bin:/usr/bin:/usr/local/bin])
+		if test x$EASY_INSTALL = x; then
+			AC_MSG_ERROR(Python easy_install not found)
+		fi
 	fi
 	if test "x$pythoneggdir" = "xmain site-packages directory"; then
 		AC_SUBST(PYTHONEGGINSTALLDIR, "")
@@ -1200,6 +1225,7 @@ if test x$python_eggs = xtrue; then
 	fi
 	AC_PATH_PROG([PY_TEST], [py.test], [], [$PATH:/bin:/usr/bin:/usr/local/bin])
 fi
+AM_CONDITIONAL(PYTHON_EGGS_INSTALL, [test "x$python_eggs_install" = xtrue])
 
 # ===============================================
 #  collect plugin list for strongSwan components
@@ -1232,6 +1258,7 @@ ADD_PLUGIN([test-vectors],         [s charon scepclient pki])
 ADD_PLUGIN([unbound],              [s charon scripts])
 ADD_PLUGIN([ldap],                 [s charon scepclient scripts nm cmd])
 ADD_PLUGIN([pkcs11],               [s charon pki nm cmd])
+ADD_PLUGIN([aesni],                [s charon scepclient pki scripts medsrv attest nm cmd aikgen])
 ADD_PLUGIN([aes],                  [s charon scepclient pki scripts nm cmd])
 ADD_PLUGIN([des],                  [s charon scepclient pki scripts nm cmd])
 ADD_PLUGIN([blowfish],             [s charon scepclient pki scripts nm cmd])
@@ -1395,6 +1422,7 @@ AM_CONDITIONAL(USE_SHA2, test x$sha2 = xtrue)
 AM_CONDITIONAL(USE_FIPS_PRF, test x$fips_prf = xtrue)
 AM_CONDITIONAL(USE_GMP, test x$gmp = xtrue)
 AM_CONDITIONAL(USE_RDRAND, test x$rdrand = xtrue)
+AM_CONDITIONAL(USE_AESNI, test x$aesni = xtrue)
 AM_CONDITIONAL(USE_RANDOM, test x$random = xtrue)
 AM_CONDITIONAL(USE_NONCE, test x$nonce = xtrue)
 AM_CONDITIONAL(USE_X509, test x$x509 = xtrue)
@@ -1638,6 +1666,7 @@ AC_CONFIG_FILES([
 	src/libstrongswan/plugins/fips_prf/Makefile
 	src/libstrongswan/plugins/gmp/Makefile
 	src/libstrongswan/plugins/rdrand/Makefile
+	src/libstrongswan/plugins/aesni/Makefile
 	src/libstrongswan/plugins/random/Makefile
 	src/libstrongswan/plugins/nonce/Makefile
 	src/libstrongswan/plugins/hmac/Makefile
diff --git a/init/Makefile.am b/init/Makefile.am
index a72706c..6fff422 100644
--- a/init/Makefile.am
+++ b/init/Makefile.am
@@ -2,8 +2,10 @@
 SUBDIRS =
 
 if USE_LEGACY_SYSTEMD
+if USE_CHARON
   SUBDIRS += systemd
 endif
+endif
 
 if USE_SYSTEMD
 if USE_SWANCTL
diff --git a/init/Makefile.in b/init/Makefile.in
index 18c69f1..883d424 100644
--- a/init/Makefile.in
+++ b/init/Makefile.in
@@ -77,7 +77,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
- at USE_LEGACY_SYSTEMD_TRUE@am__append_1 = systemd
+ at USE_CHARON_TRUE@@USE_LEGACY_SYSTEMD_TRUE at am__append_1 = systemd
 @USE_SWANCTL_TRUE@@USE_SYSTEMD_TRUE at am__append_2 = systemd-swanctl
 subdir = init
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am
diff --git a/man/ipsec.conf.5.in b/man/ipsec.conf.5.in
index 39c3b2b..6501217 100644
--- a/man/ipsec.conf.5.in
+++ b/man/ipsec.conf.5.in
@@ -237,7 +237,7 @@ or
 .B esp
 keyword may be used, AH+ESP bundles are not supported.
 
-There is no default, by default ESP is used.
+There is no default AH cipher suite since by default ESP is used.
 The daemon adds its extensive default proposal to the configured value. To
 restrict it to the configured proposal an
 exclamation mark
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index abc6d75..c5155ef 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -5,7 +5,7 @@ AM_CPPFLAGS = \
 
 noinst_PROGRAMS = bin2array bin2sql id2sql key2keyid keyid2sql oid2der \
 	thread_analysis dh_speed pubkey_speed crypt_burn hash_burn fetch \
-	dnssec malloc_speed aes-test settings-test
+	dnssec malloc_speed aes-test settings-test timeattack
 
 if USE_TLS
   noinst_PROGRAMS += tls_test
@@ -28,6 +28,7 @@ hash_burn_SOURCES = hash_burn.c
 malloc_speed_SOURCES = malloc_speed.c
 fetch_SOURCES = fetch.c
 dnssec_SOURCES = dnssec.c
+timeattack_SOURCES = timeattack.c
 id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 keyid2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
@@ -41,6 +42,7 @@ fetch_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 dnssec_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 aes_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 settings_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+timeattack_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 
 key2keyid.o :	$(top_builddir)/config.status
 
diff --git a/scripts/Makefile.in b/scripts/Makefile.in
index d28783b..b03ff9d 100644
--- a/scripts/Makefile.in
+++ b/scripts/Makefile.in
@@ -83,7 +83,8 @@ noinst_PROGRAMS = bin2array$(EXEEXT) bin2sql$(EXEEXT) id2sql$(EXEEXT) \
 	thread_analysis$(EXEEXT) dh_speed$(EXEEXT) \
 	pubkey_speed$(EXEEXT) crypt_burn$(EXEEXT) hash_burn$(EXEEXT) \
 	fetch$(EXEEXT) dnssec$(EXEEXT) malloc_speed$(EXEEXT) \
-	aes-test$(EXEEXT) settings-test$(EXEEXT) $(am__EXEEXT_1)
+	aes-test$(EXEEXT) settings-test$(EXEEXT) timeattack$(EXEEXT) \
+	$(am__EXEEXT_1)
 @USE_TLS_TRUE at am__append_1 = tls_test
 subdir = scripts
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
@@ -176,6 +177,10 @@ settings_test_DEPENDENCIES =  \
 am_thread_analysis_OBJECTS = thread_analysis.$(OBJEXT)
 thread_analysis_OBJECTS = $(am_thread_analysis_OBJECTS)
 thread_analysis_LDADD = $(LDADD)
+am_timeattack_OBJECTS = timeattack.$(OBJEXT)
+timeattack_OBJECTS = $(am_timeattack_OBJECTS)
+timeattack_DEPENDENCIES =  \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la
 am__tls_test_SOURCES_DIST = tls_test.c
 @USE_TLS_TRUE at am_tls_test_OBJECTS = tls_test.$(OBJEXT)
 tls_test_OBJECTS = $(am_tls_test_OBJECTS)
@@ -221,14 +226,16 @@ SOURCES = aes-test.c $(bin2array_SOURCES) $(bin2sql_SOURCES) \
 	$(key2keyid_SOURCES) $(keyid2sql_SOURCES) \
 	$(malloc_speed_SOURCES) $(oid2der_SOURCES) \
 	$(pubkey_speed_SOURCES) settings-test.c \
-	$(thread_analysis_SOURCES) $(tls_test_SOURCES)
+	$(thread_analysis_SOURCES) $(timeattack_SOURCES) \
+	$(tls_test_SOURCES)
 DIST_SOURCES = aes-test.c $(bin2array_SOURCES) $(bin2sql_SOURCES) \
 	$(crypt_burn_SOURCES) $(dh_speed_SOURCES) $(dnssec_SOURCES) \
 	$(fetch_SOURCES) $(hash_burn_SOURCES) $(id2sql_SOURCES) \
 	$(key2keyid_SOURCES) $(keyid2sql_SOURCES) \
 	$(malloc_speed_SOURCES) $(oid2der_SOURCES) \
 	$(pubkey_speed_SOURCES) settings-test.c \
-	$(thread_analysis_SOURCES) $(am__tls_test_SOURCES_DIST)
+	$(thread_analysis_SOURCES) $(timeattack_SOURCES) \
+	$(am__tls_test_SOURCES_DIST)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -502,6 +509,7 @@ hash_burn_SOURCES = hash_burn.c
 malloc_speed_SOURCES = malloc_speed.c
 fetch_SOURCES = fetch.c
 dnssec_SOURCES = dnssec.c
+timeattack_SOURCES = timeattack.c
 id2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 key2keyid_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 keyid2sql_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
@@ -515,6 +523,7 @@ fetch_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 dnssec_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 aes_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 settings_test_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
+timeattack_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
 all: all-am
 
 .SUFFIXES:
@@ -623,6 +632,10 @@ thread_analysis$(EXEEXT): $(thread_analysis_OBJECTS) $(thread_analysis_DEPENDENC
 	@rm -f thread_analysis$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(thread_analysis_OBJECTS) $(thread_analysis_LDADD) $(LIBS)
 
+timeattack$(EXEEXT): $(timeattack_OBJECTS) $(timeattack_DEPENDENCIES) $(EXTRA_timeattack_DEPENDENCIES) 
+	@rm -f timeattack$(EXEEXT)
+	$(AM_V_CCLD)$(LINK) $(timeattack_OBJECTS) $(timeattack_LDADD) $(LIBS)
+
 tls_test$(EXEEXT): $(tls_test_OBJECTS) $(tls_test_DEPENDENCIES) $(EXTRA_tls_test_DEPENDENCIES) 
 	@rm -f tls_test$(EXEEXT)
 	$(AM_V_CCLD)$(LINK) $(tls_test_OBJECTS) $(tls_test_LDADD) $(LIBS)
@@ -649,6 +662,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/pubkey_speed.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/settings-test.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/thread_analysis.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/timeattack.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/tls_test.Po at am__quote@
 
 .c.o:
diff --git a/scripts/crypt_burn.c b/scripts/crypt_burn.c
index 1768d76..3bd36d2 100644
--- a/scripts/crypt_burn.c
+++ b/scripts/crypt_burn.c
@@ -16,34 +16,190 @@
 #include <stdio.h>
 #include <library.h>
 
-int main(int argc, char *argv[])
+static int burn_crypter(const proposal_token_t *token, u_int limit, u_int len)
 {
-	const proposal_token_t *token;
-	aead_t *aead;
+	chunk_t iv, key, data;
 	crypter_t *crypter;
-	char buffer[1024], assoc[8], iv[32];
-	size_t bs;
-	int i = 0, limit = 0;
+	int i = 0;
+	bool ok;
+
+	crypter = lib->crypto->create_crypter(lib->crypto, token->algorithm,
+										  token->keysize / 8);
+	if (!crypter)
+	{
+		fprintf(stderr, "%N-%zu not supported\n",
+				encryption_algorithm_names, token->algorithm, token->keysize);
+		return FALSE;
+	}
+
+	iv = chunk_alloc(crypter->get_iv_size(crypter));
+	memset(iv.ptr, 0xFF, iv.len);
+	data = chunk_alloc(round_up(len, crypter->get_block_size(crypter)));
+	memset(data.ptr, 0xDD, data.len);
+	key = chunk_alloc(crypter->get_key_size(crypter));
+	memset(key.ptr, 0xAA, key.len);
+
+	ok = crypter->set_key(crypter, key);
+	while (ok)
+	{
+		if (!crypter->encrypt(crypter, data, iv, NULL))
+		{
+			fprintf(stderr, "encryption failed!\n");
+			ok = FALSE;
+			break;
+		}
+		if (!crypter->decrypt(crypter, data, iv, NULL))
+		{
+			fprintf(stderr, "decryption failed!\n");
+			ok = FALSE;
+			break;
+		}
+		if (limit && ++i == limit)
+		{
+			break;
+		}
+	}
+	crypter->destroy(crypter);
+
+	free(iv.ptr);
+	free(data.ptr);
+	free(key.ptr);
+
+	return ok;
+}
+
+static bool burn_aead(const proposal_token_t *token, u_int limit, u_int len)
+{
+	chunk_t iv, key, data, dataicv, assoc;
+	aead_t *aead;
+	int i = 0;
+	bool ok;
+
+	aead = lib->crypto->create_aead(lib->crypto, token->algorithm,
+									token->keysize / 8, 0);
+	if (!aead)
+	{
+		fprintf(stderr, "%N-%zu not supported\n",
+				encryption_algorithm_names, token->algorithm, token->keysize);
+		return FALSE;
+	}
+
+	iv = chunk_alloc(aead->get_iv_size(aead));
+	memset(iv.ptr, 0xFF, iv.len);
+	dataicv = chunk_alloc(round_up(len, aead->get_block_size(aead)) +
+						  aead->get_icv_size(aead));
+	data = chunk_create(dataicv.ptr, dataicv.len - aead->get_icv_size(aead));
+	memset(data.ptr, 0xDD, data.len);
+	assoc = chunk_alloc(13);
+	memset(assoc.ptr, 0xCC, assoc.len);
+	key = chunk_alloc(aead->get_key_size(aead));
+	memset(key.ptr, 0xAA, key.len);
+
+	ok = aead->set_key(aead, key);
+	while (ok)
+	{
+		if (!aead->encrypt(aead, data, assoc, iv, NULL))
+		{
+			fprintf(stderr, "aead encryption failed!\n");
+			ok = FALSE;
+			break;
+		}
+		if (!aead->decrypt(aead, dataicv, assoc, iv, NULL))
+		{
+			fprintf(stderr, "aead integrity check failed!\n");
+			ok = FALSE;
+			break;
+		}
+		if (limit && ++i == limit)
+		{
+			break;
+		}
+	}
+	aead->destroy(aead);
+
+	free(iv.ptr);
+	free(data.ptr);
+	free(key.ptr);
+	free(assoc.ptr);
+
+	return ok;
+}
+
+static int burn_signer(const proposal_token_t *token, u_int limit, u_int len)
+{
+	chunk_t  key, data, sig;
+	signer_t *signer;
+	int i = 0;
+	bool ok;
+
+	signer = lib->crypto->create_signer(lib->crypto, token->algorithm);
+	if (!signer)
+	{
+		fprintf(stderr, "%N not supported\n",
+				integrity_algorithm_names, token->algorithm);
+		return FALSE;
+	}
+
+	data = chunk_alloc(len);
+	memset(data.ptr, 0xDD, data.len);
+	key = chunk_alloc(signer->get_key_size(signer));
+	memset(key.ptr, 0xAA, key.len);
+	sig = chunk_alloc(signer->get_block_size(signer));
+
+	ok = signer->set_key(signer, key);
+	while (ok)
+	{
+		if (!signer->get_signature(signer, data, sig.ptr))
+		{
+			fprintf(stderr, "creating signature failed!\n");
+			ok = FALSE;
+			break;
+		}
+		if (!signer->verify_signature(signer, data, sig))
+		{
+			fprintf(stderr, "verifying signature failed!\n");
+			ok = FALSE;
+			break;
+		}
+		if (limit && ++i == limit)
+		{
+			break;
+		}
+	}
+	signer->destroy(signer);
 
+	free(data.ptr);
+	free(key.ptr);
+	free(sig.ptr);
+
+	return ok;
+}
+
+int main(int argc, char *argv[])
+{
+	const proposal_token_t *token;
+	u_int limit = 0, len = 1024;
+	bool ok;
 
 	library_init(NULL, "crypt_burn");
-	lib->plugins->load(lib->plugins, PLUGINS);
+	lib->plugins->load(lib->plugins, getenv("PLUGINS") ?: PLUGINS);
 	atexit(library_deinit);
 
-	printf("loaded: %s\n", PLUGINS);
-
-	memset(buffer, 0x12, sizeof(buffer));
-	memset(assoc, 0x34, sizeof(assoc));
-	memset(iv, 0x56, sizeof(iv));
+	fprintf(stderr, "loaded: %s\n", lib->plugins->loaded_plugins(lib->plugins));
 
 	if (argc < 2)
 	{
-		fprintf(stderr, "usage: %s <algorithm>!\n", argv[0]);
+		fprintf(stderr, "usage: %s <algorithm> [buflen=%u] [rounds=%u]\n",
+				argv[0], len, limit);
 		return 1;
 	}
 	if (argc > 2)
 	{
-		limit = atoi(argv[2]);
+		len = atoi(argv[2]);
+	}
+	if (argc > 3)
+	{
+		limit = atoi(argv[3]);
 	}
 
 	token = lib->proposal->get_token(lib->proposal, argv[1]);
@@ -52,76 +208,26 @@ int main(int argc, char *argv[])
 		fprintf(stderr, "algorithm '%s' unknown!\n", argv[1]);
 		return 1;
 	}
-	if (token->type != ENCRYPTION_ALGORITHM)
-	{
-		fprintf(stderr, "'%s' is not an encryption/aead algorithm!\n", argv[1]);
-		return 1;
-	}
 
-	if (encryption_algorithm_is_aead(token->algorithm))
+	switch (token->type)
 	{
-		aead = lib->crypto->create_aead(lib->crypto,
-									token->algorithm, token->keysize / 8, 0);
-		if (!aead)
-		{
-			fprintf(stderr, "aead '%s' not supported!\n", argv[1]);
-			return 1;
-		}
-		while (TRUE)
-		{
-			if (!aead->encrypt(aead,
-				chunk_create(buffer, sizeof(buffer) - aead->get_icv_size(aead)),
-				chunk_from_thing(assoc),
-				chunk_create(iv, aead->get_iv_size(aead)), NULL))
+		case ENCRYPTION_ALGORITHM:
+			if (encryption_algorithm_is_aead(token->algorithm))
 			{
-				fprintf(stderr, "aead encryption failed!\n");
-				return 1;
+				ok = burn_aead(token, limit, len);
 			}
-			if (!aead->decrypt(aead, chunk_create(buffer, sizeof(buffer)),
-				chunk_from_thing(assoc),
-				chunk_create(iv, aead->get_iv_size(aead)), NULL))
+			else
 			{
-				fprintf(stderr, "aead integrity check failed!\n");
-				return 1;
+				ok = burn_crypter(token, limit, len);
 			}
-			if (limit && ++i == limit)
-			{
-				break;
-			}
-		}
-		aead->destroy(aead);
-	}
-	else
-	{
-		crypter = lib->crypto->create_crypter(lib->crypto,
-										token->algorithm, token->keysize / 8);
-		if (!crypter)
-		{
-			fprintf(stderr, "crypter '%s' not supported!\n", argv[1]);
-			return 1;
-		}
-		bs = crypter->get_block_size(crypter);
-
-		while (TRUE)
-		{
-			if (!crypter->encrypt(crypter,
-					chunk_create(buffer, sizeof(buffer) / bs * bs),
-					chunk_create(iv, crypter->get_iv_size(crypter)), NULL))
-			{
-				continue;
-			}
-			if (!crypter->decrypt(crypter,
-					chunk_create(buffer, sizeof(buffer) / bs * bs),
-					chunk_create(iv, crypter->get_iv_size(crypter)), NULL))
-			{
-				continue;
-			}
-			if (limit && ++i == limit)
-			{
-				break;
-			}
-		}
-		crypter->destroy(crypter);
+			break;
+		case INTEGRITY_ALGORITHM:
+			ok = burn_signer(token, limit, len);
+			break;
+		default:
+			fprintf(stderr, "'%s' is not a crypter/aead algorithm!\n", argv[1]);
+			ok = FALSE;
+			break;
 	}
-	return 0;
+	return !ok;
 }
diff --git a/scripts/timeattack.c b/scripts/timeattack.c
new file mode 100644
index 0000000..ef00e8c
--- /dev/null
+++ b/scripts/timeattack.c
@@ -0,0 +1,418 @@
+#include <stdio.h>
+#include <time.h>
+
+#include <library.h>
+
+typedef bool (*attackfn_t)(void *subj, u_char *data, size_t len);
+
+static void start_timing(struct timespec *start)
+{
+	clock_gettime(CLOCK_PROCESS_CPUTIME_ID, start);
+}
+
+static u_int64_t end_timing(struct timespec *start)
+{
+	struct timespec end;
+
+	clock_gettime(CLOCK_THREAD_CPUTIME_ID, &end);
+	return (end.tv_nsec - start->tv_nsec) +
+		   (end.tv_sec - start->tv_sec) * 1000000000;
+}
+
+static int intcmp(const void *a, const void *b)
+{
+	return *(u_int64_t*)a - *(u_int64_t*)b;
+}
+
+static u_int64_t median(u_int64_t *m, int count)
+{
+	qsort(m, count, sizeof(u_int64_t), intcmp);
+	return m[count / 2];
+}
+
+static bool timeattack(attackfn_t attackfn, void *subj, size_t dlen,
+					   u_int iterations, u_int distance)
+{
+	struct timespec start;
+	u_char test[dlen];
+	u_int64_t mini, maxi, t[256], m[256][10];
+	float fastdist = 0, slowdist = 0;
+	int i, j, k, l, byte, limit, retry = 0;
+	int fastest = 0, slowest = 0;
+
+	memset(test, 0, dlen);
+
+	/* do some iterations to fill caches */
+	for (i = 0; i < iterations; i++)
+	{
+		attackfn(subj, test, dlen);
+	}
+
+	for (byte = 0; byte < dlen;)
+	{
+		memset(t, 0, sizeof(t));
+		memset(m, 0, sizeof(m));
+
+		limit = iterations * (retry + 1);
+
+		/* measure timing for all patterns in next byte */
+		for (k = 0; k < 10; k++)
+		{
+			for (j = 0; j < 256; j++)
+			{
+				for (l = 0; l < 100; l++)
+				{
+					test[byte] = j;
+					start_timing(&start);
+					for (i = 0; i < limit; i++)
+					{
+						attackfn(subj, test, dlen);
+					}
+					m[j][k] += end_timing(&start);
+				}
+			}
+		}
+
+		for (j = 0; j < 256; j++)
+		{
+			t[j] = median(m[j], countof(m[j]));
+		}
+
+		/* find fastest/slowest runs */
+		mini = ~0;
+		maxi = 0;
+		for (j = 0; j < 256; j++)
+		{
+			if (t[j] < mini)
+			{
+				mini = min(t[j], mini);
+				fastest = j;
+			}
+			if (t[j] > maxi)
+			{
+				maxi = max(t[j], maxi);
+				slowest = j;
+			}
+		}
+		/* calculate distance to next result */
+		mini = ~0;
+		maxi = 0;
+		for (j = 0; j < 256; j++)
+		{
+			if (fastest != j && t[j] < mini)
+			{
+				mini = min(t[j], mini);
+				fastdist = (float)(t[j] - t[fastest]) / distance;
+			}
+			if (slowest != j && t[j] > maxi)
+			{
+				maxi = max(t[j], maxi);
+				slowdist = (float)(t[slowest] - t[j]) / distance;
+			}
+		}
+		if (fastdist > 1.0f)
+		{
+			fprintf(stderr, "byte %02d: %02x (fastest, dist %02.2f)\n",
+					byte, fastest, fastdist);
+			test[byte] = fastest;
+			retry = 0;
+			byte++;
+		}
+		else if (slowdist > 1.0f)
+		{
+			fprintf(stderr, "byte %02d: %02x (slowest, dist %02.2f)\n",
+					byte, slowest, slowdist);
+			test[byte] = slowest;
+			retry = 0;
+			byte++;
+		}
+		else
+		{
+			if (retry++ > 5 && byte > 0)
+			{
+				fprintf(stderr, "distance fastest %02.2f (%02x), "
+						"slowest %02.2f (%02x), stepping back\n",
+						fastdist, fastest, slowdist, slowest);
+				test[byte--] = 0;
+			}
+			else if (retry < 10)
+			{
+				fprintf(stderr, "distance fastest %02.2f (%02x), "
+						"slowest %02.2f (%02x), retrying (%d)\n",
+						fastdist, fastest, slowdist, slowest, retry);
+			}
+			else
+			{
+				printf("attack failed, giving up\n");
+				return FALSE;
+			}
+		}
+	}
+	if (attackfn(subj, test, dlen))
+	{
+		printf("attack successful with %b\n", test, dlen);
+		return TRUE;
+	}
+	printf("attack failed with %b\n", test, dlen);
+	return FALSE;
+}
+
+CALLBACK(attack_memeq1, bool,
+	u_char *subj, u_char *data, size_t len)
+{
+	return memeq(data, subj, len);
+}
+
+CALLBACK(attack_memeq2, bool,
+	u_char *subj, u_char *data, size_t len)
+{
+	return memeq(subj, data, len);
+}
+
+CALLBACK(attack_memeq3, bool,
+	u_char *subj, u_char *data, size_t len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+	{
+		if (subj[i] != data[i])
+		{
+			return FALSE;
+		}
+	}
+	return TRUE;
+}
+
+CALLBACK(attack_memeq4, bool,
+	u_char *subj, u_char *data, size_t len)
+{
+	int i, m = 0;
+
+	for (i = 0; i < len; i++)
+	{
+		m |= subj[i] != data[i];
+	}
+	return !m;
+}
+
+CALLBACK(attack_memeq5, bool,
+	u_char *subj, u_char *data, size_t len)
+{
+	return memeq_const(subj, data, len);
+}
+
+static bool attack_memeq(char *name, u_int iterations, u_int distance)
+{
+	struct {
+		char *name;
+		attackfn_t fn;
+	} attacks[] = {
+		{ "memeq1", attack_memeq1 },
+		{ "memeq2", attack_memeq2 },
+		{ "memeq3", attack_memeq3 },
+		{ "memeq4", attack_memeq4 },
+		{ "memeq5", attack_memeq5 },
+	};
+	u_char exp[16];
+	int i;
+
+	srandom(time(NULL));
+	for (i = 0; i < sizeof(exp); i++)
+	{
+		exp[i] = random();
+	}
+	fprintf(stderr, "attacking %b\n", exp, sizeof(exp));
+
+	for (i = 0; i < countof(attacks); i++)
+	{
+		if (streq(name, attacks[i].name))
+		{
+			return timeattack(attacks[i].fn, exp, sizeof(exp),
+							  iterations, distance);
+		}
+	}
+	return FALSE;
+}
+
+CALLBACK(attack_chunk1, bool,
+	u_char *subj, u_char *data, size_t len)
+{
+	return chunk_equals(chunk_create(subj, len), chunk_create(data, len));
+}
+
+CALLBACK(attack_chunk2, bool,
+	u_char *subj, u_char *data, size_t len)
+{
+	return chunk_equals_const(chunk_create(subj, len), chunk_create(data, len));
+}
+
+static bool attack_chunk(char *name, u_int iterations, u_int distance)
+{
+	struct {
+		char *name;
+		attackfn_t fn;
+	} attacks[] = {
+		{ "chunk1", attack_chunk1 },
+		{ "chunk2", attack_chunk2 },
+	};
+	u_char exp[16];
+	int i;
+
+	srandom(time(NULL));
+	for (i = 0; i < sizeof(exp); i++)
+	{
+		exp[i] = random();
+	}
+	fprintf(stderr, "attacking %b\n", exp, sizeof(exp));
+
+	for (i = 0; i < countof(attacks); i++)
+	{
+		if (streq(name, attacks[i].name))
+		{
+			return timeattack(attacks[i].fn, exp, sizeof(exp),
+							  iterations, distance);
+		}
+	}
+	return FALSE;
+}
+
+CALLBACK(attack_aead, bool,
+	aead_t *aead, u_char *data, size_t len)
+{
+	u_char iv[aead->get_iv_size(aead)];
+
+	memset(iv, 0, sizeof(iv));
+	return aead->decrypt(aead, chunk_create(data, len), chunk_empty,
+						 chunk_from_thing(iv), NULL);
+}
+
+static bool attack_aeads(encryption_algorithm_t alg, size_t key_size,
+						 u_int iterations, u_int distance)
+{
+	u_char buf[64];
+	aead_t *aead;
+	bool res;
+
+	aead = lib->crypto->create_aead(lib->crypto, alg, key_size, 0);
+	if (!aead)
+	{
+		fprintf(stderr, "creating AEAD %N failed\n",
+				encryption_algorithm_names, alg);
+		return FALSE;
+	}
+	memset(buf, 0xe3, sizeof(buf));
+	if (!aead->set_key(aead, chunk_create(buf, aead->get_key_size(aead))))
+	{
+		aead->destroy(aead);
+		return FALSE;
+	}
+	memset(buf, 0, aead->get_iv_size(aead));
+	if (!aead->encrypt(aead, chunk_create(buf, 0), chunk_empty,
+					   chunk_create(buf, aead->get_iv_size(aead)), NULL))
+	{
+		aead->destroy(aead);
+		return FALSE;
+	}
+	fprintf(stderr, "attacking %b\n", buf, aead->get_icv_size(aead));
+
+	res = timeattack(attack_aead, aead, aead->get_icv_size(aead),
+					 iterations, distance);
+	aead->destroy(aead);
+	return res;
+}
+
+CALLBACK(attack_signer, bool,
+	signer_t *signer, u_char *data, size_t len)
+{
+	return signer->verify_signature(signer, chunk_empty, chunk_create(data, len));
+}
+
+static bool attack_signers(integrity_algorithm_t alg,
+						   u_int iterations, u_int distance)
+{
+	u_char buf[64];
+	signer_t *signer;
+	bool res;
+
+	signer = lib->crypto->create_signer(lib->crypto, alg);
+	if (!signer)
+	{
+		fprintf(stderr, "creating signer %N failed\n",
+				integrity_algorithm_names, alg);
+		return FALSE;
+	}
+	memset(buf, 0xe3, sizeof(buf));
+	if (!signer->set_key(signer, chunk_create(buf, signer->get_key_size(signer))))
+	{
+		signer->destroy(signer);
+		return FALSE;
+	}
+	if (!signer->get_signature(signer, chunk_empty, buf))
+	{
+		signer->destroy(signer);
+		return FALSE;
+	}
+	fprintf(stderr, "attacking %b\n", buf, signer->get_block_size(signer));
+
+	res = timeattack(attack_signer, signer, signer->get_block_size(signer),
+					 iterations, distance);
+	signer->destroy(signer);
+	return res;
+}
+
+static bool attack_transform(char *name, u_int iterations, u_int distance)
+{
+	const proposal_token_t *token;
+
+	token = lib->proposal->get_token(lib->proposal, name);
+	if (!token)
+	{
+		fprintf(stderr, "algorithm '%s' unknown\n", name);
+		return FALSE;
+	}
+
+	switch (token->type)
+	{
+		case ENCRYPTION_ALGORITHM:
+			if (encryption_algorithm_is_aead(token->algorithm))
+			{
+				return attack_aeads(token->algorithm, token->keysize / 8,
+									iterations, distance);
+			}
+			fprintf(stderr, "can't attack a crypter\n");
+			return FALSE;
+		case INTEGRITY_ALGORITHM:
+			return attack_signers(token->algorithm, iterations, distance);
+		default:
+			fprintf(stderr, "can't attack a %N\n", transform_type_names, token->type);
+			return FALSE;
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	library_init(NULL, "timeattack");
+	atexit(library_deinit);
+	lib->plugins->load(lib->plugins, getenv("PLUGINS") ?: PLUGINS);
+
+	if (argc < 3)
+	{
+		fprintf(stderr, "usage: %s <attack> <iterations> <distance>\n", argv[0]);
+		fprintf(stderr, "  <attack>: memeq[1-5] / chunk[1-2] / aead / signer\n");
+		fprintf(stderr, "  <iterations>: number of invocations * 1000\n");
+		fprintf(stderr, "  <distance>: time difference in ns for a hit\n");
+		fprintf(stderr, "  example: %s memeq1 100 500\n", argv[0]);
+		fprintf(stderr, "  example: %s aes128gcm16 100 4000\n", argv[0]);
+		return 1;
+	}
+	if (strpfx(argv[1], "memeq"))
+	{
+		return !attack_memeq(argv[1], atoi(argv[2]), atoi(argv[3]));
+	}
+	if (strpfx(argv[1], "chunk"))
+	{
+		return !attack_chunk(argv[1], atoi(argv[2]), atoi(argv[3]));
+	}
+	return !attack_transform(argv[1], atoi(argv[2]), atoi(argv[3]));
+}
diff --git a/src/charon-nm/charon-nm.c b/src/charon-nm/charon-nm.c
index 32cec36..80551f8 100644
--- a/src/charon-nm/charon-nm.c
+++ b/src/charon-nm/charon-nm.c
@@ -160,6 +160,9 @@ int main(int argc, char *argv[])
 	/* logging for library during initialization, as we have no bus yet */
 	dbg = dbg_syslog;
 
+	/* LD causes a crash probably due to Glib */
+	setenv("LEAK_DETECTIVE_DISABLE", "1", 1);
+
 	/* initialize library */
 	if (!library_init(NULL, "charon-nm"))
 	{
diff --git a/src/charon-tkm/src/tkm/tkm_id_manager.c b/src/charon-tkm/src/tkm/tkm_id_manager.c
index e6d571b..d8ff675 100644
--- a/src/charon-tkm/src/tkm/tkm_id_manager.c
+++ b/src/charon-tkm/src/tkm/tkm_id_manager.c
@@ -19,8 +19,6 @@
 #include <utils/debug.h>
 #include <threading/rwlock.h>
 
-#define TKM_LIMIT 100
-
 ENUM_BEGIN(tkm_context_kind_names, TKM_CTX_NONCE, TKM_CTX_ESA,
 	"NONCE_CONTEXT",
 	"DH_CONTEXT",
diff --git a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
index 734b1ec..7a0672a 100644
--- a/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
+++ b/src/charon-tkm/src/tkm/tkm_kernel_ipsec.c
@@ -132,7 +132,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 	}
 
 	esa_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_ESA);
-	if (!tkm->sad->insert(tkm->sad, reqid, esa_id, local, peer, spi_rem,
+	if (!tkm->sad->insert(tkm->sad, esa_id, reqid, local, peer, spi_loc, spi_rem,
 						  protocol))
 	{
 		DBG1(DBG_KNL, "unable to add entry (%llu) to SAD", esa_id);
@@ -164,6 +164,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 			DBG1(DBG_KNL, "child SA (%llu, no PFS) creation failed", esa_id);
 			goto failure;
 		}
+		tkm->chunk_map->remove(tkm->chunk_map, nonce_loc);
 		tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id);
 	}
 	/* creation of subsequent child SA with PFS: nonce and dh context are set */
@@ -176,6 +177,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
 			DBG1(DBG_KNL, "child SA (%llu) creation failed", esa_id);
 			goto failure;
 		}
+		tkm->chunk_map->remove(tkm->chunk_map, nonce_loc);
 		tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nonce_loc_id);
 	}
 	if (ike_esa_select(esa_id) != TKM_OK)
@@ -217,11 +219,22 @@ METHOD(kernel_ipsec_t, del_sa, status_t,
 	private_tkm_kernel_ipsec_t *this, host_t *src, host_t *dst,
 	u_int32_t spi, u_int8_t protocol, u_int16_t cpi, mark_t mark)
 {
-	esa_id_type esa_id;
+	esa_id_type esa_id, other_esa_id;
 
 	esa_id = tkm->sad->get_esa_id(tkm->sad, src, dst, spi, protocol);
 	if (esa_id)
 	{
+		other_esa_id = tkm->sad->get_other_esa_id(tkm->sad, esa_id);
+		if (other_esa_id)
+		{
+			DBG1(DBG_KNL, "selecting child SA (esa: %llu)", other_esa_id);
+			if (ike_esa_select(other_esa_id) != TKM_OK)
+			{
+				DBG1(DBG_KNL, "error selecting other child SA (esa: %llu)",
+						other_esa_id);
+			}
+		}
+
 		DBG1(DBG_KNL, "deleting child SA (esa: %llu, spi: %x)", esa_id,
 			 ntohl(spi));
 		if (ike_esa_reset(esa_id) != TKM_OK)
diff --git a/src/charon-tkm/src/tkm/tkm_kernel_sad.c b/src/charon-tkm/src/tkm/tkm_kernel_sad.c
index 3394b58..2556f6b 100644
--- a/src/charon-tkm/src/tkm/tkm_kernel_sad.c
+++ b/src/charon-tkm/src/tkm/tkm_kernel_sad.c
@@ -72,9 +72,14 @@ struct sad_entry_t {
 	host_t *dst;
 
 	/**
-	 * SPI of CHILD SA.
+	 * Local SPI of CHILD SA.
 	 */
-	u_int32_t spi;
+	u_int32_t spi_loc;
+
+	/**
+	 * Remote SPI of CHILD SA.
+	 */
+	u_int32_t spi_rem;
 
 	/**
 	 * Protocol of CHILD SA (ESP/AH).
@@ -97,7 +102,7 @@ static void sad_entry_destroy(sad_entry_t *entry)
 }
 
 /**
- * Find a list entry with given src, dst, spi and proto values.
+ * Find a list entry with given src, dst, (remote) spi and proto values.
  */
 static bool sad_entry_match(sad_entry_t * const entry, const host_t * const src,
 							const host_t * const dst, const u_int32_t * const spi,
@@ -110,7 +115,7 @@ static bool sad_entry_match(sad_entry_t * const entry, const host_t * const src,
 
 	return src->ip_equals(entry->src, (host_t *)src) &&
 		   dst->ip_equals(entry->dst, (host_t *)dst) &&
-		   entry->spi == *spi && entry->proto == *proto;
+		   entry->spi_rem == *spi && entry->proto == *proto;
 }
 
 /**
@@ -121,9 +126,29 @@ static bool sad_entry_match_dst(sad_entry_t * const entry,
 								const u_int32_t * const spi,
 								const u_int8_t * const proto)
 {
-	return entry->reqid == *reqid &&
-		   entry->spi   == *spi &&
-		   entry->proto == *proto;
+	return entry->reqid   == *reqid &&
+		   entry->spi_rem == *spi   &&
+		   entry->proto   == *proto;
+}
+
+/**
+ * Find a list entry with given esa id.
+ */
+static bool sad_entry_match_esa_id(sad_entry_t * const entry,
+								   const esa_id_type * const esa_id)
+{
+	return entry->esa_id == *esa_id;
+}
+
+/**
+ * Find a list entry with given reqid and different esa id.
+ */
+static bool sad_entry_match_other_esa(sad_entry_t * const entry,
+									  const esa_id_type * const esa_id,
+									  const u_int32_t * const reqid)
+{
+	return entry->reqid  == *reqid &&
+		   entry->esa_id != *esa_id;
 }
 
 /**
@@ -140,13 +165,15 @@ static bool sad_entry_equal(sad_entry_t * const left, sad_entry_t * const right)
 		   left->reqid == right->reqid &&
 		   left->src->ip_equals(left->src, right->src) &&
 		   left->dst->ip_equals(left->dst, right->dst) &&
-		   left->spi == right->spi && left->proto == right->proto;
+		   left->spi_loc == right->spi_loc &&
+		   left->spi_rem == right->spi_rem &&
+		   left->proto == right->proto;
 }
 
 METHOD(tkm_kernel_sad_t, insert, bool,
 	private_tkm_kernel_sad_t * const this, const esa_id_type esa_id,
 	const u_int32_t reqid, const host_t * const src, const host_t * const dst,
-	const u_int32_t spi, const u_int8_t proto)
+	const u_int32_t spi_loc, const u_int32_t spi_rem, const u_int8_t proto)
 {
 	status_t result;
 	sad_entry_t *new_entry;
@@ -156,7 +183,8 @@ METHOD(tkm_kernel_sad_t, insert, bool,
 		 .reqid = reqid,
 		 .src = (host_t *)src,
 		 .dst = (host_t *)dst,
-		 .spi = spi,
+		 .spi_loc = spi_loc,
+		 .spi_rem = spi_rem,
 		 .proto = proto,
 	);
 
@@ -167,8 +195,8 @@ METHOD(tkm_kernel_sad_t, insert, bool,
 	if (result == NOT_FOUND)
 	{
 		DBG3(DBG_KNL, "inserting SAD entry (esa: %llu, reqid: %u, src: %H, "
-			 "dst: %H, spi: %x, proto: %u)", esa_id, reqid, src, dst,
-			 ntohl(spi), proto);
+			 "dst: %H, spi_loc: %x, spi_rem: %x,proto: %u)", esa_id, reqid, src,
+			 dst, ntohl(spi_loc), ntohl(spi_rem), proto);
 		new_entry->src = src->clone((host_t *)src);
 		new_entry->dst = dst->clone((host_t *)dst);
 		this->data->insert_last(this->data, new_entry);
@@ -209,6 +237,42 @@ METHOD(tkm_kernel_sad_t, get_esa_id, esa_id_type,
 	return id;
 }
 
+METHOD(tkm_kernel_sad_t, get_other_esa_id, esa_id_type,
+	private_tkm_kernel_sad_t * const this, const esa_id_type esa_id)
+{
+	esa_id_type id = 0;
+	sad_entry_t *entry = NULL;
+	u_int32_t reqid;
+	status_t res;
+
+	this->mutex->lock(this->mutex);
+	res = this->data->find_first(this->data,
+								 (linked_list_match_t)sad_entry_match_esa_id,
+								 (void**)&entry, &esa_id);
+	if (res == SUCCESS && entry)
+	{
+		reqid = entry->reqid;
+	}
+	else
+	{
+		DBG3(DBG_KNL, "no SAD entry found for ESA id %llu", esa_id);
+		this->mutex->unlock(this->mutex);
+		return id;
+	}
+
+	res = this->data->find_first(this->data,
+								 (linked_list_match_t)sad_entry_match_other_esa,
+								 (void**)&entry, &esa_id, &reqid);
+	if (res == SUCCESS && entry)
+	{
+		id = entry->esa_id;
+		DBG3(DBG_KNL, "returning ESA id %llu of other SAD entry with reqid %u",
+			 id, reqid);
+	}
+	this->mutex->unlock(this->mutex);
+	return id;
+}
+
 METHOD(tkm_kernel_sad_t, get_dst_host, host_t *,
 	private_tkm_kernel_sad_t * const this, const u_int32_t reqid,
 	const u_int32_t spi, const u_int8_t proto)
@@ -289,6 +353,7 @@ tkm_kernel_sad_t *tkm_kernel_sad_create()
 		.public = {
 			.insert = _insert,
 			.get_esa_id = _get_esa_id,
+			.get_other_esa_id = _get_other_esa_id,
 			.get_dst_host = _get_dst_host,
 			.remove = __remove,
 			.destroy = _destroy,
diff --git a/src/charon-tkm/src/tkm/tkm_kernel_sad.h b/src/charon-tkm/src/tkm/tkm_kernel_sad.h
index 38b19dd..3a84def 100644
--- a/src/charon-tkm/src/tkm/tkm_kernel_sad.h
+++ b/src/charon-tkm/src/tkm/tkm_kernel_sad.h
@@ -40,21 +40,22 @@ struct tkm_kernel_sad_t {
 	 * @param reqid			reqid of the SA
 	 * @param src			source address of CHILD SA
 	 * @param dst			destination address of CHILD SA
-	 * @param spi			SPI of CHILD SA
+	 * @param spi_loc		Local SPI of CHILD SA
+	 * @param spi_rem		Remote SPI of CHILD SA
 	 * @param proto			protocol of CHILD SA (ESP/AH)
 	 * @return				TRUE if entry was inserted, FALSE otherwise
 	 */
 	bool (*insert)(tkm_kernel_sad_t * const this, const esa_id_type esa_id,
 				   const u_int32_t reqid, const host_t * const src,
-				   const host_t * const dst, const u_int32_t spi,
-				   const u_int8_t proto);
+				   const host_t * const dst, const u_int32_t spi_loc,
+				   const u_int32_t spi_rem, const u_int8_t proto);
 
 	/**
 	 * Get ESA id for entry with given parameters.
 	 *
 	 * @param src			source address of CHILD SA
 	 * @param dst			destination address of CHILD SA
-	 * @param spi			SPI of CHILD SA
+	 * @param spi			Remote SPI of CHILD SA
 	 * @param proto			protocol of CHILD SA (ESP/AH)
 	 * @return				ESA id of entry if found, 0 otherwise
 	 */
@@ -63,10 +64,20 @@ struct tkm_kernel_sad_t {
 				 const u_int32_t spi, const u_int8_t proto);
 
 	/**
+	 * Get ESA id for entry associated with same security policy as the
+	 * specified ESA.
+	 *
+	 * @param esa_id		id of ESA identifying the security policy
+	 * @return				ESA id of entry if found, 0 otherwise
+	 */
+	esa_id_type (*get_other_esa_id)(tkm_kernel_sad_t * const this,
+									const esa_id_type esa_id);
+
+	/**
 	 * Get destination host for entry with given parameters.
 	 *
 	 * @param reqid			reqid of CHILD SA
-	 * @param spi			SPI of CHILD SA
+	 * @param spi			Remote SPI of CHILD SA
 	 * @param proto			protocol of CHILD SA (ESP/AH)
 	 * @return				destination host of entry if found, NULL otherwise
 	 */
diff --git a/src/charon-tkm/src/tkm/tkm_keymat.c b/src/charon-tkm/src/tkm/tkm_keymat.c
index 80721fa..1e1fa4f 100644
--- a/src/charon-tkm/src/tkm/tkm_keymat.c
+++ b/src/charon-tkm/src/tkm/tkm_keymat.c
@@ -102,6 +102,7 @@ static void aead_create_from_keys(aead_t **in, aead_t **out,
 	*in = *out = NULL;
 	signer_t *signer_i, *signer_r;
 	crypter_t *crypter_i, *crypter_r;
+	iv_gen_t *ivg_i, *ivg_r;
 
 	signer_i = lib->crypto->create_signer(lib->crypto, int_alg);
 	signer_r = lib->crypto->create_signer(lib->crypto, int_alg);
@@ -145,15 +146,21 @@ static void aead_create_from_keys(aead_t **in, aead_t **out,
 		return;
 	}
 
+	ivg_i = iv_gen_create_for_alg(enc_alg);
+	ivg_r = iv_gen_create_for_alg(enc_alg);
+	if (!ivg_i || !ivg_r)
+	{
+		return;
+	}
 	if (initiator)
 	{
-		*in = aead_create(crypter_r, signer_r);
-		*out = aead_create(crypter_i, signer_i);
+		*in = aead_create(crypter_r, signer_r, ivg_r);
+		*out = aead_create(crypter_i, signer_i, ivg_i);
 	}
 	else
 	{
-		*in = aead_create(crypter_i, signer_i);
-		*out = aead_create(crypter_r, signer_r);
+		*in = aead_create(crypter_i, signer_i, ivg_i);
+		*out = aead_create(crypter_r, signer_r, ivg_r);
 	}
 }
 
diff --git a/src/charon-tkm/src/tkm/tkm_listener.c b/src/charon-tkm/src/tkm/tkm_listener.c
index bb12182..f575276 100644
--- a/src/charon-tkm/src/tkm/tkm_listener.c
+++ b/src/charon-tkm/src/tkm/tkm_listener.c
@@ -14,6 +14,8 @@
  * for more details.
  */
 
+#include <stdarg.h>
+
 #include <daemon.h>
 #include <encoding/payloads/auth_payload.h>
 #include <utils/chunk.h>
@@ -209,6 +211,13 @@ METHOD(listener_t, alert, bool,
 	{
 		tkm_keymat_t *keymat;
 		isa_id_type isa_id;
+		int is_first;
+
+		is_first = va_arg(args, int);
+		if (!is_first)
+		{
+			return TRUE;
+		}
 
 		keymat = (tkm_keymat_t*)ike_sa->get_keymat(ike_sa);
 		isa_id = keymat->get_isa_id(keymat);
diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.c b/src/charon-tkm/src/tkm/tkm_nonceg.c
index a073267..336f16e 100644
--- a/src/charon-tkm/src/tkm/tkm_nonceg.c
+++ b/src/charon-tkm/src/tkm/tkm_nonceg.c
@@ -33,23 +33,32 @@ struct private_tkm_nonceg_t {
 	tkm_nonceg_t public;
 
 	/**
-	 * Context id.
+	 * Nonce chunk.
 	 */
-	nc_id_type context_id;
-
+	chunk_t nonce;
 };
 
 METHOD(nonce_gen_t, get_nonce, bool,
 	private_tkm_nonceg_t *this, size_t size, u_int8_t *buffer)
 {
 	nonce_type nonce;
+	uint64_t nc_id;
+
+	nc_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_NONCE);
+	if (!nc_id)
+	{
+		return FALSE;
+	}
 
-	if (ike_nc_create(this->context_id, size, &nonce) != TKM_OK)
+	if (ike_nc_create(nc_id, size, &nonce) != TKM_OK)
 	{
+		tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nc_id);
 		return FALSE;
 	}
 
 	memcpy(buffer, &nonce.data, size);
+	this->nonce = chunk_clone(chunk_create(buffer, size));
+	tkm->chunk_map->insert(tkm->chunk_map, &this->nonce, nc_id);
 	return TRUE;
 }
 
@@ -57,24 +66,28 @@ METHOD(nonce_gen_t, allocate_nonce, bool,
 	private_tkm_nonceg_t *this, size_t size, chunk_t *chunk)
 {
 	*chunk = chunk_alloc(size);
-	if (get_nonce(this, chunk->len, chunk->ptr))
-	{
-		tkm->chunk_map->insert(tkm->chunk_map, chunk, this->context_id);
-		return TRUE;
-	}
-	return FALSE;
+	return get_nonce(this, chunk->len, chunk->ptr);
 }
 
 METHOD(nonce_gen_t, destroy, void,
 	private_tkm_nonceg_t *this)
 {
-	free(this);
-}
+	uint64_t nc_id;
 
-METHOD(tkm_nonceg_t, get_id, nc_id_type,
-	private_tkm_nonceg_t *this)
-{
-	return this->context_id;
+	nc_id = tkm->chunk_map->get_id(tkm->chunk_map, &this->nonce);
+	if (nc_id)
+	{
+		DBG1(DBG_IKE, "resetting stale nonce context %llu", nc_id);
+
+		if (ike_nc_reset(nc_id) != TKM_OK)
+		{
+			DBG1(DBG_IKE, "failed to reset nonce context %llu", nc_id);
+		}
+		tkm->idmgr->release_id(tkm->idmgr, TKM_CTX_NONCE, nc_id);
+		tkm->chunk_map->remove(tkm->chunk_map, &this->nonce);
+	}
+	chunk_free(&this->nonce);
+	free(this);
 }
 
 /*
@@ -91,16 +104,8 @@ tkm_nonceg_t *tkm_nonceg_create()
 				.allocate_nonce = _allocate_nonce,
 				.destroy = _destroy,
 			},
-			.get_id = _get_id,
 		},
-		.context_id = tkm->idmgr->acquire_id(tkm->idmgr, TKM_CTX_NONCE),
 	);
 
-	if (!this->context_id)
-	{
-		free(this);
-		return NULL;
-	}
-
 	return &this->public;
 }
diff --git a/src/charon-tkm/src/tkm/tkm_nonceg.h b/src/charon-tkm/src/tkm/tkm_nonceg.h
index ceadb08..d158551 100644
--- a/src/charon-tkm/src/tkm/tkm_nonceg.h
+++ b/src/charon-tkm/src/tkm/tkm_nonceg.h
@@ -36,14 +36,6 @@ struct tkm_nonceg_t {
 	 * Implements nonce_gen_t.
 	 */
 	nonce_gen_t nonce_gen;
-
-	/**
-	 * Get nonce context id.
-	 *
-	 * @return	context id of this nonce generator.
-	 */
-	nc_id_type (*get_id)(tkm_nonceg_t * const this);
-
 };
 
 /**
diff --git a/src/charon-tkm/tests/kernel_sad_tests.c b/src/charon-tkm/tests/kernel_sad_tests.c
index b9ab3cb..2a033d2 100644
--- a/src/charon-tkm/tests/kernel_sad_tests.c
+++ b/src/charon-tkm/tests/kernel_sad_tests.c
@@ -34,7 +34,7 @@ START_TEST(test_insert)
 	host_t *addr = host_create_from_string("127.0.0.1", 1024);
 	tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
 
-	fail_unless(sad->insert(sad, 1, 2, addr, addr, 42, 50),
+	fail_unless(sad->insert(sad, 1, 2, addr, addr, 27, 42, 50),
 				"Error inserting SAD entry");
 
 	sad->destroy(sad);
@@ -47,9 +47,9 @@ START_TEST(test_insert_duplicate)
 	host_t *addr = host_create_from_string("127.0.0.1", 1024);
 	tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
 
-	fail_unless(sad->insert(sad, 1, 2, addr, addr, 42, 50),
+	fail_unless(sad->insert(sad, 1, 2, addr, addr, 27, 42, 50),
 				"Error inserting SAD entry");
-	fail_if(sad->insert(sad, 1, 2, addr, addr, 42, 50),
+	fail_if(sad->insert(sad, 1, 2, addr, addr, 27, 42, 50),
 			"Expected error inserting duplicate entry");
 
 	sad->destroy(sad);
@@ -61,7 +61,7 @@ START_TEST(test_get_esa_id)
 {
 	host_t *addr = host_create_from_string("127.0.0.1", 1024);
 	tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
-	fail_unless(sad->insert(sad, 23, 54, addr, addr, 42, 50),
+	fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
 				"Error inserting SAD entry");
 	fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 23,
 				"Error getting esa id");
@@ -81,11 +81,42 @@ START_TEST(test_get_esa_id_nonexistent)
 }
 END_TEST
 
+START_TEST(test_get_other_esa_id)
+{
+	host_t *addr = host_create_from_string("127.0.0.1", 1024);
+	tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
+	fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
+				"Error inserting SAD entry");
+	fail_unless(sad->insert(sad, 24, 54, addr, addr, 27, 42, 50),
+				"Error inserting SAD entry");
+	fail_unless(sad->get_other_esa_id(sad, 23) == 24,
+				"Error getting other esa id");
+	sad->destroy(sad);
+	addr->destroy(addr);
+}
+END_TEST
+
+START_TEST(test_get_other_esa_id_nonexistent)
+{
+	host_t *addr = host_create_from_string("127.0.0.1", 1024);
+	tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
+	fail_unless(sad->get_other_esa_id(sad, 1) == 0,
+				"Got other esa id for nonexistent SAD entry");
+	fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
+				"Error inserting SAD entry");
+	fail_unless(sad->get_other_esa_id(sad, 23) == 0,
+				"Got own esa id");
+
+	sad->destroy(sad);
+	addr->destroy(addr);
+}
+END_TEST
+
 START_TEST(test_get_dst_host)
 {
 	host_t *addr = host_create_from_string("127.0.0.1", 1024);
 	tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
-	fail_unless(sad->insert(sad, 23, 54, addr, addr, 42, 50),
+	fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
 				"Error inserting SAD entry");
 
 	host_t *dst = sad->get_dst_host(sad, 54, 42, 50);
@@ -108,7 +139,7 @@ START_TEST(test_remove)
 {
 	host_t *addr = host_create_from_string("127.0.0.1", 1024);
 	tkm_kernel_sad_t *sad = tkm_kernel_sad_create();
-	fail_unless(sad->insert(sad, 23, 54, addr, addr, 42, 50),
+	fail_unless(sad->insert(sad, 23, 54, addr, addr, 27, 42, 50),
 				"Error inserting SAD entry");
 	fail_unless(sad->get_esa_id(sad, addr, addr, 42, 50) == 23,
 				"Error getting esa id");
@@ -151,6 +182,11 @@ Suite *make_kernel_sad_tests()
 	tcase_add_test(tc, test_get_esa_id_nonexistent);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("get_other_esa_id");
+	tcase_add_test(tc, test_get_other_esa_id);
+	tcase_add_test(tc, test_get_other_esa_id_nonexistent);
+	suite_add_tcase(s, tc);
+
 	tc = tcase_create("get_dst_host");
 	tcase_add_test(tc, test_get_dst_host);
 	tcase_add_test(tc, test_get_dst_host_nonexistent);
diff --git a/src/charon-tkm/tests/keymat_tests.c b/src/charon-tkm/tests/keymat_tests.c
index 889965a..d087bee 100644
--- a/src/charon-tkm/tests/keymat_tests.c
+++ b/src/charon-tkm/tests/keymat_tests.c
@@ -46,7 +46,6 @@ START_TEST(test_derive_ike_keys)
 	fail_if(!ng, "Unable to create nonce generator");
 	fail_unless(ng->nonce_gen.allocate_nonce(&ng->nonce_gen, 32, &nonce),
 			"Unable to allocate nonce");
-	ng->nonce_gen.destroy(&ng->nonce_gen);
 
 	tkm_diffie_hellman_t *dh = tkm_diffie_hellman_create(MODP_4096_BIT);
 	fail_if(!dh, "Unable to create DH");
@@ -69,6 +68,7 @@ START_TEST(test_derive_ike_keys)
 	fail_if(aead->get_block_size(aead) != 16, "Block size mismatch %d",
 			aead->get_block_size(aead));
 
+	ng->nonce_gen.destroy(&ng->nonce_gen);
 	proposal->destroy(proposal);
 	dh->dh.destroy(&dh->dh);
 	ike_sa_id->destroy(ike_sa_id);
diff --git a/src/charon-tkm/tests/nonceg_tests.c b/src/charon-tkm/tests/nonceg_tests.c
index 6f524cb..d150891 100644
--- a/src/charon-tkm/tests/nonceg_tests.c
+++ b/src/charon-tkm/tests/nonceg_tests.c
@@ -27,7 +27,6 @@ START_TEST(test_nonceg_creation)
 
 	ng = tkm_nonceg_create();
 	fail_if(ng == NULL, "Error creating tkm nonce generator");
-	fail_if(ng->get_id(ng) == 0, "Invalid context id (0)");
 
 	ng->nonce_gen.destroy(&ng->nonce_gen);
 }
diff --git a/src/ipsec/_ipsec.8 b/src/ipsec/_ipsec.8
index d2d0c2e..f9c54f8 100644
--- a/src/ipsec/_ipsec.8
+++ b/src/ipsec/_ipsec.8
@@ -1,4 +1,4 @@
-.TH IPSEC 8 "2013-10-29" "5.3.0" "strongSwan"
+.TH IPSEC 8 "2013-10-29" "5.3.1dr1" "strongSwan"
 .
 .SH NAME
 .
diff --git a/src/libcharon/bus/bus.c b/src/libcharon/bus/bus.c
index 7938f46..53ded6b 100644
--- a/src/libcharon/bus/bus.c
+++ b/src/libcharon/bus/bus.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2014 Tobias Brunner
+ * Copyright (C) 2011-2015 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -687,6 +687,37 @@ METHOD(bus_t, child_rekey, void,
 	this->mutex->unlock(this->mutex);
 }
 
+METHOD(bus_t, children_migrate, void,
+	private_bus_t *this, ike_sa_id_t *new, u_int32_t unique)
+{
+	enumerator_t *enumerator;
+	ike_sa_t *ike_sa;
+	entry_t *entry;
+	bool keep;
+
+	ike_sa = this->thread_sa->get(this->thread_sa);
+
+	this->mutex->lock(this->mutex);
+	enumerator = this->listeners->create_enumerator(this->listeners);
+	while (enumerator->enumerate(enumerator, &entry))
+	{
+		if (entry->calling || !entry->listener->children_migrate)
+		{
+			continue;
+		}
+		entry->calling++;
+		keep = entry->listener->children_migrate(entry->listener, ike_sa, new,
+												 unique);
+		entry->calling--;
+		if (!keep)
+		{
+			unregister_listener(this, entry, enumerator);
+		}
+	}
+	enumerator->destroy(enumerator);
+	this->mutex->unlock(this->mutex);
+}
+
 METHOD(bus_t, ike_updown, void,
 	private_bus_t *this, ike_sa_t *ike_sa, bool up)
 {
@@ -1038,6 +1069,7 @@ bus_t *bus_create()
 			.ike_reestablish_post = _ike_reestablish_post,
 			.child_updown = _child_updown,
 			.child_rekey = _child_rekey,
+			.children_migrate = _children_migrate,
 			.authorize = _authorize,
 			.narrow = _narrow,
 			.assign_vips = _assign_vips,
diff --git a/src/libcharon/bus/bus.h b/src/libcharon/bus/bus.h
index 051c429..b6757b1 100644
--- a/src/libcharon/bus/bus.h
+++ b/src/libcharon/bus/bus.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2014 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
  * Copyright (C) 2006-2009 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -130,7 +130,8 @@ enum alert_t {
 	ALERT_UNIQUE_REPLACE,
 	/** IKE_SA deleted because of "keep" unique policy, no argument */
 	ALERT_UNIQUE_KEEP,
-	/** IKE_SA kept on failed child SA establishment, no argument */
+	/** IKE_SA kept on failed child SA establishment, argument is an int (!=0 if
+	 * first child SA) */
 	ALERT_KEEP_ON_CHILD_SA_FAILURE,
 	/** allocating virtual IP failed, linked_list_t of host_t requested */
 	ALERT_VIP_FAILURE,
@@ -426,6 +427,14 @@ struct bus_t {
 	void (*child_rekey)(bus_t *this, child_sa_t *old, child_sa_t *new);
 
 	/**
+	 * CHILD_SA migration hook.
+	 *
+	 * @param new		ID of new SA when called for the old, NULL otherwise
+	 * @param uniue		unique ID of new SA when called for the old, 0 otherwise
+	 */
+	void (*children_migrate)(bus_t *this, ike_sa_id_t *new, u_int32_t unique);
+
+	/**
 	 * Virtual IP assignment hook.
 	 *
 	 * @param ike_sa	IKE_SA the VIPs are assigned to
diff --git a/src/libcharon/bus/listeners/listener.h b/src/libcharon/bus/listeners/listener.h
index 3447d8f..c7a8d8d 100644
--- a/src/libcharon/bus/listeners/listener.h
+++ b/src/libcharon/bus/listeners/listener.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2011-2014 Tobias Brunner
+ * Copyright (C) 2011-2015 Tobias Brunner
  * Copyright (C) 2009 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -188,6 +188,21 @@ struct listener_t {
 						child_sa_t *old, child_sa_t *new);
 
 	/**
+	 * Hook called when CHILD_SAs get migrated from one IKE_SA to another during
+	 * IKEv1 reauthentication.
+	 *
+	 * This is called twice, once for the old IKE_SA before the CHILD_SAs are
+	 * removed, and once for the new IKE_SA just after they got added.
+	 *
+	 * @param ike_sa	new or old IKE_SA
+	 * @param new		ID of new SA when called for the old, NULL otherwise
+	 * @param unique	unique ID of new SA when called for the old, 0 otherwise
+	 * @return			TRUE to stay registered, FALSE to unregister
+	 */
+	bool (*children_migrate)(listener_t *this, ike_sa_t *ike_sa,
+							 ike_sa_id_t *new, u_int32_t unique);
+
+	/**
 	 * Hook called to invoke additional authorization rules.
 	 *
 	 * An authorization hook gets invoked several times: After each
diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 0a596ff..3303024 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -1411,6 +1411,55 @@ static char* get_string(private_message_t *this, char *buf, int len)
 				len -= written;
 			}
 		}
+		if (payload->get_type(payload) == PLV1_FRAGMENT)
+		{
+			fragment_payload_t *frag;
+
+			frag = (fragment_payload_t*)payload;
+			if (frag->is_last(frag))
+			{
+				written = snprintf(pos, len, "(%u/%u)",
+							frag->get_number(frag), frag->get_number(frag));
+			}
+			else
+			{
+				written = snprintf(pos, len, "(%u)", frag->get_number(frag));
+			}
+			if (written >= len || written < 0)
+			{
+				return buf;
+			}
+			pos += written;
+			len -= written;
+		}
+		if (payload->get_type(payload) == PLV2_FRAGMENT)
+		{
+			encrypted_fragment_payload_t *frag;
+
+			frag = (encrypted_fragment_payload_t*)payload;
+			written = snprintf(pos, len, "(%u/%u)",
+							   frag->get_fragment_number(frag),
+							   frag->get_total_fragments(frag));
+			if (written >= len || written < 0)
+			{
+				return buf;
+			}
+			pos += written;
+			len -= written;
+		}
+		if (payload->get_type(payload) == PL_UNKNOWN)
+		{
+			unknown_payload_t *unknown;
+
+			unknown = (unknown_payload_t*)payload;
+			written = snprintf(pos, len, "(%d)", unknown->get_type(unknown));
+			if (written >= len || written < 0)
+			{
+				return buf;
+			}
+			pos += written;
+			len -= written;
+		}
 	}
 	enumerator->destroy(enumerator);
 
@@ -2237,9 +2286,16 @@ static status_t parse_payloads(private_message_t *this)
 			payload->destroy(payload);
 			return VERIFY_ERROR;
 		}
-
-		DBG2(DBG_ENC, "%N payload verified, adding to payload list",
-			 payload_type_names, type);
+		if (payload->get_type(payload) == PL_UNKNOWN)
+		{
+			DBG2(DBG_ENC, "%N payload unknown or not allowed",
+				 payload_type_names, type);
+		}
+		else
+		{
+			DBG2(DBG_ENC, "%N payload verified, adding to payload list",
+				 payload_type_names, type);
+		}
 		this->payloads->insert_last(this->payloads, payload);
 
 		/* an encrypted (fragment) payload MUST be the last one, so STOP here.
@@ -2477,7 +2533,7 @@ static status_t decrypt_payloads(private_message_t *this, keymat_t *keymat)
 			was_encrypted = "encrypted fragment payload";
 		}
 
-		if (payload_is_known(type, this->major_version) && !was_encrypted &&
+		if (type != PL_UNKNOWN && !was_encrypted &&
 			!is_connectivity_check(this, payload) &&
 			this->exchange_type != AGGRESSIVE)
 		{
@@ -2625,7 +2681,7 @@ METHOD(message_t, parse_body, status_t,
 			other_hash = hash_payload->get_hash(hash_payload);
 			DBG3(DBG_ENC, "HASH received %B\nHASH expected %B",
 				 &other_hash, &hash);
-			if (!chunk_equals(hash, other_hash))
+			if (!chunk_equals_const(hash, other_hash))
 			{
 				DBG1(DBG_ENC, "received HASH payload does not match");
 				chunk_free(&hash);
diff --git a/src/libcharon/encoding/payloads/encrypted_payload.c b/src/libcharon/encoding/payloads/encrypted_payload.c
index 04372fd..d1a2678 100644
--- a/src/libcharon/encoding/payloads/encrypted_payload.c
+++ b/src/libcharon/encoding/payloads/encrypted_payload.c
@@ -502,6 +502,8 @@ METHOD(encrypted_payload_t, encrypt, status_t,
 	generator = generator_create();
 	plain = generate(this, generator);
 	assoc = append_header(this, assoc);
+	/* lower 32-bits are for fragment number, if used */
+	mid <<= 32;
 	status = encrypt_content("encrypted payload", this->aead, mid, plain, assoc,
 							 &this->encrypted);
 	generator->destroy(generator);
@@ -932,6 +934,9 @@ METHOD(encrypted_payload_t, frag_encrypt, status_t,
 	}
 	free(this->encrypted.ptr);
 	assoc = append_header_frag(this, assoc);
+	/* IKEv2 message IDs are not unique if fragmentation is used, hence include
+	 * the fragment number to make it unique */
+	mid = mid << 32 | this->fragment_number;
 	status = encrypt_content("encrypted fragment payload", this->aead, mid,
 							 this->plain, assoc, &this->encrypted);
 	free(assoc.ptr);
diff --git a/src/libcharon/encoding/payloads/payload.c b/src/libcharon/encoding/payloads/payload.c
index a1cd2f9..f7c2754 100644
--- a/src/libcharon/encoding/payloads/payload.c
+++ b/src/libcharon/encoding/payloads/payload.c
@@ -97,6 +97,7 @@ ENUM_NEXT(payload_type_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_FRAGME
 #endif /* ME */
 ENUM_NEXT(payload_type_names, PL_HEADER, PLV1_ENCRYPTED, PLV1_FRAGMENT,
 	"HEADER",
+	"UNKNOWN",
 	"PROPOSAL_SUBSTRUCTURE",
 	"PROPOSAL_SUBSTRUCTURE_V1",
 	"TRANSFORM_SUBSTRUCTURE",
@@ -167,6 +168,7 @@ ENUM_NEXT(payload_type_short_names, PLV1_NAT_D_DRAFT_00_03, PLV1_FRAGMENT, PLV2_
 #endif /* ME */
 ENUM_NEXT(payload_type_short_names, PL_HEADER, PLV1_ENCRYPTED, PLV1_FRAGMENT,
 	"HDR",
+	"UNKN",
 	"PROP",
 	"PROP",
 	"TRANS",
diff --git a/src/libcharon/encoding/payloads/payload.h b/src/libcharon/encoding/payloads/payload.h
index 920779b..7200389 100644
--- a/src/libcharon/encoding/payloads/payload.h
+++ b/src/libcharon/encoding/payloads/payload.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -264,6 +264,11 @@ enum payload_type_t {
 	PL_HEADER = 256,
 
 	/**
+	 * Used to handle unknown or invalid payload types.
+	 */
+	PL_UNKNOWN,
+
+	/**
 	 * PLV2_PROPOSAL_SUBSTRUCTURE, IKEv2 proposals in a SA payload.
 	 */
 	PLV2_PROPOSAL_SUBSTRUCTURE,
diff --git a/src/libcharon/encoding/payloads/unknown_payload.c b/src/libcharon/encoding/payloads/unknown_payload.c
index 45b91fd..c69254f 100644
--- a/src/libcharon/encoding/payloads/unknown_payload.c
+++ b/src/libcharon/encoding/payloads/unknown_payload.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -121,6 +122,12 @@ METHOD(payload_t, get_header_length, int,
 METHOD(payload_t, get_payload_type, payload_type_t,
 	private_unknown_payload_t *this)
 {
+	return PL_UNKNOWN;
+}
+
+METHOD(unknown_payload_t, get_type, payload_type_t,
+	private_unknown_payload_t *this)
+{
 	return this->type;
 }
 
@@ -181,6 +188,7 @@ unknown_payload_t *unknown_payload_create(payload_type_t type)
 				.destroy = _destroy,
 			},
 			.is_critical = _is_critical,
+			.get_type = _get_type,
 			.get_data = _get_data,
 			.destroy = _destroy,
 		},
diff --git a/src/libcharon/encoding/payloads/unknown_payload.h b/src/libcharon/encoding/payloads/unknown_payload.h
index 326b550..09341bc 100644
--- a/src/libcharon/encoding/payloads/unknown_payload.h
+++ b/src/libcharon/encoding/payloads/unknown_payload.h
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner
  * Copyright (C) 2005-2006 Martin Willi
  * Copyright (C) 2005 Jan Hutter
  * Hochschule fuer Technik Rapperswil
@@ -42,6 +43,13 @@ struct unknown_payload_t {
 	payload_t payload_interface;
 
 	/**
+	 * Get the original payload type as sent by the peer.
+	 *
+	 * @return				type of the original payload
+	 */
+	payload_type_t (*get_type) (unknown_payload_t *this);
+
+	/**
 	 * Get the raw data of this payload, without
 	 * the generic payload header.
 	 *
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index 5ce9471..6902c48 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -247,7 +247,7 @@ static bool cookie_verify(private_receiver_t *this, message_t *message,
 	{
 		return FALSE;
 	}
-	if (chunk_equals(reference, cookie))
+	if (chunk_equals_const(reference, cookie))
 	{
 		chunk_free(&reference);
 		return TRUE;
diff --git a/src/libcharon/plugins/eap_aka/eap_aka_server.c b/src/libcharon/plugins/eap_aka/eap_aka_server.c
index eba7af8..04bfc17 100644
--- a/src/libcharon/plugins/eap_aka/eap_aka_server.c
+++ b/src/libcharon/plugins/eap_aka/eap_aka_server.c
@@ -425,7 +425,7 @@ static status_t process_challenge(private_eap_aka_server_t *this,
 	enumerator->destroy(enumerator);
 
 	/* compare received RES against stored XRES */
-	if (!chunk_equals(res, this->xres))
+	if (!chunk_equals_const(res, this->xres))
 	{
 		DBG1(DBG_IKE, "received RES does not match XRES");
 		return FAILED;
@@ -486,7 +486,7 @@ static status_t process_reauthentication(private_eap_aka_server_t *this,
 		this->crypto->clear_keys(this->crypto);
 		return challenge(this, out);
 	}
-	if (!chunk_equals(counter, this->counter))
+	if (!chunk_equals_const(counter, this->counter))
 	{
 		DBG1(DBG_IKE, "received counter does not match");
 		return FAILED;
@@ -730,4 +730,3 @@ eap_aka_server_t *eap_aka_server_create(identification_t *server,
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
index a71dae7..e38ee5b 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_card.c
@@ -87,7 +87,7 @@ METHOD(simaka_card_t, get_quintuplet, status_t,
 	{
 		return FAILED;
 	}
-	if (!memeq(mac, xmac, AKA_MAC_LEN))
+	if (!memeq_const(mac, xmac, AKA_MAC_LEN))
 	{
 		DBG1(DBG_IKE, "received MAC does not match XMAC");
 		DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
@@ -184,4 +184,3 @@ eap_aka_3gpp2_card_t *eap_aka_3gpp2_card_create(eap_aka_3gpp2_functions_t *f)
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
index 0be1221..f272e1e 100644
--- a/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
+++ b/src/libcharon/plugins/eap_aka_3gpp2/eap_aka_3gpp2_provider.c
@@ -158,7 +158,7 @@ METHOD(simaka_provider_t, resync, bool,
 	{
 		return FALSE;
 	}
-	if (!memeq(macs, xmacs, AKA_MAC_LEN))
+	if (!memeq_const(macs, xmacs, AKA_MAC_LEN))
 	{
 		DBG1(DBG_IKE, "received MACS does not match XMACS");
 		DBG3(DBG_IKE, "MACS %b XMACS %b",
@@ -205,4 +205,3 @@ eap_aka_3gpp2_provider_t *eap_aka_3gpp2_provider_create(
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/eap_md5/eap_md5.c b/src/libcharon/plugins/eap_md5/eap_md5.c
index b2640d1..d314e7a 100644
--- a/src/libcharon/plugins/eap_md5/eap_md5.c
+++ b/src/libcharon/plugins/eap_md5/eap_md5.c
@@ -193,7 +193,7 @@ METHOD(eap_method_t, process_server, status_t,
 	}
 	response = chunk_create(data.ptr + 6, data.ptr[5]);
 	if (response.len < expected.len ||
-		!memeq(response.ptr, expected.ptr, expected.len))
+		!memeq_const(response.ptr, expected.ptr, expected.len))
 	{
 		chunk_free(&expected);
 		DBG1(DBG_IKE, "EAP-MD5 verification failed");
@@ -299,4 +299,3 @@ eap_md5_t *eap_md5_create_peer(identification_t *server, identification_t *peer)
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
index 5115068..f7f39f9 100644
--- a/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
+++ b/src/libcharon/plugins/eap_mschapv2/eap_mschapv2.c
@@ -812,7 +812,7 @@ static status_t process_peer_success(private_eap_mschapv2_t *this,
 		goto error;
 	}
 
-	if (!chunk_equals(this->auth_response, auth_string))
+	if (!chunk_equals_const(this->auth_response, auth_string))
 	{
 		DBG1(DBG_IKE, "EAP-MS-CHAPv2 verification failed");
 		goto error;
@@ -1087,8 +1087,8 @@ static status_t process_server_response(private_eap_mschapv2_t *this,
 	userid->destroy(userid);
 	chunk_clear(&nt_hash);
 
-	if (memeq(res->response.nt_response, this->nt_response.ptr,
-			  this->nt_response.len))
+	if (memeq_const(res->response.nt_response, this->nt_response.ptr,
+					this->nt_response.len))
 	{
 		chunk_t hex;
 		char msg[AUTH_RESPONSE_LEN + sizeof(SUCCESS_MESSAGE)];
@@ -1267,4 +1267,3 @@ eap_mschapv2_t *eap_mschapv2_create_peer(identification_t *server, identificatio
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
index ac4ecfc..cef1930 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -1,4 +1,7 @@
 /*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
  * Copyright (C) 2012 Martin Willi
  * Copyright (C) 2012 revosec AG
  *
@@ -21,6 +24,7 @@
 #include <radius_message.h>
 #include <radius_client.h>
 #include <daemon.h>
+#include <collections/array.h>
 #include <collections/hashtable.h>
 #include <threading/mutex.h>
 #include <processing/jobs/callback_job.h>
@@ -93,6 +97,62 @@ typedef enum {
 } radius_acct_terminate_cause_t;
 
 /**
+ * Usage stats for bytes and packets
+ */
+typedef struct {
+	struct {
+		u_int64_t sent;
+		u_int64_t received;
+	} bytes, packets;
+} usage_t;
+
+/**
+ * Add usage stats (modifies a)
+ */
+static inline void add_usage(usage_t *a, usage_t b)
+{
+	a->bytes.sent += b.bytes.sent;
+	a->bytes.received += b.bytes.received;
+	a->packets.sent += b.packets.sent;
+	a->packets.received += b.packets.received;
+}
+
+/**
+ * Subtract usage stats (modifies a)
+ */
+static inline void sub_usage(usage_t *a, usage_t b)
+{
+	a->bytes.sent -= b.bytes.sent;
+	a->bytes.received -= b.bytes.received;
+	a->packets.sent -= b.packets.sent;
+	a->packets.received -= b.packets.received;
+}
+
+/**
+ * Usage stats for a cached/migrated SAs
+ */
+typedef struct {
+	/** unique CHILD_SA identifier */
+	u_int32_t id;
+	/** usage stats for this SA */
+	usage_t usage;
+} sa_entry_t;
+
+/**
+ * Clone an sa_entry_t
+ */
+static sa_entry_t *clone_sa(sa_entry_t *sa)
+{
+	sa_entry_t *this;
+
+	INIT(this,
+		.id = sa->id,
+		.usage = sa->usage,
+	);
+	return this;
+}
+
+/**
  * Hashtable entry with usage stats
  */
 typedef struct {
@@ -100,11 +160,12 @@ typedef struct {
 	ike_sa_id_t *id;
 	/** RADIUS accounting session ID */
 	char sid[24];
-	/** number of sent/received octets/packets */
-	struct {
-		u_int64_t sent;
-		u_int64_t received;
-	} bytes, packets;
+	/** number of sent/received octets/packets for expired SAs */
+	usage_t usage;
+	/** list of cached SAs, sa_entry_t (sorted by their unique ID) */
+	array_t *cached;
+	/** list of migrated SAs, sa_entry_t (sorted by their unique ID) */
+	array_t *migrated;
 	/** session creation time */
 	time_t created;
 	/** terminate cause */
@@ -123,6 +184,8 @@ typedef struct {
  */
 static void destroy_entry(entry_t *this)
 {
+	array_destroy_function(this->cached, (void*)free, NULL);
+	array_destroy_function(this->migrated, (void*)free, NULL);
 	this->id->destroy(this->id);
 	free(this);
 }
@@ -155,30 +218,157 @@ static bool equals(ike_sa_id_t *a, ike_sa_id_t *b)
 }
 
 /**
+ * Sort cached SAs
+ */
+static int sa_sort(const void *a, const void *b, void *user)
+{
+	const sa_entry_t *ra = a, *rb = b;
+	return ra->id - rb->id;
+}
+
+/**
+ * Find a cached SA
+ */
+static int sa_find(const void *a, const void *b)
+{
+	return sa_sort(a, b, NULL);
+}
+
+/**
+ * Update or create usage counters of a cached SA
+ */
+static void update_sa(entry_t *entry, u_int32_t id, usage_t usage)
+{
+	sa_entry_t *sa, lookup;
+
+	lookup.id = id;
+	if (array_bsearch(entry->cached, &lookup, sa_find, &sa) == -1)
+	{
+		INIT(sa,
+			.id = id,
+		);
+		array_insert_create(&entry->cached, ARRAY_TAIL, sa);
+		array_sort(entry->cached, sa_sort, NULL);
+	}
+	sa->usage = usage;
+}
+
+/**
  * Update usage counter when a CHILD_SA rekeys/goes down
  */
 static void update_usage(private_eap_radius_accounting_t *this,
 						 ike_sa_t *ike_sa, child_sa_t *child_sa)
 {
-	u_int64_t bytes_in, bytes_out, packets_in, packets_out;
+	usage_t usage;
 	entry_t *entry;
 
-	child_sa->get_usestats(child_sa, FALSE, NULL, &bytes_out, &packets_out);
-	child_sa->get_usestats(child_sa, TRUE, NULL, &bytes_in, &packets_in);
+	child_sa->get_usestats(child_sa, TRUE, NULL, &usage.bytes.received,
+						   &usage.packets.received);
+	child_sa->get_usestats(child_sa, FALSE, NULL, &usage.bytes.sent,
+						   &usage.packets.sent);
 
 	this->mutex->lock(this->mutex);
 	entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
 	if (entry)
 	{
-		entry->bytes.sent += bytes_out;
-		entry->bytes.received += bytes_in;
-		entry->packets.sent += packets_out;
-		entry->packets.received += packets_in;
+		update_sa(entry, child_sa->get_unique_id(child_sa), usage);
 	}
 	this->mutex->unlock(this->mutex);
 }
 
 /**
+ * Collect usage stats for all CHILD_SAs of the given IKE_SA, optionally returns
+ * the total number of bytes and packets
+ */
+static array_t *collect_stats(ike_sa_t *ike_sa, usage_t *total)
+{
+	enumerator_t *enumerator;
+	child_sa_t *child_sa;
+	array_t *stats;
+	sa_entry_t *sa;
+	usage_t usage;
+
+	if (total)
+	{
+		*total = (usage_t){};
+	}
+
+	stats = array_create(0, 0);
+	enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
+	while (enumerator->enumerate(enumerator, &child_sa))
+	{
+		INIT(sa,
+			.id = child_sa->get_unique_id(child_sa),
+		);
+		array_insert(stats, ARRAY_TAIL, sa);
+		array_sort(stats, sa_sort, NULL);
+
+		child_sa->get_usestats(child_sa, TRUE, NULL, &usage.bytes.received,
+							   &usage.packets.received);
+		child_sa->get_usestats(child_sa, FALSE, NULL, &usage.bytes.sent,
+							   &usage.packets.sent);
+		sa->usage = usage;
+		if (total)
+		{
+			add_usage(total, usage);
+		}
+	}
+	enumerator->destroy(enumerator);
+	return stats;
+}
+
+/**
+ * Cleanup cached SAs
+ */
+static void cleanup_sas(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
+						entry_t *entry)
+{
+	enumerator_t *enumerator;
+	child_sa_t *child_sa;
+	sa_entry_t *sa, *found;
+	array_t *sas;
+
+	sas = array_create(0, 0);
+	enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
+	while (enumerator->enumerate(enumerator, &child_sa))
+	{
+		INIT(sa,
+			.id = child_sa->get_unique_id(child_sa),
+		);
+		array_insert(sas, ARRAY_TAIL, sa);
+		array_sort(sas, sa_sort, NULL);
+	}
+	enumerator->destroy(enumerator);
+
+	enumerator = array_create_enumerator(entry->cached);
+	while (enumerator->enumerate(enumerator, &sa))
+	{
+		if (array_bsearch(sas, sa, sa_find, &found) == -1)
+		{
+			/* SA is gone, add its latest stats to the total for this IKE_SA
+			 * and remove the cache entry */
+			add_usage(&entry->usage, sa->usage);
+			array_remove_at(entry->cached, enumerator);
+			free(sa);
+		}
+	}
+	enumerator->destroy(enumerator);
+	enumerator = array_create_enumerator(entry->migrated);
+	while (enumerator->enumerate(enumerator, &sa))
+	{
+		if (array_bsearch(sas, sa, sa_find, &found) == -1)
+		{
+			/* SA is gone, subtract stats from the total for this IKE_SA */
+			sub_usage(&entry->usage, sa->usage);
+			array_remove_at(entry->migrated, enumerator);
+			free(sa);
+		}
+	}
+	enumerator->destroy(enumerator);
+	array_destroy_function(sas, (void*)free, NULL);
+}
+
+/**
  * Send a RADIUS message, wait for response
  */
 static bool send_message(private_eap_radius_accounting_t *this,
@@ -273,17 +463,15 @@ static void add_ike_sa_parameters(private_eap_radius_accounting_t *this,
  * Get an existing or create a new entry from the locked session table
  */
 static entry_t* get_or_create_entry(private_eap_radius_accounting_t *this,
-									ike_sa_t *ike_sa)
+									ike_sa_id_t *id, u_int32_t unique)
 {
-	ike_sa_id_t *id;
 	entry_t *entry;
 	time_t now;
 
-	entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
+	entry = this->sessions->get(this->sessions, id);
 	if (!entry)
 	{
 		now = time_monotonic(NULL);
-		id = ike_sa->get_id(ike_sa);
 
 		INIT(entry,
 			.id = id->clone(id),
@@ -294,8 +482,7 @@ static entry_t* get_or_create_entry(private_eap_radius_accounting_t *this,
 			/* default terminate cause, if none other catched */
 			.cause = ACCT_CAUSE_USER_REQUEST,
 		);
-		snprintf(entry->sid, sizeof(entry->sid), "%u-%u",
-				 this->prefix, ike_sa->get_unique_id(ike_sa));
+		snprintf(entry->sid, sizeof(entry->sid), "%u-%u", this->prefix, unique);
 		this->sessions->put(this->sessions, entry->id, entry);
 	}
 	return entry;
@@ -330,31 +517,21 @@ void destroy_interim_data(interim_data_t *this)
 static job_requeue_t send_interim(interim_data_t *data)
 {
 	private_eap_radius_accounting_t *this = data->this;
-	u_int64_t bytes_in = 0, bytes_out = 0, packets_in = 0, packets_out = 0;
-	u_int64_t bytes, packets;
+	usage_t usage;
 	radius_message_t *message = NULL;
 	enumerator_t *enumerator;
-	child_sa_t *child_sa;
 	ike_sa_t *ike_sa;
 	entry_t *entry;
 	u_int32_t value;
+	array_t *stats;
+	sa_entry_t *sa, *found;
 
 	ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, data->id);
 	if (!ike_sa)
 	{
 		return JOB_REQUEUE_NONE;
 	}
-	enumerator = ike_sa->create_child_sa_enumerator(ike_sa);
-	while (enumerator->enumerate(enumerator, &child_sa))
-	{
-		child_sa->get_usestats(child_sa, FALSE, NULL, &bytes, &packets);
-		bytes_out += bytes;
-		packets_out += packets;
-		child_sa->get_usestats(child_sa, TRUE, NULL, &bytes, &packets);
-		bytes_in += bytes;
-		packets_in += packets;
-	}
-	enumerator->destroy(enumerator);
+	stats = collect_stats(ike_sa, &usage);
 	charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
 
 	/* avoid any races by returning IKE_SA before acquiring lock */
@@ -365,10 +542,45 @@ static job_requeue_t send_interim(interim_data_t *data)
 	{
 		entry->interim.last = time_monotonic(NULL);
 
-		bytes_in += entry->bytes.received;
-		bytes_out += entry->bytes.sent;
-		packets_in += entry->packets.received;
-		packets_out += entry->packets.sent;
+		enumerator = array_create_enumerator(entry->cached);
+		while (enumerator->enumerate(enumerator, &sa))
+		{
+			if (array_bsearch(stats, sa, sa_find, &found) != -1)
+			{
+				/* SA is still around, update stats (e.g. for IKEv1 where
+				 * SA might get used even after rekeying) */
+				sa->usage = found->usage;
+			}
+			else
+			{
+				/* SA is gone, add its last stats to the total for this IKE_SA
+				 * and remove the cache entry */
+				add_usage(&entry->usage, sa->usage);
+				array_remove_at(entry->cached, enumerator);
+				free(sa);
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		enumerator = array_create_enumerator(entry->migrated);
+		while (enumerator->enumerate(enumerator, &sa))
+		{
+			if (array_bsearch(stats, sa, sa_find, &found) != -1)
+			{
+				/* SA is still around, but we have to compensate */
+				sub_usage(&usage, sa->usage);
+			}
+			else
+			{
+				/* SA is gone, subtract stats from the total for this IKE_SA */
+				sub_usage(&entry->usage, sa->usage);
+				array_remove_at(entry->migrated, enumerator);
+				free(sa);
+			}
+		}
+		enumerator->destroy(enumerator);
+
+		add_usage(&usage, entry->usage);
 
 		message = radius_message_create(RMC_ACCOUNTING_REQUEST);
 		value = htonl(ACCT_STATUS_INTERIM_UPDATE);
@@ -377,26 +589,26 @@ static job_requeue_t send_interim(interim_data_t *data)
 					 chunk_create(entry->sid, strlen(entry->sid)));
 		add_ike_sa_parameters(this, message, ike_sa);
 
-		value = htonl(bytes_out);
+		value = htonl(usage.bytes.sent);
 		message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
-		value = htonl(bytes_out >> 32);
+		value = htonl(usage.bytes.sent >> 32);
 		if (value)
 		{
 			message->add(message, RAT_ACCT_OUTPUT_GIGAWORDS,
 						 chunk_from_thing(value));
 		}
-		value = htonl(packets_out);
+		value = htonl(usage.packets.sent);
 		message->add(message, RAT_ACCT_OUTPUT_PACKETS, chunk_from_thing(value));
 
-		value = htonl(bytes_in);
+		value = htonl(usage.bytes.received);
 		message->add(message, RAT_ACCT_INPUT_OCTETS, chunk_from_thing(value));
-		value = htonl(bytes_in >> 32);
+		value = htonl(usage.bytes.received >> 32);
 		if (value)
 		{
 			message->add(message, RAT_ACCT_INPUT_GIGAWORDS,
 						 chunk_from_thing(value));
 		}
-		value = htonl(packets_in);
+		value = htonl(usage.packets.received);
 		message->add(message, RAT_ACCT_INPUT_PACKETS, chunk_from_thing(value));
 
 		value = htonl(entry->interim.last - entry->created);
@@ -405,6 +617,7 @@ static job_requeue_t send_interim(interim_data_t *data)
 		schedule_interim(this, entry);
 	}
 	this->mutex->unlock(this->mutex);
+	array_destroy_function(stats, (void*)free, NULL);
 
 	if (message)
 	{
@@ -479,7 +692,8 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
 
 	this->mutex->lock(this->mutex);
 
-	entry = get_or_create_entry(this, ike_sa);
+	entry = get_or_create_entry(this, ike_sa->get_id(ike_sa),
+								ike_sa->get_unique_id(ike_sa));
 	entry->start_sent = TRUE;
 
 	message = radius_message_create(RMC_ACCOUNTING_REQUEST);
@@ -515,7 +729,9 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
 static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
 {
 	radius_message_t *message;
+	enumerator_t *enumerator;
 	entry_t *entry;
+	sa_entry_t *sa;
 	u_int32_t value;
 
 	this->mutex->lock(this->mutex);
@@ -528,6 +744,20 @@ static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
 			destroy_entry(entry);
 			return;
 		}
+		enumerator = array_create_enumerator(entry->cached);
+		while (enumerator->enumerate(enumerator, &sa))
+		{
+			add_usage(&entry->usage, sa->usage);
+		}
+		enumerator->destroy(enumerator);
+
+		enumerator = array_create_enumerator(entry->migrated);
+		while (enumerator->enumerate(enumerator, &sa))
+		{
+			sub_usage(&entry->usage, sa->usage);
+		}
+		enumerator->destroy(enumerator);
+
 		message = radius_message_create(RMC_ACCOUNTING_REQUEST);
 		value = htonl(ACCT_STATUS_STOP);
 		message->add(message, RAT_ACCT_STATUS_TYPE, chunk_from_thing(value));
@@ -535,26 +765,26 @@ static void send_stop(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
 					 chunk_create(entry->sid, strlen(entry->sid)));
 		add_ike_sa_parameters(this, message, ike_sa);
 
-		value = htonl(entry->bytes.sent);
+		value = htonl(entry->usage.bytes.sent);
 		message->add(message, RAT_ACCT_OUTPUT_OCTETS, chunk_from_thing(value));
-		value = htonl(entry->bytes.sent >> 32);
+		value = htonl(entry->usage.bytes.sent >> 32);
 		if (value)
 		{
 			message->add(message, RAT_ACCT_OUTPUT_GIGAWORDS,
 						 chunk_from_thing(value));
 		}
-		value = htonl(entry->packets.sent);
+		value = htonl(entry->usage.packets.sent);
 		message->add(message, RAT_ACCT_OUTPUT_PACKETS, chunk_from_thing(value));
 
-		value = htonl(entry->bytes.received);
+		value = htonl(entry->usage.bytes.received);
 		message->add(message, RAT_ACCT_INPUT_OCTETS, chunk_from_thing(value));
-		value = htonl(entry->bytes.received >> 32);
+		value = htonl(entry->usage.bytes.received >> 32);
 		if (value)
 		{
 			message->add(message, RAT_ACCT_INPUT_GIGAWORDS,
 						 chunk_from_thing(value));
 		}
-		value = htonl(entry->packets.received);
+		value = htonl(entry->usage.packets.received);
 		message->add(message, RAT_ACCT_INPUT_PACKETS, chunk_from_thing(value));
 
 		value = htonl(time_monotonic(NULL) - entry->created);
@@ -660,6 +890,8 @@ METHOD(listener_t, ike_rekey, bool,
 		/* fire new interim update job, old gets invalid */
 		schedule_interim(this, entry);
 
+		cleanup_sas(this, new, entry);
+
 		entry = this->sessions->put(this->sessions, entry->id, entry);
 		if (entry)
 		{
@@ -675,8 +907,64 @@ METHOD(listener_t, child_rekey, bool,
 	private_eap_radius_accounting_t *this, ike_sa_t *ike_sa,
 	child_sa_t *old, child_sa_t *new)
 {
+	entry_t *entry;
+
 	update_usage(this, ike_sa, old);
+	this->mutex->lock(this->mutex);
+	entry = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
+	if (entry)
+	{
+		cleanup_sas(this, ike_sa, entry);
+	}
+	this->mutex->unlock(this->mutex);
+	return TRUE;
+}
+
+METHOD(listener_t, children_migrate, bool,
+	private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, ike_sa_id_t *new,
+	u_int32_t unique)
+{
+	enumerator_t *enumerator;
+	sa_entry_t *sa, *sa_new, *cached;
+	entry_t *entry_old, *entry_new;
+	array_t *stats;
 
+	if (!new)
+	{
+		return TRUE;
+	}
+	stats = collect_stats(ike_sa, NULL);
+	this->mutex->lock(this->mutex);
+	entry_old = this->sessions->get(this->sessions, ike_sa->get_id(ike_sa));
+	if (entry_old)
+	{
+		entry_new = get_or_create_entry(this, new, unique);
+		enumerator = array_create_enumerator(stats);
+		while (enumerator->enumerate(enumerator, &sa))
+		{
+			/* if the SA was already rekeyed/cached we cache it too on the new
+			 * SA to track it properly until it's finally gone */
+			if (array_bsearch(entry_old->cached, sa, sa_find, &cached) != -1)
+			{
+				sa_new = clone_sa(sa);
+				array_insert_create(&entry_new->cached, ARRAY_TAIL, sa_new);
+				array_sort(entry_new->cached, sa_sort, NULL);
+			}
+			/* if the SA was used, we store it to compensate on the new SA */
+			if (sa->usage.bytes.sent || sa->usage.bytes.received ||
+				sa->usage.packets.sent || sa->usage.packets.received)
+			{
+				sa_new = clone_sa(sa);
+				array_insert_create(&entry_new->migrated, ARRAY_TAIL, sa_new);
+				array_sort(entry_new->migrated, sa_sort, NULL);
+				/* store/update latest stats on old SA to report in Stop */
+				update_sa(entry_old, sa->id, sa->usage);
+			}
+		}
+		enumerator->destroy(enumerator);
+	}
+	this->mutex->unlock(this->mutex);
+	array_destroy_function(stats, (void*)free, NULL);
 	return TRUE;
 }
 
@@ -717,6 +1005,7 @@ eap_radius_accounting_t *eap_radius_accounting_create()
 				.message = _message_hook,
 				.child_updown = _child_updown,
 				.child_rekey = _child_rekey,
+				.children_migrate = _children_migrate,
 			},
 			.destroy = _destroy,
 		},
@@ -759,7 +1048,8 @@ void eap_radius_accounting_start_interim(ike_sa_t *ike_sa, u_int32_t interval)
 
 		DBG1(DBG_CFG, "scheduling RADIUS Interim-Updates every %us", interval);
 		singleton->mutex->lock(singleton->mutex);
-		entry = get_or_create_entry(singleton, ike_sa);
+		entry = get_or_create_entry(singleton, ike_sa->get_id(ike_sa),
+									ike_sa->get_unique_id(ike_sa));
 		entry->interim.interval = interval;
 		singleton->mutex->unlock(singleton->mutex);
 	}
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_peer.c b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
index ff96e92..2637b43 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_peer.c
+++ b/src/libcharon/plugins/eap_sim/eap_sim_peer.c
@@ -310,7 +310,7 @@ static status_t process_challenge(private_eap_sim_peer_t *this,
 	/* excepting two or three RAND, each 16 bytes. We require two valid
 	 * and different RANDs */
 	if ((rands.len != 2 * SIM_RAND_LEN && rands.len != 3 * SIM_RAND_LEN) ||
-		memeq(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
+		memeq_const(rands.ptr, rands.ptr + SIM_RAND_LEN, SIM_RAND_LEN))
 	{
 		DBG1(DBG_IKE, "no valid AT_RAND received");
 		if (!create_client_error(this, SIM_INSUFFICIENT_CHALLENGES, out))
@@ -734,4 +734,3 @@ eap_sim_peer_t *eap_sim_peer_create(identification_t *server,
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/eap_sim/eap_sim_server.c b/src/libcharon/plugins/eap_sim/eap_sim_server.c
index f22266b..5aa54db 100644
--- a/src/libcharon/plugins/eap_sim/eap_sim_server.c
+++ b/src/libcharon/plugins/eap_sim/eap_sim_server.c
@@ -262,7 +262,7 @@ static status_t process_reauthentication(private_eap_sim_server_t *this,
 		this->crypto->clear_keys(this->crypto);
 		return initiate(this, out);
 	}
-	if (!chunk_equals(counter, this->counter))
+	if (!chunk_equals_const(counter, this->counter))
 	{
 		DBG1(DBG_IKE, "received counter does not match");
 		return FAILED;
@@ -644,4 +644,3 @@ eap_sim_server_t *eap_sim_server_create(identification_t *server,
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c
index bd47e50..0a6aec0 100644
--- a/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c
+++ b/src/libcharon/plugins/eap_sim_file/eap_sim_file_card.c
@@ -52,7 +52,7 @@ METHOD(simaka_card_t, get_triplet, bool,
 			 c_rand, SIM_RAND_LEN, c_sres, SIM_SRES_LEN, c_kc, SIM_KC_LEN);
 		if (id->matches(id, cand))
 		{
-			if (memeq(c_rand, rand, SIM_RAND_LEN))
+			if (memeq_const(c_rand, rand, SIM_RAND_LEN))
 			{
 				DBG2(DBG_CFG, "  => triplet matches");
 				memcpy(sres, c_sres, SIM_SRES_LEN);
@@ -105,4 +105,3 @@ eap_sim_file_card_t *eap_sim_file_card_create(eap_sim_file_triplets_t *triplets)
 
 	return &this->public;
 }
-
diff --git a/src/libcharon/plugins/ha/ha_cache.c b/src/libcharon/plugins/ha/ha_cache.c
index 6c1b347..0650f7f 100644
--- a/src/libcharon/plugins/ha/ha_cache.c
+++ b/src/libcharon/plugins/ha/ha_cache.c
@@ -43,6 +43,11 @@ struct private_ha_cache_t {
 	ha_socket_t *socket;
 
 	/**
+	 * Tunnel securing sync messages
+	 */
+	ha_tunnel_t *tunnel;
+
+	/**
 	 * Total number of segments
 	 */
 	u_int count;
@@ -259,6 +264,10 @@ static void rekey_segment(private_ha_cache_t *this, u_int segment)
 												charon->ike_sa_manager, TRUE);
 	while (enumerator->enumerate(enumerator, &ike_sa))
 	{
+		if (this->tunnel && this->tunnel->is_sa(this->tunnel, ike_sa))
+		{
+			continue;
+		}
 		if (ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
 			this->kernel->get_segment(this->kernel,
 						ike_sa->get_other_host(ike_sa)) == segment)
@@ -365,7 +374,7 @@ METHOD(ha_cache_t, destroy, void,
  * See header
  */
 ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
-							bool sync, u_int count)
+							ha_tunnel_t *tunnel, bool sync, u_int count)
 {
 	private_ha_cache_t *this;
 
@@ -379,6 +388,7 @@ ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
 		.count = count,
 		.kernel = kernel,
 		.socket = socket,
+		.tunnel = tunnel,
 		.cache = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 8),
 		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
 	);
diff --git a/src/libcharon/plugins/ha/ha_cache.h b/src/libcharon/plugins/ha/ha_cache.h
index 5e3936a..8cfcbb2 100644
--- a/src/libcharon/plugins/ha/ha_cache.h
+++ b/src/libcharon/plugins/ha/ha_cache.h
@@ -69,10 +69,11 @@ struct ha_cache_t {
  *
  * @param kernel		kernel helper
  * @param socket		socket to send resync messages
+ * @param tunnel		HA tunnel
  * @param resync 		request a resync during startup?
  * @param count			total number of segments
  */
 ha_cache_t *ha_cache_create(ha_kernel_t *kernel, ha_socket_t *socket,
-							bool resync, u_int count);
+							ha_tunnel_t *tunnel, bool resync, u_int count);
 
 #endif /** HA_CACHE_H_ @}*/
diff --git a/src/libcharon/plugins/ha/ha_plugin.c b/src/libcharon/plugins/ha/ha_plugin.c
index a58377b..037b69b 100644
--- a/src/libcharon/plugins/ha/ha_plugin.c
+++ b/src/libcharon/plugins/ha/ha_plugin.c
@@ -97,13 +97,73 @@ METHOD(plugin_t, get_name, char*,
 }
 
 /**
- * Register listener
+ * Initialize plugin
+ */
+static bool initialize_plugin(private_ha_plugin_t *this)
+{
+	char *local, *remote, *secret;
+	u_int count;
+	bool fifo, monitor, resync;
+
+	local = lib->settings->get_str(lib->settings,
+								"%s.plugins.ha.local", NULL, lib->ns);
+	remote = lib->settings->get_str(lib->settings,
+								"%s.plugins.ha.remote", NULL, lib->ns);
+	secret = lib->settings->get_str(lib->settings,
+								"%s.plugins.ha.secret", NULL, lib->ns);
+	fifo = lib->settings->get_bool(lib->settings,
+								"%s.plugins.ha.fifo_interface", TRUE, lib->ns);
+	monitor = lib->settings->get_bool(lib->settings,
+								"%s.plugins.ha.monitor", TRUE, lib->ns);
+	resync = lib->settings->get_bool(lib->settings,
+								"%s.plugins.ha.resync", TRUE, lib->ns);
+	count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings,
+								"%s.plugins.ha.segment_count", 1, lib->ns));
+	if (!local || !remote)
+	{
+		DBG1(DBG_CFG, "HA config misses local/remote address");
+		return FALSE;
+	}
+
+	if (secret)
+	{
+		this->tunnel = ha_tunnel_create(local, remote, secret);
+	}
+	this->socket = ha_socket_create(local, remote);
+	if (!this->socket)
+	{
+		return FALSE;
+	}
+	this->kernel = ha_kernel_create(count);
+	this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel,
+							count, strcmp(local, remote) > 0, monitor);
+	this->cache = ha_cache_create(this->kernel, this->socket, this->tunnel,
+								  resync, count);
+	if (fifo)
+	{
+		this->ctl = ha_ctl_create(this->segments, this->cache);
+	}
+	this->attr = ha_attribute_create(this->kernel, this->segments);
+	this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
+										this->cache, this->kernel, this->attr);
+	this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
+	this->child = ha_child_create(this->socket, this->tunnel, this->segments,
+								  this->kernel);
+	return TRUE;
+}
+
+/**
+ * Initialize plugin and register listener
  */
 static bool plugin_cb(private_ha_plugin_t *this,
 					  plugin_feature_t *feature, bool reg, void *cb_data)
 {
 	if (reg)
 	{
+		if (!initialize_plugin(this))
+		{
+			return FALSE;
+		}
 		charon->bus->add_listener(charon->bus, &this->segments->listener);
 		charon->bus->add_listener(charon->bus, &this->ike->listener);
 		charon->bus->add_listener(charon->bus, &this->child->listener);
@@ -127,6 +187,7 @@ METHOD(plugin_t, get_features, int,
 	static plugin_feature_t f[] = {
 		PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL),
 			PLUGIN_PROVIDE(CUSTOM, "ha"),
+				PLUGIN_SDEPEND(CUSTOM, "kernel-ipsec"),
 	};
 	*features = f;
 	return countof(f);
@@ -136,14 +197,14 @@ METHOD(plugin_t, destroy, void,
 	private_ha_plugin_t *this)
 {
 	DESTROY_IF(this->ctl);
-	this->ike->destroy(this->ike);
-	this->child->destroy(this->child);
-	this->dispatcher->destroy(this->dispatcher);
-	this->attr->destroy(this->attr);
-	this->cache->destroy(this->cache);
-	this->segments->destroy(this->segments);
-	this->kernel->destroy(this->kernel);
-	this->socket->destroy(this->socket);
+	DESTROY_IF(this->ike);
+	DESTROY_IF(this->child);
+	DESTROY_IF(this->dispatcher);
+	DESTROY_IF(this->attr);
+	DESTROY_IF(this->cache);
+	DESTROY_IF(this->segments);
+	DESTROY_IF(this->kernel);
+	DESTROY_IF(this->socket);
 	DESTROY_IF(this->tunnel);
 	free(this);
 }
@@ -154,29 +215,6 @@ METHOD(plugin_t, destroy, void,
 plugin_t *ha_plugin_create()
 {
 	private_ha_plugin_t *this;
-	char *local, *remote, *secret;
-	u_int count;
-	bool fifo, monitor, resync;
-
-	local = lib->settings->get_str(lib->settings,
-								"%s.plugins.ha.local", NULL, lib->ns);
-	remote = lib->settings->get_str(lib->settings,
-								"%s.plugins.ha.remote", NULL, lib->ns);
-	secret = lib->settings->get_str(lib->settings,
-								"%s.plugins.ha.secret", NULL, lib->ns);
-	fifo = lib->settings->get_bool(lib->settings,
-								"%s.plugins.ha.fifo_interface", TRUE, lib->ns);
-	monitor = lib->settings->get_bool(lib->settings,
-								"%s.plugins.ha.monitor", TRUE, lib->ns);
-	resync = lib->settings->get_bool(lib->settings,
-								"%s.plugins.ha.resync", TRUE, lib->ns);
-	count = min(SEGMENTS_MAX, lib->settings->get_int(lib->settings,
-								"%s.plugins.ha.segment_count", 1, lib->ns));
-	if (!local || !remote)
-	{
-		DBG1(DBG_CFG, "HA config misses local/remote address");
-		return NULL;
-	}
 
 	if (!lib->caps->keep(lib->caps, CAP_CHOWN))
 	{	/* required to chown(2) control socket, ha_kernel also needs it at
@@ -195,31 +233,5 @@ plugin_t *ha_plugin_create()
 		},
 	);
 
-	if (secret)
-	{
-		this->tunnel = ha_tunnel_create(local, remote, secret);
-	}
-	this->socket = ha_socket_create(local, remote);
-	if (!this->socket)
-	{
-		DESTROY_IF(this->tunnel);
-		free(this);
-		return NULL;
-	}
-	this->kernel = ha_kernel_create(count);
-	this->segments = ha_segments_create(this->socket, this->kernel, this->tunnel,
-							count, strcmp(local, remote) > 0, monitor);
-	this->cache = ha_cache_create(this->kernel, this->socket, resync, count);
-	if (fifo)
-	{
-		this->ctl = ha_ctl_create(this->segments, this->cache);
-	}
-	this->attr = ha_attribute_create(this->kernel, this->segments);
-	this->dispatcher = ha_dispatcher_create(this->socket, this->segments,
-										this->cache, this->kernel, this->attr);
-	this->ike = ha_ike_create(this->socket, this->tunnel, this->cache);
-	this->child = ha_child_create(this->socket, this->tunnel, this->segments,
-								  this->kernel);
-
 	return &this->public.plugin;
 }
diff --git a/src/libcharon/plugins/vici/libvici.h b/src/libcharon/plugins/vici/libvici.h
index 641370e..3ca9de4 100644
--- a/src/libcharon/plugins/vici/libvici.h
+++ b/src/libcharon/plugins/vici/libvici.h
@@ -2,15 +2,26 @@
  * Copyright (C) 2014 Martin Willi
  * Copyright (C) 2014 revosec AG
  *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
+ * libvici.h is MIT-licensed to simplify reuse, but please note that libvici.c
+ * is not, as it depends on the GPLv2 licensed libstrongswan.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
  */
 
 /**
diff --git a/src/libcharon/plugins/vici/python/Makefile.am b/src/libcharon/plugins/vici/python/Makefile.am
index f517378..5936f2a 100644
--- a/src/libcharon/plugins/vici/python/Makefile.am
+++ b/src/libcharon/plugins/vici/python/Makefile.am
@@ -8,25 +8,27 @@ EXTRA_DIST = LICENSE MANIFEST.in \
 	vici/protocol.py \
 	vici/session.py
 
-setup.py: $(srcdir)/setup.py.in
+$(srcdir)/setup.py: $(srcdir)/setup.py.in
 	$(AM_V_GEN) sed \
 	-e "s:@EGG_VERSION@:$(PACKAGE_VERSION):" \
 	$(srcdir)/setup.py.in > $@
 
 all-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
 
-dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) setup.py
+dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) $(srcdir)/setup.py
 	(cd $(srcdir); $(PYTHON) setup.py bdist_egg \
 		-b $(shell readlink -f $(builddir))/build \
 		-d $(shell readlink -f $(builddir))/dist)
 
-clean-local: setup.py
-	$(PYTHON) setup.py clean -a
-	rm -rf vici.egg-info dist setup.py
+clean-local:
+	(cd $(srcdir); [ ! -f setup.py ] || $(PYTHON) setup.py clean -a)
+	rm -rf $(srcdir)/setup.py $(srcdir)/vici.egg-info $(builddir)/dist
 
+if PYTHON_EGGS_INSTALL
 install-exec-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
 	$(EASY_INSTALL) $(PYTHONEGGINSTALLDIR) \
 		dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
+endif
 
 if USE_PY_TEST
   TESTS = $(PY_TEST)
diff --git a/src/libcharon/plugins/vici/python/Makefile.in b/src/libcharon/plugins/vici/python/Makefile.in
index 3a5e5ea..eb4bab6 100644
--- a/src/libcharon/plugins/vici/python/Makefile.in
+++ b/src/libcharon/plugins/vici/python/Makefile.in
@@ -579,6 +579,7 @@ distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
+ at PYTHON_EGGS_INSTALL_FALSE@install-exec-local:
 clean: clean-am
 
 clean-am: clean-generic clean-libtool clean-local mostlyclean-am
@@ -661,25 +662,25 @@ uninstall-am:
 	tags-am uninstall uninstall-am
 
 
-setup.py: $(srcdir)/setup.py.in
+$(srcdir)/setup.py: $(srcdir)/setup.py.in
 	$(AM_V_GEN) sed \
 	-e "s:@EGG_VERSION@:$(PACKAGE_VERSION):" \
 	$(srcdir)/setup.py.in > $@
 
 all-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
 
-dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) setup.py
+dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg: $(EXTRA_DIST) $(srcdir)/setup.py
 	(cd $(srcdir); $(PYTHON) setup.py bdist_egg \
 		-b $(shell readlink -f $(builddir))/build \
 		-d $(shell readlink -f $(builddir))/dist)
 
-clean-local: setup.py
-	$(PYTHON) setup.py clean -a
-	rm -rf vici.egg-info dist setup.py
+clean-local:
+	(cd $(srcdir); [ ! -f setup.py ] || $(PYTHON) setup.py clean -a)
+	rm -rf $(srcdir)/setup.py $(srcdir)/vici.egg-info $(builddir)/dist
 
-install-exec-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
-	$(EASY_INSTALL) $(PYTHONEGGINSTALLDIR) \
-		dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
+ at PYTHON_EGGS_INSTALL_TRUE@install-exec-local: dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
+ at PYTHON_EGGS_INSTALL_TRUE@	$(EASY_INSTALL) $(PYTHONEGGINSTALLDIR) \
+ at PYTHON_EGGS_INSTALL_TRUE@		dist/vici-$(PACKAGE_VERSION)-py$(PYTHON_VERSION).egg
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.am b/src/libcharon/plugins/vici/ruby/Makefile.am
index 3e12f86..e2d3404 100644
--- a/src/libcharon/plugins/vici/ruby/Makefile.am
+++ b/src/libcharon/plugins/vici/ruby/Makefile.am
@@ -15,10 +15,12 @@ all-local: vici-$(PACKAGE_VERSION).gem
 clean-local:
 	rm -f vici.gemspec vici-$(PACKAGE_VERSION).gem
 
+if RUBY_GEMS_INSTALL
 install-data-local: vici-$(PACKAGE_VERSION).gem
-	$(GEM) install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+	$(GEM) install --no-user-install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
 		vici-$(PACKAGE_VERSION).gem
 
 uninstall-local:
 	$(GEM) uninstall --install-dir $(DESTDIR)$(RUBYGEMDIR) \
 		--version $(PACKAGE_VERSION) vici
+endif
diff --git a/src/libcharon/plugins/vici/ruby/Makefile.in b/src/libcharon/plugins/vici/ruby/Makefile.in
index f37c09e..bf81e53 100644
--- a/src/libcharon/plugins/vici/ruby/Makefile.in
+++ b/src/libcharon/plugins/vici/ruby/Makefile.in
@@ -453,6 +453,8 @@ distclean-generic:
 maintainer-clean-generic:
 	@echo "This command is intended for maintainers to use"
 	@echo "it deletes files that may require special tools to rebuild."
+ at RUBY_GEMS_INSTALL_FALSE@uninstall-local:
+ at RUBY_GEMS_INSTALL_FALSE@install-data-local:
 clean: clean-am
 
 clean-am: clean-generic clean-libtool clean-local mostlyclean-am
@@ -550,13 +552,13 @@ all-local: vici-$(PACKAGE_VERSION).gem
 clean-local:
 	rm -f vici.gemspec vici-$(PACKAGE_VERSION).gem
 
-install-data-local: vici-$(PACKAGE_VERSION).gem
-	$(GEM) install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
-		vici-$(PACKAGE_VERSION).gem
+ at RUBY_GEMS_INSTALL_TRUE@install-data-local: vici-$(PACKAGE_VERSION).gem
+ at RUBY_GEMS_INSTALL_TRUE@	$(GEM) install --no-user-install --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+ at RUBY_GEMS_INSTALL_TRUE@		vici-$(PACKAGE_VERSION).gem
 
-uninstall-local:
-	$(GEM) uninstall --install-dir $(DESTDIR)$(RUBYGEMDIR) \
-		--version $(PACKAGE_VERSION) vici
+ at RUBY_GEMS_INSTALL_TRUE@uninstall-local:
+ at RUBY_GEMS_INSTALL_TRUE@	$(GEM) uninstall --install-dir $(DESTDIR)$(RUBYGEMDIR) \
+ at RUBY_GEMS_INSTALL_TRUE@		--version $(PACKAGE_VERSION) vici
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index 6491610..d232599 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -13,6 +13,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #define _GNU_SOURCE
 
 #include "vici_config.h"
@@ -1460,6 +1482,21 @@ CALLBACK(peer_sn, bool,
 			return FALSE;
 		}
 
+		if (!auth.cfg->get(auth.cfg, AUTH_RULE_IDENTITY))
+		{
+			identification_t *id;
+			certificate_t *cert;
+
+			cert = auth.cfg->get(auth.cfg, AUTH_RULE_SUBJECT_CERT);
+			if (cert)
+			{
+				id = cert->get_subject(cert);
+				DBG1(DBG_CFG, "  id not specified, defaulting to cert id '%Y'",
+					 id);
+				auth.cfg->add(auth.cfg, AUTH_RULE_IDENTITY, id->clone(id));
+			}
+		}
+
 		if (strcasepfx(name, "local"))
 		{
 			peer->local->insert_last(peer->local, auth.cfg);
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.c b/src/libcharon/plugins/vici/vici_dispatcher.c
index 6db36fb..31292d6 100644
--- a/src/libcharon/plugins/vici/vici_dispatcher.c
+++ b/src/libcharon/plugins/vici/vici_dispatcher.c
@@ -13,6 +13,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "vici_dispatcher.h"
 #include "vici_socket.h"
 
@@ -446,6 +468,24 @@ METHOD(vici_dispatcher_t, manage_event, void,
 	this->mutex->unlock(this->mutex);
 }
 
+METHOD(vici_dispatcher_t, has_event_listeners, bool,
+	private_vici_dispatcher_t *this, char *name)
+{
+	bool retval = FALSE;
+
+	this->mutex->lock(this->mutex);
+	if (this->events->get(this->events, name))
+	{
+		/* the entry might be getting destroyed, but returning
+		 * false positive is not a problem as a later raise_event
+		 * will check things again. */
+		retval = TRUE;
+	}
+	this->mutex->unlock(this->mutex);
+
+	return retval;
+}
+
 METHOD(vici_dispatcher_t, raise_event, void,
 	private_vici_dispatcher_t *this, char *name, u_int id,
 	vici_message_t *message)
@@ -504,6 +544,7 @@ vici_dispatcher_t *vici_dispatcher_create(char *uri)
 		.public = {
 			.manage_command = _manage_command,
 			.manage_event = _manage_event,
+			.has_event_listeners = _has_event_listeners,
 			.raise_event = _raise_event,
 			.destroy = _destroy,
 		},
diff --git a/src/libcharon/plugins/vici/vici_dispatcher.h b/src/libcharon/plugins/vici/vici_dispatcher.h
index 2297a80..e48cf3b 100644
--- a/src/libcharon/plugins/vici/vici_dispatcher.h
+++ b/src/libcharon/plugins/vici/vici_dispatcher.h
@@ -13,6 +13,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 /**
  * @defgroup vici_dispatcher vici_dispatcher
  * @{ @ingroup vici
@@ -96,6 +118,17 @@ struct vici_dispatcher_t {
 	void (*manage_event)(vici_dispatcher_t *this, char *name, bool reg);
 
 	/**
+	 * Check if an event has listeners.
+	 *
+	 * This can be used to check if a vici message needs to be generated or not,
+	 * as in some cases the generation can be a heavy operation.
+	 *
+	 * @param name			event name to check
+	 * @return				TRUE if event has listeners
+	 */
+	bool (*has_event_listeners)(vici_dispatcher_t *this, char *name);
+
+	/**
 	 * Raise an event to a specific or all clients registered to that event.
 	 *
 	 * @param name			event name to raise
diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c
index af8bd28..7ae58a3 100644
--- a/src/libcharon/plugins/vici/vici_plugin.c
+++ b/src/libcharon/plugins/vici/vici_plugin.c
@@ -13,6 +13,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "vici_plugin.h"
 #include "vici_dispatcher.h"
 #include "vici_query.h"
@@ -106,12 +128,14 @@ static bool register_vici(private_vici_plugin_t *this,
 			charon->attributes->add_provider(charon->attributes,
 											 &this->attrs->provider);
 			charon->bus->add_logger(charon->bus, &this->logger->logger);
+			charon->bus->add_listener(charon->bus, &this->query->listener);
 			return TRUE;
 		}
 		return FALSE;
 	}
 	else
 	{
+		charon->bus->remove_listener(charon->bus, &this->query->listener);
 		charon->bus->remove_logger(charon->bus, &this->logger->logger);
 		charon->attributes->remove_provider(charon->attributes,
 											&this->attrs->provider);
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
index 3e0d73c..d94d760 100644
--- a/src/libcharon/plugins/vici/vici_query.c
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -13,6 +13,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #include "vici_query.h"
 #include "vici_builder.h"
 
@@ -1008,6 +1030,8 @@ static void manage_commands(private_vici_query_t *this, bool reg)
 	this->dispatcher->manage_event(this->dispatcher, "list-policy", reg);
 	this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
 	this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
+	this->dispatcher->manage_event(this->dispatcher, "ike-updown", reg);
+	this->dispatcher->manage_event(this->dispatcher, "child-updown", reg);
 	manage_command(this, "list-sas", list_sas, reg);
 	manage_command(this, "list-policies", list_policies, reg);
 	manage_command(this, "list-conns", list_conns, reg);
@@ -1016,6 +1040,63 @@ static void manage_commands(private_vici_query_t *this, bool reg)
 	manage_command(this, "stats", stats, reg);
 }
 
+METHOD(listener_t, ike_updown, bool,
+	private_vici_query_t *this, ike_sa_t *ike_sa, bool up)
+{
+	vici_builder_t *b;
+	time_t now;
+
+	if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-updown"))
+	{
+		return TRUE;
+	}
+
+	now = time_monotonic(NULL);
+
+	b = vici_builder_create();
+	b->begin_section(b, ike_sa->get_name(ike_sa));
+	list_ike(this, b, ike_sa, now);
+	b->begin_section(b, "child-sas");
+	b->end_section(b);
+	b->end_section(b);
+
+	this->dispatcher->raise_event(this->dispatcher,
+								  "ike-updown", 0, b->finalize(b));
+
+	return TRUE;
+}
+
+METHOD(listener_t, child_updown, bool,
+	private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, bool up)
+{
+	vici_builder_t *b;
+	time_t now;
+
+	if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-updown"))
+	{
+		return TRUE;
+	}
+
+	now = time_monotonic(NULL);
+	b = vici_builder_create();
+
+	b->begin_section(b, ike_sa->get_name(ike_sa));
+	list_ike(this, b, ike_sa, now);
+	b->begin_section(b, "child-sas");
+
+	b->begin_section(b, child_sa->get_name(child_sa));
+	list_child(this, b, child_sa, now);
+	b->end_section(b);
+
+	b->end_section(b);
+	b->end_section(b);
+
+	this->dispatcher->raise_event(this->dispatcher,
+								  "child-updown", 0, b->finalize(b));
+
+	return TRUE;
+}
+
 METHOD(vici_query_t, destroy, void,
 	private_vici_query_t *this)
 {
@@ -1032,6 +1113,10 @@ vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
 
 	INIT(this,
 		.public = {
+			.listener = {
+				.ike_updown = _ike_updown,
+				.child_updown = _child_updown,
+			},
 			.destroy = _destroy,
 		},
 		.dispatcher = dispatcher,
diff --git a/src/libcharon/plugins/vici/vici_query.h b/src/libcharon/plugins/vici/vici_query.h
index da72b14..0149e8d 100644
--- a/src/libcharon/plugins/vici/vici_query.h
+++ b/src/libcharon/plugins/vici/vici_query.h
@@ -13,11 +13,34 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 /**
  * @defgroup vici_query vici_query
  * @{ @ingroup vici
  */
 
+#include <bus/listeners/listener.h>
 #include "vici_dispatcher.h"
 
 #ifndef VICI_QUERY_H_
@@ -31,6 +54,11 @@ typedef struct vici_query_t vici_query_t;
 struct vici_query_t {
 
 	/**
+	 * Implements listener_t.
+	 */
+	listener_t listener;
+
+	/**
 	 * Destroy a vici_query_t.
 	 */
 	void (*destroy)(vici_query_t *this);
diff --git a/src/libcharon/plugins/vici/vici_socket.c b/src/libcharon/plugins/vici/vici_socket.c
index 9167728..67fd7e8 100644
--- a/src/libcharon/plugins/vici/vici_socket.c
+++ b/src/libcharon/plugins/vici/vici_socket.c
@@ -118,6 +118,8 @@ typedef struct {
 	array_t *queue;
 	/** do we have job processing input queue? */
 	bool has_processor;
+	/** is this client disconnecting */
+	bool disconnecting;
 	/** client connection identifier */
 	u_int id;
 	/** any users reading over this connection? */
@@ -187,6 +189,10 @@ static entry_t* find_entry(private_vici_socket_t *this, stream_t *stream,
 					continue;
 				}
 			}
+			if (entry->disconnecting)
+			{
+				continue;
+			}
 			candidate = TRUE;
 
 			if ((reader && entry->readers) ||
@@ -304,7 +310,7 @@ static void disconnect(private_vici_socket_t *this, u_int id)
  * Write queued output data
  */
 static bool do_write(private_vici_socket_t *this, entry_t *entry,
-					 stream_t *stream)
+					 stream_t *stream, char *errmsg, size_t errlen)
 {
 	msg_buf_t *out;
 	ssize_t len;
@@ -326,7 +332,8 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
 				{
 					return TRUE;
 				}
-				DBG1(DBG_CFG, "vici header write error: %s", strerror(errno));
+				snprintf(errmsg, errlen, "vici header write error: %s",
+						 strerror(errno));
 				return FALSE;
 			}
 			out->hdrlen += len;
@@ -339,7 +346,7 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
 								out->buf.len - out->done, FALSE);
 			if (len == 0)
 			{
-				DBG1(DBG_CFG, "premature vici disconnect");
+				snprintf(errmsg, errlen, "premature vici disconnect");
 				return FALSE;
 			}
 			if (len < 0)
@@ -348,7 +355,7 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
 				{
 					return TRUE;
 				}
-				DBG1(DBG_CFG, "vici write error: %s", strerror(errno));
+				snprintf(errmsg, errlen, "vici write error: %s", strerror(errno));
 				return FALSE;
 			}
 			out->done += len;
@@ -369,13 +376,14 @@ static bool do_write(private_vici_socket_t *this, entry_t *entry,
 CALLBACK(on_write, bool,
 	private_vici_socket_t *this, stream_t *stream)
 {
+	char errmsg[256] = "";
 	entry_t *entry;
 	bool ret = FALSE;
 
 	entry = find_entry(this, stream, 0, FALSE, TRUE);
 	if (entry)
 	{
-		ret = do_write(this, entry, stream);
+		ret = do_write(this, entry, stream, errmsg, sizeof(errmsg));
 		if (ret)
 		{
 			/* unregister if we have no more messages to send */
@@ -383,9 +391,15 @@ CALLBACK(on_write, bool,
 		}
 		else
 		{
+			entry->disconnecting = TRUE;
 			disconnect(entry->this, entry->id);
 		}
 		put_entry(this, entry, FALSE, TRUE);
+
+		if (!ret && errmsg[0])
+		{
+			DBG1(DBG_CFG, errmsg);
+		}
 	}
 
 	return ret;
@@ -395,7 +409,7 @@ CALLBACK(on_write, bool,
  * Read in available header with data, non-blocking cumulating to buffer
  */
 static bool do_read(private_vici_socket_t *this, entry_t *entry,
-					stream_t *stream)
+					stream_t *stream, char *errmsg, size_t errlen)
 {
 	u_int32_t msglen;
 	ssize_t len;
@@ -415,7 +429,8 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
 			{
 				return TRUE;
 			}
-			DBG1(DBG_CFG, "vici header read error: %s", strerror(errno));
+			snprintf(errmsg, errlen, "vici header read error: %s",
+					 strerror(errno));
 			return FALSE;
 		}
 		entry->in.hdrlen += len;
@@ -424,8 +439,8 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
 			msglen = untoh32(entry->in.hdr);
 			if (msglen > VICI_MESSAGE_SIZE_MAX)
 			{
-				DBG1(DBG_CFG, "vici message length %u exceeds %u bytes limit, "
-					 "ignored", msglen, VICI_MESSAGE_SIZE_MAX);
+				snprintf(errmsg, errlen, "vici message length %u exceeds %u "
+						 "bytes limit, ignored", msglen, VICI_MESSAGE_SIZE_MAX);
 				return FALSE;
 			}
 			/* header complete, continue with data */
@@ -440,7 +455,7 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
 						   entry->in.buf.len - entry->in.done, FALSE);
 		if (len == 0)
 		{
-			DBG1(DBG_CFG, "premature vici disconnect");
+			snprintf(errmsg, errlen, "premature vici disconnect");
 			return FALSE;
 		}
 		if (len < 0)
@@ -449,7 +464,7 @@ static bool do_read(private_vici_socket_t *this, entry_t *entry,
 			{
 				return TRUE;
 			}
-			DBG1(DBG_CFG, "vici read error: %s", strerror(errno));
+			snprintf(errmsg, errlen, "vici read error: %s", strerror(errno));
 			return FALSE;
 		}
 		entry->in.done += len;
@@ -502,6 +517,7 @@ CALLBACK(process_queue, job_requeue_t,
 CALLBACK(on_read, bool,
 	private_vici_socket_t *this, stream_t *stream)
 {
+	char errmsg[256] = "";
 	entry_selector_t *sel;
 	entry_t *entry;
 	bool ret = FALSE;
@@ -509,9 +525,10 @@ CALLBACK(on_read, bool,
 	entry = find_entry(this, stream, 0, TRUE, FALSE);
 	if (entry)
 	{
-		ret = do_read(this, entry, stream);
+		ret = do_read(this, entry, stream, errmsg, sizeof(errmsg));
 		if (!ret)
 		{
+			entry->disconnecting = TRUE;
 			disconnect(this, entry->id);
 		}
 		else if (entry->in.hdrlen == sizeof(entry->in.hdr) &&
@@ -534,6 +551,11 @@ CALLBACK(on_read, bool,
 			}
 		}
 		put_entry(this, entry, TRUE, FALSE);
+
+		if (!ret && errmsg[0])
+		{
+			DBG1(DBG_CFG, errmsg);
+		}
 	}
 
 	return ret;
diff --git a/src/libcharon/plugins/xauth_generic/xauth_generic.c b/src/libcharon/plugins/xauth_generic/xauth_generic.c
index c37da0c..e65d1a1 100644
--- a/src/libcharon/plugins/xauth_generic/xauth_generic.c
+++ b/src/libcharon/plugins/xauth_generic/xauth_generic.c
@@ -180,7 +180,7 @@ METHOD(xauth_method_t, process_server, status_t,
 										SHARED_EAP, this->server, this->peer);
 	while (enumerator->enumerate(enumerator, &shared, NULL, NULL))
 	{
-		if (chunk_equals(shared->get_key(shared), pass))
+		if (chunk_equals_const(shared->get_key(shared), pass))
 		{
 			status = SUCCESS;
 			break;
diff --git a/src/libcharon/processing/jobs/adopt_children_job.c b/src/libcharon/processing/jobs/adopt_children_job.c
index c8a9c17..b4f135a 100644
--- a/src/libcharon/processing/jobs/adopt_children_job.c
+++ b/src/libcharon/processing/jobs/adopt_children_job.c
@@ -21,6 +21,7 @@
 #include <daemon.h>
 #include <hydra.h>
 #include <collections/array.h>
+#include <processing/jobs/delete_ike_sa_job.h>
 
 typedef struct private_adopt_children_job_t private_adopt_children_job_t;
 
@@ -64,11 +65,13 @@ METHOD(job_t, execute, job_requeue_t,
 	ike_sa_id_t *id;
 	ike_sa_t *ike_sa;
 	child_sa_t *child_sa;
+	u_int32_t unique;
 
 	ike_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager, this->id);
 	if (ike_sa)
 	{
 		/* get what we need from new SA */
+		unique = ike_sa->get_unique_id(ike_sa);
 		me = ike_sa->get_my_host(ike_sa);
 		me = me->clone(me);
 		other = ike_sa->get_other_host(ike_sa);
@@ -106,6 +109,7 @@ METHOD(job_t, execute, job_requeue_t,
 					other_id->equals(other_id, ike_sa->get_other_id(ike_sa)) &&
 					cfg->equals(cfg, ike_sa->get_peer_cfg(ike_sa)))
 				{
+					charon->bus->children_migrate(charon->bus, this->id, unique);
 					subenum = ike_sa->create_child_sa_enumerator(ike_sa);
 					while (subenum->enumerate(subenum, &child_sa))
 					{
@@ -130,10 +134,19 @@ METHOD(job_t, execute, job_requeue_t,
 							 "adopting %d children and %d virtual IPs",
 							 children->get_count(children), vips->get_count(vips));
 					}
-					ike_sa->set_state(ike_sa, IKE_DELETING);
-					charon->bus->ike_updown(charon->bus, ike_sa, FALSE);
-					charon->ike_sa_manager->checkin_and_destroy(
+					if (ike_sa->get_state(ike_sa) == IKE_PASSIVE)
+					{
+						charon->ike_sa_manager->checkin_and_destroy(
+											charon->ike_sa_manager, ike_sa);
+					}
+					else
+					{
+						lib->scheduler->schedule_job(lib->scheduler, (job_t*)
+								delete_ike_sa_job_create(ike_sa->get_id(ike_sa),
+														 TRUE), 10);
+						charon->ike_sa_manager->checkin(
 											charon->ike_sa_manager, ike_sa);
+					}
 				}
 				else
 				{
@@ -176,6 +189,7 @@ METHOD(job_t, execute, job_requeue_t,
 					}
 					charon->bus->assign_vips(charon->bus, ike_sa, TRUE);
 				}
+				charon->bus->children_migrate(charon->bus, NULL, 0);
 				charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
 			}
 		}
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 13fc74f..938f784 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -1737,7 +1737,8 @@ static void adopt_children_and_vips(ike_sa_t *old, ike_sa_t *new)
 	host_t *vip;
 	int chcount = 0, vipcount = 0;
 
-
+	charon->bus->children_migrate(charon->bus, new->get_id(new),
+								  new->get_unique_id(new));
 	enumerator = old->create_child_sa_enumerator(old);
 	while (enumerator->enumerate(enumerator, &child_sa))
 	{
@@ -1760,6 +1761,7 @@ static void adopt_children_and_vips(ike_sa_t *old, ike_sa_t *new)
 	/* ...trigger the analogous event on the new SA */
 	charon->bus->set_sa(charon->bus, new);
 	charon->bus->assign_vips(charon->bus, new, TRUE);
+	charon->bus->children_migrate(charon->bus, NULL, 0);
 	charon->bus->set_sa(charon->bus, old);
 
 	if (chcount || vipcount)
diff --git a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
index bb187f0..5debeeb 100644
--- a/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
+++ b/src/libcharon/sa/ikev1/authenticators/psk_v1_authenticator.c
@@ -124,7 +124,7 @@ METHOD(authenticator_t, process, status_t,
 		return FAILED;
 	}
 	free(dh.ptr);
-	if (chunk_equals(hash, hash_payload->get_hash(hash_payload)))
+	if (chunk_equals_const(hash, hash_payload->get_hash(hash_payload)))
 	{
 		free(hash.ptr);
 		if (!this->hybrid)
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index cb22bf6..ed547c4 100644
--- a/src/libcharon/sa/ikev1/task_manager_v1.c
+++ b/src/libcharon/sa/ikev1/task_manager_v1.c
@@ -1475,6 +1475,8 @@ METHOD(task_manager_t, queue_ike_reauth, void,
 	}
 	enumerator->destroy(enumerator);
 
+	charon->bus->children_migrate(charon->bus, new->get_id(new),
+								  new->get_unique_id(new));
 	enumerator = this->ike_sa->create_child_sa_enumerator(this->ike_sa);
 	while (enumerator->enumerate(enumerator, &child_sa))
 	{
@@ -1482,6 +1484,9 @@ METHOD(task_manager_t, queue_ike_reauth, void,
 		new->add_child_sa(new, child_sa);
 	}
 	enumerator->destroy(enumerator);
+	charon->bus->set_sa(charon->bus, new);
+	charon->bus->children_migrate(charon->bus, NULL, 0);
+	charon->bus->set_sa(charon->bus, this->ike_sa);
 
 	if (!new->get_child_count(new))
 	{	/* check if a Quick Mode task is queued (UNITY_LOAD_BALANCE case) */
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index ebef319..f144209 100644
--- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -464,7 +464,7 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
 		return FALSE;
 	}
 	recv_auth_data = auth_payload->get_data(auth_payload);
-	if (!auth_data.len || !chunk_equals(auth_data, recv_auth_data))
+	if (!auth_data.len || !chunk_equals_const(auth_data, recv_auth_data))
 	{
 		DBG1(DBG_IKE, "verification of AUTH payload with%s EAP MSK failed",
 			 this->msk.ptr ? "" : "out");
diff --git a/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
index c6a4b6b..5355810 100644
--- a/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/psk_authenticator.c
@@ -123,7 +123,7 @@ METHOD(authenticator_t, process, status_t,
 		{
 			continue;
 		}
-		if (auth_data.len && chunk_equals(auth_data, recv_auth_data))
+		if (auth_data.len && chunk_equals_const(auth_data, recv_auth_data))
 		{
 			DBG1(DBG_IKE, "authentication of '%Y' with %N successful",
 				 other_id, auth_method_names, AUTH_PSK);
diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c
index f70f5cf..6fedc8e 100644
--- a/src/libcharon/sa/ikev2/keymat_v2.c
+++ b/src/libcharon/sa/ikev2/keymat_v2.c
@@ -193,6 +193,7 @@ static bool derive_ike_traditional(private_keymat_v2_t *this, u_int16_t enc_alg,
 {
 	crypter_t *crypter_i = NULL, *crypter_r = NULL;
 	signer_t *signer_i, *signer_r;
+	iv_gen_t *ivg_i, *ivg_r;
 	size_t key_size;
 	chunk_t key = chunk_empty;
 
@@ -264,15 +265,21 @@ static bool derive_ike_traditional(private_keymat_v2_t *this, u_int16_t enc_alg,
 		goto failure;
 	}
 
+	ivg_i = iv_gen_create_for_alg(enc_alg);
+	ivg_r = iv_gen_create_for_alg(enc_alg);
+	if (!ivg_i || !ivg_r)
+	{
+		goto failure;
+	}
 	if (this->initiator)
 	{
-		this->aead_in = aead_create(crypter_r, signer_r);
-		this->aead_out = aead_create(crypter_i, signer_i);
+		this->aead_in = aead_create(crypter_r, signer_r, ivg_r);
+		this->aead_out = aead_create(crypter_i, signer_i, ivg_i);
 	}
 	else
 	{
-		this->aead_in = aead_create(crypter_i, signer_i);
-		this->aead_out = aead_create(crypter_r, signer_r);
+		this->aead_in = aead_create(crypter_i, signer_i, ivg_i);
+		this->aead_out = aead_create(crypter_r, signer_r, ivg_r);
 	}
 	signer_i = signer_r = NULL;
 	crypter_i = crypter_r = NULL;
diff --git a/src/libcharon/sa/ikev2/task_manager_v2.c b/src/libcharon/sa/ikev2/task_manager_v2.c
index 2981677..4676867 100644
--- a/src/libcharon/sa/ikev2/task_manager_v2.c
+++ b/src/libcharon/sa/ikev2/task_manager_v2.c
@@ -1184,15 +1184,17 @@ static status_t parse_message(private_task_manager_t *this, message_t *msg)
 		enumerator = msg->create_payload_enumerator(msg);
 		while (enumerator->enumerate(enumerator, &payload))
 		{
-			unknown = (unknown_payload_t*)payload;
-			type = payload->get_type(payload);
-			if (!payload_is_known(type, msg->get_major_version(msg)) &&
-				unknown->is_critical(unknown))
+			if (payload->get_type(payload) == PL_UNKNOWN)
 			{
-				DBG1(DBG_ENC, "payload type %N is not supported, "
-					 "but its critical!", payload_type_names, type);
-				status = NOT_SUPPORTED;
-				break;
+				unknown = (unknown_payload_t*)payload;
+				if (unknown->is_critical(unknown))
+				{
+					type = unknown->get_type(unknown);
+					DBG1(DBG_ENC, "payload type %N is not supported, "
+						 "but its critical!", payload_type_names, type);
+					status = NOT_SUPPORTED;
+					break;
+				}
 			}
 		}
 		enumerator->destroy(enumerator);
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index 6d9132a..e0f930c 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -65,6 +65,11 @@ struct private_child_create_t {
 	chunk_t other_nonce;
 
 	/**
+	 * nonce generator
+	 */
+	nonce_gen_t *nonceg;
+
+	/**
 	 * config to create the CHILD_SA from
 	 */
 	child_cfg_t *config;
@@ -214,25 +219,21 @@ static status_t get_nonce(message_t *message, chunk_t *nonce)
 /**
  * generate a new nonce to include in a CREATE_CHILD_SA message
  */
-static status_t generate_nonce(private_child_create_t *this)
+static bool generate_nonce(private_child_create_t *this)
 {
-	nonce_gen_t *nonceg;
-
-	nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
-	if (!nonceg)
+	this->nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
+	if (!this->nonceg)
 	{
 		DBG1(DBG_IKE, "no nonce generator found to create nonce");
-		return FAILED;
+		return FALSE;
 	}
-	if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &this->my_nonce))
+	if (!this->nonceg->allocate_nonce(this->nonceg, NONCE_SIZE,
+									  &this->my_nonce))
 	{
 		DBG1(DBG_IKE, "nonce allocation failed");
-		nonceg->destroy(nonceg);
-		return FAILED;
+		return FALSE;
 	}
-	nonceg->destroy(nonceg);
-
-	return SUCCESS;
+	return TRUE;
 }
 
 /**
@@ -933,9 +934,10 @@ METHOD(task_t, build_i, status_t,
 		case IKE_SA_INIT:
 			return get_nonce(message, &this->my_nonce);
 		case CREATE_CHILD_SA:
-			if (generate_nonce(this) != SUCCESS)
+			if (!generate_nonce(this))
 			{
-				message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN, chunk_empty);
+				message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
+									chunk_empty);
 				return SUCCESS;
 			}
 			if (!this->retry)
@@ -1092,7 +1094,10 @@ METHOD(task_t, process_r, status_t,
 static void handle_child_sa_failure(private_child_create_t *this,
 									message_t *message)
 {
-	if (message->get_exchange_type(message) == IKE_AUTH &&
+	bool is_first;
+
+	is_first = message->get_exchange_type(message) == IKE_AUTH;
+	if (is_first &&
 		lib->settings->get_bool(lib->settings,
 								"%s.close_ike_on_child_failure", FALSE, lib->ns))
 	{
@@ -1106,7 +1111,8 @@ static void handle_child_sa_failure(private_child_create_t *this,
 	else
 	{
 		DBG1(DBG_IKE, "failed to establish CHILD_SA, keeping IKE_SA");
-		charon->bus->alert(charon->bus, ALERT_KEEP_ON_CHILD_SA_FAILURE);
+		charon->bus->alert(charon->bus, ALERT_KEEP_ON_CHILD_SA_FAILURE,
+						   is_first);
 	}
 }
 
@@ -1190,7 +1196,7 @@ METHOD(task_t, build_r, status_t,
 		case IKE_SA_INIT:
 			return get_nonce(message, &this->my_nonce);
 		case CREATE_CHILD_SA:
-			if (generate_nonce(this) != SUCCESS )
+			if (!generate_nonce(this))
 			{
 				message->add_notify(message, FALSE, NO_PROPOSAL_CHOSEN,
 									chunk_empty);
@@ -1575,6 +1581,7 @@ METHOD(task_t, migrate, void,
 	}
 	DESTROY_IF(this->child_sa);
 	DESTROY_IF(this->proposal);
+	DESTROY_IF(this->nonceg);
 	DESTROY_IF(this->dh);
 	this->dh_failed = FALSE;
 	if (this->proposals)
@@ -1627,6 +1634,7 @@ METHOD(task_t, destroy, void,
 	}
 
 	DESTROY_IF(this->config);
+	DESTROY_IF(this->nonceg);
 	free(this);
 }
 
@@ -1678,6 +1686,5 @@ child_create_t *child_create_create(ike_sa_t *ike_sa,
 		this->public.task.process = _process_r;
 		this->initiator = FALSE;
 	}
-
 	return &this->public;
 }
diff --git a/src/libcharon/sa/ikev2/tasks/ike_init.c b/src/libcharon/sa/ikev2/tasks/ike_init.c
index 0d5700e..1ff643d 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_init.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_init.c
@@ -90,6 +90,11 @@ struct private_ike_init_t {
 	chunk_t other_nonce;
 
 	/**
+	 * nonce generator
+	 */
+	nonce_gen_t *nonceg;
+
+	/**
 	 * Negotiated proposal used for IKE_SA
 	 */
 	proposal_t *proposal;
@@ -116,6 +121,25 @@ struct private_ike_init_t {
 };
 
 /**
+ * Allocate our own nonce value
+ */
+static bool generate_nonce(private_ike_init_t *this)
+{
+	if (!this->nonceg)
+	{
+		DBG1(DBG_IKE, "no nonce generator found to create nonce");
+		return FALSE;
+	}
+	if (!this->nonceg->allocate_nonce(this->nonceg, NONCE_SIZE,
+									  &this->my_nonce))
+	{
+		DBG1(DBG_IKE, "nonce allocation failed");
+		return FALSE;
+	}
+	return TRUE;
+}
+
+/**
  * Notify the peer about the hash algorithms we support or expect,
  * as per RFC 7427
  */
@@ -428,21 +452,10 @@ METHOD(task_t, build_i, status_t,
 	/* generate nonce only when we are trying the first time */
 	if (this->my_nonce.ptr == NULL)
 	{
-		nonce_gen_t *nonceg;
-
-		nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
-		if (!nonceg)
+		if (!generate_nonce(this))
 		{
-			DBG1(DBG_IKE, "no nonce generator found to create nonce");
 			return FAILED;
 		}
-		if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &this->my_nonce))
-		{
-			DBG1(DBG_IKE, "nonce allocation failed");
-			nonceg->destroy(nonceg);
-			return FAILED;
-		}
-		nonceg->destroy(nonceg);
 	}
 
 	if (this->cookie.ptr)
@@ -471,25 +484,14 @@ METHOD(task_t, build_i, status_t,
 METHOD(task_t, process_r,  status_t,
 	private_ike_init_t *this, message_t *message)
 {
-	nonce_gen_t *nonceg;
-
 	this->config = this->ike_sa->get_ike_cfg(this->ike_sa);
 	DBG0(DBG_IKE, "%H is initiating an IKE_SA", message->get_source(message));
 	this->ike_sa->set_state(this->ike_sa, IKE_CONNECTING);
 
-	nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
-	if (!nonceg)
+	if (!generate_nonce(this))
 	{
-		DBG1(DBG_IKE, "no nonce generator found to create nonce");
 		return FAILED;
 	}
-	if (!nonceg->allocate_nonce(nonceg, NONCE_SIZE, &this->my_nonce))
-	{
-		DBG1(DBG_IKE, "nonce allocation failed");
-		nonceg->destroy(nonceg);
-		return FAILED;
-	}
-	nonceg->destroy(nonceg);
 
 #ifdef ME
 	{
@@ -756,6 +758,7 @@ METHOD(task_t, destroy, void,
 {
 	DESTROY_IF(this->dh);
 	DESTROY_IF(this->proposal);
+	DESTROY_IF(this->nonceg);
 	chunk_free(&this->my_nonce);
 	chunk_free(&this->other_nonce);
 	chunk_free(&this->cookie);
@@ -800,6 +803,7 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
 		.signature_authentication = lib->settings->get_bool(lib->settings,
 								"%s.signature_authentication", TRUE, lib->ns),
 	);
+	this->nonceg = this->keymat->keymat.create_nonce_gen(&this->keymat->keymat);
 
 	if (initiator)
 	{
@@ -811,6 +815,5 @@ ike_init_t *ike_init_create(ike_sa_t *ike_sa, bool initiator, ike_sa_t *old_sa)
 		this->public.task.build = _build_r;
 		this->public.task.process = _process_r;
 	}
-
 	return &this->public;
 }
diff --git a/src/libcharon/sa/ikev2/tasks/ike_mobike.c b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
index 6295d79..11b0bb2 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_mobike.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_mobike.c
@@ -537,7 +537,7 @@ METHOD(task_t, process_i, status_t,
 			cookie2 = this->cookie2;
 			this->cookie2 = chunk_empty;
 			process_payloads(this, message);
-			if (!chunk_equals(cookie2, this->cookie2))
+			if (!chunk_equals_const(cookie2, this->cookie2))
 			{
 				chunk_free(&cookie2);
 				DBG1(DBG_IKE, "COOKIE2 mismatch, closing IKE_SA");
diff --git a/src/libcharon/sa/ikev2/tasks/ike_vendor.c b/src/libcharon/sa/ikev2/tasks/ike_vendor.c
index d536af2..cb3c270 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_vendor.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_vendor.c
@@ -76,6 +76,16 @@ static vid_data_t vids[] = {
 	  "CISCO(COPYRIGHT)&Copyright (c) 2009 Cisco Systems, Inc." },
 	{ "FRAGMENTATION", 0, 16,
 	  "\x40\x48\xb7\xd5\x6e\xbc\xe8\x85\x25\xe7\xde\x7f\x00\xd6\xc2\xd3"},
+	{ "MS NT5 ISAKMPOAKLEY v7", 0, 20,
+	  "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x07"},
+	{ "MS NT5 ISAKMPOAKLEY v8", 0, 20,
+	  "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x08"},
+	{ "MS NT5 ISAKMPOAKLEY v9", 0, 20,
+	  "\x1e\x2b\x51\x69\x05\x99\x1c\x7d\x7c\x96\xfc\xbf\xb5\x87\xe4\x61\x00\x00\x00\x09"},
+	{ "MS-Negotiation Discovery Capable", 0, 16,
+	  "\xfb\x1d\xe3\xcd\xf3\x41\xb7\xea\x16\xb7\xe5\xbe\x08\x55\xf1\x20"},
+	{ "Vid-Initial-Contact", 0, 16,
+	  "\x26\x24\x4d\x38\xed\xdb\x61\xb3\x17\x2a\x36\xe3\xd0\xcf\xb8\x19"},
 };
 
 METHOD(task_t, build, status_t,
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index 03e44e5..f22e07d 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -1822,7 +1822,7 @@ METHOD(kernel_ipsec_t, update_sa, status_t,
 	struct xfrm_replay_state *replay = NULL;
 	struct xfrm_replay_state_esn *replay_esn = NULL;
 	struct xfrm_lifetime_cur *lifetime = NULL;
-	u_int32_t replay_esn_len;
+	u_int32_t replay_esn_len = 0;
 	status_t status = FAILED;
 
 	/* if IPComp is used, we first update the IPComp SA */
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index a431e49..1515b01 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -1551,6 +1551,26 @@ static void rt_entry_destroy(rt_entry_t *this)
 }
 
 /**
+ * Check if the route received with RTM_NEWROUTE is usable based on its type.
+ */
+static bool route_usable(struct nlmsghdr *hdr)
+{
+	struct rtmsg *msg;
+
+	msg = NLMSG_DATA(hdr);
+	switch (msg->rtm_type)
+	{
+		case RTN_BLACKHOLE:
+		case RTN_UNREACHABLE:
+		case RTN_PROHIBIT:
+		case RTN_THROW:
+			return FALSE;
+		default:
+			return TRUE;
+	}
+}
+
+/**
  * Parse route received with RTM_NEWROUTE. The given rt_entry_t object will be
  * reused if not NULL.
  *
@@ -1700,6 +1720,10 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
 				rt_entry_t *other;
 				uintptr_t table;
 
+				if (!route_usable(current))
+				{
+					continue;
+				}
 				route = parse_route(current, route);
 
 				table = (uintptr_t)route->table;
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
index a9adfe0..b0e3103 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -83,6 +83,11 @@ struct private_netlink_socket_t {
 	u_int retries;
 
 	/**
+	 * Buffer size for received Netlink messages
+	 */
+	u_int buflen;
+
+	/**
 	 * Use parallel netlink queries
 	 */
 	bool parallel;
@@ -161,7 +166,7 @@ static bool write_msg(private_netlink_socket_t *this, struct nlmsghdr *msg)
  * Read a single Netlink message from socket, return 0 on error, -1 on timeout
  */
 static ssize_t read_msg(private_netlink_socket_t *this,
-						char buf[4096], size_t buflen, bool block)
+						char *buf, size_t buflen, bool block)
 {
 	ssize_t len;
 
@@ -236,20 +241,17 @@ static bool queue(private_netlink_socket_t *this, struct nlmsghdr *buf)
 static bool read_and_queue(private_netlink_socket_t *this, bool block)
 {
 	struct nlmsghdr *hdr;
-	union {
-		struct nlmsghdr hdr;
-		char bytes[4096];
-	} buf;
+	char buf[this->buflen];
 	ssize_t len;
 
-	len = read_msg(this, buf.bytes, sizeof(buf.bytes), block);
+	len = read_msg(this, buf, sizeof(buf), block);
 	if (len == -1)
 	{
 		return TRUE;
 	}
 	if (len)
 	{
-		hdr = &buf.hdr;
+		hdr = (struct nlmsghdr*)buf;
 		while (NLMSG_OK(hdr, len))
 		{
 			if (!queue(this, hdr))
@@ -568,6 +570,8 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names,
 		.entries = hashtable_create(hashtable_hash_ptr, hashtable_equals_ptr, 4),
 		.protocol = protocol,
 		.names = names,
+		.buflen = lib->settings->get_int(lib->settings,
+							"%s.plugins.kernel-netlink.buflen", 4096, lib->ns),
 		.timeout = lib->settings->get_int(lib->settings,
 							"%s.plugins.kernel-netlink.timeout", 0, lib->ns),
 		.retries = lib->settings->get_int(lib->settings,
diff --git a/src/libhydra/plugins/kernel_netlink/tests.c b/src/libhydra/plugins/kernel_netlink/tests.c
index 136b34d..52985b4 100644
--- a/src/libhydra/plugins/kernel_netlink/tests.c
+++ b/src/libhydra/plugins/kernel_netlink/tests.c
@@ -33,9 +33,7 @@ static bool test_runner_init(bool init)
 {
 	if (init)
 	{
-		dbg_default_set_level(0);
 		lib->processor->set_threads(lib->processor, 8);
-		dbg_default_set_level(1);
 	}
 	else
 	{
diff --git a/src/libimcv/ietf/ietf_attr_attr_request.c b/src/libimcv/ietf/ietf_attr_attr_request.c
index 3862a0a..08658e2 100644
--- a/src/libimcv/ietf/ietf_attr_attr_request.c
+++ b/src/libimcv/ietf/ietf_attr_attr_request.c
@@ -138,8 +138,21 @@ METHOD(pa_tnc_attr_t, build, void,
 METHOD(ietf_attr_attr_request_t, add, void,
 	private_ietf_attr_attr_request_t *this, pen_t vendor_id, u_int32_t type)
 {
+	enum_name_t *pa_attr_names;
 	pen_type_t *entry;
 
+	pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+														  vendor_id);
+	if (pa_attr_names)
+	{
+		DBG2(DBG_TNC, "  0x%06x/0x%08x '%N/%N'", vendor_id, type,
+						 pen_names, vendor_id, pa_attr_names, type);
+	}
+	else
+	{
+		DBG2(DBG_TNC, "  0x%06x/0x%08x '%N'", vendor_id, type,
+						 pen_names, vendor_id);
+	}
 	entry = malloc_thing(pen_type_t);
 	entry->vendor_id = vendor_id;
 	entry->type = type;
@@ -150,7 +163,6 @@ METHOD(pa_tnc_attr_t, process, status_t,
 	private_ietf_attr_attr_request_t *this, u_int32_t *offset)
 {
 	bio_reader_t *reader;
-	enum_name_t *pa_attr_names;
 	pen_t vendor_id;
 	u_int32_t type;
 	u_int8_t reserved;
@@ -176,19 +188,6 @@ METHOD(pa_tnc_attr_t, process, status_t,
 		reader->read_uint8 (reader, &reserved);
 		reader->read_uint24(reader, &vendor_id);
 		reader->read_uint32(reader, &type);
-
-		pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
-														  vendor_id);
-		if (pa_attr_names)
-		{
-			DBG2(DBG_TNC, "  0x%06x/0x%08x '%N/%N'", vendor_id, type,
-							 pen_names, vendor_id, pa_attr_names, type);
-		}
-		else
-		{
-			DBG2(DBG_TNC, "  0x%06x/0x%08x '%N'", vendor_id, type,
-							 pen_names, vendor_id);
-		}
 		add(this, vendor_id, type);
 	}
 	reader->destroy(reader);
diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.h b/src/libimcv/ietf/ietf_attr_fwd_enabled.h
index c4b6c15..3d55436 100644
--- a/src/libimcv/ietf/ietf_attr_fwd_enabled.h
+++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-14 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
diff --git a/src/libimcv/ietf/ietf_attr_numeric_version.h b/src/libimcv/ietf/ietf_attr_numeric_version.h
index 34393c6..8808d48 100644
--- a/src/libimcv/ietf/ietf_attr_numeric_version.h
+++ b/src/libimcv/ietf/ietf_attr_numeric_version.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-14 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
diff --git a/src/libimcv/ietf/ietf_attr_op_status.h b/src/libimcv/ietf/ietf_attr_op_status.h
index f19185f..ceb13fe 100644
--- a/src/libimcv/ietf/ietf_attr_op_status.h
+++ b/src/libimcv/ietf/ietf_attr_op_status.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-14 Andreas Steffen
+ * Copyright (C) 2012-2014 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
diff --git a/src/libimcv/imc/imc_os_info.c b/src/libimcv/imc/imc_os_info.c
index b01a14c..47697f1 100644
--- a/src/libimcv/imc/imc_os_info.c
+++ b/src/libimcv/imc/imc_os_info.c
@@ -586,9 +586,9 @@ imc_os_info_t *imc_os_info_create(void)
 
 	/* As an option OS name and OS version can be configured manually */
 	name.ptr = lib->settings->get_str(lib->settings,
-									  "%s.imcv.imc_os_info.name", NULL, lib->ns);
+									  "%s.imcv.os_info.name", NULL, lib->ns);
 	version.ptr = lib->settings->get_str(lib->settings,
-									  "%s.imcv.imc_os_info.version", NULL, lib->ns);
+									  "%s.imcv.os_info.version", NULL, lib->ns);
 	if (name.ptr && version.ptr)
 	{
 		name.len = strlen(name.ptr);
diff --git a/src/libimcv/imv/imv_policy_manager.c b/src/libimcv/imv/imv_policy_manager.c
index 9f7e4e8..b730f8c 100644
--- a/src/libimcv/imv/imv_policy_manager.c
+++ b/src/libimcv/imv/imv_policy_manager.c
@@ -255,7 +255,8 @@ static bool policy_stop(database_t *db, int session_id)
 	enumerator_t *e;
 	int rec, policy, final_rec, id_type;
 	chunk_t id_value;
-	char *result, *ip_address = NULL;
+	char *result, *format, *ip_address = NULL;
+	char command[512];
 	bool success = TRUE;
 
 	/* store all workitem results for this session in the results table */
@@ -334,6 +335,25 @@ static bool policy_stop(database_t *db, int session_id)
 	fprintf(stderr, "recommendation for access requestor %s is %N\n",
 			ip_address ? ip_address : "0.0.0.0",
 			TNC_IMV_Action_Recommendation_names, final_rec);
+
+	if (final_rec == TNC_IMV_ACTION_RECOMMENDATION_ALLOW)
+	{
+		format = lib->settings->get_str(lib->settings,
+						"imv_policy_manager.command_allow", NULL);
+	}
+	else
+	{
+		format = lib->settings->get_str(lib->settings,
+						"imv_policy_manager.command_block", NULL);
+	}
+	if (format && ip_address)
+	{
+		/* the IP address can occur at most twice in the command string */
+		snprintf(command, sizeof(command), format, ip_address, ip_address);
+		success = system(command) == 0;
+		fprintf(stderr, "%s system command: %s\n",
+			    success ? "successful" : "failed", command);
+	}
 	free(ip_address);
 
 	return success;
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c
index d9b4417..ea4dee9 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.c
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.c
@@ -226,7 +226,14 @@ METHOD(pa_tnc_msg_t, process, status_t,
 							reader, FALSE, &offset, this->encoding, &error);
 		if (!attr)
 		{
-			goto err;
+			if (error)
+			{
+				goto err;
+			}
+			else
+			{
+				continue;
+			}
 		}
 		attr_value = attr->get_value(attr);
 		attr_type  = attr->get_type(attr);
diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c
index 86d2e09..4fe8856 100644
--- a/src/libimcv/plugins/imc_os/imc_os.c
+++ b/src/libimcv/plugins/imc_os/imc_os.c
@@ -345,9 +345,13 @@ static void add_installed_packages(imc_state_t *state, imc_msg_t *msg)
 	enumerator_t *enumerator;
 	chunk_t name, version;
 
+	enumerator = os->create_package_enumerator(os);
+	if (!enumerator)
+	{
+		return;
+	}
 	attr = ietf_attr_installed_packages_create();
 
-	enumerator = os->create_package_enumerator(os);
 	while (enumerator->enumerate(enumerator, &name, &version))
 	{
 		DBG2(DBG_IMC, "package '%.*s' (%.*s)",
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_process.c b/src/libimcv/plugins/imv_attestation/imv_attestation_process.c
index fbeb661..c3e053d 100644
--- a/src/libimcv/plugins/imv_attestation/imv_attestation_process.c
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_process.c
@@ -181,7 +181,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 			DBG1(DBG_IMV, "verifying AIK with keyid %#B", &keyid);
 			keyid_hex = chunk_to_hex(keyid, NULL, FALSE);
 			if (session->get_device_id(session, &device_id) &&
-				chunk_equals(keyid_hex, device_id))
+				chunk_equals_const(keyid_hex, device_id))
 			{
 				trusted = session->get_device_trust(session);
 			}
@@ -290,7 +290,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 
 						/* check hashes from database against measurements */
 						e = pts_db->create_file_hash_enumerator(pts_db,
-											pts->get_platform_id(pts), 
+											pts->get_platform_id(pts),
 											algo, is_dir, arg_int);
 						if (!e)
 						{
@@ -446,7 +446,7 @@ bool imv_attestation_process(pa_tnc_attr_t *attr, imv_msg_t *out_msg,
 					return FALSE;
 				}
 
-				if (!chunk_equals(pcr_comp, pcr_composite))
+				if (!chunk_equals_const(pcr_comp, pcr_composite))
 				{
 					DBG1(DBG_IMV, "received PCR Composite does not match "
 								  "constructed one");
@@ -564,4 +564,3 @@ quote_error:
 	}
 	return TRUE;
 }
-
diff --git a/src/libimcv/pts/components/ita/ita_comp_ima.c b/src/libimcv/pts/components/ita/ita_comp_ima.c
index 3f92b04..448ca9f 100644
--- a/src/libimcv/pts/components/ita/ita_comp_ima.c
+++ b/src/libimcv/pts/components/ita/ita_comp_ima.c
@@ -307,7 +307,7 @@ static bool check_boot_aggregate(pts_pcr_t *pcrs, chunk_t measurement,
 	}
 	if (pcr_ok)
 	{
-		success = chunk_equals(boot_aggregate, measurement);
+		success = chunk_equals_const(boot_aggregate, measurement);
 		DBG1(DBG_PTS, "boot aggregate value is %scorrect",
 					   success ? "":"in");
 		return success;
@@ -693,7 +693,7 @@ METHOD(pts_component_t, verify, status_t,
 							status = FAILED;
 							break;
 						}
-						if (chunk_equals(measurement, hash))
+						if (chunk_equals_const(measurement, hash))
 						{
 							status = SUCCESS;
 							break;
@@ -748,7 +748,7 @@ METHOD(pts_component_t, verify, status_t,
 	has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
 	if (has_pcr_info)
 	{
-		if (!chunk_equals(pcr_before, pcrs->get(pcrs, pcr)))
+		if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, pcr)))
 		{
 			DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
 						   pcr);
@@ -876,7 +876,7 @@ METHOD(pts_component_t, destroy, void,
 		DESTROY_IF(this->bios_list);
 		DESTROY_IF(this->ima_list);
 		this->name->destroy(this->name);
-		
+
 		free(this);
 	}
 }
@@ -911,4 +911,3 @@ pts_component_t *pts_ita_comp_ima_create(uint32_t depth,
 
 	return &this->public;
 }
-
diff --git a/src/libimcv/pts/components/ita/ita_comp_tboot.c b/src/libimcv/pts/components/ita/ita_comp_tboot.c
index ce318ec..3d990f6 100644
--- a/src/libimcv/pts/components/ita/ita_comp_tboot.c
+++ b/src/libimcv/pts/components/ita/ita_comp_tboot.c
@@ -249,7 +249,7 @@ METHOD(pts_component_t, verify, status_t,
 	has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
 	if (has_pcr_info)
 	{
-		if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
+		if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, extended_pcr)))
 		{
 			DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to register value",
 						   extended_pcr);
@@ -354,4 +354,3 @@ pts_component_t *pts_ita_comp_tboot_create(u_int32_t depth,
 
 	return &this->public;
 }
-
diff --git a/src/libimcv/pts/components/ita/ita_comp_tgrub.c b/src/libimcv/pts/components/ita/ita_comp_tgrub.c
index 097e4c8..e955572 100644
--- a/src/libimcv/pts/components/ita/ita_comp_tgrub.c
+++ b/src/libimcv/pts/components/ita/ita_comp_tgrub.c
@@ -141,7 +141,7 @@ METHOD(pts_component_t, verify, status_t,
 	has_pcr_info = evidence->get_pcr_info(evidence, &pcr_before, &pcr_after);
 	if (has_pcr_info)
 	{
-		if (!chunk_equals(pcr_before, pcrs->get(pcrs, extended_pcr)))
+		if (!chunk_equals_const(pcr_before, pcrs->get(pcrs, extended_pcr)))
 		{
 			DBG1(DBG_PTS, "PCR %2u: pcr_before is not equal to pcr value");
 		}
diff --git a/src/libimcv/pts/pts_database.c b/src/libimcv/pts/pts_database.c
index d7b85c1..1a4c421 100644
--- a/src/libimcv/pts/pts_database.c
+++ b/src/libimcv/pts/pts_database.c
@@ -187,7 +187,7 @@ METHOD(pts_database_t, add_file_measurement, status_t,
 	}
 	if (e->enumerate(e, &hash_id, &hash_value))
 	{
-		if (!chunk_equals(measurement, hash_value))
+		if (!chunk_equals_const(measurement, hash_value))
 		{
 			/* update hash measurement value */
 			if (this->db->execute(this->db, &hash_id,
@@ -289,7 +289,7 @@ METHOD(pts_database_t, check_comp_measurement, status_t,
 
 	while (e->enumerate(e, &hash))
 	{
-		if (chunk_equals(hash, measurement))
+		if (chunk_equals_const(hash, measurement))
 		{
 			status = SUCCESS;
 			break;
diff --git a/src/libimcv/pts/pts_file_meas.c b/src/libimcv/pts/pts_file_meas.c
index 478892a..966d54b 100644
--- a/src/libimcv/pts/pts_file_meas.c
+++ b/src/libimcv/pts/pts_file_meas.c
@@ -133,7 +133,7 @@ METHOD(pts_file_meas_t, check, bool,
 		{
 			while (e->enumerate(e, &hash))
 			{
-				if (chunk_equals(entry->measurement, hash))
+				if (chunk_equals_const(entry->measurement, hash))
 				{
 					status = SUCCESS;
 					break;
@@ -223,7 +223,7 @@ METHOD(pts_file_meas_t, verify, bool,
 				}
 			}
 
-			/* no PTS measurement returned for this filename */ 
+			/* no PTS measurement returned for this filename */
 			if (!found)
 			{
 				success = FALSE;
@@ -234,7 +234,7 @@ METHOD(pts_file_meas_t, verify, bool,
 
 		if (found && !match)
 		{
-			if (chunk_equals(measurement, entry->measurement))
+			if (chunk_equals_const(measurement, entry->measurement))
 			{
 				match = TRUE;
 				DBG2(DBG_PTS, "  %#B for '%s' is ok",
@@ -252,7 +252,7 @@ METHOD(pts_file_meas_t, verify, bool,
 			 &entry->measurement, entry->filename);
 			enumerator->destroy(enumerator);
 	}
-	
+
 	return success;
 }
 
diff --git a/src/libipsec/esp_context.c b/src/libipsec/esp_context.c
index 5e58f66..a2307e0 100644
--- a/src/libipsec/esp_context.c
+++ b/src/libipsec/esp_context.c
@@ -244,6 +244,7 @@ static bool create_traditional(private_esp_context_t *this, int enc_alg,
 {
 	crypter_t *crypter = NULL;
 	signer_t *signer = NULL;
+	iv_gen_t *ivg;
 
 	crypter = lib->crypto->create_crypter(lib->crypto, enc_alg, enc_key.len);
 	if (!crypter)
@@ -272,7 +273,13 @@ static bool create_traditional(private_esp_context_t *this, int enc_alg,
 			 "failed");
 		goto failed;
 	}
-	this->aead = aead_create(crypter, signer);
+	ivg = iv_gen_create_for_alg(enc_alg);
+	if (!ivg)
+	{
+		DBG1(DBG_ESP, "failed to create ESP context: creating iv gen failed");
+		goto failed;
+	}
+	this->aead = aead_create(crypter, signer, ivg);
 	return TRUE;
 
 failed:
diff --git a/src/libipsec/ipsec_sa_mgr.c b/src/libipsec/ipsec_sa_mgr.c
index 07ffa9e..9d461f2 100644
--- a/src/libipsec/ipsec_sa_mgr.c
+++ b/src/libipsec/ipsec_sa_mgr.c
@@ -482,7 +482,7 @@ METHOD(ipsec_sa_mgr_t, add_sa, status_t,
 
 	entry = create_entry(sa_new);
 	schedule_expiration(this, entry);
-	this->sas->insert_last(this->sas, entry);
+	this->sas->insert_first(this->sas, entry);
 
 	this->mutex->unlock(this->mutex);
 	return SUCCESS;
diff --git a/src/libpttls/sasl/sasl_plain/sasl_plain.c b/src/libpttls/sasl/sasl_plain/sasl_plain.c
index 019c1b0..b2d30e6 100644
--- a/src/libpttls/sasl/sasl_plain/sasl_plain.c
+++ b/src/libpttls/sasl/sasl_plain/sasl_plain.c
@@ -86,7 +86,7 @@ METHOD(sasl_mechanism_t, process_server, status_t,
 		DBG1(DBG_CFG, "no shared secret found for '%Y'", this->client);
 		return FAILED;
 	}
-	if (!chunk_equals(shared->get_key(shared), password))
+	if (!chunk_equals_const(shared->get_key(shared), password))
 	{
 		DBG1(DBG_CFG, "shared secret for '%Y' does not match", this->client);
 		shared->destroy(shared);
diff --git a/src/libradius/radius_message.c b/src/libradius/radius_message.c
index 3905a06..e6abfe2 100644
--- a/src/libradius/radius_message.c
+++ b/src/libradius/radius_message.c
@@ -536,7 +536,7 @@ METHOD(radius_message_t, verify, bool,
 		/* verify Response-Authenticator */
 		if (!hasher->get_hash(hasher, msg, NULL) ||
 			!hasher->get_hash(hasher, secret, buf) ||
-			!memeq(buf, res_auth, HASH_SIZE_MD5))
+			!memeq_const(buf, res_auth, HASH_SIZE_MD5))
 		{
 			DBG1(DBG_CFG, "RADIUS Response-Authenticator verification failed");
 			return FALSE;
diff --git a/src/libradius/radius_socket.c b/src/libradius/radius_socket.c
index fe9cf3c..ad5daa5 100644
--- a/src/libradius/radius_socket.c
+++ b/src/libradius/radius_socket.c
@@ -125,9 +125,65 @@ static bool check_connection(private_radius_socket_t *this,
 	return TRUE;
 }
 
+/**
+ * Receive the response to the message with the given ID
+ */
+static status_t receive_response(int fd, int timeout, u_int8_t id,
+								 radius_message_t **response)
+{
+	radius_message_t *msg;
+	char buf[4096];
+	int res;
+	struct pollfd pfd = {
+		.fd = fd,
+		.events = POLLIN,
+	};
+
+	while (TRUE)
+	{
+		res = poll(&pfd, 1, timeout);
+		if (res < 0)
+		{
+			DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
+				 strerror(errno));
+			return FAILED;
+		}
+		if (res == 0)
+		{	/* timeout */
+			return OUT_OF_RES;
+		}
+		res = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
+		if (res <= 0)
+		{
+			DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
+				 strerror(errno));
+			return FAILED;
+		}
+		msg = radius_message_parse(chunk_create(buf, res));
+		if (!msg)
+		{
+			DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
+			return FAILED;
+		}
+		if (id != msg->get_identifier(msg))
+		{
+			/* we haven't received the response to our current request, but
+			 * perhaps one for an earlier request for which we didn't wait
+			 * long enough */
+			DBG1(DBG_CFG, "received RADIUS message with unexpected ID %d "
+				 "[%d expected], ignored", msg->get_identifier(msg), id);
+			msg->destroy(msg);
+			continue;
+		}
+		*response = msg;
+		return SUCCESS;
+	}
+}
+
 METHOD(radius_socket_t, request, radius_message_t*,
 	private_radius_socket_t *this, radius_message_t *request)
 {
+	radius_message_t *response;
 	chunk_t data;
 	int i, *fd, retransmit = 0;
 	u_int16_t port;
@@ -165,14 +221,6 @@ METHOD(radius_socket_t, request, radius_message_t*,
 	/* timeout after 2, 3, 4, 5 seconds */
 	for (i = 2; i <= 5; i++)
 	{
-		radius_message_t *response;
-		char buf[4096];
-		int res;
-		struct pollfd pfd = {
-			.fd = *fd,
-			.events = POLLIN,
-		};
-
 		if (retransmit)
 		{
 			DBG1(DBG_CFG, "retransmitting RADIUS %N (attempt %d)",
@@ -184,37 +232,23 @@ METHOD(radius_socket_t, request, radius_message_t*,
 			DBG1(DBG_CFG, "sending RADIUS message failed: %s", strerror(errno));
 			return NULL;
 		}
-		res = poll(&pfd, 1, i * 1000);
-		if (res < 0)
-		{
-			DBG1(DBG_CFG, "waiting for RADIUS message failed: %s",
-				 strerror(errno));
-			return NULL;
-		}
-		if (res == 0)
-		{	/* timeout */
-			retransmit++;
-			continue;
-		}
-		res = recv(*fd, buf, sizeof(buf), MSG_DONTWAIT);
-		if (res <= 0)
+		switch (receive_response(*fd, i*1000, request->get_identifier(request),
+								 &response))
 		{
-			DBG1(DBG_CFG, "receiving RADIUS message failed: %s",
-				 strerror(errno));
-			return NULL;
+			case SUCCESS:
+				break;
+			case OUT_OF_RES:
+				retransmit++;
+				continue;
+			default:
+				return NULL;
 		}
-		response = radius_message_parse(chunk_create(buf, res));
-		if (response)
+		if (response->verify(response, request->get_authenticator(request),
+							 this->secret, this->hasher, this->signer))
 		{
-			if (response->verify(response,
-						request->get_authenticator(request), this->secret,
-						this->hasher, this->signer))
-			{
-				return response;
-			}
-			response->destroy(response);
+			return response;
 		}
-		DBG1(DBG_CFG, "received invalid RADIUS message, ignored");
+		response->destroy(response);
 		return NULL;
 	}
 	DBG1(DBG_CFG, "RADIUS %N timed out after %d retransmits",
diff --git a/src/libsimaka/Makefile.am b/src/libsimaka/Makefile.am
index 6878133..9997ece 100644
--- a/src/libsimaka/Makefile.am
+++ b/src/libsimaka/Makefile.am
@@ -11,6 +11,10 @@ ipseclib_LTLIBRARIES = libsimaka.la
 libsimaka_la_LIBADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la
 
+if USE_WINDOWS
+  libsimaka_la_LIBADD += -lws2_32
+endif
+
 libsimaka_la_SOURCES = simaka_message.h simaka_message.c \
   simaka_crypto.h simaka_crypto.c simaka_manager.h simaka_manager.c \
   simaka_card.h simaka_provider.h simaka_hooks.h
diff --git a/src/libsimaka/Makefile.in b/src/libsimaka/Makefile.in
index 79962d3..637137c 100644
--- a/src/libsimaka/Makefile.in
+++ b/src/libsimaka/Makefile.in
@@ -78,6 +78,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
+ at USE_WINDOWS_TRUE@am__append_1 = -lws2_32
 subdir = src/libsimaka
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
@@ -127,8 +128,10 @@ am__uninstall_files_from_dir = { \
   }
 am__installdirs = "$(DESTDIR)$(ipseclibdir)"
 LTLIBRARIES = $(ipseclib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
 libsimaka_la_DEPENDENCIES =  \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(am__DEPENDENCIES_1)
 am_libsimaka_la_OBJECTS = simaka_message.lo simaka_crypto.lo \
 	simaka_manager.lo
 libsimaka_la_OBJECTS = $(am_libsimaka_la_OBJECTS)
@@ -431,9 +434,9 @@ AM_LDFLAGS = \
 	-no-undefined
 
 ipseclib_LTLIBRARIES = libsimaka.la
-libsimaka_la_LIBADD = \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
-
+libsimaka_la_LIBADD =  \
+	$(top_builddir)/src/libstrongswan/libstrongswan.la \
+	$(am__append_1)
 libsimaka_la_SOURCES = simaka_message.h simaka_message.c \
   simaka_crypto.h simaka_crypto.c simaka_manager.h simaka_manager.c \
   simaka_card.h simaka_provider.h simaka_hooks.h
diff --git a/src/libstrongswan/Android.mk b/src/libstrongswan/Android.mk
index 2a8894b..d019d96 100644
--- a/src/libstrongswan/Android.mk
+++ b/src/libstrongswan/Android.mk
@@ -14,7 +14,7 @@ crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
 crypto/rngs/rng.c crypto/prf_plus.c crypto/signers/signer.c \
 crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
 crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
-crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
+crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
 crypto/mgf1/mgf1.c crypto/mgf1/mgf1_bitspender.c \
 credentials/credential_factory.c credentials/builder.c \
 credentials/cred_encoding.c credentials/keys/private_key.c \
@@ -36,10 +36,13 @@ pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c
 processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
 processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \
 selectors/traffic_selector.c settings/settings.c settings/settings_types.c \
-settings/settings_parser.c settings/settings_lexer.c \
+settings/settings_parser.c settings/settings_lexer.c utils/cpu_feature.c \
 utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
 utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
-utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c
+utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c \
+utils/utils/atomics.c utils/utils/string.c utils/utils/memory.c \
+utils/utils/tty.c utils/utils/path.c utils/utils/status.c utils/utils/time.c \
+utils/utils/align.c
 
 libstrongswan_la_SOURCES += \
     threading/thread.c \
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index fbc7526..b3636cf 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -12,7 +12,7 @@ crypto/prfs/prf.c crypto/prfs/mac_prf.c crypto/pkcs5.c \
 crypto/rngs/rng.c crypto/prf_plus.c crypto/signers/signer.c \
 crypto/signers/mac_signer.c crypto/crypto_factory.c crypto/crypto_tester.c \
 crypto/diffie_hellman.c crypto/aead.c crypto/transform.c \
-crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
+crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c crypto/iv/iv_gen_seq.c \
 crypto/mgf1/mgf1.c crypto/mgf1/mgf1_bitspender.c \
 credentials/credential_factory.c credentials/builder.c \
 credentials/cred_encoding.c credentials/keys/private_key.c \
@@ -34,10 +34,13 @@ pen/pen.c plugins/plugin_loader.c plugins/plugin_feature.c processing/jobs/job.c
 processing/jobs/callback_job.c processing/processor.c processing/scheduler.c \
 processing/watcher.c resolver/resolver_manager.c resolver/rr_set.c \
 selectors/traffic_selector.c settings/settings.c settings/settings_types.c \
-settings/settings_parser.y settings/settings_lexer.l \
+settings/settings_parser.y settings/settings_lexer.l utils/cpu_feature.c \
 utils/utils.c utils/chunk.c utils/debug.c utils/enum.c utils/identification.c \
 utils/lexparser.c utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
-utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c
+utils/parser_helper.c utils/test.c utils/process.c utils/utils/strerror.c \
+utils/utils/atomics.c utils/utils/string.c utils/utils/memory.c \
+utils/utils/tty.c utils/utils/path.c utils/utils/status.c utils/utils/time.c \
+utils/utils/align.c
 
 if !USE_WINDOWS
   libstrongswan_la_SOURCES += \
@@ -103,10 +106,13 @@ threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h
 threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \
 utils/utils.h utils/chunk.h utils/debug.h utils/enum.h utils/identification.h \
 utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
-utils/leak_detective.h utils/printf_hook/printf_hook.h \
+utils/cpu_feature.h utils/leak_detective.h utils/printf_hook/printf_hook.h \
 utils/printf_hook/printf_hook_vstr.h utils/printf_hook/printf_hook_builtin.h \
 utils/parser_helper.h utils/test.h utils/integrity_checker.h utils/process.h \
-utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h
+utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h \
+utils/utils/atomics.h utils/utils/types.h utils/utils/byteorder.h \
+utils/utils/string.h utils/utils/memory.h utils/utils/tty.h utils/utils/path.h \
+utils/utils/status.h utils/utils/object.h utils/utils/time.h utils/utils/align.h
 endif
 
 library.lo :	$(top_builddir)/config.status
@@ -296,6 +302,13 @@ if MONOLITHIC
 endif
 endif
 
+if USE_AESNI
+  SUBDIRS += plugins/aesni
+if MONOLITHIC
+  libstrongswan_la_LIBADD += plugins/aesni/libstrongswan-aesni.la
+endif
+endif
+
 if USE_RANDOM
   SUBDIRS += plugins/random
 if MONOLITHIC
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index 99b18a7..5b20f6e 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -135,85 +135,87 @@ host_triplet = @host@
 @MONOLITHIC_TRUE@@USE_GMP_TRUE at am__append_37 = plugins/gmp/libstrongswan-gmp.la
 @USE_RDRAND_TRUE at am__append_38 = plugins/rdrand
 @MONOLITHIC_TRUE@@USE_RDRAND_TRUE at am__append_39 = plugins/rdrand/libstrongswan-rdrand.la
- at USE_RANDOM_TRUE@am__append_40 = plugins/random
- at MONOLITHIC_TRUE@@USE_RANDOM_TRUE at am__append_41 = plugins/random/libstrongswan-random.la
- at USE_NONCE_TRUE@am__append_42 = plugins/nonce
- at MONOLITHIC_TRUE@@USE_NONCE_TRUE at am__append_43 = plugins/nonce/libstrongswan-nonce.la
- at USE_HMAC_TRUE@am__append_44 = plugins/hmac
- at MONOLITHIC_TRUE@@USE_HMAC_TRUE at am__append_45 = plugins/hmac/libstrongswan-hmac.la
- at USE_CMAC_TRUE@am__append_46 = plugins/cmac
- at MONOLITHIC_TRUE@@USE_CMAC_TRUE at am__append_47 = plugins/cmac/libstrongswan-cmac.la
- at USE_XCBC_TRUE@am__append_48 = plugins/xcbc
- at MONOLITHIC_TRUE@@USE_XCBC_TRUE at am__append_49 = plugins/xcbc/libstrongswan-xcbc.la
- at USE_X509_TRUE@am__append_50 = plugins/x509
- at MONOLITHIC_TRUE@@USE_X509_TRUE at am__append_51 = plugins/x509/libstrongswan-x509.la
- at USE_REVOCATION_TRUE@am__append_52 = plugins/revocation
- at MONOLITHIC_TRUE@@USE_REVOCATION_TRUE at am__append_53 = plugins/revocation/libstrongswan-revocation.la
- at USE_CONSTRAINTS_TRUE@am__append_54 = plugins/constraints
- at MONOLITHIC_TRUE@@USE_CONSTRAINTS_TRUE at am__append_55 = plugins/constraints/libstrongswan-constraints.la
- at USE_ACERT_TRUE@am__append_56 = plugins/acert
- at MONOLITHIC_TRUE@@USE_ACERT_TRUE at am__append_57 = plugins/acert/libstrongswan-acert.la
- at USE_PUBKEY_TRUE@am__append_58 = plugins/pubkey
- at MONOLITHIC_TRUE@@USE_PUBKEY_TRUE at am__append_59 = plugins/pubkey/libstrongswan-pubkey.la
- at USE_PKCS1_TRUE@am__append_60 = plugins/pkcs1
- at MONOLITHIC_TRUE@@USE_PKCS1_TRUE at am__append_61 = plugins/pkcs1/libstrongswan-pkcs1.la
- at USE_PKCS7_TRUE@am__append_62 = plugins/pkcs7
- at MONOLITHIC_TRUE@@USE_PKCS7_TRUE at am__append_63 = plugins/pkcs7/libstrongswan-pkcs7.la
- at USE_PKCS8_TRUE@am__append_64 = plugins/pkcs8
- at MONOLITHIC_TRUE@@USE_PKCS8_TRUE at am__append_65 = plugins/pkcs8/libstrongswan-pkcs8.la
- at USE_PKCS12_TRUE@am__append_66 = plugins/pkcs12
- at MONOLITHIC_TRUE@@USE_PKCS12_TRUE at am__append_67 = plugins/pkcs12/libstrongswan-pkcs12.la
- at USE_PGP_TRUE@am__append_68 = plugins/pgp
- at MONOLITHIC_TRUE@@USE_PGP_TRUE at am__append_69 = plugins/pgp/libstrongswan-pgp.la
- at USE_DNSKEY_TRUE@am__append_70 = plugins/dnskey
- at MONOLITHIC_TRUE@@USE_DNSKEY_TRUE at am__append_71 = plugins/dnskey/libstrongswan-dnskey.la
- at USE_SSHKEY_TRUE@am__append_72 = plugins/sshkey
- at MONOLITHIC_TRUE@@USE_SSHKEY_TRUE at am__append_73 = plugins/sshkey/libstrongswan-sshkey.la
- at USE_PEM_TRUE@am__append_74 = plugins/pem
- at MONOLITHIC_TRUE@@USE_PEM_TRUE at am__append_75 = plugins/pem/libstrongswan-pem.la
- at USE_CURL_TRUE@am__append_76 = plugins/curl
- at MONOLITHIC_TRUE@@USE_CURL_TRUE at am__append_77 = plugins/curl/libstrongswan-curl.la
- at USE_FILES_TRUE@am__append_78 = plugins/files
- at MONOLITHIC_TRUE@@USE_FILES_TRUE at am__append_79 = plugins/files/libstrongswan-files.la
- at USE_WINHTTP_TRUE@am__append_80 = plugins/winhttp
- at MONOLITHIC_TRUE@@USE_WINHTTP_TRUE at am__append_81 = plugins/winhttp/libstrongswan-winhttp.la
- at USE_UNBOUND_TRUE@am__append_82 = plugins/unbound
- at MONOLITHIC_TRUE@@USE_UNBOUND_TRUE at am__append_83 = plugins/unbound/libstrongswan-unbound.la
- at USE_SOUP_TRUE@am__append_84 = plugins/soup
- at MONOLITHIC_TRUE@@USE_SOUP_TRUE at am__append_85 = plugins/soup/libstrongswan-soup.la
- at USE_LDAP_TRUE@am__append_86 = plugins/ldap
- at MONOLITHIC_TRUE@@USE_LDAP_TRUE at am__append_87 = plugins/ldap/libstrongswan-ldap.la
- at USE_MYSQL_TRUE@am__append_88 = plugins/mysql
- at MONOLITHIC_TRUE@@USE_MYSQL_TRUE at am__append_89 = plugins/mysql/libstrongswan-mysql.la
- at USE_SQLITE_TRUE@am__append_90 = plugins/sqlite
- at MONOLITHIC_TRUE@@USE_SQLITE_TRUE at am__append_91 = plugins/sqlite/libstrongswan-sqlite.la
- at USE_PADLOCK_TRUE@am__append_92 = plugins/padlock
- at MONOLITHIC_TRUE@@USE_PADLOCK_TRUE at am__append_93 = plugins/padlock/libstrongswan-padlock.la
- at USE_OPENSSL_TRUE@am__append_94 = plugins/openssl
- at MONOLITHIC_TRUE@@USE_OPENSSL_TRUE at am__append_95 = plugins/openssl/libstrongswan-openssl.la
- at USE_GCRYPT_TRUE@am__append_96 = plugins/gcrypt
- at MONOLITHIC_TRUE@@USE_GCRYPT_TRUE at am__append_97 = plugins/gcrypt/libstrongswan-gcrypt.la
- at USE_FIPS_PRF_TRUE@am__append_98 = plugins/fips_prf
- at MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE at am__append_99 = plugins/fips_prf/libstrongswan-fips-prf.la
- at USE_AGENT_TRUE@am__append_100 = plugins/agent
- at MONOLITHIC_TRUE@@USE_AGENT_TRUE at am__append_101 = plugins/agent/libstrongswan-agent.la
- at USE_KEYCHAIN_TRUE@am__append_102 = plugins/keychain
- at MONOLITHIC_TRUE@@USE_KEYCHAIN_TRUE at am__append_103 = plugins/keychain/libstrongswan-keychain.la
- at USE_PKCS11_TRUE@am__append_104 = plugins/pkcs11
- at MONOLITHIC_TRUE@@USE_PKCS11_TRUE at am__append_105 = plugins/pkcs11/libstrongswan-pkcs11.la
- at USE_CTR_TRUE@am__append_106 = plugins/ctr
- at MONOLITHIC_TRUE@@USE_CTR_TRUE at am__append_107 = plugins/ctr/libstrongswan-ctr.la
- at USE_CCM_TRUE@am__append_108 = plugins/ccm
- at MONOLITHIC_TRUE@@USE_CCM_TRUE at am__append_109 = plugins/ccm/libstrongswan-ccm.la
- at USE_GCM_TRUE@am__append_110 = plugins/gcm
- at MONOLITHIC_TRUE@@USE_GCM_TRUE at am__append_111 = plugins/gcm/libstrongswan-gcm.la
- at USE_NTRU_TRUE@am__append_112 = plugins/ntru
- at MONOLITHIC_TRUE@@USE_NTRU_TRUE at am__append_113 = plugins/ntru/libstrongswan-ntru.la
- at USE_BLISS_TRUE@am__append_114 = plugins/bliss
- at MONOLITHIC_TRUE@@USE_BLISS_TRUE at am__append_115 = plugins/bliss/libstrongswan-bliss.la
- at USE_TEST_VECTORS_TRUE@am__append_116 = plugins/test_vectors
- at MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE at am__append_117 = plugins/test_vectors/libstrongswan-test-vectors.la
- at USE_BLISS_TRUE@am__append_118 = plugins/bliss/tests
+ at USE_AESNI_TRUE@am__append_40 = plugins/aesni
+ at MONOLITHIC_TRUE@@USE_AESNI_TRUE at am__append_41 = plugins/aesni/libstrongswan-aesni.la
+ at USE_RANDOM_TRUE@am__append_42 = plugins/random
+ at MONOLITHIC_TRUE@@USE_RANDOM_TRUE at am__append_43 = plugins/random/libstrongswan-random.la
+ at USE_NONCE_TRUE@am__append_44 = plugins/nonce
+ at MONOLITHIC_TRUE@@USE_NONCE_TRUE at am__append_45 = plugins/nonce/libstrongswan-nonce.la
+ at USE_HMAC_TRUE@am__append_46 = plugins/hmac
+ at MONOLITHIC_TRUE@@USE_HMAC_TRUE at am__append_47 = plugins/hmac/libstrongswan-hmac.la
+ at USE_CMAC_TRUE@am__append_48 = plugins/cmac
+ at MONOLITHIC_TRUE@@USE_CMAC_TRUE at am__append_49 = plugins/cmac/libstrongswan-cmac.la
+ at USE_XCBC_TRUE@am__append_50 = plugins/xcbc
+ at MONOLITHIC_TRUE@@USE_XCBC_TRUE at am__append_51 = plugins/xcbc/libstrongswan-xcbc.la
+ at USE_X509_TRUE@am__append_52 = plugins/x509
+ at MONOLITHIC_TRUE@@USE_X509_TRUE at am__append_53 = plugins/x509/libstrongswan-x509.la
+ at USE_REVOCATION_TRUE@am__append_54 = plugins/revocation
+ at MONOLITHIC_TRUE@@USE_REVOCATION_TRUE at am__append_55 = plugins/revocation/libstrongswan-revocation.la
+ at USE_CONSTRAINTS_TRUE@am__append_56 = plugins/constraints
+ at MONOLITHIC_TRUE@@USE_CONSTRAINTS_TRUE at am__append_57 = plugins/constraints/libstrongswan-constraints.la
+ at USE_ACERT_TRUE@am__append_58 = plugins/acert
+ at MONOLITHIC_TRUE@@USE_ACERT_TRUE at am__append_59 = plugins/acert/libstrongswan-acert.la
+ at USE_PUBKEY_TRUE@am__append_60 = plugins/pubkey
+ at MONOLITHIC_TRUE@@USE_PUBKEY_TRUE at am__append_61 = plugins/pubkey/libstrongswan-pubkey.la
+ at USE_PKCS1_TRUE@am__append_62 = plugins/pkcs1
+ at MONOLITHIC_TRUE@@USE_PKCS1_TRUE at am__append_63 = plugins/pkcs1/libstrongswan-pkcs1.la
+ at USE_PKCS7_TRUE@am__append_64 = plugins/pkcs7
+ at MONOLITHIC_TRUE@@USE_PKCS7_TRUE at am__append_65 = plugins/pkcs7/libstrongswan-pkcs7.la
+ at USE_PKCS8_TRUE@am__append_66 = plugins/pkcs8
+ at MONOLITHIC_TRUE@@USE_PKCS8_TRUE at am__append_67 = plugins/pkcs8/libstrongswan-pkcs8.la
+ at USE_PKCS12_TRUE@am__append_68 = plugins/pkcs12
+ at MONOLITHIC_TRUE@@USE_PKCS12_TRUE at am__append_69 = plugins/pkcs12/libstrongswan-pkcs12.la
+ at USE_PGP_TRUE@am__append_70 = plugins/pgp
+ at MONOLITHIC_TRUE@@USE_PGP_TRUE at am__append_71 = plugins/pgp/libstrongswan-pgp.la
+ at USE_DNSKEY_TRUE@am__append_72 = plugins/dnskey
+ at MONOLITHIC_TRUE@@USE_DNSKEY_TRUE at am__append_73 = plugins/dnskey/libstrongswan-dnskey.la
+ at USE_SSHKEY_TRUE@am__append_74 = plugins/sshkey
+ at MONOLITHIC_TRUE@@USE_SSHKEY_TRUE at am__append_75 = plugins/sshkey/libstrongswan-sshkey.la
+ at USE_PEM_TRUE@am__append_76 = plugins/pem
+ at MONOLITHIC_TRUE@@USE_PEM_TRUE at am__append_77 = plugins/pem/libstrongswan-pem.la
+ at USE_CURL_TRUE@am__append_78 = plugins/curl
+ at MONOLITHIC_TRUE@@USE_CURL_TRUE at am__append_79 = plugins/curl/libstrongswan-curl.la
+ at USE_FILES_TRUE@am__append_80 = plugins/files
+ at MONOLITHIC_TRUE@@USE_FILES_TRUE at am__append_81 = plugins/files/libstrongswan-files.la
+ at USE_WINHTTP_TRUE@am__append_82 = plugins/winhttp
+ at MONOLITHIC_TRUE@@USE_WINHTTP_TRUE at am__append_83 = plugins/winhttp/libstrongswan-winhttp.la
+ at USE_UNBOUND_TRUE@am__append_84 = plugins/unbound
+ at MONOLITHIC_TRUE@@USE_UNBOUND_TRUE at am__append_85 = plugins/unbound/libstrongswan-unbound.la
+ at USE_SOUP_TRUE@am__append_86 = plugins/soup
+ at MONOLITHIC_TRUE@@USE_SOUP_TRUE at am__append_87 = plugins/soup/libstrongswan-soup.la
+ at USE_LDAP_TRUE@am__append_88 = plugins/ldap
+ at MONOLITHIC_TRUE@@USE_LDAP_TRUE at am__append_89 = plugins/ldap/libstrongswan-ldap.la
+ at USE_MYSQL_TRUE@am__append_90 = plugins/mysql
+ at MONOLITHIC_TRUE@@USE_MYSQL_TRUE at am__append_91 = plugins/mysql/libstrongswan-mysql.la
+ at USE_SQLITE_TRUE@am__append_92 = plugins/sqlite
+ at MONOLITHIC_TRUE@@USE_SQLITE_TRUE at am__append_93 = plugins/sqlite/libstrongswan-sqlite.la
+ at USE_PADLOCK_TRUE@am__append_94 = plugins/padlock
+ at MONOLITHIC_TRUE@@USE_PADLOCK_TRUE at am__append_95 = plugins/padlock/libstrongswan-padlock.la
+ at USE_OPENSSL_TRUE@am__append_96 = plugins/openssl
+ at MONOLITHIC_TRUE@@USE_OPENSSL_TRUE at am__append_97 = plugins/openssl/libstrongswan-openssl.la
+ at USE_GCRYPT_TRUE@am__append_98 = plugins/gcrypt
+ at MONOLITHIC_TRUE@@USE_GCRYPT_TRUE at am__append_99 = plugins/gcrypt/libstrongswan-gcrypt.la
+ at USE_FIPS_PRF_TRUE@am__append_100 = plugins/fips_prf
+ at MONOLITHIC_TRUE@@USE_FIPS_PRF_TRUE at am__append_101 = plugins/fips_prf/libstrongswan-fips-prf.la
+ at USE_AGENT_TRUE@am__append_102 = plugins/agent
+ at MONOLITHIC_TRUE@@USE_AGENT_TRUE at am__append_103 = plugins/agent/libstrongswan-agent.la
+ at USE_KEYCHAIN_TRUE@am__append_104 = plugins/keychain
+ at MONOLITHIC_TRUE@@USE_KEYCHAIN_TRUE at am__append_105 = plugins/keychain/libstrongswan-keychain.la
+ at USE_PKCS11_TRUE@am__append_106 = plugins/pkcs11
+ at MONOLITHIC_TRUE@@USE_PKCS11_TRUE at am__append_107 = plugins/pkcs11/libstrongswan-pkcs11.la
+ at USE_CTR_TRUE@am__append_108 = plugins/ctr
+ at MONOLITHIC_TRUE@@USE_CTR_TRUE at am__append_109 = plugins/ctr/libstrongswan-ctr.la
+ at USE_CCM_TRUE@am__append_110 = plugins/ccm
+ at MONOLITHIC_TRUE@@USE_CCM_TRUE at am__append_111 = plugins/ccm/libstrongswan-ccm.la
+ at USE_GCM_TRUE@am__append_112 = plugins/gcm
+ at MONOLITHIC_TRUE@@USE_GCM_TRUE at am__append_113 = plugins/gcm/libstrongswan-gcm.la
+ at USE_NTRU_TRUE@am__append_114 = plugins/ntru
+ at MONOLITHIC_TRUE@@USE_NTRU_TRUE at am__append_115 = plugins/ntru/libstrongswan-ntru.la
+ at USE_BLISS_TRUE@am__append_116 = plugins/bliss
+ at MONOLITHIC_TRUE@@USE_BLISS_TRUE at am__append_117 = plugins/bliss/libstrongswan-bliss.la
+ at USE_TEST_VECTORS_TRUE@am__append_118 = plugins/test_vectors
+ at MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE at am__append_119 = plugins/test_vectors/libstrongswan-test-vectors.la
+ at USE_BLISS_TRUE@am__append_120 = plugins/bliss/tests
 subdir = src/libstrongswan
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	settings/settings_parser.h settings/settings_parser.c \
@@ -292,7 +294,8 @@ libstrongswan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
 	$(am__append_95) $(am__append_97) $(am__append_99) \
 	$(am__append_101) $(am__append_103) $(am__append_105) \
 	$(am__append_107) $(am__append_109) $(am__append_111) \
-	$(am__append_113) $(am__append_115) $(am__append_117)
+	$(am__append_113) $(am__append_115) $(am__append_117) \
+	$(am__append_119)
 am__libstrongswan_la_SOURCES_DIST = library.c asn1/asn1.c \
 	asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c \
 	bio/bio_writer.c collections/blocking_queue.c \
@@ -306,7 +309,7 @@ am__libstrongswan_la_SOURCES_DIST = library.c asn1/asn1.c \
 	crypto/prf_plus.c crypto/signers/signer.c \
 	crypto/signers/mac_signer.c crypto/crypto_factory.c \
 	crypto/crypto_tester.c crypto/diffie_hellman.c crypto/aead.c \
-	crypto/transform.c crypto/iv/iv_gen_rand.c \
+	crypto/transform.c crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c \
 	crypto/iv/iv_gen_seq.c crypto/mgf1/mgf1.c \
 	crypto/mgf1/mgf1_bitspender.c credentials/credential_factory.c \
 	credentials/builder.c credentials/cred_encoding.c \
@@ -338,12 +341,16 @@ am__libstrongswan_la_SOURCES_DIST = library.c asn1/asn1.c \
 	resolver/rr_set.c selectors/traffic_selector.c \
 	settings/settings.c settings/settings_types.c \
 	settings/settings_parser.y settings/settings_lexer.l \
-	utils/utils.c utils/chunk.c utils/debug.c utils/enum.c \
-	utils/identification.c utils/lexparser.c utils/optionsfrom.c \
-	utils/capabilities.c utils/backtrace.c utils/parser_helper.c \
-	utils/test.c utils/process.c utils/utils/strerror.c \
-	threading/thread.c threading/thread_value.c threading/mutex.c \
-	threading/rwlock.c threading/spinlock.c threading/semaphore.c \
+	utils/cpu_feature.c utils/utils.c utils/chunk.c utils/debug.c \
+	utils/enum.c utils/identification.c utils/lexparser.c \
+	utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
+	utils/parser_helper.c utils/test.c utils/process.c \
+	utils/utils/strerror.c utils/utils/atomics.c \
+	utils/utils/string.c utils/utils/memory.c utils/utils/tty.c \
+	utils/utils/path.c utils/utils/status.c utils/utils/time.c \
+	utils/utils/align.c threading/thread.c \
+	threading/thread_value.c threading/mutex.c threading/rwlock.c \
+	threading/spinlock.c threading/semaphore.c \
 	networking/streams/stream_unix.c \
 	networking/streams/stream_service_unix.c \
 	threading/windows/thread.c threading/windows/thread_value.c \
@@ -386,9 +393,9 @@ am_libstrongswan_la_OBJECTS = library.lo asn1/asn1.lo \
 	crypto/prf_plus.lo crypto/signers/signer.lo \
 	crypto/signers/mac_signer.lo crypto/crypto_factory.lo \
 	crypto/crypto_tester.lo crypto/diffie_hellman.lo \
-	crypto/aead.lo crypto/transform.lo crypto/iv/iv_gen_rand.lo \
-	crypto/iv/iv_gen_seq.lo crypto/mgf1/mgf1.lo \
-	crypto/mgf1/mgf1_bitspender.lo \
+	crypto/aead.lo crypto/transform.lo crypto/iv/iv_gen.lo \
+	crypto/iv/iv_gen_rand.lo crypto/iv/iv_gen_seq.lo \
+	crypto/mgf1/mgf1.lo crypto/mgf1/mgf1_bitspender.lo \
 	credentials/credential_factory.lo credentials/builder.lo \
 	credentials/cred_encoding.lo credentials/keys/private_key.lo \
 	credentials/keys/public_key.lo credentials/keys/shared_key.lo \
@@ -418,13 +425,17 @@ am_libstrongswan_la_OBJECTS = library.lo asn1/asn1.lo \
 	resolver/rr_set.lo selectors/traffic_selector.lo \
 	settings/settings.lo settings/settings_types.lo \
 	settings/settings_parser.lo settings/settings_lexer.lo \
-	utils/utils.lo utils/chunk.lo utils/debug.lo utils/enum.lo \
-	utils/identification.lo utils/lexparser.lo \
-	utils/optionsfrom.lo utils/capabilities.lo utils/backtrace.lo \
-	utils/parser_helper.lo utils/test.lo utils/process.lo \
-	utils/utils/strerror.lo $(am__objects_1) $(am__objects_2) \
-	$(am__objects_3) $(am__objects_4) $(am__objects_5) \
-	$(am__objects_6) $(am__objects_7)
+	utils/cpu_feature.lo utils/utils.lo utils/chunk.lo \
+	utils/debug.lo utils/enum.lo utils/identification.lo \
+	utils/lexparser.lo utils/optionsfrom.lo utils/capabilities.lo \
+	utils/backtrace.lo utils/parser_helper.lo utils/test.lo \
+	utils/process.lo utils/utils/strerror.lo \
+	utils/utils/atomics.lo utils/utils/string.lo \
+	utils/utils/memory.lo utils/utils/tty.lo utils/utils/path.lo \
+	utils/utils/status.lo utils/utils/time.lo utils/utils/align.lo \
+	$(am__objects_1) $(am__objects_2) $(am__objects_3) \
+	$(am__objects_4) $(am__objects_5) $(am__objects_6) \
+	$(am__objects_7)
 libstrongswan_la_OBJECTS = $(am_libstrongswan_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
@@ -554,13 +565,17 @@ am__nobase_strongswan_include_HEADERS_DIST = library.h asn1/asn1.h \
 	threading/rwlock_condvar.h threading/lock_profiler.h \
 	utils/utils.h utils/chunk.h utils/debug.h utils/enum.h \
 	utils/identification.h utils/lexparser.h utils/optionsfrom.h \
-	utils/capabilities.h utils/backtrace.h utils/leak_detective.h \
-	utils/printf_hook/printf_hook.h \
+	utils/capabilities.h utils/backtrace.h utils/cpu_feature.h \
+	utils/leak_detective.h utils/printf_hook/printf_hook.h \
 	utils/printf_hook/printf_hook_vstr.h \
 	utils/printf_hook/printf_hook_builtin.h utils/parser_helper.h \
 	utils/test.h utils/integrity_checker.h utils/process.h \
 	utils/utils/strerror.h utils/compat/windows.h \
-	utils/compat/apple.h
+	utils/compat/apple.h utils/utils/atomics.h utils/utils/types.h \
+	utils/utils/byteorder.h utils/utils/string.h \
+	utils/utils/memory.h utils/utils/tty.h utils/utils/path.h \
+	utils/utils/status.h utils/utils/object.h utils/utils/time.h \
+	utils/utils/align.h
 HEADERS = $(nobase_strongswan_include_HEADERS) $(noinst_HEADERS)
 RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive	\
   distclean-recursive maintainer-clean-recursive
@@ -592,8 +607,8 @@ CTAGS = ctags
 DIST_SUBDIRS = . plugins/af_alg plugins/aes plugins/des \
 	plugins/blowfish plugins/rc2 plugins/md4 plugins/md5 \
 	plugins/sha1 plugins/sha2 plugins/gmp plugins/rdrand \
-	plugins/random plugins/nonce plugins/hmac plugins/cmac \
-	plugins/xcbc plugins/x509 plugins/revocation \
+	plugins/aesni plugins/random plugins/nonce plugins/hmac \
+	plugins/cmac plugins/xcbc plugins/x509 plugins/revocation \
 	plugins/constraints plugins/acert plugins/pubkey plugins/pkcs1 \
 	plugins/pkcs7 plugins/pkcs8 plugins/pkcs12 plugins/pgp \
 	plugins/dnskey plugins/sshkey plugins/pem plugins/curl \
@@ -867,7 +882,7 @@ libstrongswan_la_SOURCES = library.c asn1/asn1.c asn1/asn1_parser.c \
 	crypto/prf_plus.c crypto/signers/signer.c \
 	crypto/signers/mac_signer.c crypto/crypto_factory.c \
 	crypto/crypto_tester.c crypto/diffie_hellman.c crypto/aead.c \
-	crypto/transform.c crypto/iv/iv_gen_rand.c \
+	crypto/transform.c crypto/iv/iv_gen.c crypto/iv/iv_gen_rand.c \
 	crypto/iv/iv_gen_seq.c crypto/mgf1/mgf1.c \
 	crypto/mgf1/mgf1_bitspender.c credentials/credential_factory.c \
 	credentials/builder.c credentials/cred_encoding.c \
@@ -899,13 +914,16 @@ libstrongswan_la_SOURCES = library.c asn1/asn1.c asn1/asn1_parser.c \
 	resolver/rr_set.c selectors/traffic_selector.c \
 	settings/settings.c settings/settings_types.c \
 	settings/settings_parser.y settings/settings_lexer.l \
-	utils/utils.c utils/chunk.c utils/debug.c utils/enum.c \
-	utils/identification.c utils/lexparser.c utils/optionsfrom.c \
-	utils/capabilities.c utils/backtrace.c utils/parser_helper.c \
-	utils/test.c utils/process.c utils/utils/strerror.c \
-	$(am__append_1) $(am__append_3) $(am__append_8) \
-	$(am__append_11) $(am__append_12) $(am__append_14) \
-	$(am__append_16)
+	utils/cpu_feature.c utils/utils.c utils/chunk.c utils/debug.c \
+	utils/enum.c utils/identification.c utils/lexparser.c \
+	utils/optionsfrom.c utils/capabilities.c utils/backtrace.c \
+	utils/parser_helper.c utils/test.c utils/process.c \
+	utils/utils/strerror.c utils/utils/atomics.c \
+	utils/utils/string.c utils/utils/memory.c utils/utils/tty.c \
+	utils/utils/path.c utils/utils/status.c utils/utils/time.c \
+	utils/utils/align.c $(am__append_1) $(am__append_3) \
+	$(am__append_8) $(am__append_11) $(am__append_12) \
+	$(am__append_14) $(am__append_16)
 
 # private header files
 noinst_HEADERS = \
@@ -958,10 +976,13 @@ settings/settings_types.h
 @USE_DEV_HEADERS_TRUE at threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \
 @USE_DEV_HEADERS_TRUE at utils/utils.h utils/chunk.h utils/debug.h utils/enum.h utils/identification.h \
 @USE_DEV_HEADERS_TRUE at utils/lexparser.h utils/optionsfrom.h utils/capabilities.h utils/backtrace.h \
- at USE_DEV_HEADERS_TRUE@utils/leak_detective.h utils/printf_hook/printf_hook.h \
+ at USE_DEV_HEADERS_TRUE@utils/cpu_feature.h utils/leak_detective.h utils/printf_hook/printf_hook.h \
 @USE_DEV_HEADERS_TRUE at utils/printf_hook/printf_hook_vstr.h utils/printf_hook/printf_hook_builtin.h \
 @USE_DEV_HEADERS_TRUE at utils/parser_helper.h utils/test.h utils/integrity_checker.h utils/process.h \
- at USE_DEV_HEADERS_TRUE@utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h
+ at USE_DEV_HEADERS_TRUE@utils/utils/strerror.h utils/compat/windows.h utils/compat/apple.h \
+ at USE_DEV_HEADERS_TRUE@utils/utils/atomics.h utils/utils/types.h utils/utils/byteorder.h \
+ at USE_DEV_HEADERS_TRUE@utils/utils/string.h utils/utils/memory.h utils/utils/tty.h utils/utils/path.h \
+ at USE_DEV_HEADERS_TRUE@utils/utils/status.h utils/utils/object.h utils/utils/time.h utils/utils/align.h
 
 libstrongswan_la_LIBADD = $(DLLIB) $(BTLIB) $(SOCKLIB) $(RTLIB) \
 	$(BFDLIB) $(UNWINDLIB) $(am__append_2) $(am__append_4) \
@@ -982,7 +1003,8 @@ libstrongswan_la_LIBADD = $(DLLIB) $(BTLIB) $(SOCKLIB) $(RTLIB) \
 	$(am__append_95) $(am__append_97) $(am__append_99) \
 	$(am__append_101) $(am__append_103) $(am__append_105) \
 	$(am__append_107) $(am__append_109) $(am__append_111) \
-	$(am__append_113) $(am__append_115) $(am__append_117)
+	$(am__append_113) $(am__append_115) $(am__append_117) \
+	$(am__append_119)
 AM_CPPFLAGS = -I$(top_srcdir)/src/libstrongswan \
 	-DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_LIB_DIR=\"${ipseclibdir}\" \
 	-DPLUGINDIR=\"${plugindir}\" \
@@ -1033,8 +1055,8 @@ $(srcdir)/crypto/proposal/proposal_keywords_static.c
 @MONOLITHIC_FALSE@	$(am__append_102) $(am__append_104) \
 @MONOLITHIC_FALSE@	$(am__append_106) $(am__append_108) \
 @MONOLITHIC_FALSE@	$(am__append_110) $(am__append_112) \
- at MONOLITHIC_FALSE@	$(am__append_114) $(am__append_116) tests \
- at MONOLITHIC_FALSE@	$(am__append_118)
+ at MONOLITHIC_FALSE@	$(am__append_114) $(am__append_116) \
+ at MONOLITHIC_FALSE@	$(am__append_118) tests $(am__append_120)
 
 # build plugins with their own Makefile
 #######################################
@@ -1062,8 +1084,8 @@ $(srcdir)/crypto/proposal/proposal_keywords_static.c
 @MONOLITHIC_TRUE@	$(am__append_102) $(am__append_104) \
 @MONOLITHIC_TRUE@	$(am__append_106) $(am__append_108) \
 @MONOLITHIC_TRUE@	$(am__append_110) $(am__append_112) \
- at MONOLITHIC_TRUE@	$(am__append_114) $(am__append_116) . tests \
- at MONOLITHIC_TRUE@	$(am__append_118)
+ at MONOLITHIC_TRUE@	$(am__append_114) $(am__append_116) \
+ at MONOLITHIC_TRUE@	$(am__append_118) . tests $(am__append_120)
 all: $(BUILT_SOURCES)
 	$(MAKE) $(AM_MAKEFLAGS) all-recursive
 
@@ -1251,6 +1273,8 @@ crypto/iv/$(am__dirstamp):
 crypto/iv/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) crypto/iv/$(DEPDIR)
 	@: > crypto/iv/$(DEPDIR)/$(am__dirstamp)
+crypto/iv/iv_gen.lo: crypto/iv/$(am__dirstamp) \
+	crypto/iv/$(DEPDIR)/$(am__dirstamp)
 crypto/iv/iv_gen_rand.lo: crypto/iv/$(am__dirstamp) \
 	crypto/iv/$(DEPDIR)/$(am__dirstamp)
 crypto/iv/iv_gen_seq.lo: crypto/iv/$(am__dirstamp) \
@@ -1486,6 +1510,8 @@ utils/$(am__dirstamp):
 utils/$(DEPDIR)/$(am__dirstamp):
 	@$(MKDIR_P) utils/$(DEPDIR)
 	@: > utils/$(DEPDIR)/$(am__dirstamp)
+utils/cpu_feature.lo: utils/$(am__dirstamp) \
+	utils/$(DEPDIR)/$(am__dirstamp)
 utils/utils.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp)
 utils/chunk.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp)
 utils/debug.lo: utils/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp)
@@ -1513,6 +1539,22 @@ utils/utils/$(DEPDIR)/$(am__dirstamp):
 	@: > utils/utils/$(DEPDIR)/$(am__dirstamp)
 utils/utils/strerror.lo: utils/utils/$(am__dirstamp) \
 	utils/utils/$(DEPDIR)/$(am__dirstamp)
+utils/utils/atomics.lo: utils/utils/$(am__dirstamp) \
+	utils/utils/$(DEPDIR)/$(am__dirstamp)
+utils/utils/string.lo: utils/utils/$(am__dirstamp) \
+	utils/utils/$(DEPDIR)/$(am__dirstamp)
+utils/utils/memory.lo: utils/utils/$(am__dirstamp) \
+	utils/utils/$(DEPDIR)/$(am__dirstamp)
+utils/utils/tty.lo: utils/utils/$(am__dirstamp) \
+	utils/utils/$(DEPDIR)/$(am__dirstamp)
+utils/utils/path.lo: utils/utils/$(am__dirstamp) \
+	utils/utils/$(DEPDIR)/$(am__dirstamp)
+utils/utils/status.lo: utils/utils/$(am__dirstamp) \
+	utils/utils/$(DEPDIR)/$(am__dirstamp)
+utils/utils/time.lo: utils/utils/$(am__dirstamp) \
+	utils/utils/$(DEPDIR)/$(am__dirstamp)
+utils/utils/align.lo: utils/utils/$(am__dirstamp) \
+	utils/utils/$(DEPDIR)/$(am__dirstamp)
 threading/$(am__dirstamp):
 	@$(MKDIR_P) threading
 	@: > threading/$(am__dirstamp)
@@ -1702,6 +1744,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at crypto/crypters/$(DEPDIR)/crypter.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at crypto/hashers/$(DEPDIR)/hash_algorithm_set.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at crypto/hashers/$(DEPDIR)/hasher.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at crypto/iv/$(DEPDIR)/iv_gen.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at crypto/iv/$(DEPDIR)/iv_gen_rand.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at crypto/iv/$(DEPDIR)/iv_gen_seq.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at crypto/mgf1/$(DEPDIR)/mgf1.Plo at am__quote@
@@ -1760,6 +1803,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/backtrace.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/capabilities.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/chunk.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/cpu_feature.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/debug.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/enum.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/$(DEPDIR)/identification.Plo at am__quote@
@@ -1775,7 +1819,15 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at utils/printf_hook/$(DEPDIR)/printf_hook_builtin.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/printf_hook/$(DEPDIR)/printf_hook_glibc.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/printf_hook/$(DEPDIR)/printf_hook_vstr.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/align.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/atomics.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/memory.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/path.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/status.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/strerror.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/string.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/time.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at utils/utils/$(DEPDIR)/tty.Plo at am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index dca12bd..37b89c6 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -913,6 +913,10 @@ static const asn1Object_t timeObjects[] = {
 	{ 0, "end opt",			ASN1_EOC,				ASN1_END			}, /* 3 */
 	{ 0, "exit",			ASN1_EOC,				ASN1_EXIT			}
 };
+#ifdef TIME_UTC
+/* used by C11 timespec_get(), <time.h> */
+# undef TIME_UTC
+#endif
 #define TIME_UTC			0
 #define TIME_GENERALIZED	2
 
diff --git a/src/libstrongswan/crypto/aead.c b/src/libstrongswan/crypto/aead.c
index afcc11f..d50bd4d 100644
--- a/src/libstrongswan/crypto/aead.c
+++ b/src/libstrongswan/crypto/aead.c
@@ -172,7 +172,7 @@ METHOD(aead_t, destroy, void,
 /**
  * See header
  */
-aead_t *aead_create(crypter_t *crypter, signer_t *signer)
+aead_t *aead_create(crypter_t *crypter, signer_t *signer, iv_gen_t *iv_gen)
 {
 	private_aead_t *this;
 
@@ -190,7 +190,7 @@ aead_t *aead_create(crypter_t *crypter, signer_t *signer)
 		},
 		.crypter = crypter,
 		.signer = signer,
-		.iv_gen = iv_gen_rand_create(),
+		.iv_gen = iv_gen,
 	);
 
 	return &this->public;
diff --git a/src/libstrongswan/crypto/aead.h b/src/libstrongswan/crypto/aead.h
index 43f71b6..9d1b8df 100644
--- a/src/libstrongswan/crypto/aead.h
+++ b/src/libstrongswan/crypto/aead.h
@@ -135,8 +135,9 @@ struct aead_t {
  *
  * @param crypter		encryption transform for this aead
  * @param signer		integrity transform for this aead
+ * @param iv_gen		suitable IV generator for encryption algorithm
  * @return				aead transform
  */
-aead_t *aead_create(crypter_t *crypter, signer_t *signer);
+aead_t *aead_create(crypter_t *crypter, signer_t *signer, iv_gen_t *iv_gen);
 
 #endif /** AEAD_H_ @}*/
diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c
index 96fbc0d..b0b8637 100644
--- a/src/libstrongswan/crypto/crypto_factory.c
+++ b/src/libstrongswan/crypto/crypto_factory.c
@@ -377,6 +377,12 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
 	{
 		if (entry->algo == group)
 		{
+			if (this->test_on_create && group != MODP_CUSTOM &&
+				!this->tester->test_dh(this->tester, group,
+								entry->create_dh, NULL, default_plugin_name))
+			{
+				continue;
+			}
 			diffie_hellman = entry->create_dh(group, g, p);
 			if (diffie_hellman)
 			{
@@ -439,14 +445,14 @@ static void add_entry(private_crypto_factory_t *this, linked_list_t *list,
 }
 
 METHOD(crypto_factory_t, add_crypter, bool,
-	private_crypto_factory_t *this, encryption_algorithm_t algo,
+	private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size,
 	const char *plugin_name, crypter_constructor_t create)
 {
 	u_int speed = 0;
 
 	if (!this->test_on_add ||
-		this->tester->test_crypter(this->tester, algo, 0, create,
-								   this->bench ? &speed : NULL,	plugin_name))
+		this->tester->test_crypter(this->tester, algo, key_size, create,
+								   this->bench ? &speed : NULL, plugin_name))
 	{
 		add_entry(this, this->crypters, algo, plugin_name, speed, create);
 		return TRUE;
@@ -476,13 +482,13 @@ METHOD(crypto_factory_t, remove_crypter, void,
 }
 
 METHOD(crypto_factory_t, add_aead, bool,
-	private_crypto_factory_t *this, encryption_algorithm_t algo,
+	private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size,
 	const char *plugin_name, aead_constructor_t create)
 {
 	u_int speed = 0;
 
 	if (!this->test_on_add ||
-		this->tester->test_aead(this->tester, algo, 0, 0, create,
+		this->tester->test_aead(this->tester, algo, key_size, 0, create,
 								this->bench ? &speed : NULL, plugin_name))
 	{
 		add_entry(this, this->aeads, algo, plugin_name, speed, create);
@@ -692,8 +698,17 @@ METHOD(crypto_factory_t, add_dh, bool,
 	private_crypto_factory_t *this, diffie_hellman_group_t group,
 	const char *plugin_name, dh_constructor_t create)
 {
-	add_entry(this, this->dhs, group, plugin_name, 0, create);
-	return TRUE;
+	u_int speed = 0;
+
+	if (!this->test_on_add ||
+		this->tester->test_dh(this->tester, group, create,
+							  this->bench ? &speed : NULL, plugin_name))
+	{
+		add_entry(this, this->dhs, group, plugin_name, 0, create);
+		return TRUE;
+	}
+	this->test_failures++;
+	return FALSE;
 }
 
 METHOD(crypto_factory_t, remove_dh, void,
@@ -892,16 +907,125 @@ METHOD(crypto_factory_t, add_test_vector, void,
 			return this->tester->add_prf_vector(this->tester, vector);
 		case RANDOM_NUMBER_GENERATOR:
 			return this->tester->add_rng_vector(this->tester, vector);
+		case DIFFIE_HELLMAN_GROUP:
+			return this->tester->add_dh_vector(this->tester, vector);
 		default:
 			DBG1(DBG_LIB, "%N test vectors not supported, ignored",
 				 transform_type_names, type);
 	}
 }
 
-METHOD(crypto_factory_t, get_test_vector_failures, u_int,
-	private_crypto_factory_t *this)
+/**
+ * Private enumerator for create_verify_enumerator()
+ */
+typedef struct {
+	enumerator_t public;
+	enumerator_t *inner;
+	transform_type_t type;
+	crypto_tester_t *tester;
+	rwlock_t *lock;
+} verify_enumerator_t;
+
+METHOD(enumerator_t, verify_enumerate, bool,
+	verify_enumerator_t *this, u_int *alg, const char **plugin, bool *valid)
 {
-	return this->test_failures;
+	entry_t *entry;
+
+	if (!this->inner->enumerate(this->inner, &entry))
+	{
+		return FALSE;
+	}
+	switch (this->type)
+	{
+		case ENCRYPTION_ALGORITHM:
+			*valid = this->tester->test_crypter(this->tester, entry->algo, 0,
+							entry->create_crypter, NULL, entry->plugin_name);
+			break;
+		case AEAD_ALGORITHM:
+			*valid = this->tester->test_aead(this->tester, entry->algo, 0, 0,
+							entry->create_aead, NULL, entry->plugin_name);
+			break;
+		case INTEGRITY_ALGORITHM:
+			*valid = this->tester->test_signer(this->tester, entry->algo,
+							entry->create_signer, NULL, entry->plugin_name);
+			break;
+		case HASH_ALGORITHM:
+			*valid = this->tester->test_hasher(this->tester, entry->algo,
+							entry->create_hasher, NULL, entry->plugin_name);
+			break;
+		case PSEUDO_RANDOM_FUNCTION:
+			*valid = this->tester->test_prf(this->tester, entry->algo,
+							entry->create_prf, NULL, entry->plugin_name);
+			break;
+		case RANDOM_NUMBER_GENERATOR:
+			*valid = this->tester->test_rng(this->tester, entry->algo,
+							entry->create_rng, NULL, entry->plugin_name);
+			break;
+		case DIFFIE_HELLMAN_GROUP:
+			*valid = this->tester->test_dh(this->tester, entry->algo,
+							entry->create_dh, NULL, entry->plugin_name);
+			break;
+		default:
+			return FALSE;
+	}
+	*plugin = entry->plugin_name;
+	*alg = entry->algo;
+	return TRUE;
+}
+
+METHOD(enumerator_t, verify_destroy, void,
+	verify_enumerator_t *this)
+{
+	this->inner->destroy(this->inner);
+	this->lock->unlock(this->lock);
+	free(this);
+}
+
+METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
+	private_crypto_factory_t *this, transform_type_t type)
+{
+	verify_enumerator_t *enumerator;
+	enumerator_t *inner;
+
+	this->lock->read_lock(this->lock);
+	switch (type)
+	{
+		case ENCRYPTION_ALGORITHM:
+			inner = this->crypters->create_enumerator(this->crypters);
+			break;
+		case AEAD_ALGORITHM:
+			inner = this->aeads->create_enumerator(this->aeads);
+			break;
+		case INTEGRITY_ALGORITHM:
+			inner = this->signers->create_enumerator(this->signers);
+			break;
+		case HASH_ALGORITHM:
+			inner = this->hashers->create_enumerator(this->hashers);
+			break;
+		case PSEUDO_RANDOM_FUNCTION:
+			inner = this->prfs->create_enumerator(this->prfs);
+			break;
+		case RANDOM_NUMBER_GENERATOR:
+			inner = this->rngs->create_enumerator(this->rngs);
+			break;
+		case DIFFIE_HELLMAN_GROUP:
+			inner = this->dhs->create_enumerator(this->dhs);
+			break;
+		default:
+			this->lock->unlock(this->lock);
+			return enumerator_create_empty();
+	}
+	INIT(enumerator,
+		.public = {
+			.enumerate = (void*)_verify_enumerate,
+			.destroy = _verify_destroy,
+		},
+		.inner = inner,
+		.type = type,
+		.tester = this->tester,
+		.lock = this->lock,
+	);
+	return &enumerator->public;
 }
 
 METHOD(crypto_factory_t, destroy, void,
@@ -962,7 +1086,7 @@ crypto_factory_t *crypto_factory_create()
 			.create_rng_enumerator = _create_rng_enumerator,
 			.create_nonce_gen_enumerator = _create_nonce_gen_enumerator,
 			.add_test_vector = _add_test_vector,
-			.get_test_vector_failures = _get_test_vector_failures,
+			.create_verify_enumerator = _create_verify_enumerator,
 			.destroy = _destroy,
 		},
 		.crypters = linked_list_create(),
@@ -985,39 +1109,3 @@ crypto_factory_t *crypto_factory_create()
 
 	return &this->public;
 }
-
-/**
- * Manually verify all registered algorithms against test vectors
- */
-static u_int verify_registered_algorithms(crypto_factory_t *factory)
-{
-	private_crypto_factory_t *this = (private_crypto_factory_t*)factory;
-	enumerator_t *enumerator;
-	entry_t *entry;
-	u_int failures = 0;
-
-#define TEST_ALGORITHMS(test, ...) do { \
-	enumerator = this->test##s->create_enumerator(this->test##s); \
-	while (enumerator->enumerate(enumerator, &entry)) \
-	{ \
-		if (!this->tester->test_##test(this->tester, entry->algo, ##__VA_ARGS__, \
-							entry->create_##test, NULL, entry->plugin_name)) \
-		{ \
-			failures++; \
-		} \
-	} \
-	enumerator->destroy(enumerator); \
-} while (0)
-
-	this->lock->read_lock(this->lock);
-	TEST_ALGORITHMS(crypter, 0);
-	TEST_ALGORITHMS(aead, 0, 0);
-	TEST_ALGORITHMS(signer);
-	TEST_ALGORITHMS(hasher);
-	TEST_ALGORITHMS(prf);
-	TEST_ALGORITHMS(rng);
-	this->lock->unlock(this->lock);
-	return failures;
-}
-
-EXPORT_FUNCTION_FOR_TESTS(crypto, verify_registered_algorithms);
diff --git a/src/libstrongswan/crypto/crypto_factory.h b/src/libstrongswan/crypto/crypto_factory.h
index 7865bcb..e039156 100644
--- a/src/libstrongswan/crypto/crypto_factory.h
+++ b/src/libstrongswan/crypto/crypto_factory.h
@@ -162,12 +162,14 @@ struct crypto_factory_t {
 	 * Register a crypter constructor.
 	 *
 	 * @param algo			algorithm to constructor
+	 * @param key size		key size to peform benchmarking for
 	 * @param plugin_name	plugin that registered this algorithm
 	 * @param create		constructor function for that algorithm
 	 * @return				TRUE if registered, FALSE if test vector failed
 	 */
 	bool (*add_crypter)(crypto_factory_t *this, encryption_algorithm_t algo,
-						const char *plugin_name, crypter_constructor_t create);
+						size_t key_size, const char *plugin_name,
+						crypter_constructor_t create);
 
 	/**
 	 * Unregister a crypter constructor.
@@ -187,12 +189,14 @@ struct crypto_factory_t {
 	 * Register a aead constructor.
 	 *
 	 * @param algo			algorithm to constructor
+	 * @param key size		key size to peform benchmarking for
 	 * @param plugin_name	plugin that registered this algorithm
 	 * @param create		constructor function for that algorithm
 	 * @return				TRUE if registered, FALSE if test vector failed
 	 */
 	bool (*add_aead)(crypto_factory_t *this, encryption_algorithm_t algo,
-					 const char *plugin_name, aead_constructor_t create);
+					 size_t key_size, const char *plugin_name,
+					 aead_constructor_t create);
 
 	/**
 	 * Register a signer constructor.
@@ -368,14 +372,17 @@ struct crypto_factory_t {
 							void *vector);
 
 	/**
-	 * Get the number of test vector failures encountered during add.
+	 * Create an enumerator verifying transforms using known test vectors.
 	 *
-	 * This counter gets incremented only if transforms get tested during
-	 * registration.
+	 * The resulting enumerator enumerates over an u_int with the type
+	 * specific transform identifier, the plugin name providing the transform,
+	 * and a boolean value indicating success/failure for the given transform.
 	 *
-	 * @return				number of failed test vectors
+	 * @param type			transform type to test
+	 * @return				enumerator over (u_int, char*, bool)
 	 */
-	u_int (*get_test_vector_failures)(crypto_factory_t *this);
+	enumerator_t* (*create_verify_enumerator)(crypto_factory_t *this,
+											  transform_type_t type);
 
 	/**
 	 * Destroy a crypto_factory instance.
diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c
index 15ed173..5607d35 100644
--- a/src/libstrongswan/crypto/crypto_tester.c
+++ b/src/libstrongswan/crypto/crypto_tester.c
@@ -68,6 +68,11 @@ struct private_crypto_tester_t {
 	linked_list_t *rng;
 
 	/**
+	 * List of Diffie-Hellman test vectors
+	 */
+	linked_list_t *dh;
+
+	/**
 	 * Is a test vector required to pass a test?
 	 */
 	bool required;
@@ -138,11 +143,11 @@ static u_int end_timing(struct timespec *start)
  * Benchmark a crypter
  */
 static u_int bench_crypter(private_crypto_tester_t *this,
-	encryption_algorithm_t alg, crypter_constructor_t create)
+	encryption_algorithm_t alg, crypter_constructor_t create, size_t key_size)
 {
 	crypter_t *crypter;
 
-	crypter = create(alg, 0);
+	crypter = create(alg, key_size);
 	if (crypter)
 	{
 		char iv[crypter->get_iv_size(crypter)];
@@ -280,8 +285,8 @@ failure:
 	{
 		if (failed)
 		{
-			DBG1(DBG_LIB,"disable %N[%s]: no key size supported",
-				 encryption_algorithm_names, alg, plugin_name);
+			DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported",
+				 encryption_algorithm_names, alg, plugin_name, key_size);
 			return FALSE;
 		}
 		else
@@ -296,9 +301,10 @@ failure:
 	{
 		if (speed)
 		{
-			*speed = bench_crypter(this, alg, create);
-			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
-				 encryption_algorithm_names, alg, plugin_name, tested, *speed);
+			*speed = bench_crypter(this, alg, create, key_size);
+			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points "
+				 "(%zd bit key)", encryption_algorithm_names, alg,
+				 plugin_name, tested, *speed, key_size * 8);
 		}
 		else
 		{
@@ -313,11 +319,11 @@ failure:
  * Benchmark an aead transform
  */
 static u_int bench_aead(private_crypto_tester_t *this,
-	encryption_algorithm_t alg, aead_constructor_t create)
+	encryption_algorithm_t alg, aead_constructor_t create, size_t key_size)
 {
 	aead_t *aead;
 
-	aead = create(alg, 0, 0);
+	aead = create(alg, key_size, 0);
 	if (aead)
 	{
 		char iv[aead->get_iv_size(aead)];
@@ -474,8 +480,8 @@ failure:
 	{
 		if (failed)
 		{
-			DBG1(DBG_LIB,"disable %N[%s]: no key size supported",
-				 encryption_algorithm_names, alg, plugin_name);
+			DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported",
+				 encryption_algorithm_names, alg, plugin_name, key_size);
 			return FALSE;
 		}
 		else
@@ -490,9 +496,10 @@ failure:
 	{
 		if (speed)
 		{
-			*speed = bench_aead(this, alg, create);
-			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
-				 encryption_algorithm_names, alg, plugin_name, tested, *speed);
+			*speed = bench_aead(this, alg, create, key_size);
+			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points "
+				 "(%zd bit key)", encryption_algorithm_names, alg,
+				 plugin_name, tested, *speed, key_size * 8);
 		}
 		else
 		{
@@ -1153,6 +1160,154 @@ failure:
 	return !failed;
 }
 
+/**
+ * Benchmark a DH backend
+ */
+static u_int bench_dh(private_crypto_tester_t *this,
+					  diffie_hellman_group_t group, dh_constructor_t create)
+{
+	chunk_t pub = chunk_empty, shared = chunk_empty;
+	diffie_hellman_t *dh;
+	struct timespec start;
+	u_int runs;
+
+	runs = 0;
+	start_timing(&start);
+	while (end_timing(&start) < this->bench_time)
+	{
+		dh = create(group);
+		if (!dh)
+		{
+			return 0;
+		}
+		if (dh->get_my_public_value(dh, &pub) &&
+			dh->set_other_public_value(dh, pub) &&
+			dh->get_shared_secret(dh, &shared))
+		{
+			runs++;
+		}
+		chunk_free(&pub);
+		chunk_free(&shared);
+		dh->destroy(dh);
+	}
+	return runs;
+}
+
+METHOD(crypto_tester_t, test_dh, bool,
+	private_crypto_tester_t *this, diffie_hellman_group_t group,
+	dh_constructor_t create, u_int *speed, const char *plugin_name)
+{
+	enumerator_t *enumerator;
+	dh_test_vector_t *v;
+	bool failed = FALSE;
+	u_int tested = 0;
+
+	enumerator = this->dh->create_enumerator(this->dh);
+	while (enumerator->enumerate(enumerator, &v))
+	{
+		diffie_hellman_t *a, *b;
+		chunk_t apub, bpub, asec, bsec;
+
+		if (v->group != group)
+		{
+			continue;
+		}
+
+		a = create(group);
+		b = create(group);
+		if (!a || !b)
+		{
+			DESTROY_IF(a);
+			DESTROY_IF(b);
+			failed = TRUE;
+			tested++;
+			DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
+				 diffie_hellman_group_names, group, plugin_name);
+			break;
+		}
+
+		if (!a->set_private_value || !b->set_private_value)
+		{	/* does not support testing */
+			a->destroy(a);
+			b->destroy(b);
+			continue;
+		}
+		failed = TRUE;
+		tested++;
+
+		apub = bpub = asec = bsec = chunk_empty;
+
+		if (!a->set_private_value(a, chunk_create(v->priv_a, v->priv_len)) ||
+			!b->set_private_value(b, chunk_create(v->priv_b, v->priv_len)))
+		{
+			goto failure;
+		}
+		if (!a->get_my_public_value(a, &apub) ||
+			!chunk_equals(apub, chunk_create(v->pub_a, v->pub_len)))
+		{
+			goto failure;
+		}
+		if (!b->get_my_public_value(b, &bpub) ||
+			!chunk_equals(bpub, chunk_create(v->pub_b, v->pub_len)))
+		{
+			goto failure;
+		}
+		if (!a->set_other_public_value(a, bpub) ||
+			!b->set_other_public_value(b, apub))
+		{
+			goto failure;
+		}
+		if (!a->get_shared_secret(a, &asec) ||
+			!chunk_equals(asec, chunk_create(v->shared, v->shared_len)))
+		{
+			goto failure;
+		}
+		if (!b->get_shared_secret(b, &bsec) ||
+			!chunk_equals(bsec, chunk_create(v->shared, v->shared_len)))
+		{
+			goto failure;
+		}
+
+		failed = FALSE;
+failure:
+		a->destroy(a);
+		b->destroy(b);
+		chunk_free(&apub);
+		chunk_free(&bpub);
+		chunk_free(&asec);
+		chunk_free(&bsec);
+		if (failed)
+		{
+			DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
+				 diffie_hellman_group_names, group, plugin_name, get_name(v));
+			break;
+		}
+	}
+	enumerator->destroy(enumerator);
+	if (!tested)
+	{
+		DBG1(DBG_LIB, "%s %N[%s]: no test vectors found / untestable",
+			 this->required ? "disabled" : "enabled ",
+			 diffie_hellman_group_names, group, plugin_name);
+		return !this->required;
+	}
+	if (!failed)
+	{
+		if (speed)
+		{
+			*speed = bench_dh(this, group, create);
+			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors, %d points",
+				 diffie_hellman_group_names, group, plugin_name, tested, *speed);
+		}
+		else
+		{
+			DBG1(DBG_LIB, "enabled  %N[%s]: passed %u test vectors",
+				 diffie_hellman_group_names, group, plugin_name, tested);
+		}
+	}
+	return !failed;
+}
+
 METHOD(crypto_tester_t, add_crypter_vector, void,
 	private_crypto_tester_t *this, crypter_test_vector_t *vector)
 {
@@ -1189,6 +1344,12 @@ METHOD(crypto_tester_t, add_rng_vector, void,
 	this->rng->insert_last(this->rng, vector);
 }
 
+METHOD(crypto_tester_t, add_dh_vector, void,
+	private_crypto_tester_t *this, dh_test_vector_t *vector)
+{
+	this->dh->insert_last(this->dh, vector);
+}
+
 METHOD(crypto_tester_t, destroy, void,
 	private_crypto_tester_t *this)
 {
@@ -1198,6 +1359,7 @@ METHOD(crypto_tester_t, destroy, void,
 	this->hasher->destroy(this->hasher);
 	this->prf->destroy(this->prf);
 	this->rng->destroy(this->rng);
+	this->dh->destroy(this->dh);
 	free(this);
 }
 
@@ -1216,12 +1378,14 @@ crypto_tester_t *crypto_tester_create()
 			.test_hasher = _test_hasher,
 			.test_prf = _test_prf,
 			.test_rng = _test_rng,
+			.test_dh = _test_dh,
 			.add_crypter_vector = _add_crypter_vector,
 			.add_aead_vector = _add_aead_vector,
 			.add_signer_vector = _add_signer_vector,
 			.add_hasher_vector = _add_hasher_vector,
 			.add_prf_vector = _add_prf_vector,
 			.add_rng_vector = _add_rng_vector,
+			.add_dh_vector = _add_dh_vector,
 			.destroy = _destroy,
 		},
 		.crypter = linked_list_create(),
@@ -1230,6 +1394,7 @@ crypto_tester_t *crypto_tester_create()
 		.hasher = linked_list_create(),
 		.prf = linked_list_create(),
 		.rng = linked_list_create(),
+		.dh = linked_list_create(),
 
 		.required = lib->settings->get_bool(lib->settings,
 								"%s.crypto_test.required", FALSE, lib->ns),
diff --git a/src/libstrongswan/crypto/crypto_tester.h b/src/libstrongswan/crypto/crypto_tester.h
index add3b1c..6cc9b0d 100644
--- a/src/libstrongswan/crypto/crypto_tester.h
+++ b/src/libstrongswan/crypto/crypto_tester.h
@@ -31,6 +31,7 @@ typedef struct signer_test_vector_t signer_test_vector_t;
 typedef struct hasher_test_vector_t hasher_test_vector_t;
 typedef struct prf_test_vector_t prf_test_vector_t;
 typedef struct rng_test_vector_t rng_test_vector_t;
+typedef struct dh_test_vector_t dh_test_vector_t;
 
 struct crypter_test_vector_t {
 	/** encryption algorithm this vector tests */
@@ -129,6 +130,27 @@ struct rng_test_vector_t {
 	void *user;
 };
 
+struct dh_test_vector_t {
+	/** diffie hellman group to test */
+	diffie_hellman_group_t group;
+	/** private value of alice */
+	u_char *priv_a;
+	/** private value of bob */
+	u_char *priv_b;
+	/** length of private values */
+	size_t priv_len;
+	/** expected public value of alice */
+	u_char *pub_a;
+	/** expected public value of bob */
+	u_char *pub_b;
+	/** size of public values */
+	size_t pub_len;
+	/** expected shared secret */
+	u_char *shared;
+	/** size of shared secret */
+	size_t shared_len;
+};
+
 /**
  * Cryptographic primitive testing framework.
  */
@@ -206,6 +228,18 @@ struct crypto_tester_t {
 					 rng_constructor_t create,
 					 u_int *speed, const char *plugin_name);
 	/**
+	 * Test a Diffie-Hellman implementation.
+	 *
+	 * @param group			group to test
+	 * @param create		constructor function for the DH backend
+	 * @param speed			speeed test result, NULL to omit
+	 * @return				TRUE if test passed
+	 */
+	bool (*test_dh)(crypto_tester_t *this, diffie_hellman_group_t group,
+					dh_constructor_t create,
+					u_int *speed, const char *plugin_name);
+
+	/**
 	 * Add a test vector to test a crypter.
 	 *
 	 * @param vector		pointer to test vector
@@ -248,6 +282,13 @@ struct crypto_tester_t {
 	void (*add_rng_vector)(crypto_tester_t *this, rng_test_vector_t *vector);
 
 	/**
+	 * Add a test vector to test a Diffie-Hellman backend.
+	 *
+	 * @param vector		pointer to test vector
+	 */
+	void (*add_dh_vector)(crypto_tester_t *this, dh_test_vector_t *vector);
+
+	/**
 	 * Destroy a crypto_tester_t.
 	 */
 	void (*destroy)(crypto_tester_t *this);
diff --git a/src/libstrongswan/crypto/diffie_hellman.h b/src/libstrongswan/crypto/diffie_hellman.h
index 4704cd0..abebd66 100644
--- a/src/libstrongswan/crypto/diffie_hellman.h
+++ b/src/libstrongswan/crypto/diffie_hellman.h
@@ -117,6 +117,18 @@ struct diffie_hellman_t {
 		__attribute__((warn_unused_result));
 
 	/**
+	 * Set an explicit own private value to use.
+	 *
+	 * Calling this method is usually not required, as the DH backend generates
+	 * an appropriate private value itself. It is optional to implement, and
+	 * used mostly for testing purposes.
+	 *
+	 * @param value		private value to set
+	 */
+	bool (*set_private_value)(diffie_hellman_t *this, chunk_t value)
+		__attribute__((warn_unused_result));
+
+	/**
 	 * Get the DH group used.
 	 *
 	 * @return			DH group set in construction
diff --git a/src/libstrongswan/crypto/iv/iv_gen.c b/src/libstrongswan/crypto/iv/iv_gen.c
new file mode 100644
index 0000000..e188432
--- /dev/null
+++ b/src/libstrongswan/crypto/iv/iv_gen.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "iv_gen.h"
+#include "iv_gen_rand.h"
+#include "iv_gen_seq.h"
+
+/**
+ * See header.
+ */
+iv_gen_t* iv_gen_create_for_alg(encryption_algorithm_t alg)
+{
+	switch (alg)
+	{
+		case ENCR_DES:
+		case ENCR_3DES:
+		case ENCR_RC5:
+		case ENCR_IDEA:
+		case ENCR_CAST:
+		case ENCR_BLOWFISH:
+		case ENCR_3IDEA:
+		case ENCR_AES_CBC:
+		case ENCR_CAMELLIA_CBC:
+		case ENCR_SERPENT_CBC:
+		case ENCR_TWOFISH_CBC:
+		case ENCR_RC2_CBC:
+			return iv_gen_rand_create();
+		case ENCR_AES_CTR:
+		case ENCR_AES_CCM_ICV8:
+		case ENCR_AES_CCM_ICV12:
+		case ENCR_AES_CCM_ICV16:
+		case ENCR_AES_GCM_ICV8:
+		case ENCR_AES_GCM_ICV12:
+		case ENCR_AES_GCM_ICV16:
+		case ENCR_CAMELLIA_CTR:
+		case ENCR_CAMELLIA_CCM_ICV8:
+		case ENCR_CAMELLIA_CCM_ICV12:
+		case ENCR_CAMELLIA_CCM_ICV16:
+		case ENCR_NULL_AUTH_AES_GMAC:
+			return iv_gen_seq_create();
+		case ENCR_NULL:
+		case ENCR_UNDEFINED:
+		case ENCR_DES_ECB:
+		case ENCR_DES_IV32:
+		case ENCR_DES_IV64:
+			break;
+	}
+	return NULL;
+}
diff --git a/src/libstrongswan/crypto/iv/iv_gen.h b/src/libstrongswan/crypto/iv/iv_gen.h
index f6bc647..81b0701 100644
--- a/src/libstrongswan/crypto/iv/iv_gen.h
+++ b/src/libstrongswan/crypto/iv/iv_gen.h
@@ -58,4 +58,12 @@ struct iv_gen_t {
 	void (*destroy)(iv_gen_t *this);
 };
 
+/**
+ * Select an IV generator for a given encryption algorithm.
+ *
+ * @param alg			encryption algorithm
+ * @return				IV generator
+ */
+iv_gen_t* iv_gen_create_for_alg(encryption_algorithm_t alg);
+
 #endif /** IV_GEN_H_ @}*/
diff --git a/src/libstrongswan/crypto/iv/iv_gen_seq.c b/src/libstrongswan/crypto/iv/iv_gen_seq.c
index 98d0c15..4de1374 100644
--- a/src/libstrongswan/crypto/iv/iv_gen_seq.c
+++ b/src/libstrongswan/crypto/iv/iv_gen_seq.c
@@ -15,6 +15,11 @@
 
 #include "iv_gen_seq.h"
 
+/**
+ * Magic value for the initial IV state
+ */
+#define SEQ_IV_INIT_STATE (~(u_int64_t)0)
+
 typedef struct private_iv_gen_t private_iv_gen_t;
 
 /**
@@ -28,6 +33,11 @@ struct private_iv_gen_t {
 	iv_gen_t public;
 
 	/**
+	 * Previously passed sequence number to enforce uniqueness
+	 */
+	u_int64_t prev;
+
+	/**
 	 * Salt to mask counter
 	 */
 	u_int8_t *salt;
@@ -43,6 +53,19 @@ METHOD(iv_gen_t, get_iv, bool,
 	{
 		return FALSE;
 	}
+	if (size < sizeof(u_int64_t))
+	{
+		return FALSE;
+	}
+	if (this->prev != SEQ_IV_INIT_STATE && seq <= this->prev)
+	{
+		return FALSE;
+	}
+	if (seq == SEQ_IV_INIT_STATE)
+	{
+		return FALSE;
+	}
+	this->prev = seq;
 	if (len > sizeof(u_int64_t))
 	{
 		len = sizeof(u_int64_t);
@@ -84,6 +107,7 @@ iv_gen_t *iv_gen_seq_create()
 			.allocate_iv = _allocate_iv,
 			.destroy = _destroy,
 		},
+		.prev = SEQ_IV_INIT_STATE,
 	);
 
 	rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
diff --git a/src/libstrongswan/crypto/iv/iv_gen_seq.h b/src/libstrongswan/crypto/iv/iv_gen_seq.h
index 329dcca..43ff4f6 100644
--- a/src/libstrongswan/crypto/iv/iv_gen_seq.h
+++ b/src/libstrongswan/crypto/iv/iv_gen_seq.h
@@ -25,6 +25,9 @@
 /**
  * Create an IV generator that generates sequential IVs (counter).
  *
+ * The passed external IV must be larger than the one passed to any previous
+ * call.
+ *
  * @return		IV generator
  */
 iv_gen_t *iv_gen_seq_create();
diff --git a/src/libstrongswan/crypto/signers/mac_signer.c b/src/libstrongswan/crypto/signers/mac_signer.c
index 7c52aa3..1094c44 100644
--- a/src/libstrongswan/crypto/signers/mac_signer.c
+++ b/src/libstrongswan/crypto/signers/mac_signer.c
@@ -85,7 +85,7 @@ METHOD(signer_t, verify_signature, bool,
 		return FALSE;
 	}
 	return this->mac->get_mac(this->mac, data, mac) &&
-		   memeq(signature.ptr, mac, this->truncation);
+		   memeq_const(signature.ptr, mac, this->truncation);
 }
 
 METHOD(signer_t, get_key_size, size_t,
@@ -136,4 +136,3 @@ signer_t *mac_signer_create(mac_t *mac, size_t len)
 
 	return &this->public;
 }
-
diff --git a/src/libstrongswan/crypto/transform.c b/src/libstrongswan/crypto/transform.c
index 5625297..7c6678b 100644
--- a/src/libstrongswan/crypto/transform.c
+++ b/src/libstrongswan/crypto/transform.c
@@ -14,6 +14,8 @@
  */
 
 #include <crypto/transform.h>
+#include <crypto/hashers/hasher.h>
+#include <crypto/rngs/rng.h>
 
 ENUM_BEGIN(transform_type_names, UNDEFINED_TRANSFORM_TYPE, COMPRESSION_ALGORITHM,
 	"UNDEFINED_TRANSFORM_TYPE",
@@ -34,3 +36,33 @@ ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS,
 	"NO_EXT_SEQ",
 	"EXT_SEQ",
 );
+
+
+/**
+ * See header
+ */
+enum_name_t* transform_get_enum_names(transform_type_t type)
+{
+	switch (type)
+	{
+		case HASH_ALGORITHM:
+			return hash_algorithm_names;
+		case RANDOM_NUMBER_GENERATOR:
+			return rng_quality_names;
+		case AEAD_ALGORITHM:
+		case ENCRYPTION_ALGORITHM:
+			return encryption_algorithm_names;
+		case PSEUDO_RANDOM_FUNCTION:
+			return pseudo_random_function_names;
+		case INTEGRITY_ALGORITHM:
+			return integrity_algorithm_names;
+		case DIFFIE_HELLMAN_GROUP:
+			return diffie_hellman_group_names;
+		case EXTENDED_SEQUENCE_NUMBERS:
+			return extended_sequence_numbers_names;
+		case UNDEFINED_TRANSFORM_TYPE:
+		case COMPRESSION_ALGORITHM:
+			break;
+	}
+	return NULL;
+}
diff --git a/src/libstrongswan/crypto/transform.h b/src/libstrongswan/crypto/transform.h
index a585e97..0cb84f0 100644
--- a/src/libstrongswan/crypto/transform.h
+++ b/src/libstrongswan/crypto/transform.h
@@ -47,6 +47,14 @@ enum transform_type_t {
 extern enum_name_t *transform_type_names;
 
 /**
+ * Get the enum names for a specific transform type.
+ *
+ * @param type		type of transform to get enum names for
+ * @return			enum names
+ */
+enum_name_t *transform_get_enum_names(transform_type_t type);
+
+/**
  * Extended sequence numbers, as in IKEv2 RFC 3.3.2.
  */
 enum extended_sequence_numbers_t {
diff --git a/src/libstrongswan/plugins/aesni/Makefile.am b/src/libstrongswan/plugins/aesni/Makefile.am
new file mode 100644
index 0000000..2fe85c6
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/Makefile.am
@@ -0,0 +1,26 @@
+AM_CPPFLAGS = \
+	-I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+	-maes \
+	-mpclmul \
+	-mssse3 \
+	$(PLUGIN_CFLAGS)
+
+if MONOLITHIC
+noinst_LTLIBRARIES = libstrongswan-aesni.la
+else
+plugin_LTLIBRARIES = libstrongswan-aesni.la
+endif
+
+libstrongswan_aesni_la_SOURCES = \
+	aesni_key.h aesni_key.c \
+	aesni_cbc.h aesni_cbc.c \
+	aesni_ctr.h aesni_ctr.c \
+	aesni_ccm.h aesni_ccm.c \
+	aesni_gcm.h aesni_gcm.c \
+	aesni_xcbc.h aesni_xcbc.c \
+	aesni_cmac.h aesni_cmac.c \
+	aesni_plugin.h aesni_plugin.c
+
+libstrongswan_aesni_la_LDFLAGS = -module -avoid-version
diff --git a/src/libsimaka/Makefile.in b/src/libstrongswan/plugins/aesni/Makefile.in
similarity index 82%
copy from src/libsimaka/Makefile.in
copy to src/libstrongswan/plugins/aesni/Makefile.in
index 79962d3..34adaa3 100644
--- a/src/libsimaka/Makefile.in
+++ b/src/libstrongswan/plugins/aesni/Makefile.in
@@ -78,7 +78,7 @@ PRE_UNINSTALL = :
 POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
-subdir = src/libsimaka
+subdir = src/libstrongswan/plugins/aesni
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	$(top_srcdir)/depcomp
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -125,17 +125,24 @@ am__uninstall_files_from_dir = { \
     || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
          $(am__cd) "$$dir" && rm -f $$files; }; \
   }
-am__installdirs = "$(DESTDIR)$(ipseclibdir)"
-LTLIBRARIES = $(ipseclib_LTLIBRARIES)
-libsimaka_la_DEPENDENCIES =  \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
-am_libsimaka_la_OBJECTS = simaka_message.lo simaka_crypto.lo \
-	simaka_manager.lo
-libsimaka_la_OBJECTS = $(am_libsimaka_la_OBJECTS)
+am__installdirs = "$(DESTDIR)$(plugindir)"
+LTLIBRARIES = $(noinst_LTLIBRARIES) $(plugin_LTLIBRARIES)
+libstrongswan_aesni_la_LIBADD =
+am_libstrongswan_aesni_la_OBJECTS = aesni_key.lo aesni_cbc.lo \
+	aesni_ctr.lo aesni_ccm.lo aesni_gcm.lo aesni_xcbc.lo \
+	aesni_cmac.lo aesni_plugin.lo
+libstrongswan_aesni_la_OBJECTS = $(am_libstrongswan_aesni_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
 am__v_lt_ = $(am__v_lt_ at AM_DEFAULT_V@)
 am__v_lt_0 = --silent
 am__v_lt_1 = 
+libstrongswan_aesni_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+	$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+	$(AM_CFLAGS) $(CFLAGS) $(libstrongswan_aesni_la_LDFLAGS) \
+	$(LDFLAGS) -o $@
+ at MONOLITHIC_FALSE@am_libstrongswan_aesni_la_rpath = -rpath \
+ at MONOLITHIC_FALSE@	$(plugindir)
+ at MONOLITHIC_TRUE@am_libstrongswan_aesni_la_rpath =
 AM_V_P = $(am__v_P_ at AM_V@)
 am__v_P_ = $(am__v_P_ at AM_DEFAULT_V@)
 am__v_P_0 = false
@@ -170,8 +177,8 @@ AM_V_CCLD = $(am__v_CCLD_ at AM_V@)
 am__v_CCLD_ = $(am__v_CCLD_ at AM_DEFAULT_V@)
 am__v_CCLD_0 = @echo "  CCLD    " $@;
 am__v_CCLD_1 = 
-SOURCES = $(libsimaka_la_SOURCES)
-DIST_SOURCES = $(libsimaka_la_SOURCES)
+SOURCES = $(libstrongswan_aesni_la_SOURCES)
+DIST_SOURCES = $(libstrongswan_aesni_la_SOURCES)
 am__can_run_installinfo = \
   case $$AM_UPDATE_INFO_DIR in \
     n|no|NO) false;; \
@@ -423,21 +430,27 @@ urandom_device = @urandom_device@
 xml_CFLAGS = @xml_CFLAGS@
 xml_LIBS = @xml_LIBS@
 AM_CPPFLAGS = \
-	-I$(top_srcdir)/src/libstrongswan \
-	-I$(top_srcdir)/src/libhydra \
-	-I$(top_srcdir)/src/libcharon
-
-AM_LDFLAGS = \
-	-no-undefined
-
-ipseclib_LTLIBRARIES = libsimaka.la
-libsimaka_la_LIBADD = \
-	$(top_builddir)/src/libstrongswan/libstrongswan.la
-
-libsimaka_la_SOURCES = simaka_message.h simaka_message.c \
-  simaka_crypto.h simaka_crypto.c simaka_manager.h simaka_manager.c \
-  simaka_card.h simaka_provider.h simaka_hooks.h
-
+	-I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+	-maes \
+	-mpclmul \
+	-mssse3 \
+	$(PLUGIN_CFLAGS)
+
+ at MONOLITHIC_TRUE@noinst_LTLIBRARIES = libstrongswan-aesni.la
+ at MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-aesni.la
+libstrongswan_aesni_la_SOURCES = \
+	aesni_key.h aesni_key.c \
+	aesni_cbc.h aesni_cbc.c \
+	aesni_ctr.h aesni_ctr.c \
+	aesni_ccm.h aesni_ccm.c \
+	aesni_gcm.h aesni_gcm.c \
+	aesni_xcbc.h aesni_xcbc.c \
+	aesni_cmac.h aesni_cmac.c \
+	aesni_plugin.h aesni_plugin.c
+
+libstrongswan_aesni_la_LDFLAGS = -module -avoid-version
 all: all-am
 
 .SUFFIXES:
@@ -451,9 +464,9 @@ $(srcdir)/Makefile.in:  $(srcdir)/Makefile.am  $(am__configure_deps)
 	      exit 1;; \
 	  esac; \
 	done; \
-	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libsimaka/Makefile'; \
+	echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libstrongswan/plugins/aesni/Makefile'; \
 	$(am__cd) $(top_srcdir) && \
-	  $(AUTOMAKE) --gnu src/libsimaka/Makefile
+	  $(AUTOMAKE) --gnu src/libstrongswan/plugins/aesni/Makefile
 .PRECIOUS: Makefile
 Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
 	@case '$?' in \
@@ -473,33 +486,44 @@ $(ACLOCAL_M4):  $(am__aclocal_m4_deps)
 	cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 $(am__aclocal_m4_deps):
 
-install-ipseclibLTLIBRARIES: $(ipseclib_LTLIBRARIES)
+clean-noinstLTLIBRARIES:
+	-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+	@list='$(noinst_LTLIBRARIES)'; \
+	locs=`for p in $$list; do echo $$p; done | \
+	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+	      sort -u`; \
+	test -z "$$locs" || { \
+	  echo rm -f $${locs}; \
+	  rm -f $${locs}; \
+	}
+
+install-pluginLTLIBRARIES: $(plugin_LTLIBRARIES)
 	@$(NORMAL_INSTALL)
-	@list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
 	list2=; for p in $$list; do \
 	  if test -f $$p; then \
 	    list2="$$list2 $$p"; \
 	  else :; fi; \
 	done; \
 	test -z "$$list2" || { \
-	  echo " $(MKDIR_P) '$(DESTDIR)$(ipseclibdir)'"; \
-	  $(MKDIR_P) "$(DESTDIR)$(ipseclibdir)" || exit 1; \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(ipseclibdir)'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(ipseclibdir)"; \
+	  echo " $(MKDIR_P) '$(DESTDIR)$(plugindir)'"; \
+	  $(MKDIR_P) "$(DESTDIR)$(plugindir)" || exit 1; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(plugindir)'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(plugindir)"; \
 	}
 
-uninstall-ipseclibLTLIBRARIES:
+uninstall-pluginLTLIBRARIES:
 	@$(NORMAL_UNINSTALL)
-	@list='$(ipseclib_LTLIBRARIES)'; test -n "$(ipseclibdir)" || list=; \
+	@list='$(plugin_LTLIBRARIES)'; test -n "$(plugindir)" || list=; \
 	for p in $$list; do \
 	  $(am__strip_dir) \
-	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(ipseclibdir)/$$f'"; \
-	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(ipseclibdir)/$$f"; \
+	  echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(plugindir)/$$f'"; \
+	  $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(plugindir)/$$f"; \
 	done
 
-clean-ipseclibLTLIBRARIES:
-	-test -z "$(ipseclib_LTLIBRARIES)" || rm -f $(ipseclib_LTLIBRARIES)
-	@list='$(ipseclib_LTLIBRARIES)'; \
+clean-pluginLTLIBRARIES:
+	-test -z "$(plugin_LTLIBRARIES)" || rm -f $(plugin_LTLIBRARIES)
+	@list='$(plugin_LTLIBRARIES)'; \
 	locs=`for p in $$list; do echo $$p; done | \
 	      sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
 	      sort -u`; \
@@ -508,8 +532,8 @@ clean-ipseclibLTLIBRARIES:
 	  rm -f $${locs}; \
 	}
 
-libsimaka.la: $(libsimaka_la_OBJECTS) $(libsimaka_la_DEPENDENCIES) $(EXTRA_libsimaka_la_DEPENDENCIES) 
-	$(AM_V_CCLD)$(LINK) -rpath $(ipseclibdir) $(libsimaka_la_OBJECTS) $(libsimaka_la_LIBADD) $(LIBS)
+libstrongswan-aesni.la: $(libstrongswan_aesni_la_OBJECTS) $(libstrongswan_aesni_la_DEPENDENCIES) $(EXTRA_libstrongswan_aesni_la_DEPENDENCIES) 
+	$(AM_V_CCLD)$(libstrongswan_aesni_la_LINK) $(am_libstrongswan_aesni_la_rpath) $(libstrongswan_aesni_la_OBJECTS) $(libstrongswan_aesni_la_LIBADD) $(LIBS)
 
 mostlyclean-compile:
 	-rm -f *.$(OBJEXT)
@@ -517,9 +541,14 @@ mostlyclean-compile:
 distclean-compile:
 	-rm -f *.tab.c
 
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/simaka_crypto.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/simaka_manager.Plo at am__quote@
- at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/simaka_message.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aesni_cbc.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aesni_ccm.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aesni_cmac.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aesni_ctr.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aesni_gcm.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aesni_key.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aesni_plugin.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/aesni_xcbc.Plo at am__quote@
 
 .c.o:
 @am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -637,7 +666,7 @@ check-am: all-am
 check: check-am
 all-am: Makefile $(LTLIBRARIES)
 installdirs:
-	for dir in "$(DESTDIR)$(ipseclibdir)"; do \
+	for dir in "$(DESTDIR)$(plugindir)"; do \
 	  test -z "$$dir" || $(MKDIR_P) "$$dir"; \
 	done
 install: install-am
@@ -672,8 +701,8 @@ maintainer-clean-generic:
 	@echo "it deletes files that may require special tools to rebuild."
 clean: clean-am
 
-clean-am: clean-generic clean-ipseclibLTLIBRARIES clean-libtool \
-	mostlyclean-am
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+	clean-pluginLTLIBRARIES mostlyclean-am
 
 distclean: distclean-am
 	-rm -rf ./$(DEPDIR)
@@ -693,7 +722,7 @@ info: info-am
 
 info-am:
 
-install-data-am: install-ipseclibLTLIBRARIES
+install-data-am: install-pluginLTLIBRARIES
 
 install-dvi: install-dvi-am
 
@@ -739,24 +768,24 @@ ps: ps-am
 
 ps-am:
 
-uninstall-am: uninstall-ipseclibLTLIBRARIES
+uninstall-am: uninstall-pluginLTLIBRARIES
 
 .MAKE: install-am install-strip
 
 .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
-	clean-ipseclibLTLIBRARIES clean-libtool cscopelist-am ctags \
-	ctags-am distclean distclean-compile distclean-generic \
-	distclean-libtool distclean-tags distdir dvi dvi-am html \
-	html-am info info-am install install-am install-data \
-	install-data-am install-dvi install-dvi-am install-exec \
-	install-exec-am install-html install-html-am install-info \
-	install-info-am install-ipseclibLTLIBRARIES install-man \
-	install-pdf install-pdf-am install-ps install-ps-am \
-	install-strip installcheck installcheck-am installdirs \
-	maintainer-clean maintainer-clean-generic mostlyclean \
-	mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
-	pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
-	uninstall-ipseclibLTLIBRARIES
+	clean-libtool clean-noinstLTLIBRARIES clean-pluginLTLIBRARIES \
+	cscopelist-am ctags ctags-am distclean distclean-compile \
+	distclean-generic distclean-libtool distclean-tags distdir dvi \
+	dvi-am html html-am info info-am install install-am \
+	install-data install-data-am install-dvi install-dvi-am \
+	install-exec install-exec-am install-html install-html-am \
+	install-info install-info-am install-man install-pdf \
+	install-pdf-am install-pluginLTLIBRARIES install-ps \
+	install-ps-am install-strip installcheck installcheck-am \
+	installdirs maintainer-clean maintainer-clean-generic \
+	mostlyclean mostlyclean-compile mostlyclean-generic \
+	mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+	uninstall-am uninstall-pluginLTLIBRARIES
 
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
diff --git a/src/libstrongswan/plugins/aesni/aesni_cbc.c b/src/libstrongswan/plugins/aesni/aesni_cbc.c
new file mode 100644
index 0000000..78ada76
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_cbc.c
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "aesni_cbc.h"
+#include "aesni_key.h"
+
+/**
+ * Pipeline parallelism we use for CBC decryption
+ */
+#define CBC_DECRYPT_PARALLELISM 4
+
+typedef struct private_aesni_cbc_t private_aesni_cbc_t;
+
+/**
+ * CBC en/decryption method type
+ */
+typedef void (*aesni_cbc_fn_t)(aesni_key_t*, u_int, u_char*, u_char*, u_char*);
+
+/**
+ * Private data of an aesni_cbc_t object.
+ */
+struct private_aesni_cbc_t {
+
+	/**
+	 * Public aesni_cbc_t interface.
+	 */
+	aesni_cbc_t public;
+
+	/**
+	 * Key size
+	 */
+	u_int key_size;
+
+	/**
+	 * Encryption key schedule
+	 */
+	aesni_key_t *ekey;
+
+	/**
+	 * Decryption key schedule
+	 */
+	aesni_key_t *dkey;
+
+	/**
+	 * Encryption method
+	 */
+	aesni_cbc_fn_t encrypt;
+
+	/**
+	 * Decryption method
+	 */
+	aesni_cbc_fn_t decrypt;
+};
+
+/**
+ * AES-128 CBC encryption
+ */
+static void encrypt_cbc128(aesni_key_t *key, u_int blocks, u_char *in,
+						   u_char *iv, u_char *out)
+{
+	__m128i *ks, t, fb, *bi, *bo;
+	int i;
+
+	ks = key->schedule;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	fb = _mm_loadu_si128((__m128i*)iv);
+	for (i = 0; i < blocks; i++)
+	{
+		t = _mm_loadu_si128(bi + i);
+		fb = _mm_xor_si128(t, fb);
+		fb = _mm_xor_si128(fb, ks[0]);
+
+		fb = _mm_aesenc_si128(fb, ks[1]);
+		fb = _mm_aesenc_si128(fb, ks[2]);
+		fb = _mm_aesenc_si128(fb, ks[3]);
+		fb = _mm_aesenc_si128(fb, ks[4]);
+		fb = _mm_aesenc_si128(fb, ks[5]);
+		fb = _mm_aesenc_si128(fb, ks[6]);
+		fb = _mm_aesenc_si128(fb, ks[7]);
+		fb = _mm_aesenc_si128(fb, ks[8]);
+		fb = _mm_aesenc_si128(fb, ks[9]);
+
+		fb = _mm_aesenclast_si128(fb, ks[10]);
+		_mm_storeu_si128(bo + i, fb);
+	}
+}
+
+/**
+ * AES-128 CBC decryption
+ */
+static void decrypt_cbc128(aesni_key_t *key, u_int blocks, u_char *in,
+						   u_char *iv, u_char *out)
+{
+	__m128i *ks, last, *bi, *bo;
+	__m128i t1, t2, t3, t4;
+	__m128i f1, f2, f3, f4;
+	u_int i, pblocks;
+
+	ks = key->schedule;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+	pblocks = blocks - (blocks % CBC_DECRYPT_PARALLELISM);
+
+	f1 = _mm_loadu_si128((__m128i*)iv);
+
+	for (i = 0; i < pblocks; i += CBC_DECRYPT_PARALLELISM)
+	{
+		t1 = _mm_loadu_si128(bi + i + 0);
+		t2 = _mm_loadu_si128(bi + i + 1);
+		t3 = _mm_loadu_si128(bi + i + 2);
+		t4 = _mm_loadu_si128(bi + i + 3);
+
+		f2 = t1;
+		f3 = t2;
+		f4 = t3;
+		last = t4;
+
+		t1 = _mm_xor_si128(t1, ks[0]);
+		t2 = _mm_xor_si128(t2, ks[0]);
+		t3 = _mm_xor_si128(t3, ks[0]);
+		t4 = _mm_xor_si128(t4, ks[0]);
+
+		t1 = _mm_aesdec_si128(t1, ks[1]);
+		t2 = _mm_aesdec_si128(t2, ks[1]);
+		t3 = _mm_aesdec_si128(t3, ks[1]);
+		t4 = _mm_aesdec_si128(t4, ks[1]);
+		t1 = _mm_aesdec_si128(t1, ks[2]);
+		t2 = _mm_aesdec_si128(t2, ks[2]);
+		t3 = _mm_aesdec_si128(t3, ks[2]);
+		t4 = _mm_aesdec_si128(t4, ks[2]);
+		t1 = _mm_aesdec_si128(t1, ks[3]);
+		t2 = _mm_aesdec_si128(t2, ks[3]);
+		t3 = _mm_aesdec_si128(t3, ks[3]);
+		t4 = _mm_aesdec_si128(t4, ks[3]);
+		t1 = _mm_aesdec_si128(t1, ks[4]);
+		t2 = _mm_aesdec_si128(t2, ks[4]);
+		t3 = _mm_aesdec_si128(t3, ks[4]);
+		t4 = _mm_aesdec_si128(t4, ks[4]);
+		t1 = _mm_aesdec_si128(t1, ks[5]);
+		t2 = _mm_aesdec_si128(t2, ks[5]);
+		t3 = _mm_aesdec_si128(t3, ks[5]);
+		t4 = _mm_aesdec_si128(t4, ks[5]);
+		t1 = _mm_aesdec_si128(t1, ks[6]);
+		t2 = _mm_aesdec_si128(t2, ks[6]);
+		t3 = _mm_aesdec_si128(t3, ks[6]);
+		t4 = _mm_aesdec_si128(t4, ks[6]);
+		t1 = _mm_aesdec_si128(t1, ks[7]);
+		t2 = _mm_aesdec_si128(t2, ks[7]);
+		t3 = _mm_aesdec_si128(t3, ks[7]);
+		t4 = _mm_aesdec_si128(t4, ks[7]);
+		t1 = _mm_aesdec_si128(t1, ks[8]);
+		t2 = _mm_aesdec_si128(t2, ks[8]);
+		t3 = _mm_aesdec_si128(t3, ks[8]);
+		t4 = _mm_aesdec_si128(t4, ks[8]);
+		t1 = _mm_aesdec_si128(t1, ks[9]);
+		t2 = _mm_aesdec_si128(t2, ks[9]);
+		t3 = _mm_aesdec_si128(t3, ks[9]);
+		t4 = _mm_aesdec_si128(t4, ks[9]);
+
+		t1 = _mm_aesdeclast_si128(t1, ks[10]);
+		t2 = _mm_aesdeclast_si128(t2, ks[10]);
+		t3 = _mm_aesdeclast_si128(t3, ks[10]);
+		t4 = _mm_aesdeclast_si128(t4, ks[10]);
+		t1 = _mm_xor_si128(t1, f1);
+		t2 = _mm_xor_si128(t2, f2);
+		t3 = _mm_xor_si128(t3, f3);
+		t4 = _mm_xor_si128(t4, f4);
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+		f1 = last;
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		last = _mm_loadu_si128(bi + i);
+		t1 = _mm_xor_si128(last, ks[0]);
+
+		t1 = _mm_aesdec_si128(t1, ks[1]);
+		t1 = _mm_aesdec_si128(t1, ks[2]);
+		t1 = _mm_aesdec_si128(t1, ks[3]);
+		t1 = _mm_aesdec_si128(t1, ks[4]);
+		t1 = _mm_aesdec_si128(t1, ks[5]);
+		t1 = _mm_aesdec_si128(t1, ks[6]);
+		t1 = _mm_aesdec_si128(t1, ks[7]);
+		t1 = _mm_aesdec_si128(t1, ks[8]);
+		t1 = _mm_aesdec_si128(t1, ks[9]);
+
+		t1 = _mm_aesdeclast_si128(t1, ks[10]);
+		t1 = _mm_xor_si128(t1, f1);
+		_mm_storeu_si128(bo + i, t1);
+		f1 = last;
+	}
+}
+
+/**
+ * AES-192 CBC encryption
+ */
+static void encrypt_cbc192(aesni_key_t *key, u_int blocks, u_char *in,
+						   u_char *iv, u_char *out)
+{
+	__m128i *ks, t, fb, *bi, *bo;
+	int i;
+
+	ks = key->schedule;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	fb = _mm_loadu_si128((__m128i*)iv);
+	for (i = 0; i < blocks; i++)
+	{
+		t = _mm_loadu_si128(bi + i);
+		fb = _mm_xor_si128(t, fb);
+		fb = _mm_xor_si128(fb, ks[0]);
+
+		fb = _mm_aesenc_si128(fb, ks[1]);
+		fb = _mm_aesenc_si128(fb, ks[2]);
+		fb = _mm_aesenc_si128(fb, ks[3]);
+		fb = _mm_aesenc_si128(fb, ks[4]);
+		fb = _mm_aesenc_si128(fb, ks[5]);
+		fb = _mm_aesenc_si128(fb, ks[6]);
+		fb = _mm_aesenc_si128(fb, ks[7]);
+		fb = _mm_aesenc_si128(fb, ks[8]);
+		fb = _mm_aesenc_si128(fb, ks[9]);
+		fb = _mm_aesenc_si128(fb, ks[10]);
+		fb = _mm_aesenc_si128(fb, ks[11]);
+
+		fb = _mm_aesenclast_si128(fb, ks[12]);
+		_mm_storeu_si128(bo + i, fb);
+	}
+}
+
+/**
+ * AES-192 CBC decryption
+ */
+static void decrypt_cbc192(aesni_key_t *key, u_int blocks, u_char *in,
+						   u_char *iv, u_char *out)
+{
+	__m128i *ks, last, *bi, *bo;
+	__m128i t1, t2, t3, t4;
+	__m128i f1, f2, f3, f4;
+	u_int i, pblocks;
+
+	ks = key->schedule;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+	pblocks = blocks - (blocks % CBC_DECRYPT_PARALLELISM);
+
+	f1 = _mm_loadu_si128((__m128i*)iv);
+
+	for (i = 0; i < pblocks; i += CBC_DECRYPT_PARALLELISM)
+	{
+		t1 = _mm_loadu_si128(bi + i + 0);
+		t2 = _mm_loadu_si128(bi + i + 1);
+		t3 = _mm_loadu_si128(bi + i + 2);
+		t4 = _mm_loadu_si128(bi + i + 3);
+
+		f2 = t1;
+		f3 = t2;
+		f4 = t3;
+		last = t4;
+
+		t1 = _mm_xor_si128(t1, ks[0]);
+		t2 = _mm_xor_si128(t2, ks[0]);
+		t3 = _mm_xor_si128(t3, ks[0]);
+		t4 = _mm_xor_si128(t4, ks[0]);
+
+		t1 = _mm_aesdec_si128(t1, ks[1]);
+		t2 = _mm_aesdec_si128(t2, ks[1]);
+		t3 = _mm_aesdec_si128(t3, ks[1]);
+		t4 = _mm_aesdec_si128(t4, ks[1]);
+		t1 = _mm_aesdec_si128(t1, ks[2]);
+		t2 = _mm_aesdec_si128(t2, ks[2]);
+		t3 = _mm_aesdec_si128(t3, ks[2]);
+		t4 = _mm_aesdec_si128(t4, ks[2]);
+		t1 = _mm_aesdec_si128(t1, ks[3]);
+		t2 = _mm_aesdec_si128(t2, ks[3]);
+		t3 = _mm_aesdec_si128(t3, ks[3]);
+		t4 = _mm_aesdec_si128(t4, ks[3]);
+		t1 = _mm_aesdec_si128(t1, ks[4]);
+		t2 = _mm_aesdec_si128(t2, ks[4]);
+		t3 = _mm_aesdec_si128(t3, ks[4]);
+		t4 = _mm_aesdec_si128(t4, ks[4]);
+		t1 = _mm_aesdec_si128(t1, ks[5]);
+		t2 = _mm_aesdec_si128(t2, ks[5]);
+		t3 = _mm_aesdec_si128(t3, ks[5]);
+		t4 = _mm_aesdec_si128(t4, ks[5]);
+		t1 = _mm_aesdec_si128(t1, ks[6]);
+		t2 = _mm_aesdec_si128(t2, ks[6]);
+		t3 = _mm_aesdec_si128(t3, ks[6]);
+		t4 = _mm_aesdec_si128(t4, ks[6]);
+		t1 = _mm_aesdec_si128(t1, ks[7]);
+		t2 = _mm_aesdec_si128(t2, ks[7]);
+		t3 = _mm_aesdec_si128(t3, ks[7]);
+		t4 = _mm_aesdec_si128(t4, ks[7]);
+		t1 = _mm_aesdec_si128(t1, ks[8]);
+		t2 = _mm_aesdec_si128(t2, ks[8]);
+		t3 = _mm_aesdec_si128(t3, ks[8]);
+		t4 = _mm_aesdec_si128(t4, ks[8]);
+		t1 = _mm_aesdec_si128(t1, ks[9]);
+		t2 = _mm_aesdec_si128(t2, ks[9]);
+		t3 = _mm_aesdec_si128(t3, ks[9]);
+		t4 = _mm_aesdec_si128(t4, ks[9]);
+		t1 = _mm_aesdec_si128(t1, ks[10]);
+		t2 = _mm_aesdec_si128(t2, ks[10]);
+		t3 = _mm_aesdec_si128(t3, ks[10]);
+		t4 = _mm_aesdec_si128(t4, ks[10]);
+		t1 = _mm_aesdec_si128(t1, ks[11]);
+		t2 = _mm_aesdec_si128(t2, ks[11]);
+		t3 = _mm_aesdec_si128(t3, ks[11]);
+		t4 = _mm_aesdec_si128(t4, ks[11]);
+
+		t1 = _mm_aesdeclast_si128(t1, ks[12]);
+		t2 = _mm_aesdeclast_si128(t2, ks[12]);
+		t3 = _mm_aesdeclast_si128(t3, ks[12]);
+		t4 = _mm_aesdeclast_si128(t4, ks[12]);
+		t1 = _mm_xor_si128(t1, f1);
+		t2 = _mm_xor_si128(t2, f2);
+		t3 = _mm_xor_si128(t3, f3);
+		t4 = _mm_xor_si128(t4, f4);
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+		f1 = last;
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		last = _mm_loadu_si128(bi + i);
+		t1 = _mm_xor_si128(last, ks[0]);
+
+		t1 = _mm_aesdec_si128(t1, ks[1]);
+		t1 = _mm_aesdec_si128(t1, ks[2]);
+		t1 = _mm_aesdec_si128(t1, ks[3]);
+		t1 = _mm_aesdec_si128(t1, ks[4]);
+		t1 = _mm_aesdec_si128(t1, ks[5]);
+		t1 = _mm_aesdec_si128(t1, ks[6]);
+		t1 = _mm_aesdec_si128(t1, ks[7]);
+		t1 = _mm_aesdec_si128(t1, ks[8]);
+		t1 = _mm_aesdec_si128(t1, ks[9]);
+		t1 = _mm_aesdec_si128(t1, ks[10]);
+		t1 = _mm_aesdec_si128(t1, ks[11]);
+
+		t1 = _mm_aesdeclast_si128(t1, ks[12]);
+		t1 = _mm_xor_si128(t1, f1);
+		_mm_storeu_si128(bo + i, t1);
+		f1 = last;
+	}
+}
+
+/**
+ * AES-256 CBC encryption
+ */
+static void encrypt_cbc256(aesni_key_t *key, u_int blocks, u_char *in,
+						   u_char *iv, u_char *out)
+{
+	__m128i *ks, t, fb, *bi, *bo;
+	int i;
+
+	ks = key->schedule;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	fb = _mm_loadu_si128((__m128i*)iv);
+	for (i = 0; i < blocks; i++)
+	{
+		t = _mm_loadu_si128(bi + i);
+		fb = _mm_xor_si128(t, fb);
+		fb = _mm_xor_si128(fb, ks[0]);
+
+		fb = _mm_aesenc_si128(fb, ks[1]);
+		fb = _mm_aesenc_si128(fb, ks[2]);
+		fb = _mm_aesenc_si128(fb, ks[3]);
+		fb = _mm_aesenc_si128(fb, ks[4]);
+		fb = _mm_aesenc_si128(fb, ks[5]);
+		fb = _mm_aesenc_si128(fb, ks[6]);
+		fb = _mm_aesenc_si128(fb, ks[7]);
+		fb = _mm_aesenc_si128(fb, ks[8]);
+		fb = _mm_aesenc_si128(fb, ks[9]);
+		fb = _mm_aesenc_si128(fb, ks[10]);
+		fb = _mm_aesenc_si128(fb, ks[11]);
+		fb = _mm_aesenc_si128(fb, ks[12]);
+		fb = _mm_aesenc_si128(fb, ks[13]);
+
+		fb = _mm_aesenclast_si128(fb, ks[14]);
+		_mm_storeu_si128(bo + i, fb);
+	}
+}
+
+/**
+ * AES-256 CBC decryption
+ */
+static void decrypt_cbc256(aesni_key_t *key, u_int blocks, u_char *in,
+						   u_char *iv, u_char *out)
+{
+	__m128i *ks, last, *bi, *bo;
+	__m128i t1, t2, t3, t4;
+	__m128i f1, f2, f3, f4;
+	u_int i, pblocks;
+
+	ks = key->schedule;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+	pblocks = blocks - (blocks % CBC_DECRYPT_PARALLELISM);
+
+	f1 = _mm_loadu_si128((__m128i*)iv);
+
+	for (i = 0; i < pblocks; i += CBC_DECRYPT_PARALLELISM)
+	{
+		t1 = _mm_loadu_si128(bi + i + 0);
+		t2 = _mm_loadu_si128(bi + i + 1);
+		t3 = _mm_loadu_si128(bi + i + 2);
+		t4 = _mm_loadu_si128(bi + i + 3);
+
+		f2 = t1;
+		f3 = t2;
+		f4 = t3;
+		last = t4;
+
+		t1 = _mm_xor_si128(t1, ks[0]);
+		t2 = _mm_xor_si128(t2, ks[0]);
+		t3 = _mm_xor_si128(t3, ks[0]);
+		t4 = _mm_xor_si128(t4, ks[0]);
+
+		t1 = _mm_aesdec_si128(t1, ks[1]);
+		t2 = _mm_aesdec_si128(t2, ks[1]);
+		t3 = _mm_aesdec_si128(t3, ks[1]);
+		t4 = _mm_aesdec_si128(t4, ks[1]);
+		t1 = _mm_aesdec_si128(t1, ks[2]);
+		t2 = _mm_aesdec_si128(t2, ks[2]);
+		t3 = _mm_aesdec_si128(t3, ks[2]);
+		t4 = _mm_aesdec_si128(t4, ks[2]);
+		t1 = _mm_aesdec_si128(t1, ks[3]);
+		t2 = _mm_aesdec_si128(t2, ks[3]);
+		t3 = _mm_aesdec_si128(t3, ks[3]);
+		t4 = _mm_aesdec_si128(t4, ks[3]);
+		t1 = _mm_aesdec_si128(t1, ks[4]);
+		t2 = _mm_aesdec_si128(t2, ks[4]);
+		t3 = _mm_aesdec_si128(t3, ks[4]);
+		t4 = _mm_aesdec_si128(t4, ks[4]);
+		t1 = _mm_aesdec_si128(t1, ks[5]);
+		t2 = _mm_aesdec_si128(t2, ks[5]);
+		t3 = _mm_aesdec_si128(t3, ks[5]);
+		t4 = _mm_aesdec_si128(t4, ks[5]);
+		t1 = _mm_aesdec_si128(t1, ks[6]);
+		t2 = _mm_aesdec_si128(t2, ks[6]);
+		t3 = _mm_aesdec_si128(t3, ks[6]);
+		t4 = _mm_aesdec_si128(t4, ks[6]);
+		t1 = _mm_aesdec_si128(t1, ks[7]);
+		t2 = _mm_aesdec_si128(t2, ks[7]);
+		t3 = _mm_aesdec_si128(t3, ks[7]);
+		t4 = _mm_aesdec_si128(t4, ks[7]);
+		t1 = _mm_aesdec_si128(t1, ks[8]);
+		t2 = _mm_aesdec_si128(t2, ks[8]);
+		t3 = _mm_aesdec_si128(t3, ks[8]);
+		t4 = _mm_aesdec_si128(t4, ks[8]);
+		t1 = _mm_aesdec_si128(t1, ks[9]);
+		t2 = _mm_aesdec_si128(t2, ks[9]);
+		t3 = _mm_aesdec_si128(t3, ks[9]);
+		t4 = _mm_aesdec_si128(t4, ks[9]);
+		t1 = _mm_aesdec_si128(t1, ks[10]);
+		t2 = _mm_aesdec_si128(t2, ks[10]);
+		t3 = _mm_aesdec_si128(t3, ks[10]);
+		t4 = _mm_aesdec_si128(t4, ks[10]);
+		t1 = _mm_aesdec_si128(t1, ks[11]);
+		t2 = _mm_aesdec_si128(t2, ks[11]);
+		t3 = _mm_aesdec_si128(t3, ks[11]);
+		t4 = _mm_aesdec_si128(t4, ks[11]);
+		t1 = _mm_aesdec_si128(t1, ks[12]);
+		t2 = _mm_aesdec_si128(t2, ks[12]);
+		t3 = _mm_aesdec_si128(t3, ks[12]);
+		t4 = _mm_aesdec_si128(t4, ks[12]);
+		t1 = _mm_aesdec_si128(t1, ks[13]);
+		t2 = _mm_aesdec_si128(t2, ks[13]);
+		t3 = _mm_aesdec_si128(t3, ks[13]);
+		t4 = _mm_aesdec_si128(t4, ks[13]);
+
+		t1 = _mm_aesdeclast_si128(t1, ks[14]);
+		t2 = _mm_aesdeclast_si128(t2, ks[14]);
+		t3 = _mm_aesdeclast_si128(t3, ks[14]);
+		t4 = _mm_aesdeclast_si128(t4, ks[14]);
+		t1 = _mm_xor_si128(t1, f1);
+		t2 = _mm_xor_si128(t2, f2);
+		t3 = _mm_xor_si128(t3, f3);
+		t4 = _mm_xor_si128(t4, f4);
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+		f1 = last;
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		last = _mm_loadu_si128(bi + i);
+		t1 = _mm_xor_si128(last, ks[0]);
+
+		t1 = _mm_aesdec_si128(t1, ks[1]);
+		t1 = _mm_aesdec_si128(t1, ks[2]);
+		t1 = _mm_aesdec_si128(t1, ks[3]);
+		t1 = _mm_aesdec_si128(t1, ks[4]);
+		t1 = _mm_aesdec_si128(t1, ks[5]);
+		t1 = _mm_aesdec_si128(t1, ks[6]);
+		t1 = _mm_aesdec_si128(t1, ks[7]);
+		t1 = _mm_aesdec_si128(t1, ks[8]);
+		t1 = _mm_aesdec_si128(t1, ks[9]);
+		t1 = _mm_aesdec_si128(t1, ks[10]);
+		t1 = _mm_aesdec_si128(t1, ks[11]);
+		t1 = _mm_aesdec_si128(t1, ks[12]);
+		t1 = _mm_aesdec_si128(t1, ks[13]);
+
+		t1 = _mm_aesdeclast_si128(t1, ks[14]);
+		t1 = _mm_xor_si128(t1, f1);
+		_mm_storeu_si128(bo + i, t1);
+		f1 = last;
+	}
+}
+
+/**
+ * Do inline or allocated de/encryption using key schedule
+ */
+static bool crypt(aesni_cbc_fn_t fn, aesni_key_t *key,
+				  chunk_t data, chunk_t iv, chunk_t *out)
+{
+	u_char *buf;
+
+	if (!key || iv.len != AES_BLOCK_SIZE || data.len % AES_BLOCK_SIZE)
+	{
+		return FALSE;
+	}
+	if (out)
+	{
+		*out = chunk_alloc(data.len);
+		buf = out->ptr;
+	}
+	else
+	{
+		buf = data.ptr;
+	}
+	fn(key, data.len / AES_BLOCK_SIZE, data.ptr, iv.ptr, buf);
+	return TRUE;
+}
+
+METHOD(crypter_t, encrypt, bool,
+	private_aesni_cbc_t *this, chunk_t data, chunk_t iv, chunk_t *encrypted)
+{
+	return crypt(this->encrypt, this->ekey, data, iv, encrypted);
+}
+
+METHOD(crypter_t, decrypt, bool,
+	private_aesni_cbc_t *this, chunk_t data, chunk_t iv, chunk_t *decrypted)
+{
+	return crypt(this->decrypt, this->dkey, data, iv, decrypted);
+}
+
+METHOD(crypter_t, get_block_size, size_t,
+	private_aesni_cbc_t *this)
+{
+	return AES_BLOCK_SIZE;
+}
+
+METHOD(crypter_t, get_iv_size, size_t,
+	private_aesni_cbc_t *this)
+{
+	return AES_BLOCK_SIZE;
+}
+
+METHOD(crypter_t, get_key_size, size_t,
+	private_aesni_cbc_t *this)
+{
+	return this->key_size;
+}
+
+METHOD(crypter_t, set_key, bool,
+	private_aesni_cbc_t *this, chunk_t key)
+{
+	if (key.len != this->key_size)
+	{
+		return FALSE;
+	}
+
+	DESTROY_IF(this->ekey);
+	DESTROY_IF(this->dkey);
+
+	this->ekey = aesni_key_create(TRUE, key);
+	this->dkey = aesni_key_create(FALSE, key);
+
+	return this->ekey && this->dkey;
+}
+
+METHOD(crypter_t, destroy, void,
+	private_aesni_cbc_t *this)
+{
+	DESTROY_IF(this->ekey);
+	DESTROY_IF(this->dkey);
+	free_align(this);
+}
+
+/**
+ * See header
+ */
+aesni_cbc_t *aesni_cbc_create(encryption_algorithm_t algo, size_t key_size)
+{
+	private_aesni_cbc_t *this;
+
+	if (algo != ENCR_AES_CBC)
+	{
+		return NULL;
+	}
+	switch (key_size)
+	{
+		case 0:
+			key_size = 16;
+			break;
+		case 16:
+		case 24:
+		case 32:
+			break;
+		default:
+			return NULL;
+	}
+
+	INIT_ALIGN(this, sizeof(__m128i),
+		.public = {
+			.crypter = {
+				.encrypt = _encrypt,
+				.decrypt = _decrypt,
+				.get_block_size = _get_block_size,
+				.get_iv_size = _get_iv_size,
+				.get_key_size = _get_key_size,
+				.set_key = _set_key,
+				.destroy = _destroy,
+			},
+		},
+		.key_size = key_size,
+	);
+
+	switch (key_size)
+	{
+		case 16:
+			this->encrypt = encrypt_cbc128;
+			this->decrypt = decrypt_cbc128;
+			break;
+		case 24:
+			this->encrypt = encrypt_cbc192;
+			this->decrypt = decrypt_cbc192;
+			break;
+		case 32:
+			this->encrypt = encrypt_cbc256;
+			this->decrypt = decrypt_cbc256;
+			break;
+	}
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/plugins/aesni/aesni_cbc.h b/src/libstrongswan/plugins/aesni/aesni_cbc.h
new file mode 100644
index 0000000..c004ec6
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_cbc.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup aesni_cbc aesni_cbc
+ * @{ @ingroup aesni
+ */
+
+#ifndef AESNI_CBC_H_
+#define AESNI_CBC_H_
+
+#include <library.h>
+
+typedef struct aesni_cbc_t aesni_cbc_t;
+
+/**
+ * CBC mode crypter using AES-NI
+ */
+struct aesni_cbc_t {
+
+	/**
+	 * Implements crypter interface
+	 */
+	crypter_t crypter;
+};
+
+/**
+ * Create a aesni_cbc instance.
+ *
+ * @param algo			encryption algorithm, AES_ENCR_CBC
+ * @param key_size		AES key size, in bytes
+ * @return				AES-CBC crypter, NULL if not supported
+ */
+aesni_cbc_t *aesni_cbc_create(encryption_algorithm_t algo, size_t key_size);
+
+#endif /** AESNI_CBC_H_ @}*/
diff --git a/src/libstrongswan/plugins/aesni/aesni_ccm.c b/src/libstrongswan/plugins/aesni/aesni_ccm.c
new file mode 100644
index 0000000..d523bc1
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_ccm.c
@@ -0,0 +1,914 @@
+/*
+ * Copyright (C) 2010-2015 Martin Willi
+ * Copyright (C) 2010-2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "aesni_ccm.h"
+#include "aesni_key.h"
+
+#include <crypto/iv/iv_gen_seq.h>
+
+#include <tmmintrin.h>
+
+#define SALT_SIZE 3
+#define IV_SIZE 8
+#define NONCE_SIZE (SALT_SIZE + IV_SIZE) /* 11 */
+#define Q_SIZE (AES_BLOCK_SIZE - NONCE_SIZE - 1) /* 4 */
+
+typedef struct private_aesni_ccm_t private_aesni_ccm_t;
+
+/**
+ * CCM en/decryption method type
+ */
+typedef void (*aesni_ccm_fn_t)(private_aesni_ccm_t*, size_t, u_char*, u_char*,
+							   u_char*, size_t, u_char*, u_char*);
+
+/**
+ * Private data of an aesni_ccm_t object.
+ */
+struct private_aesni_ccm_t {
+
+	/**
+	 * Public aesni_ccm_t interface.
+	 */
+	aesni_ccm_t public;
+
+	/**
+	 * Encryption key schedule
+	 */
+	aesni_key_t *key;
+
+	/**
+	 * IV generator.
+	 */
+	iv_gen_t *iv_gen;
+
+	/**
+	 * Length of the integrity check value
+	 */
+	size_t icv_size;
+
+	/**
+	 * Length of the key in bytes
+	 */
+	size_t key_size;
+
+	/**
+	 * CCM encryption function
+	 */
+	aesni_ccm_fn_t encrypt;
+
+	/**
+	 * CCM decryption function
+	 */
+	aesni_ccm_fn_t decrypt;
+
+	/**
+	 * salt to add to nonce
+	 */
+	u_char salt[SALT_SIZE];
+};
+
+/**
+ * First block with control information
+ */
+typedef struct __attribute__((packed)) {
+	BITFIELD4(u_int8_t,
+		/* size of p length field q, as q-1 */
+		q_len: 3,
+		/* size of our ICV t, as (t-2)/2 */
+		t_len: 3,
+		/* do we have associated data */
+		assoc: 1,
+		reserved: 1,
+	) flags;
+	/* nonce value */
+	struct __attribute__((packed)) {
+		u_char salt[SALT_SIZE];
+		u_char iv[IV_SIZE];
+	} nonce;
+	/* length of plain text, q */
+	u_char q[Q_SIZE];
+} b0_t;
+
+/**
+ * Counter block
+ */
+typedef struct __attribute__((packed)) {
+	BITFIELD3(u_int8_t,
+		/* size of p length field q, as q-1 */
+		q_len: 3,
+		zero: 3,
+		reserved: 2,
+	) flags;
+	/* nonce value */
+	struct __attribute__((packed)) {
+		u_char salt[SALT_SIZE];
+		u_char iv[IV_SIZE];
+	} nonce;
+	/* counter value */
+	u_char i[Q_SIZE];
+} ctr_t;
+
+/**
+ * Build the first block B0
+ */
+static void build_b0(private_aesni_ccm_t *this, size_t len, size_t alen,
+					 u_char *iv, void *out)
+{
+	b0_t *block = out;
+
+	block->flags.reserved = 0;
+	block->flags.assoc = alen ? 1 : 0;
+	block->flags.t_len = (this->icv_size - 2) / 2;
+	block->flags.q_len = Q_SIZE - 1;
+	memcpy(block->nonce.salt, this->salt, SALT_SIZE);
+	memcpy(block->nonce.iv, iv, IV_SIZE);
+	htoun32(block->q, len);
+}
+
+/**
+ * Build a counter block for counter i
+ */
+static void build_ctr(private_aesni_ccm_t *this, u_int32_t i, u_char *iv,
+					  void *out)
+{
+	ctr_t *ctr = out;
+
+	ctr->flags.reserved = 0;
+	ctr->flags.zero = 0;
+	ctr->flags.q_len = Q_SIZE - 1;
+	memcpy(ctr->nonce.salt, this->salt, SALT_SIZE);
+	memcpy(ctr->nonce.iv, iv, IV_SIZE);
+	htoun32(ctr->i, i);
+}
+
+/**
+ * Calculate the ICV for the b0 and associated data
+ */
+static __m128i icv_header(private_aesni_ccm_t *this, size_t len, u_char *iv,
+						  u_int16_t alen, u_char *assoc)
+{
+	__m128i *ks, b, t, c;
+	u_int i, round, blocks, rem;
+
+	ks = this->key->schedule;
+	build_b0(this, len, alen, iv, &b);
+	c = _mm_loadu_si128(&b);
+	c = _mm_xor_si128(c, ks[0]);
+	for (round = 1; round < this->key->rounds; round++)
+	{
+		c = _mm_aesenc_si128(c, ks[round]);
+	}
+	c = _mm_aesenclast_si128(c, ks[this->key->rounds]);
+
+	if (alen)
+	{
+		blocks = (alen + sizeof(alen)) / AES_BLOCK_SIZE;
+		rem = (alen + sizeof(alen)) % AES_BLOCK_SIZE;
+		if (rem)
+		{
+			blocks++;
+		}
+		for (i = 0; i < blocks; i++)
+		{
+			if (i == 0)
+			{	/* first block */
+				memset(&b, 0, sizeof(b));
+				htoun16(&b, alen);
+				memcpy(((u_char*)&b) + sizeof(alen), assoc,
+					   min(alen, sizeof(b) - sizeof(alen)));
+				t = _mm_loadu_si128(&b);
+			}
+			else if (i == blocks - 1 && rem)
+			{	/* last block with padding */
+				memset(&b, 0, sizeof(b));
+				memcpy(&b, ((__m128i*)(assoc - sizeof(alen))) + i, rem);
+				t = _mm_loadu_si128(&b);
+			}
+			else
+			{	/* full block */
+				t = _mm_loadu_si128(((__m128i*)(assoc - sizeof(alen))) + i);
+			}
+			c = _mm_xor_si128(t, c);
+			c = _mm_xor_si128(c, ks[0]);
+			for (round = 1; round < this->key->rounds; round++)
+			{
+				c = _mm_aesenc_si128(c, ks[round]);
+			}
+			c = _mm_aesenclast_si128(c, ks[this->key->rounds]);
+		}
+	}
+	return c;
+}
+
+/**
+ * En-/Decrypt the ICV, trim and store it
+ */
+static void crypt_icv(private_aesni_ccm_t *this, u_char *iv,
+					  __m128i c, u_char *icv)
+{
+	__m128i *ks, b, t;
+	u_int round;
+
+	ks = this->key->schedule;
+	build_ctr(this, 0, iv, &b);
+
+	t = _mm_loadu_si128(&b);
+	t = _mm_xor_si128(t, ks[0]);
+	for (round = 1; round < this->key->rounds; round++)
+	{
+		t = _mm_aesenc_si128(t, ks[round]);
+	}
+	t = _mm_aesenclast_si128(t, ks[this->key->rounds]);
+
+	t = _mm_xor_si128(t, c);
+
+	_mm_storeu_si128(&b, t);
+	memcpy(icv, &b, this->icv_size);
+}
+
+/**
+ * Do big-endian increment on x
+ */
+static inline __m128i increment_be(__m128i x)
+{
+	__m128i swap;
+
+	swap = _mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
+
+	x = _mm_shuffle_epi8(x, swap);
+	x = _mm_add_epi64(x, _mm_set_epi32(0, 0, 0, 1));
+	x = _mm_shuffle_epi8(x, swap);
+
+	return x;
+}
+
+/**
+ * Encrypt a remaining incomplete block
+ */
+static __m128i encrypt_ccm_rem(aesni_key_t *key, u_int rem, __m128i state,
+							   void *in, void *out, __m128i c)
+{
+	__m128i *ks, t, b, d;
+	u_int round;
+
+	ks = key->schedule;
+	memset(&b, 0, sizeof(b));
+	memcpy(&b, in, rem);
+	d = _mm_loadu_si128(&b);
+
+	c = _mm_xor_si128(d, c);
+	c = _mm_xor_si128(c, ks[0]);
+	t = _mm_xor_si128(state, ks[0]);
+	for (round = 1; round < key->rounds; round++)
+	{
+		c = _mm_aesenc_si128(c, ks[round]);
+		t = _mm_aesenc_si128(t, ks[round]);
+	}
+	c = _mm_aesenclast_si128(c, ks[key->rounds]);
+	t = _mm_aesenclast_si128(t, ks[key->rounds]);
+
+	t = _mm_xor_si128(t, d);
+	_mm_storeu_si128(&b, t);
+
+	memcpy(out, &b, rem);
+
+	return c;
+}
+
+/**
+ * Decrypt a remaining incomplete block
+ */
+static __m128i decrypt_ccm_rem(aesni_key_t *key, u_int rem, __m128i state,
+							   void *in, void *out, __m128i c)
+{
+	__m128i *ks, t, b, d;
+	u_int round;
+
+	ks = key->schedule;
+	memset(&b, 0, sizeof(b));
+	memcpy(&b, in, rem);
+	d = _mm_loadu_si128(&b);
+
+	t = _mm_xor_si128(state, ks[0]);
+	for (round = 1; round < key->rounds; round++)
+	{
+		t = _mm_aesenc_si128(t, ks[round]);
+	}
+	t = _mm_aesenclast_si128(t, ks[key->rounds]);
+	t = _mm_xor_si128(t, d);
+	_mm_storeu_si128(&b, t);
+
+	memset((u_char*)&b + rem, 0, sizeof(b) - rem);
+	t = _mm_loadu_si128(&b);
+	c = _mm_xor_si128(t, c);
+	c = _mm_xor_si128(c, ks[0]);
+	for (round = 1; round < key->rounds; round++)
+	{
+		c = _mm_aesenc_si128(c, ks[round]);
+	}
+	c = _mm_aesenclast_si128(c, ks[key->rounds]);
+
+	memcpy(out, &b, rem);
+
+	return c;
+}
+
+/**
+ * AES-128 CCM encryption/ICV generation
+ */
+static void encrypt_ccm128(private_aesni_ccm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i *ks, d, t, c, b, state, *bi, *bo;
+	u_int blocks, rem, i;
+
+	c = icv_header(this, len, iv, alen, assoc);
+	build_ctr(this, 1, iv, &b);
+	state = _mm_load_si128(&b);
+	blocks = len / AES_BLOCK_SIZE;
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < blocks; i++)
+	{
+		d = _mm_loadu_si128(bi + i);
+
+		c = _mm_xor_si128(d, c);
+		c = _mm_xor_si128(c, ks[0]);
+		t = _mm_xor_si128(state, ks[0]);
+
+		c = _mm_aesenc_si128(c, ks[1]);
+		t = _mm_aesenc_si128(t, ks[1]);
+		c = _mm_aesenc_si128(c, ks[2]);
+		t = _mm_aesenc_si128(t, ks[2]);
+		c = _mm_aesenc_si128(c, ks[3]);
+		t = _mm_aesenc_si128(t, ks[3]);
+		c = _mm_aesenc_si128(c, ks[4]);
+		t = _mm_aesenc_si128(t, ks[4]);
+		c = _mm_aesenc_si128(c, ks[5]);
+		t = _mm_aesenc_si128(t, ks[5]);
+		c = _mm_aesenc_si128(c, ks[6]);
+		t = _mm_aesenc_si128(t, ks[6]);
+		c = _mm_aesenc_si128(c, ks[7]);
+		t = _mm_aesenc_si128(t, ks[7]);
+		c = _mm_aesenc_si128(c, ks[8]);
+		t = _mm_aesenc_si128(t, ks[8]);
+		c = _mm_aesenc_si128(c, ks[9]);
+		t = _mm_aesenc_si128(t, ks[9]);
+
+		c = _mm_aesenclast_si128(c, ks[10]);
+		t = _mm_aesenclast_si128(t, ks[10]);
+
+		t = _mm_xor_si128(t, d);
+		_mm_storeu_si128(bo + i, t);
+
+		state = increment_be(state);
+	}
+
+	if (rem)
+	{
+		c = encrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
+	}
+	crypt_icv(this, iv, c, icv);
+}
+
+/**
+ * AES-128 CCM decryption/ICV generation
+ */
+static void decrypt_ccm128(private_aesni_ccm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i *ks, d, t, c, b, state, *bi, *bo;
+	u_int blocks, rem, i;
+
+	c = icv_header(this, len, iv, alen, assoc);
+	build_ctr(this, 1, iv, &b);
+	state = _mm_load_si128(&b);
+	blocks = len / AES_BLOCK_SIZE;
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < blocks; i++)
+	{
+		d = _mm_loadu_si128(bi + i);
+
+		t = _mm_xor_si128(state, ks[0]);
+
+		t = _mm_aesenc_si128(t, ks[1]);
+		t = _mm_aesenc_si128(t, ks[2]);
+		t = _mm_aesenc_si128(t, ks[3]);
+		t = _mm_aesenc_si128(t, ks[4]);
+		t = _mm_aesenc_si128(t, ks[5]);
+		t = _mm_aesenc_si128(t, ks[6]);
+		t = _mm_aesenc_si128(t, ks[7]);
+		t = _mm_aesenc_si128(t, ks[8]);
+		t = _mm_aesenc_si128(t, ks[9]);
+
+		t = _mm_aesenclast_si128(t, ks[10]);
+		t = _mm_xor_si128(t, d);
+		_mm_storeu_si128(bo + i, t);
+
+		c = _mm_xor_si128(t, c);
+		c = _mm_xor_si128(c, ks[0]);
+
+		c = _mm_aesenc_si128(c, ks[1]);
+		c = _mm_aesenc_si128(c, ks[2]);
+		c = _mm_aesenc_si128(c, ks[3]);
+		c = _mm_aesenc_si128(c, ks[4]);
+		c = _mm_aesenc_si128(c, ks[5]);
+		c = _mm_aesenc_si128(c, ks[6]);
+		c = _mm_aesenc_si128(c, ks[7]);
+		c = _mm_aesenc_si128(c, ks[8]);
+		c = _mm_aesenc_si128(c, ks[9]);
+
+		c = _mm_aesenclast_si128(c, ks[10]);
+
+		state = increment_be(state);
+	}
+
+	if (rem)
+	{
+		c = decrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
+	}
+	crypt_icv(this, iv, c, icv);
+}
+
+/**
+ * AES-192 CCM encryption/ICV generation
+ */
+static void encrypt_ccm192(private_aesni_ccm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i *ks, d, t, c, b, state, *bi, *bo;
+	u_int blocks, rem, i;
+
+	c = icv_header(this, len, iv, alen, assoc);
+	build_ctr(this, 1, iv, &b);
+	state = _mm_load_si128(&b);
+	blocks = len / AES_BLOCK_SIZE;
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < blocks; i++)
+	{
+		d = _mm_loadu_si128(bi + i);
+
+		c = _mm_xor_si128(d, c);
+		c = _mm_xor_si128(c, ks[0]);
+		t = _mm_xor_si128(state, ks[0]);
+
+		c = _mm_aesenc_si128(c, ks[1]);
+		t = _mm_aesenc_si128(t, ks[1]);
+		c = _mm_aesenc_si128(c, ks[2]);
+		t = _mm_aesenc_si128(t, ks[2]);
+		c = _mm_aesenc_si128(c, ks[3]);
+		t = _mm_aesenc_si128(t, ks[3]);
+		c = _mm_aesenc_si128(c, ks[4]);
+		t = _mm_aesenc_si128(t, ks[4]);
+		c = _mm_aesenc_si128(c, ks[5]);
+		t = _mm_aesenc_si128(t, ks[5]);
+		c = _mm_aesenc_si128(c, ks[6]);
+		t = _mm_aesenc_si128(t, ks[6]);
+		c = _mm_aesenc_si128(c, ks[7]);
+		t = _mm_aesenc_si128(t, ks[7]);
+		c = _mm_aesenc_si128(c, ks[8]);
+		t = _mm_aesenc_si128(t, ks[8]);
+		c = _mm_aesenc_si128(c, ks[9]);
+		t = _mm_aesenc_si128(t, ks[9]);
+		c = _mm_aesenc_si128(c, ks[10]);
+		t = _mm_aesenc_si128(t, ks[10]);
+		c = _mm_aesenc_si128(c, ks[11]);
+		t = _mm_aesenc_si128(t, ks[11]);
+
+		c = _mm_aesenclast_si128(c, ks[12]);
+		t = _mm_aesenclast_si128(t, ks[12]);
+
+		t = _mm_xor_si128(t, d);
+		_mm_storeu_si128(bo + i, t);
+
+		state = increment_be(state);
+	}
+
+	if (rem)
+	{
+		c = encrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
+	}
+	crypt_icv(this, iv, c, icv);
+}
+
+/**
+ * AES-192 CCM decryption/ICV generation
+ */
+static void decrypt_ccm192(private_aesni_ccm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i *ks, d, t, c, b, state, *bi, *bo;
+	u_int blocks, rem, i;
+
+	c = icv_header(this, len, iv, alen, assoc);
+	build_ctr(this, 1, iv, &b);
+	state = _mm_load_si128(&b);
+	blocks = len / AES_BLOCK_SIZE;
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < blocks; i++)
+	{
+		d = _mm_loadu_si128(bi + i);
+
+		t = _mm_xor_si128(state, ks[0]);
+
+		t = _mm_aesenc_si128(t, ks[1]);
+		t = _mm_aesenc_si128(t, ks[2]);
+		t = _mm_aesenc_si128(t, ks[3]);
+		t = _mm_aesenc_si128(t, ks[4]);
+		t = _mm_aesenc_si128(t, ks[5]);
+		t = _mm_aesenc_si128(t, ks[6]);
+		t = _mm_aesenc_si128(t, ks[7]);
+		t = _mm_aesenc_si128(t, ks[8]);
+		t = _mm_aesenc_si128(t, ks[9]);
+		t = _mm_aesenc_si128(t, ks[10]);
+		t = _mm_aesenc_si128(t, ks[11]);
+
+		t = _mm_aesenclast_si128(t, ks[12]);
+		t = _mm_xor_si128(t, d);
+		_mm_storeu_si128(bo + i, t);
+
+		c = _mm_xor_si128(t, c);
+		c = _mm_xor_si128(c, ks[0]);
+
+		c = _mm_aesenc_si128(c, ks[1]);
+		c = _mm_aesenc_si128(c, ks[2]);
+		c = _mm_aesenc_si128(c, ks[3]);
+		c = _mm_aesenc_si128(c, ks[4]);
+		c = _mm_aesenc_si128(c, ks[5]);
+		c = _mm_aesenc_si128(c, ks[6]);
+		c = _mm_aesenc_si128(c, ks[7]);
+		c = _mm_aesenc_si128(c, ks[8]);
+		c = _mm_aesenc_si128(c, ks[9]);
+		c = _mm_aesenc_si128(c, ks[10]);
+		c = _mm_aesenc_si128(c, ks[11]);
+
+		c = _mm_aesenclast_si128(c, ks[12]);
+
+		state = increment_be(state);
+	}
+
+	if (rem)
+	{
+		c = decrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
+	}
+	crypt_icv(this, iv, c, icv);
+}
+
+/**
+ * AES-256 CCM encryption/ICV generation
+ */
+static void encrypt_ccm256(private_aesni_ccm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i *ks, d, t, c, b, state, *bi, *bo;
+	u_int blocks, rem, i;
+
+	c = icv_header(this, len, iv, alen, assoc);
+	build_ctr(this, 1, iv, &b);
+	state = _mm_load_si128(&b);
+	blocks = len / AES_BLOCK_SIZE;
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < blocks; i++)
+	{
+		d = _mm_loadu_si128(bi + i);
+
+		c = _mm_xor_si128(d, c);
+		c = _mm_xor_si128(c, ks[0]);
+		t = _mm_xor_si128(state, ks[0]);
+
+		c = _mm_aesenc_si128(c, ks[1]);
+		t = _mm_aesenc_si128(t, ks[1]);
+		c = _mm_aesenc_si128(c, ks[2]);
+		t = _mm_aesenc_si128(t, ks[2]);
+		c = _mm_aesenc_si128(c, ks[3]);
+		t = _mm_aesenc_si128(t, ks[3]);
+		c = _mm_aesenc_si128(c, ks[4]);
+		t = _mm_aesenc_si128(t, ks[4]);
+		c = _mm_aesenc_si128(c, ks[5]);
+		t = _mm_aesenc_si128(t, ks[5]);
+		c = _mm_aesenc_si128(c, ks[6]);
+		t = _mm_aesenc_si128(t, ks[6]);
+		c = _mm_aesenc_si128(c, ks[7]);
+		t = _mm_aesenc_si128(t, ks[7]);
+		c = _mm_aesenc_si128(c, ks[8]);
+		t = _mm_aesenc_si128(t, ks[8]);
+		c = _mm_aesenc_si128(c, ks[9]);
+		t = _mm_aesenc_si128(t, ks[9]);
+		c = _mm_aesenc_si128(c, ks[10]);
+		t = _mm_aesenc_si128(t, ks[10]);
+		c = _mm_aesenc_si128(c, ks[11]);
+		t = _mm_aesenc_si128(t, ks[11]);
+		c = _mm_aesenc_si128(c, ks[12]);
+		t = _mm_aesenc_si128(t, ks[12]);
+		c = _mm_aesenc_si128(c, ks[13]);
+		t = _mm_aesenc_si128(t, ks[13]);
+
+		c = _mm_aesenclast_si128(c, ks[14]);
+		t = _mm_aesenclast_si128(t, ks[14]);
+
+		t = _mm_xor_si128(t, d);
+		_mm_storeu_si128(bo + i, t);
+
+		state = increment_be(state);
+	}
+
+	if (rem)
+	{
+		c = encrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
+	}
+	crypt_icv(this, iv, c, icv);
+}
+
+/**
+ * AES-256 CCM decryption/ICV generation
+ */
+static void decrypt_ccm256(private_aesni_ccm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i *ks, d, t, c, b, state, *bi, *bo;
+	u_int blocks, rem, i;
+
+	c = icv_header(this, len, iv, alen, assoc);
+	build_ctr(this, 1, iv, &b);
+	state = _mm_load_si128(&b);
+	blocks = len / AES_BLOCK_SIZE;
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < blocks; i++)
+	{
+		d = _mm_loadu_si128(bi + i);
+
+		t = _mm_xor_si128(state, ks[0]);
+
+		t = _mm_aesenc_si128(t, ks[1]);
+		t = _mm_aesenc_si128(t, ks[2]);
+		t = _mm_aesenc_si128(t, ks[3]);
+		t = _mm_aesenc_si128(t, ks[4]);
+		t = _mm_aesenc_si128(t, ks[5]);
+		t = _mm_aesenc_si128(t, ks[6]);
+		t = _mm_aesenc_si128(t, ks[7]);
+		t = _mm_aesenc_si128(t, ks[8]);
+		t = _mm_aesenc_si128(t, ks[9]);
+		t = _mm_aesenc_si128(t, ks[10]);
+		t = _mm_aesenc_si128(t, ks[11]);
+		t = _mm_aesenc_si128(t, ks[12]);
+		t = _mm_aesenc_si128(t, ks[13]);
+
+		t = _mm_aesenclast_si128(t, ks[14]);
+		t = _mm_xor_si128(t, d);
+		_mm_storeu_si128(bo + i, t);
+
+		c = _mm_xor_si128(t, c);
+		c = _mm_xor_si128(c, ks[0]);
+
+		c = _mm_aesenc_si128(c, ks[1]);
+		c = _mm_aesenc_si128(c, ks[2]);
+		c = _mm_aesenc_si128(c, ks[3]);
+		c = _mm_aesenc_si128(c, ks[4]);
+		c = _mm_aesenc_si128(c, ks[5]);
+		c = _mm_aesenc_si128(c, ks[6]);
+		c = _mm_aesenc_si128(c, ks[7]);
+		c = _mm_aesenc_si128(c, ks[8]);
+		c = _mm_aesenc_si128(c, ks[9]);
+		c = _mm_aesenc_si128(c, ks[10]);
+		c = _mm_aesenc_si128(c, ks[11]);
+		c = _mm_aesenc_si128(c, ks[12]);
+		c = _mm_aesenc_si128(c, ks[13]);
+
+		c = _mm_aesenclast_si128(c, ks[14]);
+
+		state = increment_be(state);
+	}
+
+	if (rem)
+	{
+		c = decrypt_ccm_rem(this->key, rem, state, bi + blocks, bo + blocks, c);
+	}
+	crypt_icv(this, iv, c, icv);
+}
+
+METHOD(aead_t, encrypt, bool,
+	private_aesni_ccm_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
+	chunk_t *encr)
+{
+	u_char *out;
+
+	if (!this->key || iv.len != IV_SIZE)
+	{
+		return FALSE;
+	}
+	out = plain.ptr;
+	if (encr)
+	{
+		*encr = chunk_alloc(plain.len + this->icv_size);
+		out = encr->ptr;
+	}
+	this->encrypt(this, plain.len, plain.ptr, out, iv.ptr,
+				  assoc.len, assoc.ptr, out + plain.len);
+	return TRUE;
+}
+
+METHOD(aead_t, decrypt, bool,
+	private_aesni_ccm_t *this, chunk_t encr, chunk_t assoc, chunk_t iv,
+	chunk_t *plain)
+{
+	u_char *out, icv[this->icv_size];
+
+	if (!this->key || iv.len != IV_SIZE || encr.len < this->icv_size)
+	{
+		return FALSE;
+	}
+	encr.len -= this->icv_size;
+	out = encr.ptr;
+	if (plain)
+	{
+		*plain = chunk_alloc(encr.len);
+		out = plain->ptr;
+	}
+
+	this->decrypt(this, encr.len, encr.ptr, out, iv.ptr,
+				  assoc.len, assoc.ptr, icv);
+	return memeq_const(icv, encr.ptr + encr.len, this->icv_size);
+}
+
+METHOD(aead_t, get_block_size, size_t,
+	private_aesni_ccm_t *this)
+{
+	return 1;
+}
+
+METHOD(aead_t, get_icv_size, size_t,
+	private_aesni_ccm_t *this)
+{
+	return this->icv_size;
+}
+
+METHOD(aead_t, get_iv_size, size_t,
+	private_aesni_ccm_t *this)
+{
+	return IV_SIZE;
+}
+
+METHOD(aead_t, get_iv_gen, iv_gen_t*,
+	private_aesni_ccm_t *this)
+{
+	return this->iv_gen;
+}
+
+METHOD(aead_t, get_key_size, size_t,
+	private_aesni_ccm_t *this)
+{
+	return this->key_size + SALT_SIZE;
+}
+
+METHOD(aead_t, set_key, bool,
+	private_aesni_ccm_t *this, chunk_t key)
+{
+	if (key.len != this->key_size + SALT_SIZE)
+	{
+		return FALSE;
+	}
+
+	memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
+	key.len -= SALT_SIZE;
+
+	DESTROY_IF(this->key);
+	this->key = aesni_key_create(TRUE, key);
+	return TRUE;
+}
+
+METHOD(aead_t, destroy, void,
+	private_aesni_ccm_t *this)
+{
+	DESTROY_IF(this->key);
+	this->iv_gen->destroy(this->iv_gen);
+	free_align(this);
+}
+
+/**
+ * See header
+ */
+aesni_ccm_t *aesni_ccm_create(encryption_algorithm_t algo,
+							  size_t key_size, size_t salt_size)
+{
+	private_aesni_ccm_t *this;
+	size_t icv_size;
+
+	switch (key_size)
+	{
+		case 0:
+			key_size = 16;
+			break;
+		case 16:
+		case 24:
+		case 32:
+			break;
+		default:
+			return NULL;
+	}
+	if (salt_size && salt_size != SALT_SIZE)
+	{
+		/* currently not supported */
+		return NULL;
+	}
+	switch (algo)
+	{
+		case ENCR_AES_CCM_ICV8:
+			algo = ENCR_AES_CBC;
+			icv_size = 8;
+			break;
+		case ENCR_AES_CCM_ICV12:
+			algo = ENCR_AES_CBC;
+			icv_size = 12;
+			break;
+		case ENCR_AES_CCM_ICV16:
+			algo = ENCR_AES_CBC;
+			icv_size = 16;
+			break;
+		default:
+			return NULL;
+	}
+
+	INIT_ALIGN(this, sizeof(__m128i),
+		.public = {
+			.aead = {
+				.encrypt = _encrypt,
+				.decrypt = _decrypt,
+				.get_block_size = _get_block_size,
+				.get_icv_size = _get_icv_size,
+				.get_iv_size = _get_iv_size,
+				.get_iv_gen = _get_iv_gen,
+				.get_key_size = _get_key_size,
+				.set_key = _set_key,
+				.destroy = _destroy,
+			},
+		},
+		.key_size = key_size,
+		.iv_gen = iv_gen_seq_create(),
+		.icv_size = icv_size,
+	);
+
+	switch (key_size)
+	{
+		case 16:
+			this->encrypt = encrypt_ccm128;
+			this->decrypt = decrypt_ccm128;
+			break;
+		case 24:
+			this->encrypt = encrypt_ccm192;
+			this->decrypt = decrypt_ccm192;
+			break;
+		case 32:
+			this->encrypt = encrypt_ccm256;
+			this->decrypt = decrypt_ccm256;
+			break;
+	}
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/plugins/aesni/aesni_ccm.h b/src/libstrongswan/plugins/aesni/aesni_ccm.h
new file mode 100644
index 0000000..69612b5
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_ccm.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup aesni_ccm aesni_ccm
+ * @{ @ingroup aesni
+ */
+
+#ifndef AESNI_CCM_H_
+#define AESNI_CCM_H_
+
+#include <library.h>
+
+typedef struct aesni_ccm_t aesni_ccm_t;
+
+/**
+ * CCM mode AEAD using AES-NI
+ */
+struct aesni_ccm_t {
+
+	/**
+	 * Implements aead_t interface
+	 */
+	aead_t aead;
+};
+
+/**
+ * Create a aesni_ccm instance.
+ *
+ * @param algo			encryption algorithm, ENCR_AES_CCM*
+ * @param key_size		AES key size, in bytes
+ * @param salt_size		size of salt value
+ * @return				AES-CCM AEAD, NULL if not supported
+ */
+aesni_ccm_t *aesni_ccm_create(encryption_algorithm_t algo,
+							  size_t key_size, size_t salt_size);
+
+#endif /** AESNI_CCM_H_ @}*/
diff --git a/src/libstrongswan/plugins/aesni/aesni_cmac.c b/src/libstrongswan/plugins/aesni/aesni_cmac.c
new file mode 100644
index 0000000..d6a87e6
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_cmac.c
@@ -0,0 +1,371 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "aesni_cmac.h"
+#include "aesni_key.h"
+
+#include <crypto/prfs/mac_prf.h>
+#include <crypto/signers/mac_signer.h>
+
+typedef struct private_mac_t private_mac_t;
+
+/**
+ * Private data of a mac_t object.
+ */
+struct private_mac_t {
+
+	/**
+	 * Public interface.
+	 */
+	mac_t public;
+
+	/**
+	 * Key schedule for key K
+	 */
+	aesni_key_t *k;
+
+	/**
+	 * K1
+	 */
+	__m128i k1;
+
+	/**
+	 * K2
+	 */
+	__m128i k2;
+
+	/**
+	 * T
+	 */
+	__m128i t;
+
+	/**
+	 * remaining, unprocessed bytes in append mode
+	 */
+	u_char rem[AES_BLOCK_SIZE];
+
+	/**
+	 * number of bytes in remaining
+	 */
+	int rem_size;
+};
+
+METHOD(mac_t, get_mac, bool,
+	private_mac_t *this, chunk_t data, u_int8_t *out)
+{
+	__m128i *ks, t, l, *bi;
+	u_int blocks, rem, i;
+
+	if (!this->k)
+	{
+		return FALSE;
+	}
+
+	ks = this->k->schedule;
+	t = this->t;
+
+	if (this->rem_size + data.len > AES_BLOCK_SIZE)
+	{
+		/* T := 0x00000000000000000000000000000000 (initially)
+		 * for each block M_i (except the last)
+		 *   X := T XOR M_i;
+		 *   T := AES-128(K, X);
+		 */
+
+		/* append data to remaining bytes, process block M_1 */
+		memcpy(this->rem + this->rem_size, data.ptr,
+			   AES_BLOCK_SIZE - this->rem_size);
+		data = chunk_skip(data, AES_BLOCK_SIZE - this->rem_size);
+
+		t = _mm_xor_si128(t, _mm_loadu_si128((__m128i*)this->rem));
+
+		t = _mm_xor_si128(t, ks[0]);
+		t = _mm_aesenc_si128(t, ks[1]);
+		t = _mm_aesenc_si128(t, ks[2]);
+		t = _mm_aesenc_si128(t, ks[3]);
+		t = _mm_aesenc_si128(t, ks[4]);
+		t = _mm_aesenc_si128(t, ks[5]);
+		t = _mm_aesenc_si128(t, ks[6]);
+		t = _mm_aesenc_si128(t, ks[7]);
+		t = _mm_aesenc_si128(t, ks[8]);
+		t = _mm_aesenc_si128(t, ks[9]);
+		t = _mm_aesenclast_si128(t, ks[10]);
+
+		/* process blocks M_2 ... M_n-1 */
+		bi = (__m128i*)data.ptr;
+		rem = data.len % AES_BLOCK_SIZE;
+		blocks = data.len / AES_BLOCK_SIZE;
+		if (!rem && blocks)
+		{	/* don't do last block */
+			rem = AES_BLOCK_SIZE;
+			blocks--;
+		}
+
+		/* process blocks M[2] ... M[n-1] */
+		for (i = 0; i < blocks; i++)
+		{
+			t = _mm_xor_si128(t, _mm_loadu_si128(bi + i));
+
+			t = _mm_xor_si128(t, ks[0]);
+			t = _mm_aesenc_si128(t, ks[1]);
+			t = _mm_aesenc_si128(t, ks[2]);
+			t = _mm_aesenc_si128(t, ks[3]);
+			t = _mm_aesenc_si128(t, ks[4]);
+			t = _mm_aesenc_si128(t, ks[5]);
+			t = _mm_aesenc_si128(t, ks[6]);
+			t = _mm_aesenc_si128(t, ks[7]);
+			t = _mm_aesenc_si128(t, ks[8]);
+			t = _mm_aesenc_si128(t, ks[9]);
+			t = _mm_aesenclast_si128(t, ks[10]);
+		}
+
+		/* store remaining bytes of block M_n */
+		memcpy(this->rem, data.ptr + data.len - rem, rem);
+		this->rem_size = rem;
+	}
+	else
+	{
+		/* no complete block (or last block), just copy into remaining */
+		memcpy(this->rem + this->rem_size, data.ptr, data.len);
+		this->rem_size += data.len;
+	}
+	if (out)
+	{
+		/* if last block is complete
+		 *   M_last := M_n XOR K1;
+		 * else
+		 *   M_last := padding(M_n) XOR K2;
+		 */
+		if (this->rem_size == AES_BLOCK_SIZE)
+		{
+			l = _mm_loadu_si128((__m128i*)this->rem);
+			l = _mm_xor_si128(l, this->k1);
+		}
+		else
+		{
+			/* padding(x) = x || 10^i  where i is 128-8*r-1
+			 * That is, padding(x) is the concatenation of x and a single '1',
+			 * followed by the minimum number of '0's, so that the total length is
+			 * equal to 128 bits.
+			 */
+			if (this->rem_size < AES_BLOCK_SIZE)
+			{
+				memset(this->rem + this->rem_size, 0,
+					   AES_BLOCK_SIZE - this->rem_size);
+				this->rem[this->rem_size] = 0x80;
+			}
+			l = _mm_loadu_si128((__m128i*)this->rem);
+			l = _mm_xor_si128(l, this->k2);
+		}
+		/* T := M_last XOR T;
+		 * T := AES-128(K,T);
+		 */
+		t = _mm_xor_si128(l, t);
+
+		t = _mm_xor_si128(t, ks[0]);
+		t = _mm_aesenc_si128(t, ks[1]);
+		t = _mm_aesenc_si128(t, ks[2]);
+		t = _mm_aesenc_si128(t, ks[3]);
+		t = _mm_aesenc_si128(t, ks[4]);
+		t = _mm_aesenc_si128(t, ks[5]);
+		t = _mm_aesenc_si128(t, ks[6]);
+		t = _mm_aesenc_si128(t, ks[7]);
+		t = _mm_aesenc_si128(t, ks[8]);
+		t = _mm_aesenc_si128(t, ks[9]);
+		t = _mm_aesenclast_si128(t, ks[10]);
+
+		_mm_storeu_si128((__m128i*)out, t);
+
+		/* reset state */
+		t = _mm_setzero_si128();
+		this->rem_size = 0;
+	}
+	this->t = t;
+	return TRUE;
+}
+
+METHOD(mac_t, get_mac_size, size_t,
+	private_mac_t *this)
+{
+	return AES_BLOCK_SIZE;
+}
+
+/**
+ * Left-shift the given chunk by one bit.
+ */
+static void bit_shift(chunk_t chunk)
+{
+	size_t i;
+
+	for (i = 0; i < chunk.len; i++)
+	{
+		chunk.ptr[i] <<= 1;
+		if (i < chunk.len - 1 && chunk.ptr[i + 1] & 0x80)
+		{
+			chunk.ptr[i] |= 0x01;
+		}
+	}
+}
+
+METHOD(mac_t, set_key, bool,
+	private_mac_t *this, chunk_t key)
+{
+	__m128i rb, msb, l, a;
+	u_int round;
+	chunk_t k;
+
+	this->t = _mm_setzero_si128();
+	this->rem_size = 0;
+
+	/* we support variable keys as defined in RFC 4615 */
+	if (key.len == AES_BLOCK_SIZE)
+	{
+		k = key;
+	}
+	else
+	{	/* use cmac recursively to resize longer or shorter keys */
+		k = chunk_alloca(AES_BLOCK_SIZE);
+		memset(k.ptr, 0, k.len);
+		if (!set_key(this, k) || !get_mac(this, key, k.ptr))
+		{
+			return FALSE;
+		}
+	}
+
+	DESTROY_IF(this->k);
+	this->k = aesni_key_create(TRUE, k);
+	if (!this->k)
+	{
+		return FALSE;
+	}
+
+	/*
+	 * Rb = 0x00000000000000000000000000000087
+	 * L = 0x00000000000000000000000000000000 encrypted with K
+	 * if MSB(L) == 0
+	 *   K1 = L << 1
+	 * else
+	 *   K1 = (L << 1) XOR Rb
+	 * if MSB(K1) == 0
+	 *   K2 = K1 << 1
+	 * else
+	 *   K2 = (K1 << 1) XOR Rb
+	 */
+
+	rb = _mm_set_epi32(0x87000000, 0, 0, 0);
+	msb = _mm_set_epi32(0, 0, 0, 0x80);
+
+	l = _mm_setzero_si128();
+
+	l = _mm_xor_si128(l, this->k->schedule[0]);
+	for (round = 1; round < this->k->rounds; round++)
+	{
+		l = _mm_aesenc_si128(l, this->k->schedule[round]);
+	}
+	l = _mm_aesenclast_si128(l, this->k->schedule[this->k->rounds]);
+
+	this->k1 = l;
+	bit_shift(chunk_from_thing(this->k1));
+	a = _mm_and_si128(l, msb);
+	if (memchr(&a, 0x80, 1))
+	{
+		this->k1 = _mm_xor_si128(this->k1, rb);
+	}
+	this->k2 = this->k1;
+	bit_shift(chunk_from_thing(this->k2));
+	a = _mm_and_si128(this->k1, msb);
+	if (memchr(&a, 0x80, 1))
+	{
+		this->k2 = _mm_xor_si128(this->k2, rb);
+	}
+
+	return TRUE;
+}
+
+METHOD(mac_t, destroy, void,
+	private_mac_t *this)
+{
+	DESTROY_IF(this->k);
+	memwipe(&this->k1, sizeof(this->k1));
+	memwipe(&this->k2, sizeof(this->k2));
+	free_align(this);
+}
+
+/*
+ * Described in header
+ */
+mac_t *aesni_cmac_create(encryption_algorithm_t algo, size_t key_size)
+{
+	private_mac_t *this;
+
+	INIT_ALIGN(this, sizeof(__m128i),
+		.public = {
+			.get_mac = _get_mac,
+			.get_mac_size = _get_mac_size,
+			.set_key = _set_key,
+			.destroy = _destroy,
+		},
+	);
+
+	return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+prf_t *aesni_cmac_prf_create(pseudo_random_function_t algo)
+{
+	mac_t *cmac;
+
+	switch (algo)
+	{
+		case PRF_AES128_CMAC:
+			cmac = aesni_cmac_create(ENCR_AES_CBC, 16);
+			break;
+		default:
+			return NULL;
+	}
+	if (cmac)
+	{
+		return mac_prf_create(cmac);
+	}
+	return NULL;
+}
+
+/*
+ * Described in header
+ */
+signer_t *aesni_cmac_signer_create(integrity_algorithm_t algo)
+{
+	size_t truncation;
+	mac_t *cmac;
+
+	switch (algo)
+	{
+		case AUTH_AES_CMAC_96:
+			cmac = aesni_cmac_create(ENCR_AES_CBC, 16);
+			truncation = 12;
+			break;
+		default:
+			return NULL;
+	}
+	if (cmac)
+	{
+		return mac_signer_create(cmac, truncation);
+	}
+	return NULL;
+}
diff --git a/src/libstrongswan/plugins/aesni/aesni_cmac.h b/src/libstrongswan/plugins/aesni/aesni_cmac.h
new file mode 100644
index 0000000..5f0af73
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_cmac.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup aesni_xcbc aesni_xcbc
+ * @{ @ingroup aesni
+ */
+
+#ifndef CMAC_H_
+#define CMAC_H_
+
+#include <crypto/mac.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/signers/signer.h>
+
+/**
+ * Create a generic mac_t object using AESNI CMAC.
+ *
+ * @param algo		underlying encryption algorithm
+ * @param key_size	size of encryption key, in bytes
+ */
+mac_t *aesni_cmac_create(encryption_algorithm_t algo, size_t key_size);
+
+/**
+ * Creates a new prf_t object based AESNI CMAC.
+ *
+ * @param algo		algorithm to implement
+ * @return			prf_t object, NULL if not supported
+ */
+prf_t *aesni_cmac_prf_create(pseudo_random_function_t algo);
+
+/**
+ * Creates a new signer_t object based on AESNI CMAC.
+ *
+ * @param algo		algorithm to implement
+ * @return			signer_t, NULL if  not supported
+ */
+signer_t *aesni_cmac_signer_create(integrity_algorithm_t algo);
+
+#endif /** CMAC_H_ @}*/
diff --git a/src/libstrongswan/plugins/aesni/aesni_ctr.c b/src/libstrongswan/plugins/aesni/aesni_ctr.c
new file mode 100644
index 0000000..9898138
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_ctr.c
@@ -0,0 +1,643 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "aesni_ctr.h"
+#include "aesni_key.h"
+
+#include <tmmintrin.h>
+
+/**
+ * Pipeline parallelism we use for CTR en/decryption
+ */
+#define CTR_CRYPT_PARALLELISM 4
+
+typedef struct private_aesni_ctr_t private_aesni_ctr_t;
+
+/**
+ * CTR en/decryption method type
+ */
+typedef void (*aesni_ctr_fn_t)(private_aesni_ctr_t*, size_t, u_char*, u_char*);
+
+/**
+ * Private data of an aesni_ctr_t object.
+ */
+struct private_aesni_ctr_t {
+
+	/**
+	 * Public aesni_ctr_t interface.
+	 */
+	aesni_ctr_t public;
+
+	/**
+	 * Key size
+	 */
+	u_int key_size;
+
+	/**
+	 * Key schedule
+	 */
+	aesni_key_t *key;
+
+	/**
+	 * Encryption method
+	 */
+	aesni_ctr_fn_t crypt;
+
+	/**
+	 * Counter state
+	 */
+	struct {
+		char nonce[4];
+		char iv[8];
+		u_int32_t counter;
+	} __attribute__((packed, aligned(sizeof(__m128i)))) state;
+};
+
+/**
+ * Do big-endian increment on x
+ */
+static inline __m128i increment_be(__m128i x)
+{
+	__m128i swap;
+
+	swap = _mm_setr_epi8(15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0);
+
+	x = _mm_shuffle_epi8(x, swap);
+	x = _mm_add_epi64(x, _mm_set_epi32(0, 0, 0, 1));
+	x = _mm_shuffle_epi8(x, swap);
+
+	return x;
+}
+
+/**
+ * AES-128 CTR encryption
+ */
+static void encrypt_ctr128(private_aesni_ctr_t *this,
+						   size_t len, u_char *in, u_char *out)
+{
+	__m128i t1, t2, t3, t4;
+	__m128i d1, d2, d3, d4;
+	__m128i *ks, state, b, *bi, *bo;
+	u_int i, blocks, pblocks, rem;
+
+	state = _mm_load_si128((__m128i*)&this->state);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % CTR_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += CTR_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		t1 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t2 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t3 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t4 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[10]);
+		t2 = _mm_aesenclast_si128(t2, ks[10]);
+		t3 = _mm_aesenclast_si128(t3, ks[10]);
+		t4 = _mm_aesenclast_si128(t4, ks[10]);
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		t1 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[10]);
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+	}
+
+	if (rem)
+	{
+		memset(&b, 0, sizeof(b));
+		memcpy(&b, bi + blocks, rem);
+
+		d1 = _mm_loadu_si128(&b);
+		t1 = _mm_xor_si128(state, ks[0]);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[10]);
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(&b, t1);
+
+		memcpy(bo + blocks, &b, rem);
+	}
+}
+
+/**
+ * AES-192 CTR encryption
+ */
+static void encrypt_ctr192(private_aesni_ctr_t *this,
+						   size_t len, u_char *in, u_char *out)
+{
+	__m128i t1, t2, t3, t4;
+	__m128i d1, d2, d3, d4;
+	__m128i *ks, state, b, *bi, *bo;
+	u_int i, blocks, pblocks, rem;
+
+	state = _mm_load_si128((__m128i*)&this->state);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % CTR_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += CTR_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		t1 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t2 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t3 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t4 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t2 = _mm_aesenc_si128(t2, ks[10]);
+		t3 = _mm_aesenc_si128(t3, ks[10]);
+		t4 = _mm_aesenc_si128(t4, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t2 = _mm_aesenc_si128(t2, ks[11]);
+		t3 = _mm_aesenc_si128(t3, ks[11]);
+		t4 = _mm_aesenc_si128(t4, ks[11]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[12]);
+		t2 = _mm_aesenclast_si128(t2, ks[12]);
+		t3 = _mm_aesenclast_si128(t3, ks[12]);
+		t4 = _mm_aesenclast_si128(t4, ks[12]);
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		t1 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[12]);
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+	}
+
+	if (rem)
+	{
+		memset(&b, 0, sizeof(b));
+		memcpy(&b, bi + blocks, rem);
+
+		d1 = _mm_loadu_si128(&b);
+		t1 = _mm_xor_si128(state, ks[0]);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[12]);
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(&b, t1);
+
+		memcpy(bo + blocks, &b, rem);
+	}
+}
+
+/**
+ * AES-256 CTR encryption
+ */
+static void encrypt_ctr256(private_aesni_ctr_t *this,
+						   size_t len, u_char *in, u_char *out)
+{
+	__m128i t1, t2, t3, t4;
+	__m128i d1, d2, d3, d4;
+	__m128i *ks, state, b, *bi, *bo;
+	u_int i, blocks, pblocks, rem;
+
+	state = _mm_load_si128((__m128i*)&this->state);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % CTR_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += CTR_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		t1 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t2 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t3 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+		t4 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t2 = _mm_aesenc_si128(t2, ks[10]);
+		t3 = _mm_aesenc_si128(t3, ks[10]);
+		t4 = _mm_aesenc_si128(t4, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t2 = _mm_aesenc_si128(t2, ks[11]);
+		t3 = _mm_aesenc_si128(t3, ks[11]);
+		t4 = _mm_aesenc_si128(t4, ks[11]);
+		t1 = _mm_aesenc_si128(t1, ks[12]);
+		t2 = _mm_aesenc_si128(t2, ks[12]);
+		t3 = _mm_aesenc_si128(t3, ks[12]);
+		t4 = _mm_aesenc_si128(t4, ks[12]);
+		t1 = _mm_aesenc_si128(t1, ks[13]);
+		t2 = _mm_aesenc_si128(t2, ks[13]);
+		t3 = _mm_aesenc_si128(t3, ks[13]);
+		t4 = _mm_aesenc_si128(t4, ks[13]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[14]);
+		t2 = _mm_aesenclast_si128(t2, ks[14]);
+		t3 = _mm_aesenclast_si128(t3, ks[14]);
+		t4 = _mm_aesenclast_si128(t4, ks[14]);
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		t1 = _mm_xor_si128(state, ks[0]);
+		state = increment_be(state);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t1 = _mm_aesenc_si128(t1, ks[12]);
+		t1 = _mm_aesenc_si128(t1, ks[13]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[14]);
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+	}
+
+	if (rem)
+	{
+		memset(&b, 0, sizeof(b));
+		memcpy(&b, bi + blocks, rem);
+
+		d1 = _mm_loadu_si128(&b);
+		t1 = _mm_xor_si128(state, ks[0]);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t1 = _mm_aesenc_si128(t1, ks[12]);
+		t1 = _mm_aesenc_si128(t1, ks[13]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[14]);
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(&b, t1);
+
+		memcpy(bo + blocks, &b, rem);
+	}
+}
+
+METHOD(crypter_t, crypt, bool,
+	private_aesni_ctr_t *this, chunk_t in, chunk_t iv, chunk_t *out)
+{
+	u_char *buf;
+
+	if (!this->key || iv.len != sizeof(this->state.iv))
+	{
+		return FALSE;
+	}
+	memcpy(this->state.iv, iv.ptr, sizeof(this->state.iv));
+	this->state.counter = htonl(1);
+
+	buf = in.ptr;
+	if (out)
+	{
+		*out = chunk_alloc(in.len);
+		buf = out->ptr;
+	}
+	this->crypt(this, in.len, in.ptr, buf);
+	return TRUE;
+}
+
+METHOD(crypter_t, get_block_size, size_t,
+	private_aesni_ctr_t *this)
+{
+	return 1;
+}
+
+METHOD(crypter_t, get_iv_size, size_t,
+	private_aesni_ctr_t *this)
+{
+	return sizeof(this->state.iv);
+}
+
+METHOD(crypter_t, get_key_size, size_t,
+	private_aesni_ctr_t *this)
+{
+	return this->key_size + sizeof(this->state.nonce);
+}
+
+METHOD(crypter_t, set_key, bool,
+	private_aesni_ctr_t *this, chunk_t key)
+{
+	if (key.len != get_key_size(this))
+	{
+		return FALSE;
+	}
+
+	memcpy(this->state.nonce, key.ptr + key.len - sizeof(this->state.nonce),
+		   sizeof(this->state.nonce));
+	key.len -= sizeof(this->state.nonce);
+
+	DESTROY_IF(this->key);
+	this->key = aesni_key_create(TRUE, key);
+
+	return this->key;
+}
+
+METHOD(crypter_t, destroy, void,
+	private_aesni_ctr_t *this)
+{
+	DESTROY_IF(this->key);
+	free_align(this);
+}
+
+/**
+ * See header
+ */
+aesni_ctr_t *aesni_ctr_create(encryption_algorithm_t algo, size_t key_size)
+{
+	private_aesni_ctr_t *this;
+
+	if (algo != ENCR_AES_CTR)
+	{
+		return NULL;
+	}
+	switch (key_size)
+	{
+		case 0:
+			key_size = 16;
+			break;
+		case 16:
+		case 24:
+		case 32:
+			break;
+		default:
+			return NULL;
+	}
+
+	INIT_ALIGN(this, sizeof(__m128i),
+		.public = {
+			.crypter = {
+				.encrypt = _crypt,
+				.decrypt = _crypt,
+				.get_block_size = _get_block_size,
+				.get_iv_size = _get_iv_size,
+				.get_key_size = _get_key_size,
+				.set_key = _set_key,
+				.destroy = _destroy,
+			},
+		},
+		.key_size = key_size,
+	);
+
+	switch (key_size)
+	{
+		case 16:
+			this->crypt = encrypt_ctr128;
+			break;
+		case 24:
+			this->crypt = encrypt_ctr192;
+			break;
+		case 32:
+			this->crypt = encrypt_ctr256;
+			break;
+	}
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/plugins/aesni/aesni_ctr.h b/src/libstrongswan/plugins/aesni/aesni_ctr.h
new file mode 100644
index 0000000..6126a2c
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_ctr.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup aesni_ctr aesni_ctr
+ * @{ @ingroup aesni
+ */
+
+#ifndef AESNI_CTR_H_
+#define AESNI_CTR_H_
+
+#include <library.h>
+
+typedef struct aesni_ctr_t aesni_ctr_t;
+
+/**
+ * CTR mode crypter using AES-NI
+ */
+struct aesni_ctr_t {
+
+	/**
+	 * Implements crypter interface
+	 */
+	crypter_t crypter;
+};
+
+/**
+ * Create a aesni_ctr instance.
+ *
+ * @param algo			encryption algorithm, AES_ENCR_CTR
+ * @param key_size		AES key size, in bytes
+ * @return				AES-CTR crypter, NULL if not supported
+ */
+aesni_ctr_t *aesni_ctr_create(encryption_algorithm_t algo, size_t key_size);
+
+#endif /** AESNI_CTR_H_ @}*/
diff --git a/src/libstrongswan/plugins/aesni/aesni_gcm.c b/src/libstrongswan/plugins/aesni/aesni_gcm.c
new file mode 100644
index 0000000..53c0b14
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_gcm.c
@@ -0,0 +1,1447 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "aesni_gcm.h"
+#include "aesni_key.h"
+
+#include <crypto/iv/iv_gen_seq.h>
+
+#include <tmmintrin.h>
+
+#define NONCE_SIZE 12
+#define IV_SIZE 8
+#define SALT_SIZE (NONCE_SIZE - IV_SIZE)
+
+/**
+ * Parallel pipelining
+ */
+#define GCM_CRYPT_PARALLELISM 4
+
+typedef struct private_aesni_gcm_t private_aesni_gcm_t;
+
+/**
+ * GCM en/decryption method type
+ */
+typedef void (*aesni_gcm_fn_t)(private_aesni_gcm_t*, size_t, u_char*, u_char*,
+							   u_char*, size_t, u_char*, u_char*);
+
+/**
+ * Private data of an aesni_gcm_t object.
+ */
+struct private_aesni_gcm_t {
+
+	/**
+	 * Public aesni_gcm_t interface.
+	 */
+	aesni_gcm_t public;
+
+	/**
+	 * Encryption key schedule
+	 */
+	aesni_key_t *key;
+
+	/**
+	 * IV generator.
+	 */
+	iv_gen_t *iv_gen;
+
+	/**
+	 * Length of the integrity check value
+	 */
+	size_t icv_size;
+
+	/**
+	 * Length of the key in bytes
+	 */
+	size_t key_size;
+
+	/**
+	 * GCM encryption function
+	 */
+	aesni_gcm_fn_t encrypt;
+
+	/**
+	 * GCM decryption function
+	 */
+	aesni_gcm_fn_t decrypt;
+
+	/**
+	 * salt to add to nonce
+	 */
+	u_char salt[SALT_SIZE];
+
+	/**
+	 * GHASH subkey H, big-endian
+	 */
+	__m128i h;
+
+	/**
+	 * GHASH key H^2, big-endian
+	 */
+	__m128i hh;
+
+	/**
+	 * GHASH key H^3, big-endian
+	 */
+	__m128i hhh;
+
+	/**
+	 * GHASH key H^4, big-endian
+	 */
+	__m128i hhhh;
+};
+
+/**
+ * Byte-swap a 128-bit integer
+ */
+static inline __m128i swap128(__m128i x)
+{
+	return _mm_shuffle_epi8(x,
+			_mm_set_epi8(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15));
+}
+
+/**
+ * Multiply two blocks in GF128
+ */
+static __m128i mult_block(__m128i h, __m128i y)
+{
+	__m128i t1, t2, t3, t4, t5, t6;
+
+	y = swap128(y);
+
+	t1 = _mm_clmulepi64_si128(h, y, 0x00);
+	t2 = _mm_clmulepi64_si128(h, y, 0x01);
+	t3 = _mm_clmulepi64_si128(h, y, 0x10);
+	t4 = _mm_clmulepi64_si128(h, y, 0x11);
+
+	t2 = _mm_xor_si128(t2, t3);
+	t3 = _mm_slli_si128(t2, 8);
+	t2 = _mm_srli_si128(t2, 8);
+	t1 = _mm_xor_si128(t1, t3);
+	t4 = _mm_xor_si128(t4, t2);
+
+	t5 = _mm_srli_epi32(t1, 31);
+	t1 = _mm_slli_epi32(t1, 1);
+	t6 = _mm_srli_epi32(t4, 31);
+	t4 = _mm_slli_epi32(t4, 1);
+
+	t3 = _mm_srli_si128(t5, 12);
+	t6 = _mm_slli_si128(t6, 4);
+	t5 = _mm_slli_si128(t5, 4);
+	t1 = _mm_or_si128(t1, t5);
+	t4 = _mm_or_si128(t4, t6);
+	t4 = _mm_or_si128(t4, t3);
+
+	t5 = _mm_slli_epi32(t1, 31);
+	t6 = _mm_slli_epi32(t1, 30);
+	t3 = _mm_slli_epi32(t1, 25);
+
+	t5 = _mm_xor_si128(t5, t6);
+	t5 = _mm_xor_si128(t5, t3);
+	t6 = _mm_srli_si128(t5, 4);
+	t4 = _mm_xor_si128(t4, t6);
+	t5 = _mm_slli_si128(t5, 12);
+	t1 = _mm_xor_si128(t1, t5);
+	t4 = _mm_xor_si128(t4, t1);
+
+	t5 = _mm_srli_epi32(t1, 1);
+	t2 = _mm_srli_epi32(t1, 2);
+	t3 = _mm_srli_epi32(t1, 7);
+	t4 = _mm_xor_si128(t4, t2);
+	t4 = _mm_xor_si128(t4, t3);
+	t4 = _mm_xor_si128(t4, t5);
+
+	return swap128(t4);
+}
+
+/**
+ * Multiply four consecutive blocks by their respective GHASH key, XOR
+ */
+static inline __m128i mult4xor(__m128i h1, __m128i h2, __m128i h3, __m128i h4,
+							   __m128i d1, __m128i d2, __m128i d3, __m128i d4)
+{
+	__m128i t0, t1, t2, t3, t4, t5, t6, t7, t8, t9;
+
+	d1 = swap128(d1);
+	d2 = swap128(d2);
+	d3 = swap128(d3);
+	d4 = swap128(d4);
+
+	t0 = _mm_clmulepi64_si128(h1, d1, 0x00);
+	t1 = _mm_clmulepi64_si128(h2, d2, 0x00);
+	t2 = _mm_clmulepi64_si128(h3, d3, 0x00);
+	t3 = _mm_clmulepi64_si128(h4, d4, 0x00);
+	t8 = _mm_xor_si128(t0, t1);
+	t8 = _mm_xor_si128(t8, t2);
+	t8 = _mm_xor_si128(t8, t3);
+
+	t4 = _mm_clmulepi64_si128(h1, d1, 0x11);
+	t5 = _mm_clmulepi64_si128(h2, d2, 0x11);
+	t6 = _mm_clmulepi64_si128(h3, d3, 0x11);
+	t7 = _mm_clmulepi64_si128(h4, d4, 0x11);
+	t9 = _mm_xor_si128(t4, t5);
+	t9 = _mm_xor_si128(t9, t6);
+	t9 = _mm_xor_si128(t9, t7);
+
+	t0 = _mm_shuffle_epi32(h1, 78);
+	t4 = _mm_shuffle_epi32(d1, 78);
+	t0 = _mm_xor_si128(t0, h1);
+	t4 = _mm_xor_si128(t4, d1);
+	t1 = _mm_shuffle_epi32(h2, 78);
+	t5 = _mm_shuffle_epi32(d2, 78);
+	t1 = _mm_xor_si128(t1, h2);
+	t5 = _mm_xor_si128(t5, d2);
+	t2 = _mm_shuffle_epi32(h3, 78);
+	t6 = _mm_shuffle_epi32(d3, 78);
+	t2 = _mm_xor_si128(t2, h3);
+	t6 = _mm_xor_si128(t6, d3);
+	t3 = _mm_shuffle_epi32(h4, 78);
+	t7 = _mm_shuffle_epi32(d4, 78);
+	t3 = _mm_xor_si128(t3, h4);
+	t7 = _mm_xor_si128(t7, d4);
+
+	t0 = _mm_clmulepi64_si128(t0, t4, 0x00);
+	t1 = _mm_clmulepi64_si128(t1, t5, 0x00);
+	t2 = _mm_clmulepi64_si128(t2, t6, 0x00);
+	t3 = _mm_clmulepi64_si128(t3, t7, 0x00);
+	t0 = _mm_xor_si128(t0, t8);
+	t0 = _mm_xor_si128(t0, t9);
+	t0 = _mm_xor_si128(t1, t0);
+	t0 = _mm_xor_si128(t2, t0);
+
+	t0 = _mm_xor_si128(t3, t0);
+	t4 = _mm_slli_si128(t0, 8);
+	t0 = _mm_srli_si128(t0, 8);
+	t3 = _mm_xor_si128(t4, t8);
+	t6 = _mm_xor_si128(t0, t9);
+	t7 = _mm_srli_epi32(t3, 31);
+	t8 = _mm_srli_epi32(t6, 31);
+	t3 = _mm_slli_epi32(t3, 1);
+	t6 = _mm_slli_epi32(t6, 1);
+	t9 = _mm_srli_si128(t7, 12);
+	t8 = _mm_slli_si128(t8, 4);
+	t7 = _mm_slli_si128(t7, 4);
+	t3 = _mm_or_si128(t3, t7);
+	t6 = _mm_or_si128(t6, t8);
+	t6 = _mm_or_si128(t6, t9);
+	t7 = _mm_slli_epi32(t3, 31);
+	t8 = _mm_slli_epi32(t3, 30);
+	t9 = _mm_slli_epi32(t3, 25);
+	t7 = _mm_xor_si128(t7, t8);
+	t7 = _mm_xor_si128(t7, t9);
+	t8 = _mm_srli_si128(t7, 4);
+	t7 = _mm_slli_si128(t7, 12);
+	t3 = _mm_xor_si128(t3, t7);
+	t2 = _mm_srli_epi32(t3, 1);
+	t4 = _mm_srli_epi32(t3, 2);
+	t5 = _mm_srli_epi32(t3, 7);
+	t2 = _mm_xor_si128(t2, t4);
+	t2 = _mm_xor_si128(t2, t5);
+	t2 = _mm_xor_si128(t2, t8);
+	t3 = _mm_xor_si128(t3, t2);
+	t6 = _mm_xor_si128(t6, t3);
+
+	return swap128(t6);
+}
+
+/**
+ * GHASH on a single block
+ */
+static __m128i ghash(__m128i h, __m128i y, __m128i x)
+{
+	return mult_block(h, _mm_xor_si128(y, x));
+}
+
+/**
+ * Start constructing the ICV for the associated data
+ */
+static __m128i icv_header(private_aesni_gcm_t *this, void *assoc, size_t alen)
+{
+	u_int blocks, pblocks, rem, i;
+	__m128i h1, h2, h3, h4, d1, d2, d3, d4;
+	__m128i y, last, *ab;
+
+	h1 = this->hhhh;
+	h2 = this->hhh;
+	h3 = this->hh;
+	h4 = this->h;
+
+	y = _mm_setzero_si128();
+	ab = assoc;
+	blocks = alen / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % GCM_CRYPT_PARALLELISM);
+	rem = alen % AES_BLOCK_SIZE;
+	for (i = 0; i < pblocks; i += GCM_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(ab + i + 0);
+		d2 = _mm_loadu_si128(ab + i + 1);
+		d3 = _mm_loadu_si128(ab + i + 2);
+		d4 = _mm_loadu_si128(ab + i + 3);
+		y = _mm_xor_si128(y, d1);
+		y = mult4xor(h1, h2, h3, h4, y, d2, d3, d4);
+	}
+	for (i = pblocks; i < blocks; i++)
+	{
+		y = ghash(this->h, y, _mm_loadu_si128(ab + i));
+	}
+	if (rem)
+	{
+		last = _mm_setzero_si128();
+		memcpy(&last, ab + blocks, rem);
+
+		y = ghash(this->h, y, last);
+	}
+
+	return y;
+}
+
+/**
+ * Complete the ICV by hashing a assoc/data length block
+ */
+static __m128i icv_tailer(private_aesni_gcm_t *this, __m128i y,
+						  size_t alen, size_t dlen)
+{
+	__m128i b;
+
+	htoun64(&b, alen * 8);
+	htoun64((u_char*)&b + sizeof(u_int64_t), dlen * 8);
+
+	return ghash(this->h, y, b);
+}
+
+/**
+ * En-/Decrypt the ICV, trim and store it
+ */
+static void icv_crypt(private_aesni_gcm_t *this, __m128i y, __m128i j,
+					  u_char *icv)
+{
+	__m128i *ks, t, b;
+	u_int round;
+
+	ks = this->key->schedule;
+	t = _mm_xor_si128(j, ks[0]);
+	for (round = 1; round < this->key->rounds; round++)
+	{
+		t = _mm_aesenc_si128(t, ks[round]);
+	}
+	t = _mm_aesenclast_si128(t, ks[this->key->rounds]);
+
+	t = _mm_xor_si128(y, t);
+
+	_mm_storeu_si128(&b, t);
+	memcpy(icv, &b, this->icv_size);
+}
+
+/**
+ * Do big-endian increment on x
+ */
+static inline __m128i increment_be(__m128i x)
+{
+	x = swap128(x);
+	x = _mm_add_epi64(x, _mm_set_epi32(0, 0, 0, 1));
+	x = swap128(x);
+
+	return x;
+}
+
+/**
+ * Generate the block J0
+ */
+static inline __m128i create_j(private_aesni_gcm_t *this, u_char *iv)
+{
+	u_char j[AES_BLOCK_SIZE];
+
+	memcpy(j, this->salt, SALT_SIZE);
+	memcpy(j + SALT_SIZE, iv, IV_SIZE);
+	htoun32(j + SALT_SIZE + IV_SIZE, 1);
+
+	return _mm_loadu_si128((__m128i*)j);
+}
+
+/**
+ * Encrypt a remaining incomplete block, return updated Y
+ */
+static __m128i encrypt_gcm_rem(private_aesni_gcm_t *this, u_int rem,
+							   void *in, void *out, __m128i cb, __m128i y)
+{
+	__m128i *ks, t, b;
+	u_int round;
+
+	memset(&b, 0, sizeof(b));
+	memcpy(&b, in, rem);
+
+	ks = this->key->schedule;
+	t = _mm_xor_si128(cb, ks[0]);
+	for (round = 1; round < this->key->rounds; round++)
+	{
+		t = _mm_aesenc_si128(t, ks[round]);
+	}
+	t = _mm_aesenclast_si128(t, ks[this->key->rounds]);
+	b = _mm_xor_si128(t, b);
+
+	memcpy(out, &b, rem);
+
+	memset((u_char*)&b + rem, 0, AES_BLOCK_SIZE - rem);
+	return ghash(this->h, y, b);
+}
+
+/**
+ * Decrypt a remaining incomplete block, return updated Y
+ */
+static __m128i decrypt_gcm_rem(private_aesni_gcm_t *this, u_int rem,
+							   void *in, void *out, __m128i cb, __m128i y)
+{
+	__m128i *ks, t, b;
+	u_int round;
+
+	memset(&b, 0, sizeof(b));
+	memcpy(&b, in, rem);
+
+	y = ghash(this->h, y, b);
+
+	ks = this->key->schedule;
+	t = _mm_xor_si128(cb, ks[0]);
+	for (round = 1; round < this->key->rounds; round++)
+	{
+		t = _mm_aesenc_si128(t, ks[round]);
+	}
+	t = _mm_aesenclast_si128(t, ks[this->key->rounds]);
+	b = _mm_xor_si128(t, b);
+
+	memcpy(out, &b, rem);
+
+	return y;
+}
+
+/**
+ * AES-128 GCM encryption/ICV generation
+ */
+static void encrypt_gcm128(private_aesni_gcm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i d1, d2, d3, d4, t1, t2, t3, t4;
+	__m128i *ks, y, j, cb, *bi, *bo;
+	u_int blocks, pblocks, rem, i;
+
+	j = create_j(this, iv);
+	cb = increment_be(j);
+	y = icv_header(this, assoc, alen);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % GCM_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += GCM_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t2 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t3 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t4 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[10]);
+		t2 = _mm_aesenclast_si128(t2, ks[10]);
+		t3 = _mm_aesenclast_si128(t3, ks[10]);
+		t4 = _mm_aesenclast_si128(t4, ks[10]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+
+		y = _mm_xor_si128(y, t1);
+		y = mult4xor(this->hhhh, this->hhh, this->hh, this->h, y, t2, t3, t4);
+
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenclast_si128(t1, ks[10]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+
+		y = ghash(this->h, y, t1);
+
+		cb = increment_be(cb);
+	}
+
+	if (rem)
+	{
+		y = encrypt_gcm_rem(this, rem, bi + blocks, bo + blocks, cb, y);
+	}
+	y = icv_tailer(this, y, alen, len);
+	icv_crypt(this, y, j, icv);
+}
+
+/**
+ * AES-128 GCM decryption/ICV generation
+ */
+static void decrypt_gcm128(private_aesni_gcm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i d1, d2, d3, d4, t1, t2, t3, t4;
+	__m128i *ks, y, j, cb, *bi, *bo;
+	u_int blocks, pblocks, rem, i;
+
+	j = create_j(this, iv);
+	cb = increment_be(j);
+	y = icv_header(this, assoc, alen);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % GCM_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += GCM_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		y = _mm_xor_si128(y, d1);
+		y = mult4xor(this->hhhh, this->hhh, this->hh, this->h, y, d2, d3, d4);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t2 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t3 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t4 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[10]);
+		t2 = _mm_aesenclast_si128(t2, ks[10]);
+		t3 = _mm_aesenclast_si128(t3, ks[10]);
+		t4 = _mm_aesenclast_si128(t4, ks[10]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		y = ghash(this->h, y, d1);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenclast_si128(t1, ks[10]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+
+		cb = increment_be(cb);
+	}
+
+	if (rem)
+	{
+		y = decrypt_gcm_rem(this, rem, bi + blocks, bo + blocks, cb, y);
+	}
+	y = icv_tailer(this, y, alen, len);
+	icv_crypt(this, y, j, icv);
+}
+
+/**
+ * AES-192 GCM encryption/ICV generation
+ */
+static void encrypt_gcm192(private_aesni_gcm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i d1, d2, d3, d4, t1, t2, t3, t4;
+	__m128i *ks, y, j, cb, *bi, *bo;
+	u_int blocks, pblocks, rem, i;
+
+	j = create_j(this, iv);
+	cb = increment_be(j);
+	y = icv_header(this, assoc, alen);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % GCM_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += GCM_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t2 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t3 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t4 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t2 = _mm_aesenc_si128(t2, ks[10]);
+		t3 = _mm_aesenc_si128(t3, ks[10]);
+		t4 = _mm_aesenc_si128(t4, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t2 = _mm_aesenc_si128(t2, ks[11]);
+		t3 = _mm_aesenc_si128(t3, ks[11]);
+		t4 = _mm_aesenc_si128(t4, ks[11]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[12]);
+		t2 = _mm_aesenclast_si128(t2, ks[12]);
+		t3 = _mm_aesenclast_si128(t3, ks[12]);
+		t4 = _mm_aesenclast_si128(t4, ks[12]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+
+		y = _mm_xor_si128(y, t1);
+		y = mult4xor(this->hhhh, this->hhh, this->hh, this->h, y, t2, t3, t4);
+
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t1 = _mm_aesenclast_si128(t1, ks[12]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+
+		y = ghash(this->h, y, t1);
+
+		cb = increment_be(cb);
+	}
+
+	if (rem)
+	{
+		y = encrypt_gcm_rem(this, rem, bi + blocks, bo + blocks, cb, y);
+	}
+	y = icv_tailer(this, y, alen, len);
+	icv_crypt(this, y, j, icv);
+}
+
+/**
+ * AES-192 GCM decryption/ICV generation
+ */
+static void decrypt_gcm192(private_aesni_gcm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i d1, d2, d3, d4, t1, t2, t3, t4;
+	__m128i *ks, y, j, cb, *bi, *bo;
+	u_int blocks, pblocks, rem, i;
+
+	j = create_j(this, iv);
+	cb = increment_be(j);
+	y = icv_header(this, assoc, alen);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % GCM_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += GCM_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		y = _mm_xor_si128(y, d1);
+		y = mult4xor(this->hhhh, this->hhh, this->hh, this->h, y, d2, d3, d4);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t2 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t3 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t4 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t2 = _mm_aesenc_si128(t2, ks[10]);
+		t3 = _mm_aesenc_si128(t3, ks[10]);
+		t4 = _mm_aesenc_si128(t4, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t2 = _mm_aesenc_si128(t2, ks[11]);
+		t3 = _mm_aesenc_si128(t3, ks[11]);
+		t4 = _mm_aesenc_si128(t4, ks[11]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[12]);
+		t2 = _mm_aesenclast_si128(t2, ks[12]);
+		t3 = _mm_aesenclast_si128(t3, ks[12]);
+		t4 = _mm_aesenclast_si128(t4, ks[12]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		y = ghash(this->h, y, d1);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t1 = _mm_aesenclast_si128(t1, ks[12]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+
+		cb = increment_be(cb);
+	}
+
+	if (rem)
+	{
+		y = decrypt_gcm_rem(this, rem, bi + blocks, bo + blocks, cb, y);
+	}
+	y = icv_tailer(this, y, alen, len);
+	icv_crypt(this, y, j, icv);
+}
+
+/**
+ * AES-256 GCM encryption/ICV generation
+ */
+static void encrypt_gcm256(private_aesni_gcm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i d1, d2, d3, d4, t1, t2, t3, t4;
+	__m128i *ks, y, j, cb, *bi, *bo;
+	u_int blocks, pblocks, rem, i;
+
+	j = create_j(this, iv);
+	cb = increment_be(j);
+	y = icv_header(this, assoc, alen);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % GCM_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += GCM_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t2 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t3 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t4 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t2 = _mm_aesenc_si128(t2, ks[10]);
+		t3 = _mm_aesenc_si128(t3, ks[10]);
+		t4 = _mm_aesenc_si128(t4, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t2 = _mm_aesenc_si128(t2, ks[11]);
+		t3 = _mm_aesenc_si128(t3, ks[11]);
+		t4 = _mm_aesenc_si128(t4, ks[11]);
+		t1 = _mm_aesenc_si128(t1, ks[12]);
+		t2 = _mm_aesenc_si128(t2, ks[12]);
+		t3 = _mm_aesenc_si128(t3, ks[12]);
+		t4 = _mm_aesenc_si128(t4, ks[12]);
+		t1 = _mm_aesenc_si128(t1, ks[13]);
+		t2 = _mm_aesenc_si128(t2, ks[13]);
+		t3 = _mm_aesenc_si128(t3, ks[13]);
+		t4 = _mm_aesenc_si128(t4, ks[13]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[14]);
+		t2 = _mm_aesenclast_si128(t2, ks[14]);
+		t3 = _mm_aesenclast_si128(t3, ks[14]);
+		t4 = _mm_aesenclast_si128(t4, ks[14]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+
+		y = _mm_xor_si128(y, t1);
+		y = mult4xor(this->hhhh, this->hhh, this->hh, this->h, y, t2, t3, t4);
+
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t1 = _mm_aesenc_si128(t1, ks[12]);
+		t1 = _mm_aesenc_si128(t1, ks[13]);
+		t1 = _mm_aesenclast_si128(t1, ks[14]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+
+		y = ghash(this->h, y, t1);
+
+		cb = increment_be(cb);
+	}
+
+	if (rem)
+	{
+		y = encrypt_gcm_rem(this, rem, bi + blocks, bo + blocks, cb, y);
+	}
+	y = icv_tailer(this, y, alen, len);
+	icv_crypt(this, y, j, icv);
+}
+
+/**
+ * AES-256 GCM decryption/ICV generation
+ */
+static void decrypt_gcm256(private_aesni_gcm_t *this,
+						   size_t len, u_char *in, u_char *out, u_char *iv,
+						   size_t alen, u_char *assoc, u_char *icv)
+{
+	__m128i d1, d2, d3, d4, t1, t2, t3, t4;
+	__m128i *ks, y, j, cb, *bi, *bo;
+	u_int blocks, pblocks, rem, i;
+
+	j = create_j(this, iv);
+	cb = increment_be(j);
+	y = icv_header(this, assoc, alen);
+	blocks = len / AES_BLOCK_SIZE;
+	pblocks = blocks - (blocks % GCM_CRYPT_PARALLELISM);
+	rem = len % AES_BLOCK_SIZE;
+	bi = (__m128i*)in;
+	bo = (__m128i*)out;
+
+	ks = this->key->schedule;
+
+	for (i = 0; i < pblocks; i += GCM_CRYPT_PARALLELISM)
+	{
+		d1 = _mm_loadu_si128(bi + i + 0);
+		d2 = _mm_loadu_si128(bi + i + 1);
+		d3 = _mm_loadu_si128(bi + i + 2);
+		d4 = _mm_loadu_si128(bi + i + 3);
+
+		y = _mm_xor_si128(y, d1);
+		y = mult4xor(this->hhhh, this->hhh, this->hh, this->h, y, d2, d3, d4);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t2 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t3 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+		t4 = _mm_xor_si128(cb, ks[0]);
+		cb = increment_be(cb);
+
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t2 = _mm_aesenc_si128(t2, ks[1]);
+		t3 = _mm_aesenc_si128(t3, ks[1]);
+		t4 = _mm_aesenc_si128(t4, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t2 = _mm_aesenc_si128(t2, ks[2]);
+		t3 = _mm_aesenc_si128(t3, ks[2]);
+		t4 = _mm_aesenc_si128(t4, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t2 = _mm_aesenc_si128(t2, ks[3]);
+		t3 = _mm_aesenc_si128(t3, ks[3]);
+		t4 = _mm_aesenc_si128(t4, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t2 = _mm_aesenc_si128(t2, ks[4]);
+		t3 = _mm_aesenc_si128(t3, ks[4]);
+		t4 = _mm_aesenc_si128(t4, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t2 = _mm_aesenc_si128(t2, ks[5]);
+		t3 = _mm_aesenc_si128(t3, ks[5]);
+		t4 = _mm_aesenc_si128(t4, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t2 = _mm_aesenc_si128(t2, ks[6]);
+		t3 = _mm_aesenc_si128(t3, ks[6]);
+		t4 = _mm_aesenc_si128(t4, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t2 = _mm_aesenc_si128(t2, ks[7]);
+		t3 = _mm_aesenc_si128(t3, ks[7]);
+		t4 = _mm_aesenc_si128(t4, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t2 = _mm_aesenc_si128(t2, ks[8]);
+		t3 = _mm_aesenc_si128(t3, ks[8]);
+		t4 = _mm_aesenc_si128(t4, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t2 = _mm_aesenc_si128(t2, ks[9]);
+		t3 = _mm_aesenc_si128(t3, ks[9]);
+		t4 = _mm_aesenc_si128(t4, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t2 = _mm_aesenc_si128(t2, ks[10]);
+		t3 = _mm_aesenc_si128(t3, ks[10]);
+		t4 = _mm_aesenc_si128(t4, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t2 = _mm_aesenc_si128(t2, ks[11]);
+		t3 = _mm_aesenc_si128(t3, ks[11]);
+		t4 = _mm_aesenc_si128(t4, ks[11]);
+		t1 = _mm_aesenc_si128(t1, ks[12]);
+		t2 = _mm_aesenc_si128(t2, ks[12]);
+		t3 = _mm_aesenc_si128(t3, ks[12]);
+		t4 = _mm_aesenc_si128(t4, ks[12]);
+		t1 = _mm_aesenc_si128(t1, ks[13]);
+		t2 = _mm_aesenc_si128(t2, ks[13]);
+		t3 = _mm_aesenc_si128(t3, ks[13]);
+		t4 = _mm_aesenc_si128(t4, ks[13]);
+
+		t1 = _mm_aesenclast_si128(t1, ks[14]);
+		t2 = _mm_aesenclast_si128(t2, ks[14]);
+		t3 = _mm_aesenclast_si128(t3, ks[14]);
+		t4 = _mm_aesenclast_si128(t4, ks[14]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		t2 = _mm_xor_si128(t2, d2);
+		t3 = _mm_xor_si128(t3, d3);
+		t4 = _mm_xor_si128(t4, d4);
+
+		_mm_storeu_si128(bo + i + 0, t1);
+		_mm_storeu_si128(bo + i + 1, t2);
+		_mm_storeu_si128(bo + i + 2, t3);
+		_mm_storeu_si128(bo + i + 3, t4);
+	}
+
+	for (i = pblocks; i < blocks; i++)
+	{
+		d1 = _mm_loadu_si128(bi + i);
+
+		y = ghash(this->h, y, d1);
+
+		t1 = _mm_xor_si128(cb, ks[0]);
+		t1 = _mm_aesenc_si128(t1, ks[1]);
+		t1 = _mm_aesenc_si128(t1, ks[2]);
+		t1 = _mm_aesenc_si128(t1, ks[3]);
+		t1 = _mm_aesenc_si128(t1, ks[4]);
+		t1 = _mm_aesenc_si128(t1, ks[5]);
+		t1 = _mm_aesenc_si128(t1, ks[6]);
+		t1 = _mm_aesenc_si128(t1, ks[7]);
+		t1 = _mm_aesenc_si128(t1, ks[8]);
+		t1 = _mm_aesenc_si128(t1, ks[9]);
+		t1 = _mm_aesenc_si128(t1, ks[10]);
+		t1 = _mm_aesenc_si128(t1, ks[11]);
+		t1 = _mm_aesenc_si128(t1, ks[12]);
+		t1 = _mm_aesenc_si128(t1, ks[13]);
+		t1 = _mm_aesenclast_si128(t1, ks[14]);
+
+		t1 = _mm_xor_si128(t1, d1);
+		_mm_storeu_si128(bo + i, t1);
+
+		cb = increment_be(cb);
+	}
+
+	if (rem)
+	{
+		y = decrypt_gcm_rem(this, rem, bi + blocks, bo + blocks, cb, y);
+	}
+	y = icv_tailer(this, y, alen, len);
+	icv_crypt(this, y, j, icv);
+}
+
+METHOD(aead_t, encrypt, bool,
+	private_aesni_gcm_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
+	chunk_t *encr)
+{
+	u_char *out;
+
+	if (!this->key || iv.len != IV_SIZE)
+	{
+		return FALSE;
+	}
+	out = plain.ptr;
+	if (encr)
+	{
+		*encr = chunk_alloc(plain.len + this->icv_size);
+		out = encr->ptr;
+	}
+	this->encrypt(this, plain.len, plain.ptr, out, iv.ptr,
+				  assoc.len, assoc.ptr, out + plain.len);
+	return TRUE;
+}
+
+METHOD(aead_t, decrypt, bool,
+	private_aesni_gcm_t *this, chunk_t encr, chunk_t assoc, chunk_t iv,
+	chunk_t *plain)
+{
+	u_char *out, icv[this->icv_size];
+
+	if (!this->key || iv.len != IV_SIZE || encr.len < this->icv_size)
+	{
+		return FALSE;
+	}
+	encr.len -= this->icv_size;
+	out = encr.ptr;
+	if (plain)
+	{
+		*plain = chunk_alloc(encr.len);
+		out = plain->ptr;
+	}
+	this->decrypt(this, encr.len, encr.ptr, out, iv.ptr,
+				  assoc.len, assoc.ptr, icv);
+	return memeq_const(icv, encr.ptr + encr.len, this->icv_size);
+}
+
+METHOD(aead_t, get_block_size, size_t,
+	private_aesni_gcm_t *this)
+{
+	return 1;
+}
+
+METHOD(aead_t, get_icv_size, size_t,
+	private_aesni_gcm_t *this)
+{
+	return this->icv_size;
+}
+
+METHOD(aead_t, get_iv_size, size_t,
+	private_aesni_gcm_t *this)
+{
+	return IV_SIZE;
+}
+
+METHOD(aead_t, get_iv_gen, iv_gen_t*,
+	private_aesni_gcm_t *this)
+{
+	return this->iv_gen;
+}
+
+METHOD(aead_t, get_key_size, size_t,
+	private_aesni_gcm_t *this)
+{
+	return this->key_size + SALT_SIZE;
+}
+
+METHOD(aead_t, set_key, bool,
+	private_aesni_gcm_t *this, chunk_t key)
+{
+	u_int round;
+	__m128i *ks, h;
+
+	if (key.len != this->key_size + SALT_SIZE)
+	{
+		return FALSE;
+	}
+
+	memcpy(this->salt, key.ptr + key.len - SALT_SIZE, SALT_SIZE);
+	key.len -= SALT_SIZE;
+
+	DESTROY_IF(this->key);
+	this->key = aesni_key_create(TRUE, key);
+
+	ks = this->key->schedule;
+	h = _mm_xor_si128(_mm_setzero_si128(), ks[0]);
+	for (round = 1; round < this->key->rounds; round++)
+	{
+		h = _mm_aesenc_si128(h, ks[round]);
+	}
+	h = _mm_aesenclast_si128(h, ks[this->key->rounds]);
+
+	this->h = h;
+	h = swap128(h);
+	this->hh = mult_block(h, this->h);
+	this->hhh = mult_block(h, this->hh);
+	this->hhhh = mult_block(h, this->hhh);
+	this->h = swap128(this->h);
+	this->hh = swap128(this->hh);
+	this->hhh = swap128(this->hhh);
+	this->hhhh = swap128(this->hhhh);
+
+	return TRUE;
+}
+
+METHOD(aead_t, destroy, void,
+	private_aesni_gcm_t *this)
+{
+	DESTROY_IF(this->key);
+	memwipe(&this->h, sizeof(this->h));
+	memwipe(&this->hh, sizeof(this->hh));
+	memwipe(&this->hhh, sizeof(this->hhh));
+	memwipe(&this->hhhh, sizeof(this->hhhh));
+	this->iv_gen->destroy(this->iv_gen);
+	free_align(this);
+}
+
+/**
+ * See header
+ */
+aesni_gcm_t *aesni_gcm_create(encryption_algorithm_t algo,
+							  size_t key_size, size_t salt_size)
+{
+	private_aesni_gcm_t *this;
+	size_t icv_size;
+
+	switch (key_size)
+	{
+		case 0:
+			key_size = 16;
+			break;
+		case 16:
+		case 24:
+		case 32:
+			break;
+		default:
+			return NULL;
+	}
+	if (salt_size && salt_size != SALT_SIZE)
+	{
+		/* currently not supported */
+		return NULL;
+	}
+	switch (algo)
+	{
+		case ENCR_AES_GCM_ICV8:
+			algo = ENCR_AES_CBC;
+			icv_size = 8;
+			break;
+		case ENCR_AES_GCM_ICV12:
+			algo = ENCR_AES_CBC;
+			icv_size = 12;
+			break;
+		case ENCR_AES_GCM_ICV16:
+			algo = ENCR_AES_CBC;
+			icv_size = 16;
+			break;
+		default:
+			return NULL;
+	}
+
+	INIT_ALIGN(this, sizeof(__m128i),
+		.public = {
+			.aead = {
+				.encrypt = _encrypt,
+				.decrypt = _decrypt,
+				.get_block_size = _get_block_size,
+				.get_icv_size = _get_icv_size,
+				.get_iv_size = _get_iv_size,
+				.get_iv_gen = _get_iv_gen,
+				.get_key_size = _get_key_size,
+				.set_key = _set_key,
+				.destroy = _destroy,
+			},
+		},
+		.key_size = key_size,
+		.iv_gen = iv_gen_seq_create(),
+		.icv_size = icv_size,
+	);
+
+	switch (key_size)
+	{
+		case 16:
+			this->encrypt = encrypt_gcm128;
+			this->decrypt = decrypt_gcm128;
+			break;
+		case 24:
+			this->encrypt = encrypt_gcm192;
+			this->decrypt = decrypt_gcm192;
+			break;
+		case 32:
+			this->encrypt = encrypt_gcm256;
+			this->decrypt = decrypt_gcm256;
+			break;
+	}
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/plugins/aesni/aesni_gcm.h b/src/libstrongswan/plugins/aesni/aesni_gcm.h
new file mode 100644
index 0000000..5a256c8
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_gcm.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup aesni_gcm aesni_gcm
+ * @{ @ingroup aesni
+ */
+
+#ifndef AESNI_GCM_H_
+#define AESNI_GCM_H_
+
+#include <library.h>
+
+typedef struct aesni_gcm_t aesni_gcm_t;
+
+/**
+ * GCM mode AEAD using AES-NI
+ */
+struct aesni_gcm_t {
+
+	/**
+	 * Implements aead_t interface
+	 */
+	aead_t aead;
+};
+
+/**
+ * Create a aesni_gcm instance.
+ *
+ * @param algo			encryption algorithm, ENCR_AES_GCM*
+ * @param key_size		AES key size, in bytes
+ * @param salt_size		size of salt value
+ * @return				AES-GCM AEAD, NULL if not supported
+ */
+aesni_gcm_t *aesni_gcm_create(encryption_algorithm_t algo,
+							  size_t key_size, size_t salt_size);
+
+#endif /** AESNI_GCM_H_ @}*/
diff --git a/src/libstrongswan/plugins/aesni/aesni_key.c b/src/libstrongswan/plugins/aesni/aesni_key.c
new file mode 100644
index 0000000..523266a
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_key.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "aesni_key.h"
+
+/**
+ * Rounds used for each AES key size
+ */
+#define AES128_ROUNDS 10
+#define AES192_ROUNDS 12
+#define AES256_ROUNDS 14
+
+typedef struct private_aesni_key_t private_aesni_key_t;
+
+/**
+ * Private data of an aesni_key_t object.
+ */
+struct private_aesni_key_t {
+
+	/**
+	 * Public aesni_key_t interface.
+	 */
+	aesni_key_t public;
+};
+
+/**
+ * Invert round encryption keys to get a decryption key schedule
+ */
+static void reverse_key(aesni_key_t *this)
+{
+	__m128i t[this->rounds + 1];
+	int i;
+
+	for (i = 0; i <= this->rounds; i++)
+	{
+		t[i] = this->schedule[i];
+	}
+	this->schedule[this->rounds] = t[0];
+	for (i = 1; i < this->rounds; i++)
+	{
+		this->schedule[this->rounds - i] = _mm_aesimc_si128(t[i]);
+	}
+	this->schedule[0] = t[this->rounds];
+
+	memwipe(t, sizeof(t));
+}
+
+/**
+ * Assist in creating a 128-bit round key
+ */
+static __m128i assist128(__m128i a, __m128i b)
+{
+	__m128i c;
+
+	b = _mm_shuffle_epi32(b ,0xff);
+	c = _mm_slli_si128(a, 0x04);
+	a = _mm_xor_si128(a, c);
+	c = _mm_slli_si128(c, 0x04);
+	a = _mm_xor_si128(a, c);
+	c = _mm_slli_si128(c, 0x04);
+	a = _mm_xor_si128(a, c);
+	a = _mm_xor_si128(a, b);
+
+	return a;
+}
+
+/**
+ * Expand a 128-bit key to encryption round keys
+ */
+static void expand128(__m128i *key, __m128i *schedule)
+{
+	__m128i t;
+
+	schedule[0] = t = _mm_loadu_si128(key);
+	schedule[1] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x01));
+	schedule[2] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x02));
+	schedule[3] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x04));
+	schedule[4] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x08));
+	schedule[5] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x10));
+	schedule[6] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x20));
+	schedule[7] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x40));
+	schedule[8] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x80));
+	schedule[9] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x1b));
+	schedule[10]    = assist128(t, _mm_aeskeygenassist_si128(t, 0x36));
+}
+
+/**
+ * Assist in creating a 192-bit round key
+ */
+static __m128i assist192(__m128i b, __m128i c, __m128i *a)
+{
+	__m128i t;
+
+	 b = _mm_shuffle_epi32(b, 0x55);
+	 t = _mm_slli_si128(*a, 0x04);
+	*a = _mm_xor_si128(*a, t);
+	 t = _mm_slli_si128(t, 0x04);
+	*a = _mm_xor_si128(*a, t);
+	 t = _mm_slli_si128(t, 0x04);
+	*a = _mm_xor_si128(*a, t);
+	*a = _mm_xor_si128(*a, b);
+	 b = _mm_shuffle_epi32(*a, 0xff);
+	 t = _mm_slli_si128(c, 0x04);
+	 t = _mm_xor_si128(c, t);
+	 t = _mm_xor_si128(t, b);
+
+	return t;
+}
+
+/**
+ * return a[63:0] | b[63:0] << 64
+ */
+static __m128i _mm_shuffle_i00(__m128i a, __m128i b)
+{
+	return (__m128i)_mm_shuffle_pd((__m128d)a, (__m128d)b, 0);
+}
+
+/**
+ * return a[127:64] >> 64 | b[63:0] << 64
+ */
+static __m128i _mm_shuffle_i01(__m128i a, __m128i b)
+{
+	return (__m128i)_mm_shuffle_pd((__m128d)a, (__m128d)b, 1);
+}
+
+/**
+ * Expand a 192-bit encryption key to round keys
+ */
+static void expand192(__m128i *key, __m128i *schedule)
+{
+	__m128i t1, t2, t3;
+
+	schedule[0] = t1 = _mm_loadu_si128(key);
+	t2 = t3 = _mm_loadu_si128(key + 1);
+
+	t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x1), t2, &t1);
+	schedule[1] = _mm_shuffle_i00(t3, t1);
+	schedule[2] = _mm_shuffle_i01(t1, t2);
+	t2 = t3 = assist192(_mm_aeskeygenassist_si128(t2, 0x2), t2, &t1);
+	schedule[3] = t1;
+
+	t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x4), t2, &t1);
+	schedule[4] = _mm_shuffle_i00(t3, t1);
+	schedule[5] = _mm_shuffle_i01(t1, t2);
+	t2 = t3 = assist192(_mm_aeskeygenassist_si128(t2, 0x8), t2, &t1);
+	schedule[6] = t1;
+
+	t2 = assist192(_mm_aeskeygenassist_si128 (t2,0x10), t2, &t1);
+	schedule[7] = _mm_shuffle_i00(t3, t1);
+	schedule[8] = _mm_shuffle_i01(t1, t2);
+	t2 = t3 = assist192(_mm_aeskeygenassist_si128 (t2,0x20), t2, &t1);
+	schedule[9] = t1;
+
+	t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x40), t2, &t1);
+	schedule[10] = _mm_shuffle_i00(t3, t1);
+	schedule[11] = _mm_shuffle_i01(t1, t2);
+	assist192(_mm_aeskeygenassist_si128(t2, 0x80), t2, &t1);
+	schedule[12] = t1;
+}
+
+/**
+ * Assist in creating a 256-bit round key
+ */
+static __m128i assist256_1(__m128i a, __m128i b)
+{
+	__m128i x, y;
+
+	b = _mm_shuffle_epi32(b, 0xff);
+	y = _mm_slli_si128(a, 0x04);
+	x = _mm_xor_si128(a, y);
+	y = _mm_slli_si128(y, 0x04);
+	x = _mm_xor_si128 (x, y);
+	y = _mm_slli_si128(y, 0x04);
+	x = _mm_xor_si128(x, y);
+	x = _mm_xor_si128(x, b);
+
+	return x;
+}
+
+/**
+ * Assist in creating a 256-bit round key
+ */
+static __m128i assist256_2(__m128i a, __m128i b)
+{
+	__m128i x, y, z;
+
+	y = _mm_aeskeygenassist_si128(a, 0x00);
+	z = _mm_shuffle_epi32(y, 0xaa);
+	y = _mm_slli_si128(b, 0x04);
+	x = _mm_xor_si128(b, y);
+	y = _mm_slli_si128(y, 0x04);
+	x = _mm_xor_si128(x, y);
+	y = _mm_slli_si128(y, 0x04);
+	x = _mm_xor_si128(x, y);
+	x = _mm_xor_si128(x, z);
+
+	return x;
+}
+
+/**
+ * Expand a 256-bit encryption key to round keys
+ */
+static void expand256(__m128i *key, __m128i *schedule)
+{
+	__m128i t1, t2;
+
+	schedule[0] = t1 = _mm_loadu_si128(key);
+	schedule[1] = t2 = _mm_loadu_si128(key + 1);
+
+	schedule[2] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x01));
+	schedule[3] = t2 = assist256_2(t1, t2);
+
+	schedule[4] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x02));
+	schedule[5] = t2 = assist256_2(t1, t2);
+
+	schedule[6] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x04));
+	schedule[7] = t2 = assist256_2(t1, t2);
+
+	schedule[8] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x08));
+	schedule[9] = t2 = assist256_2(t1, t2);
+
+	schedule[10] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x10));
+	schedule[11] = t2 = assist256_2(t1, t2);
+
+	schedule[12] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x20));
+	schedule[13] = t2 = assist256_2(t1, t2);
+
+	schedule[14] = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x40));
+}
+
+METHOD(aesni_key_t, destroy, void,
+	private_aesni_key_t *this)
+{
+	memwipe(this, sizeof(*this) + (this->public.rounds + 1) * AES_BLOCK_SIZE);
+	free_align(this);
+}
+
+/**
+ * See header
+ */
+aesni_key_t *aesni_key_create(bool encrypt, chunk_t key)
+{
+	private_aesni_key_t *this;
+	int rounds;
+
+	switch (key.len)
+	{
+		case 16:
+			rounds = AES128_ROUNDS;
+			break;
+		case 24:
+			rounds = AES192_ROUNDS;
+			break;
+		case 32:
+			rounds = AES256_ROUNDS;
+			break;
+		default:
+			return NULL;
+	}
+
+	INIT_EXTRA_ALIGN(this, (rounds + 1) * AES_BLOCK_SIZE, sizeof(__m128i),
+		.public = {
+			.destroy = _destroy,
+			.rounds = rounds,
+		},
+	);
+
+	switch (key.len)
+	{
+		case 16:
+			expand128((__m128i*)key.ptr, this->public.schedule);
+			break;
+		case 24:
+			expand192((__m128i*)key.ptr, this->public.schedule);
+			break;
+		case 32:
+			expand256((__m128i*)key.ptr, this->public.schedule);
+			break;
+		default:
+			break;
+	}
+
+	if (!encrypt)
+	{
+		reverse_key(&this->public);
+	}
+
+	return &this->public;
+}
diff --git a/src/libstrongswan/plugins/aesni/aesni_key.h b/src/libstrongswan/plugins/aesni/aesni_key.h
new file mode 100644
index 0000000..12dcd22
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_key.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup aesni_key aesni_key
+ * @{ @ingroup aesni
+ */
+
+#ifndef AESNI_KEY_H_
+#define AESNI_KEY_H_
+
+#include <library.h>
+
+#include <wmmintrin.h>
+
+/**
+ * AES block size, in bytes
+ */
+#define AES_BLOCK_SIZE 16
+
+typedef struct aesni_key_t aesni_key_t;
+
+/**
+ * Key schedule for encryption/decryption using on AES-NI.
+ */
+struct aesni_key_t {
+
+	/**
+	 * Destroy a aesni_key_t.
+	 */
+	void (*destroy)(aesni_key_t *this);
+
+	/**
+	 * Number of AES rounds (10, 12, 14)
+	 */
+	int rounds;
+
+	/**
+	 * Key schedule, for each round + the round 0 (whitening)
+	 */
+	__attribute__((aligned(sizeof(__m128i)))) __m128i schedule[];
+};
+
+/**
+ * Create a AESNI key schedule instance.
+ *
+ * @param encrypt		TRUE for encryption schedule, FALSE for decryption
+ * @param key			non-expanded crypto key, 16, 24 or 32 bytes
+ * @return				key schedule, NULL on invalid key size
+ */
+aesni_key_t *aesni_key_create(bool encrypt, chunk_t key);
+
+#endif /** AESNI_KEY_H_ @}*/
diff --git a/src/libstrongswan/plugins/aesni/aesni_plugin.c b/src/libstrongswan/plugins/aesni/aesni_plugin.c
new file mode 100644
index 0000000..b92419d
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_plugin.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "aesni_plugin.h"
+#include "aesni_cbc.h"
+#include "aesni_ctr.h"
+#include "aesni_ccm.h"
+#include "aesni_gcm.h"
+#include "aesni_xcbc.h"
+#include "aesni_cmac.h"
+
+#include <stdio.h>
+
+#include <library.h>
+#include <utils/debug.h>
+#include <utils/cpu_feature.h>
+
+typedef struct private_aesni_plugin_t private_aesni_plugin_t;
+typedef enum cpuid_feature_t cpuid_feature_t;
+
+/**
+ * private data of aesni_plugin
+ */
+struct private_aesni_plugin_t {
+
+	/**
+	 * public functions
+	 */
+	aesni_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+	private_aesni_plugin_t *this)
+{
+	return "aesni";
+}
+
+METHOD(plugin_t, get_features, int,
+	private_aesni_plugin_t *this, plugin_feature_t *features[])
+{
+	static plugin_feature_t f[] = {
+		PLUGIN_REGISTER(CRYPTER, aesni_cbc_create),
+			PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 16),
+			PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 24),
+			PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CBC, 32),
+		PLUGIN_REGISTER(CRYPTER, aesni_ctr_create),
+			PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CTR, 16),
+			PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CTR, 24),
+			PLUGIN_PROVIDE(CRYPTER, ENCR_AES_CTR, 32),
+		PLUGIN_REGISTER(AEAD, aesni_ccm_create),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8,  16),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 16),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 16),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8,  24),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 24),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 24),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV8,  32),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV12, 32),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_CCM_ICV16, 32),
+		PLUGIN_REGISTER(AEAD, aesni_gcm_create),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8,  16),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 16),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 16),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8,  24),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 24),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 24),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV8,  32),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV12, 32),
+			PLUGIN_PROVIDE(AEAD, ENCR_AES_GCM_ICV16, 32),
+		PLUGIN_REGISTER(PRF, aesni_xcbc_prf_create),
+			PLUGIN_PROVIDE(PRF, PRF_AES128_XCBC),
+		PLUGIN_REGISTER(SIGNER, aesni_xcbc_signer_create),
+			PLUGIN_PROVIDE(SIGNER, AUTH_AES_XCBC_96),
+		PLUGIN_REGISTER(PRF, aesni_cmac_prf_create),
+			PLUGIN_PROVIDE(PRF, PRF_AES128_CMAC),
+		PLUGIN_REGISTER(SIGNER, aesni_cmac_signer_create),
+			PLUGIN_PROVIDE(SIGNER, AUTH_AES_CMAC_96),
+	};
+
+	*features = f;
+	if (cpu_feature_available(CPU_FEATURE_AESNI | CPU_FEATURE_PCLMULQDQ))
+	{
+		return countof(f);
+	}
+	return 0;
+}
+
+METHOD(plugin_t, destroy, void,
+	private_aesni_plugin_t *this)
+{
+	free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *aesni_plugin_create()
+{
+	private_aesni_plugin_t *this;
+
+	INIT(this,
+		.public = {
+			.plugin = {
+				.get_name = _get_name,
+				.get_features = _get_features,
+				.reload = (void*)return_false,
+				.destroy = _destroy,
+			},
+		},
+	);
+
+	return &this->public.plugin;
+}
diff --git a/src/libstrongswan/crypto/iv/iv_gen_seq.h b/src/libstrongswan/plugins/aesni/aesni_plugin.h
similarity index 54%
copy from src/libstrongswan/crypto/iv/iv_gen_seq.h
copy to src/libstrongswan/plugins/aesni/aesni_plugin.h
index 329dcca..2b0c92c 100644
--- a/src/libstrongswan/crypto/iv/iv_gen_seq.h
+++ b/src/libstrongswan/plugins/aesni/aesni_plugin.h
@@ -1,6 +1,6 @@
 /*
- * Copyright (C) 2013 Tobias Brunner
- * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -14,19 +14,29 @@
  */
 
 /**
- * @{ @ingroup iv
+ * @defgroup aesni aesni
+ * @ingroup plugins
+ *
+ * @defgroup aesni_plugin aesni_plugin
+ * @{ @ingroup aesni
  */
 
-#ifndef IV_GEN_SEQ_H_
-#define IV_GEN_SEQ_H_
+#ifndef AESNI_PLUGIN_H_
+#define AESNI_PLUGIN_H_
+
+#include <plugins/plugin.h>
 
-#include <crypto/iv/iv_gen.h>
+typedef struct aesni_plugin_t aesni_plugin_t;
 
 /**
- * Create an IV generator that generates sequential IVs (counter).
- *
- * @return		IV generator
+ * Plugin providing crypto primitives based on Intel AES-NI instructions.
  */
-iv_gen_t *iv_gen_seq_create();
+struct aesni_plugin_t {
+
+	/**
+	 * implements plugin interface
+	 */
+	plugin_t plugin;
+};
 
-#endif /** IV_GEN_SEQ_H_ @}*/
+#endif /** AESNI_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/aesni/aesni_xcbc.c b/src/libstrongswan/plugins/aesni/aesni_xcbc.c
new file mode 100644
index 0000000..24a75ce
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_xcbc.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (C) 2008-2015 Martin Willi
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "aesni_xcbc.h"
+#include "aesni_key.h"
+
+#include <crypto/prfs/mac_prf.h>
+#include <crypto/signers/mac_signer.h>
+
+typedef struct private_aesni_mac_t private_aesni_mac_t;
+
+/**
+ * Private data of a mac_t object.
+ */
+struct private_aesni_mac_t {
+
+	/**
+	 * Public mac_t interface.
+	 */
+	mac_t public;
+
+	/**
+	 * Key schedule for K1
+	 */
+	aesni_key_t *k1;
+
+	/**
+	 * k2
+	 */
+	__m128i k2;
+
+	/**
+	 * k3
+	 */
+	__m128i k3;
+
+	/**
+	 * E
+	 */
+	__m128i e;
+
+	/**
+	 * remaining, unprocessed bytes in append mode
+	 */
+	u_char rem[AES_BLOCK_SIZE];
+
+	/**
+	 * number of bytes used in remaining
+	 */
+	int rem_size;
+
+	/**
+	 * TRUE if we have zero bytes to xcbc in final()
+	 */
+	bool zero;
+};
+
+METHOD(mac_t, get_mac, bool,
+	private_aesni_mac_t *this, chunk_t data, u_int8_t *out)
+{
+	__m128i *ks, e, *bi;
+	u_int blocks, rem, i;
+
+	if (!this->k1)
+	{
+		return FALSE;
+	}
+
+	ks = this->k1->schedule;
+
+	e = this->e;
+
+	if (data.len)
+	{
+		this->zero = FALSE;
+	}
+
+	if (this->rem_size + data.len > AES_BLOCK_SIZE)
+	{
+		/* (3) For each block M[i], where i = 1 ... n-1:
+		 *     XOR M[i] with E[i-1], then encrypt the result with Key K1,
+		 *     yielding E[i].
+		 */
+
+		/* append data to remaining bytes, process block M[1] */
+		memcpy(this->rem + this->rem_size, data.ptr,
+			   AES_BLOCK_SIZE - this->rem_size);
+		data = chunk_skip(data, AES_BLOCK_SIZE - this->rem_size);
+
+		e = _mm_xor_si128(e, _mm_loadu_si128((__m128i*)this->rem));
+
+		e = _mm_xor_si128(e, ks[0]);
+		e = _mm_aesenc_si128(e, ks[1]);
+		e = _mm_aesenc_si128(e, ks[2]);
+		e = _mm_aesenc_si128(e, ks[3]);
+		e = _mm_aesenc_si128(e, ks[4]);
+		e = _mm_aesenc_si128(e, ks[5]);
+		e = _mm_aesenc_si128(e, ks[6]);
+		e = _mm_aesenc_si128(e, ks[7]);
+		e = _mm_aesenc_si128(e, ks[8]);
+		e = _mm_aesenc_si128(e, ks[9]);
+		e = _mm_aesenclast_si128(e, ks[10]);
+
+		bi = (__m128i*)data.ptr;
+		rem = data.len % AES_BLOCK_SIZE;
+		blocks = data.len / AES_BLOCK_SIZE;
+		if (!rem && blocks)
+		{	/* don't do last block */
+			rem = AES_BLOCK_SIZE;
+			blocks--;
+		}
+
+		/* process blocks M[2] ... M[n-1] */
+		for (i = 0; i < blocks; i++)
+		{
+			e = _mm_xor_si128(e, _mm_loadu_si128(bi + i));
+
+			e = _mm_xor_si128(e, ks[0]);
+			e = _mm_aesenc_si128(e, ks[1]);
+			e = _mm_aesenc_si128(e, ks[2]);
+			e = _mm_aesenc_si128(e, ks[3]);
+			e = _mm_aesenc_si128(e, ks[4]);
+			e = _mm_aesenc_si128(e, ks[5]);
+			e = _mm_aesenc_si128(e, ks[6]);
+			e = _mm_aesenc_si128(e, ks[7]);
+			e = _mm_aesenc_si128(e, ks[8]);
+			e = _mm_aesenc_si128(e, ks[9]);
+			e = _mm_aesenclast_si128(e, ks[10]);
+		}
+
+		/* store remaining bytes of block M[n] */
+		memcpy(this->rem, data.ptr + data.len - rem, rem);
+		this->rem_size = rem;
+	}
+	else
+	{
+		/* no complete block, just copy into remaining */
+		memcpy(this->rem + this->rem_size, data.ptr, data.len);
+		this->rem_size += data.len;
+	}
+
+	if (out)
+	{
+		/* (4) For block M[n]: */
+		if (this->rem_size == AES_BLOCK_SIZE && !this->zero)
+		{
+			/* a) If the blocksize of M[n] is 128 bits:
+			 *    XOR M[n] with E[n-1] and Key K2, then encrypt the result with
+			 *    Key K1, yielding E[n].
+			 */
+			e = _mm_xor_si128(e, this->k2);
+		}
+		else
+		{
+			/* b) If the blocksize of M[n] is less than 128 bits:
+			 *
+			 *  i) Pad M[n] with a single "1" bit, followed by the number of
+			 *     "0" bits (possibly none) required to increase M[n]'s
+			 *     blocksize to 128 bits.
+			 */
+			if (this->rem_size < AES_BLOCK_SIZE)
+			{
+				memset(this->rem + this->rem_size, 0,
+					   AES_BLOCK_SIZE - this->rem_size);
+				this->rem[this->rem_size] = 0x80;
+			}
+			/*  ii) XOR M[n] with E[n-1] and Key K3, then encrypt the result
+			 *      with Key K1, yielding E[n].
+			 */
+			e = _mm_xor_si128(e, this->k3);
+		}
+		e = _mm_xor_si128(e, _mm_loadu_si128((__m128i*)this->rem));
+
+		e = _mm_xor_si128(e, ks[0]);
+		e = _mm_aesenc_si128(e, ks[1]);
+		e = _mm_aesenc_si128(e, ks[2]);
+		e = _mm_aesenc_si128(e, ks[3]);
+		e = _mm_aesenc_si128(e, ks[4]);
+		e = _mm_aesenc_si128(e, ks[5]);
+		e = _mm_aesenc_si128(e, ks[6]);
+		e = _mm_aesenc_si128(e, ks[7]);
+		e = _mm_aesenc_si128(e, ks[8]);
+		e = _mm_aesenc_si128(e, ks[9]);
+		e = _mm_aesenclast_si128(e, ks[10]);
+		_mm_storeu_si128((__m128i*)out, e);
+
+		/* (2) Define E[0] = 0x00000000000000000000000000000000 */
+		e = _mm_setzero_si128();
+		this->rem_size = 0;
+		this->zero = TRUE;
+	}
+	this->e = e;
+	return TRUE;
+}
+
+METHOD(mac_t, get_mac_size, size_t,
+	private_aesni_mac_t *this)
+{
+	return AES_BLOCK_SIZE;
+}
+
+METHOD(mac_t, set_key, bool,
+	private_aesni_mac_t *this, chunk_t key)
+{
+	__m128i t1, t2, t3;
+	u_char k1[AES_BLOCK_SIZE];
+	u_int round;
+	chunk_t k;
+
+	/* reset state */
+	this->e = _mm_setzero_si128();
+	this->rem_size = 0;
+	this->zero = TRUE;
+
+	/* Create RFC4434 variable keys if required */
+	if (key.len == AES_BLOCK_SIZE)
+	{
+		k = key;
+	}
+	else if (key.len < AES_BLOCK_SIZE)
+	{	/* pad short keys */
+		k = chunk_alloca(AES_BLOCK_SIZE);
+		memset(k.ptr, 0, k.len);
+		memcpy(k.ptr, key.ptr, key.len);
+	}
+	else
+	{	/* shorten key using XCBC */
+		k = chunk_alloca(AES_BLOCK_SIZE);
+		memset(k.ptr, 0, k.len);
+		if (!set_key(this, k) || !get_mac(this, key, k.ptr))
+		{
+			return FALSE;
+		}
+	}
+
+	/*
+	 * (1) Derive 3 128-bit keys (K1, K2 and K3) from the 128-bit secret
+	 *     key K, as follows:
+	 *     K1 = 0x01010101010101010101010101010101 encrypted with Key K
+	 *     K2 = 0x02020202020202020202020202020202 encrypted with Key K
+	 *     K3 = 0x03030303030303030303030303030303 encrypted with Key K
+	 */
+
+	DESTROY_IF(this->k1);
+	this->k1 = aesni_key_create(TRUE, k);
+	if (!this->k1)
+	{
+		return FALSE;
+	}
+
+	t1 = _mm_set1_epi8(0x01);
+	t2 = _mm_set1_epi8(0x02);
+	t3 = _mm_set1_epi8(0x03);
+
+	t1 = _mm_xor_si128(t1, this->k1->schedule[0]);
+	t2 = _mm_xor_si128(t2, this->k1->schedule[0]);
+	t3 = _mm_xor_si128(t3, this->k1->schedule[0]);
+
+	for (round = 1; round < this->k1->rounds; round++)
+	{
+		t1 = _mm_aesenc_si128(t1, this->k1->schedule[round]);
+		t2 = _mm_aesenc_si128(t2, this->k1->schedule[round]);
+		t3 = _mm_aesenc_si128(t3, this->k1->schedule[round]);
+	}
+
+	t1 = _mm_aesenclast_si128(t1, this->k1->schedule[this->k1->rounds]);
+	t2 = _mm_aesenclast_si128(t2, this->k1->schedule[this->k1->rounds]);
+	t3 = _mm_aesenclast_si128(t3, this->k1->schedule[this->k1->rounds]);
+
+	_mm_storeu_si128((__m128i*)k1, t1);
+	this->k2 = t2;
+	this->k3 = t3;
+
+	this->k1->destroy(this->k1);
+	this->k1 = aesni_key_create(TRUE, chunk_from_thing(k1));
+
+	memwipe(k1, AES_BLOCK_SIZE);
+	return this->k1 != NULL;
+}
+
+METHOD(mac_t, destroy, void,
+	private_aesni_mac_t *this)
+{
+	DESTROY_IF(this->k1);
+	memwipe(&this->k2, sizeof(this->k2));
+	memwipe(&this->k3, sizeof(this->k3));
+	free_align(this);
+}
+
+/*
+ * Described in header
+ */
+mac_t *aesni_xcbc_create(encryption_algorithm_t algo, size_t key_size)
+{
+	private_aesni_mac_t *this;
+
+	INIT_ALIGN(this, sizeof(__m128i),
+		.public = {
+			.get_mac = _get_mac,
+			.get_mac_size = _get_mac_size,
+			.set_key = _set_key,
+			.destroy = _destroy,
+		},
+	);
+
+	return &this->public;
+}
+
+/*
+ * Described in header.
+ */
+prf_t *aesni_xcbc_prf_create(pseudo_random_function_t algo)
+{
+	mac_t *xcbc;
+
+	switch (algo)
+	{
+		case PRF_AES128_XCBC:
+			xcbc = aesni_xcbc_create(ENCR_AES_CBC, 16);
+			break;
+		default:
+			return NULL;
+	}
+	if (xcbc)
+	{
+		return mac_prf_create(xcbc);
+	}
+	return NULL;
+}
+
+/*
+ * Described in header
+ */
+signer_t *aesni_xcbc_signer_create(integrity_algorithm_t algo)
+{
+	size_t trunc;
+	mac_t *xcbc;
+
+	switch (algo)
+	{
+		case AUTH_AES_XCBC_96:
+			xcbc = aesni_xcbc_create(ENCR_AES_CBC, 16);
+			trunc = 12;
+			break;
+		default:
+			return NULL;
+	}
+	if (xcbc)
+	{
+		return mac_signer_create(xcbc, trunc);
+	}
+	return NULL;
+}
diff --git a/src/libstrongswan/plugins/aesni/aesni_xcbc.h b/src/libstrongswan/plugins/aesni/aesni_xcbc.h
new file mode 100644
index 0000000..53f559f
--- /dev/null
+++ b/src/libstrongswan/plugins/aesni/aesni_xcbc.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup aesni_xcbc aesni_xcbc
+ * @{ @ingroup aesni
+ */
+
+#ifndef AESNI_XCBC_H_
+#define AESNI_XCBC_H_
+
+#include <crypto/mac.h>
+#include <crypto/prfs/prf.h>
+#include <crypto/signers/signer.h>
+
+/**
+ * Create a generic mac_t object using AESNI XCBC
+ *
+ * @param algo		underlying encryption algorithm
+ * @param key_size	size of encryption key, in bytes
+ */
+mac_t *aesni_xcbc_create(encryption_algorithm_t algo, size_t key_size);
+
+/**
+ * Creates a new prf_t object based AESNI XCBC.
+ *
+ * @param algo		algorithm to implement
+ * @return			prf_t object, NULL if not supported
+ */
+prf_t *aesni_xcbc_prf_create(pseudo_random_function_t algo);
+
+/**
+ * Creates a new signer_t object based on AESNI XCBC.
+ *
+ * @param algo		algorithm to implement
+ * @return			signer_t, NULL if not supported
+ */
+signer_t *aesni_xcbc_signer_create(integrity_algorithm_t algo);
+
+#endif /** AESNI_XCBC_H_ @}*/
diff --git a/src/libstrongswan/plugins/af_alg/af_alg_signer.c b/src/libstrongswan/plugins/af_alg/af_alg_signer.c
index 9ad0110..1403144 100644
--- a/src/libstrongswan/plugins/af_alg/af_alg_signer.c
+++ b/src/libstrongswan/plugins/af_alg/af_alg_signer.c
@@ -138,7 +138,7 @@ METHOD(signer_t, verify_signature, bool,
 	{
 		return FALSE;
 	}
-	return memeq(signature.ptr, sig, signature.len);
+	return memeq_const(signature.ptr, sig, signature.len);
 }
 
 METHOD(signer_t, get_key_size, size_t,
diff --git a/src/libstrongswan/plugins/ccm/ccm_aead.c b/src/libstrongswan/plugins/ccm/ccm_aead.c
index 6d4b2e1..676d676 100644
--- a/src/libstrongswan/plugins/ccm/ccm_aead.c
+++ b/src/libstrongswan/plugins/ccm/ccm_aead.c
@@ -256,7 +256,7 @@ static bool verify_icv(private_ccm_aead_t *this, chunk_t plain, chunk_t assoc,
 	char buf[this->icv_size];
 
 	return create_icv(this, plain, assoc, iv, buf) &&
-		   memeq(buf, icv, this->icv_size);
+		   memeq_const(buf, icv, this->icv_size);
 }
 
 METHOD(aead_t, encrypt, bool,
diff --git a/src/libstrongswan/plugins/fips_prf/fips_prf.c b/src/libstrongswan/plugins/fips_prf/fips_prf.c
index 25accf9..9297790 100644
--- a/src/libstrongswan/plugins/fips_prf/fips_prf.c
+++ b/src/libstrongswan/plugins/fips_prf/fips_prf.c
@@ -15,8 +15,6 @@
 
 #include "fips_prf.h"
 
-#include <arpa/inet.h>
-
 #include <utils/debug.h>
 
 typedef struct private_fips_prf_t private_fips_prf_t;
diff --git a/src/libstrongswan/plugins/gcm/gcm_aead.c b/src/libstrongswan/plugins/gcm/gcm_aead.c
index 4ab1701..6e1694a 100644
--- a/src/libstrongswan/plugins/gcm/gcm_aead.c
+++ b/src/libstrongswan/plugins/gcm/gcm_aead.c
@@ -276,7 +276,7 @@ static bool verify_icv(private_gcm_aead_t *this, chunk_t assoc, chunk_t crypt,
 	char tmp[this->icv_size];
 
 	return create_icv(this, assoc, crypt, j, tmp) &&
-		   memeq(tmp, icv, this->icv_size);
+		   memeq_const(tmp, icv, this->icv_size);
 }
 
 METHOD(aead_t, encrypt, bool,
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
index 744ec0b..cee25ea 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c
@@ -145,6 +145,24 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
 	return TRUE;
 }
 
+METHOD(diffie_hellman_t, set_private_value, bool,
+	private_gcrypt_dh_t *this, chunk_t value)
+{
+	gcry_error_t err;
+	gcry_mpi_t xa;
+
+	err = gcry_mpi_scan(&xa, GCRYMPI_FMT_USG, value.ptr, value.len, NULL);
+	if (!err)
+	{
+		gcry_mpi_release(this->xa);
+		this->xa = xa;
+		gcry_mpi_powm(this->ya, this->g, this->xa, this->p);
+		gcry_mpi_release(this->zz);
+		this->zz = NULL;
+	}
+	return !err;
+}
+
 METHOD(diffie_hellman_t, get_shared_secret, bool,
 	private_gcrypt_dh_t *this, chunk_t *secret)
 {
@@ -191,6 +209,7 @@ gcrypt_dh_t *create_generic(diffie_hellman_group_t group, size_t exp_len,
 				.get_shared_secret = _get_shared_secret,
 				.set_other_public_value = _set_other_public_value,
 				.get_my_public_value = _get_my_public_value,
+				.set_private_value = _set_private_value,
 				.get_dh_group = _get_dh_group,
 				.destroy = _destroy,
 			},
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
index 480c083..04f1f43 100644
--- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
+++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c
@@ -158,6 +158,9 @@ plugin_t *gcrypt_plugin_create()
 	}
 	gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
 
+	/* initialize static allocations we want to exclude from leak-detective */
+	gcry_create_nonce(NULL, 0);
+
 	INIT(this,
 		.public = {
 			.plugin = {
diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
index 4fcb168..b7ee94e 100644
--- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
+++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c
@@ -162,6 +162,15 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
 	return TRUE;
 }
 
+METHOD(diffie_hellman_t, set_private_value, bool,
+	private_gmp_diffie_hellman_t *this, chunk_t value)
+{
+	mpz_import(this->xa, value.len, 1, 1, 1, 0, value.ptr);
+	mpz_powm(this->ya, this->g, this->xa, this->p);
+	this->computed = FALSE;
+	return TRUE;
+}
+
 METHOD(diffie_hellman_t, get_shared_secret, bool,
 	private_gmp_diffie_hellman_t *this, chunk_t *secret)
 {
@@ -212,6 +221,7 @@ static gmp_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
 				.get_shared_secret = _get_shared_secret,
 				.set_other_public_value = _set_other_public_value,
 				.get_my_public_value = _get_my_public_value,
+				.set_private_value = _set_private_value,
 				.get_dh_group = _get_dh_group,
 				.destroy = _destroy,
 			},
diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
index ad659e4..e738908 100644
--- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
+++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c
@@ -187,7 +187,7 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
 				 " %u bytes", em.len, data.len);
 			goto end;
 		}
-		success = memeq(em.ptr, data.ptr, data.len);
+		success = memeq_const(em.ptr, data.ptr, data.len);
 	}
 	else
 	{   /* IKEv2 and X.509 certificate signatures */
@@ -258,7 +258,7 @@ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
 						goto end_parser;
 					}
 					hasher->destroy(hasher);
-					success = memeq(object.ptr, hash.ptr, hash.len);
+					success = memeq_const(object.ptr, hash.ptr, hash.len);
 					free(hash.ptr);
 					break;
 				}
@@ -500,4 +500,3 @@ gmp_rsa_public_key_t *gmp_rsa_public_key_load(key_type_t type, va_list args)
 
 	return &this->public;
 }
-
diff --git a/src/libstrongswan/plugins/openssl/openssl_crypter.c b/src/libstrongswan/plugins/openssl/openssl_crypter.c
index c2478a4..26f4700 100644
--- a/src/libstrongswan/plugins/openssl/openssl_crypter.c
+++ b/src/libstrongswan/plugins/openssl/openssl_crypter.c
@@ -226,10 +226,12 @@ openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
 					return NULL;
 			}
 			break;
+#ifndef OPENSSL_NO_DES
 		case ENCR_DES_ECB:
 			key_size = 8;
 			this->cipher = EVP_des_ecb();
 			break;
+#endif
 		default:
 		{
 			char* name;
diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
index 2615d60..cac442f 100644
--- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c
@@ -112,6 +112,18 @@ METHOD(diffie_hellman_t, set_other_public_value, bool,
 	return TRUE;
 }
 
+METHOD(diffie_hellman_t, set_private_value, bool,
+	private_openssl_diffie_hellman_t *this, chunk_t value)
+{
+	if (BN_bin2bn(value.ptr, value.len, this->dh->priv_key))
+	{
+		chunk_clear(&this->shared_secret);
+		this->computed = FALSE;
+		return DH_generate_key(this->dh);
+	}
+	return FALSE;
+}
+
 METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
 	private_openssl_diffie_hellman_t *this)
 {
@@ -160,6 +172,7 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(
 				.get_shared_secret = _get_shared_secret,
 				.set_other_public_value = _set_other_public_value,
 				.get_my_public_value = _get_my_public_value,
+				.set_private_value = _set_private_value,
 				.get_dh_group = _get_dh_group,
 				.destroy = _destroy,
 			},
diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
index 550a543..a1af500 100644
--- a/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
+++ b/src/libstrongswan/plugins/openssl/openssl_ec_diffie_hellman.c
@@ -248,6 +248,49 @@ METHOD(diffie_hellman_t, get_my_public_value, bool,
 	return TRUE;
 }
 
+METHOD(diffie_hellman_t, set_private_value, bool,
+	private_openssl_ec_diffie_hellman_t *this, chunk_t value)
+{
+	EC_POINT *pub = NULL;
+	BIGNUM *priv = NULL;
+	bool ret = FALSE;
+
+	priv = BN_bin2bn(value.ptr, value.len, NULL);
+	if (!priv)
+	{
+		goto error;
+	}
+	pub = EC_POINT_new(EC_KEY_get0_group(this->key));
+	if (!pub)
+	{
+		goto error;
+	}
+	if (EC_POINT_mul(this->ec_group, pub, priv, NULL, NULL, NULL) != 1)
+	{
+		goto error;
+	}
+	if (EC_KEY_set_private_key(this->key, priv) != 1)
+	{
+		goto error;
+	}
+	if (EC_KEY_set_public_key(this->key, pub) != 1)
+	{
+		goto error;
+	}
+	ret = TRUE;
+
+error:
+	if (pub)
+	{
+		EC_POINT_free(pub);
+	}
+	if (priv)
+	{
+		BN_free(priv);
+	}
+	return ret;
+}
+
 METHOD(diffie_hellman_t, get_shared_secret, bool,
 	private_openssl_ec_diffie_hellman_t *this, chunk_t *secret)
 {
@@ -558,6 +601,7 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(diffie_hellman_gro
 				.get_shared_secret = _get_shared_secret,
 				.set_other_public_value = _set_other_public_value,
 				.get_my_public_value = _get_my_public_value,
+				.set_private_value = _set_private_value,
 				.get_dh_group = _get_dh_group,
 				.destroy = _destroy,
 			},
diff --git a/src/libstrongswan/plugins/openssl/openssl_hmac.c b/src/libstrongswan/plugins/openssl/openssl_hmac.c
index 4f0bcc7..065187a 100644
--- a/src/libstrongswan/plugins/openssl/openssl_hmac.c
+++ b/src/libstrongswan/plugins/openssl/openssl_hmac.c
@@ -69,15 +69,26 @@ struct private_mac_t {
 	 * Current HMAC context
 	 */
 	HMAC_CTX hmac;
+
+	/**
+	 * Key set on HMAC_CTX?
+	 */
+	bool key_set;
 };
 
 METHOD(mac_t, set_key, bool,
 	private_mac_t *this, chunk_t key)
 {
 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
-	return HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL);
+	if (HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL))
+	{
+		this->key_set = TRUE;
+		return TRUE;
+	}
+	return FALSE;
 #else /* OPENSSL_VERSION_NUMBER < 1.0 */
 	HMAC_Init_ex(&this->hmac, key.ptr, key.len, this->hasher, NULL);
+	this->key_set = TRUE;
 	return TRUE;
 #endif
 }
@@ -85,6 +96,10 @@ METHOD(mac_t, set_key, bool,
 METHOD(mac_t, get_mac, bool,
 	private_mac_t *this, chunk_t data, u_int8_t *out)
 {
+	if (!this->key_set)
+	{
+		return FALSE;
+	}
 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
 	if (!HMAC_Update(&this->hmac, data.ptr, data.len))
 	{
@@ -153,11 +168,6 @@ static mac_t *hmac_create(hash_algorithm_t algo)
 	}
 
 	HMAC_CTX_init(&this->hmac);
-	if (!set_key(this, chunk_empty))
-	{
-		destroy(this);
-		return NULL;
-	}
 
 	return &this->public;
 }
diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c
index 9c3c404..891e829 100644
--- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c
+++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c
@@ -305,7 +305,7 @@ static bool verify_digest(CMS_ContentInfo *cms, CMS_SignerInfo *si, int hash_oid
 	}
 	hasher->destroy(hasher);
 
-	if (!chunk_equals(digest, hash))
+	if (!chunk_equals_const(digest, hash))
 	{
 		free(hash.ptr);
 		DBG1(DBG_LIB, "invalid messageDigest");
diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
index 9748e28..aa54d3b 100644
--- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
+++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c
@@ -74,7 +74,7 @@ static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this,
 								 RSA_PKCS1_PADDING);
 		if (len != -1)
 		{
-			valid = chunk_equals(data, chunk_create(buf, len));
+			valid = chunk_equals_const(data, chunk_create(buf, len));
 		}
 		free(buf);
 	}
diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.c b/src/libstrongswan/plugins/padlock/padlock_plugin.c
index 2005ef6..9ce2109 100644
--- a/src/libstrongswan/plugins/padlock/padlock_plugin.c
+++ b/src/libstrongswan/plugins/padlock/padlock_plugin.c
@@ -23,32 +23,13 @@
 
 #include <library.h>
 #include <plugins/plugin_feature.h>
+#include <utils/cpu_feature.h>
 #include <utils/debug.h>
 
 typedef struct private_padlock_plugin_t private_padlock_plugin_t;
 typedef enum padlock_feature_t padlock_feature_t;
 
 /**
- * Feature flags of padlock, received via cpuid()
- */
-enum padlock_feature_t {
-	PADLOCK_RESERVED_1 = 		(1<<0),
-	PADLOCK_RESERVED_2 = 		(1<<1),
-	PADLOCK_RNG_AVAILABLE = 	(1<<2),
-	PADLOCK_RNG_ENABLED = 		(1<<3),
-	PADLOCK_RESERVED_3 = 		(1<<4),
-	PADLOCK_RESERVED_4 = 		(1<<5),
-	PADLOCK_ACE_AVAILABLE = 	(1<<6),
-	PADLOCK_ACE_ENABLED = 		(1<<7),
-	PADLOCK_ACE2_AVAILABLE = 	(1<<8),
-	PADLOCK_ACE2_ENABLED = 		(1<<9),
-	PADLOCK_PHE_AVAILABLE = 	(1<<10),
-	PADLOCK_PHE_ENABLED = 		(1<<11),
-	PADLOCK_PMM_AVAILABLE = 	(1<<12),
-	PADLOCK_PMM_ENABLED = 		(1<<13),
-};
-
-/**
  * private data of aes_plugin
  */
 struct private_padlock_plugin_t {
@@ -61,48 +42,9 @@ struct private_padlock_plugin_t {
 	/**
 	 * features supported by Padlock
 	 */
-	padlock_feature_t features;
+	cpu_feature_t features;
 };
 
-/**
- * Get cpuid for info, return eax, ebx, ecx and edx. -fPIC requires to save ebx.
- */
-#define cpuid(op, a, b, c, d)\
-	asm (\
-		"pushl %%ebx		\n\t"\
-		"cpuid				\n\t"\
-		"movl %%ebx, %1		\n\t"\
-		"popl %%ebx			\n\t"\
-		: "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
-		: "a" (op));
-
-/**
- * Get features supported by Padlock
- */
-static padlock_feature_t get_padlock_features()
-{
-	char vendor[3 * sizeof(int) + 1];
-	int a, b, c, d;
-
-	cpuid(0, a, b, c, d);
-	/* VendorID string is in b-d-c (yes, in this order) */
-	snprintf(vendor, sizeof(vendor), "%.4s%.4s%.4s", &b, &d, &c);
-
-	/* check if we have a VIA chip */
-	if (streq(vendor, "CentaurHauls"))
-	{
-		cpuid(0xC0000000, a, b, c, d);
-		/* check Centaur Extended Feature Flags */
-		if (a >= 0xC0000001)
-		{
-			cpuid(0xC0000001, a, b, c, d);
-			return d;
-		}
-	}
-	DBG1(DBG_LIB, "Padlock not found, CPU is %s", vendor);
-	return 0;
-}
-
 METHOD(plugin_t, get_name, char*,
 	private_padlock_plugin_t *this)
 {
@@ -132,15 +74,15 @@ METHOD(plugin_t, get_features, int,
 
 	if (!count)
 	{	/* initialize only once */
-		if (this->features & PADLOCK_RNG_ENABLED)
+		if (this->features & CPU_FEATURE_PADLOCK_RNG_ENABLED)
 		{
 			plugin_features_add(f, f_rng, countof(f_rng), &count);
 		}
-		if (this->features & PADLOCK_ACE2_ENABLED)
+		if (this->features & CPU_FEATURE_PADLOCK_ACE2_ENABLED)
 		{
 			plugin_features_add(f, f_aes, countof(f_aes), &count);
 		}
-		if (this->features & PADLOCK_PHE_ENABLED)
+		if (this->features & CPU_FEATURE_PADLOCK_PHE_ENABLED)
 		{
 			plugin_features_add(f, f_sha1, countof(f_sha1), &count);
 		}
@@ -170,25 +112,20 @@ plugin_t *padlock_plugin_create()
 				.destroy = _destroy,
 			},
 		},
-		.features = get_padlock_features(),
+		.features = cpu_feature_get_all(),
 	);
 
-	if (!this->features)
-	{
-		free(this);
-		return NULL;
-	}
-	DBG1(DBG_LIB, "Padlock found, supports:%s%s%s%s%s, enabled:%s%s%s%s%s",
-		 this->features & PADLOCK_RNG_AVAILABLE ? " RNG" : "",
-		 this->features & PADLOCK_ACE_AVAILABLE ? " ACE" : "",
-		 this->features & PADLOCK_ACE2_AVAILABLE ? " ACE2" : "",
-		 this->features & PADLOCK_PHE_AVAILABLE ? " PHE" : "",
-		 this->features & PADLOCK_PMM_AVAILABLE ? " PMM" : "",
-		 this->features & PADLOCK_RNG_ENABLED ? " RNG" : "",
-		 this->features & PADLOCK_ACE_ENABLED ? " ACE" : "",
-		 this->features & PADLOCK_ACE2_ENABLED ? " ACE2" : "",
-		 this->features & PADLOCK_PHE_ENABLED ? " PHE" : "",
-		 this->features & PADLOCK_PMM_ENABLED ? " PMM" : "");
+	DBG1(DBG_LIB, "Padlock features supported:%s%s%s%s%s, enabled:%s%s%s%s%s",
+		 this->features & CPU_FEATURE_PADLOCK_RNG_AVAILABLE ? " RNG" : "",
+		 this->features & CPU_FEATURE_PADLOCK_ACE_AVAILABLE ? " ACE" : "",
+		 this->features & CPU_FEATURE_PADLOCK_ACE2_AVAILABLE ? " ACE2" : "",
+		 this->features & CPU_FEATURE_PADLOCK_PHE_AVAILABLE ? " PHE" : "",
+		 this->features & CPU_FEATURE_PADLOCK_PMM_AVAILABLE ? " PMM" : "",
+		 this->features & CPU_FEATURE_PADLOCK_RNG_ENABLED ? " RNG" : "",
+		 this->features & CPU_FEATURE_PADLOCK_ACE_ENABLED ? " ACE" : "",
+		 this->features & CPU_FEATURE_PADLOCK_ACE2_ENABLED ? " ACE2" : "",
+		 this->features & CPU_FEATURE_PADLOCK_PHE_ENABLED ? " PHE" : "",
+		 this->features & CPU_FEATURE_PADLOCK_PMM_ENABLED ? " PMM" : "");
 
 	return &this->public.plugin;
 }
diff --git a/src/libstrongswan/plugins/pkcs12/pkcs12_decode.c b/src/libstrongswan/plugins/pkcs12/pkcs12_decode.c
index 379f247..4441b27 100644
--- a/src/libstrongswan/plugins/pkcs12/pkcs12_decode.c
+++ b/src/libstrongswan/plugins/pkcs12/pkcs12_decode.c
@@ -356,7 +356,7 @@ static bool verify_mac(hash_algorithm_t hash, chunk_t salt,
 		{
 			break;
 		}
-		if (chunk_equals(mac, calculated))
+		if (chunk_equals_const(mac, calculated))
 		{
 			success = TRUE;
 			break;
diff --git a/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c b/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c
index 48fb5e6..d224ef3 100644
--- a/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c
+++ b/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c
@@ -269,7 +269,7 @@ METHOD(enumerator_t, enumerate, bool,
 		hasher->destroy(hasher);
 		DBG3(DBG_LIB, "hash: %B", &hash);
 
-		valid = chunk_equals(chunk, hash);
+		valid = chunk_equals_const(chunk, hash);
 		free(hash.ptr);
 		if (!valid)
 		{
diff --git a/src/libstrongswan/plugins/plugin_feature.c b/src/libstrongswan/plugins/plugin_feature.c
index 65cdbe9..2d0ce8a 100644
--- a/src/libstrongswan/plugins/plugin_feature.c
+++ b/src/libstrongswan/plugins/plugin_feature.c
@@ -437,10 +437,12 @@ bool plugin_feature_load(plugin_t *plugin, plugin_feature_t *feature,
 	{
 		case FEATURE_CRYPTER:
 			lib->crypto->add_crypter(lib->crypto, feature->arg.crypter.alg,
+								feature->arg.crypter.key_size,
 								name, reg->arg.reg.f);
 			break;
 		case FEATURE_AEAD:
 			lib->crypto->add_aead(lib->crypto, feature->arg.aead.alg,
+								feature->arg.aead.key_size,
 								name, reg->arg.reg.f);
 			break;
 		case FEATURE_SIGNER:
diff --git a/src/libstrongswan/plugins/rdrand/rdrand_plugin.c b/src/libstrongswan/plugins/rdrand/rdrand_plugin.c
index b416c87..b63bc2f 100644
--- a/src/libstrongswan/plugins/rdrand/rdrand_plugin.c
+++ b/src/libstrongswan/plugins/rdrand/rdrand_plugin.c
@@ -20,6 +20,7 @@
 
 #include <library.h>
 #include <utils/debug.h>
+#include <utils/cpu_feature.h>
 
 typedef struct private_rdrand_plugin_t private_rdrand_plugin_t;
 typedef enum cpuid_feature_t cpuid_feature_t;
@@ -35,56 +36,6 @@ struct private_rdrand_plugin_t {
 	rdrand_plugin_t public;
 };
 
-/**
- * CPU feature flags, returned via cpuid(1)
- */
-enum cpuid_feature_t {
-	CPUID_RDRAND =		(1<<30),
-};
-
-/**
- * Get cpuid for info, return eax, ebx, ecx and edx.
- * -fPIC requires to save ebx on IA-32.
- */
-static void cpuid(u_int op, u_int *a, u_int *b, u_int *c, u_int *d)
-{
-#ifdef __x86_64__
-	asm("cpuid" : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) : "a" (op));
-#else /* __i386__ */
-	asm("pushl %%ebx;"
-		"cpuid;"
-		"movl %%ebx, %1;"
-		"popl %%ebx;"
-		: "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) : "a" (op));
-#endif /* __x86_64__ / __i386__*/
-}
-
-/**
- * Check if we have RDRAND instruction
- */
-static bool have_rdrand()
-{
-	char vendor[3 * sizeof(u_int32_t) + 1];
-	u_int a, b, c, d;
-
-	cpuid(0, &a, &b, &c, &d);
-	/* VendorID string is in b-d-c (yes, in this order) */
-	snprintf(vendor, sizeof(vendor), "%.4s%.4s%.4s", &b, &d, &c);
-
-	/* check if we have an Intel CPU */
-	if (streq(vendor, "GenuineIntel"))
-	{
-		cpuid(1, &a, &b, &c, &d);
-		if (c & CPUID_RDRAND)
-		{
-			DBG2(DBG_LIB, "detected RDRAND support on %s CPU", vendor);
-			return TRUE;
-		}
-	}
-	DBG2(DBG_LIB, "no RDRAND support on %s CPU, disabled", vendor);
-	return FALSE;
-}
-
 METHOD(plugin_t, get_name, char*,
 	private_rdrand_plugin_t *this)
 {
@@ -102,10 +53,12 @@ METHOD(plugin_t, get_features, int,
 				PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16),
 	};
 	*features = f;
-	if (have_rdrand())
+	if (cpu_feature_available(CPU_FEATURE_RDRAND))
 	{
+		DBG2(DBG_LIB, "detected RDRAND support, enabled");
 		return countof(f);
 	}
+	DBG2(DBG_LIB, "no RDRAND support detected, disabled");
 	return 0;
 }
 
diff --git a/src/libstrongswan/plugins/sqlite/sqlite_database.c b/src/libstrongswan/plugins/sqlite/sqlite_database.c
index ec1ca14..0a35e30 100644
--- a/src/libstrongswan/plugins/sqlite/sqlite_database.c
+++ b/src/libstrongswan/plugins/sqlite/sqlite_database.c
@@ -69,6 +69,18 @@ typedef struct {
 } transaction_t;
 
 /**
+ * Check if the SQLite library is thread safe
+ */
+static bool is_threadsave()
+{
+#if SQLITE_VERSION_NUMBER >= 3005000
+	return sqlite3_threadsafe() > 0;
+#endif
+	/* sqlite connections prior to 3.5 may be used by a single thread only */
+	return FALSE;
+}
+
+/**
  * Create and run a sqlite stmt using a sql string and args
  */
 static sqlite3_stmt* run(private_sqlite_database_t *this, char *sql,
@@ -168,9 +180,10 @@ typedef struct {
 static void sqlite_enumerator_destroy(sqlite_enumerator_t *this)
 {
 	sqlite3_finalize(this->stmt);
-#if SQLITE_VERSION_NUMBER < 3005000
-	this->database->mutex->unlock(this->database->mutex);
-#endif
+	if (!is_threadsave())
+	{
+		this->database->mutex->unlock(this->database->mutex);
+	}
 	free(this->columns);
 	free(this);
 }
@@ -248,10 +261,10 @@ METHOD(database_t, query, enumerator_t*,
 	sqlite_enumerator_t *enumerator = NULL;
 	int i;
 
-#if SQLITE_VERSION_NUMBER < 3005000
-	/* sqlite connections prior to 3.5 may be used by a single thread only, */
-	this->mutex->lock(this->mutex);
-#endif
+	if (!is_threadsave())
+	{
+		this->mutex->lock(this->mutex);
+	}
 
 	va_start(args, sql);
 	stmt = run(this, sql, &args);
diff --git a/src/libstrongswan/plugins/sqlite/sqlite_plugin.c b/src/libstrongswan/plugins/sqlite/sqlite_plugin.c
index f554a9e..7f46ace 100644
--- a/src/libstrongswan/plugins/sqlite/sqlite_plugin.c
+++ b/src/libstrongswan/plugins/sqlite/sqlite_plugin.c
@@ -16,6 +16,7 @@
 #include "sqlite_plugin.h"
 
 #include <library.h>
+#include <sqlite3.h>
 #include "sqlite_database.h"
 
 typedef struct private_sqlite_plugin_t private_sqlite_plugin_t;
@@ -60,6 +61,7 @@ METHOD(plugin_t, destroy, void,
 plugin_t *sqlite_plugin_create()
 {
 	private_sqlite_plugin_t *this;
+	int threadsave = 0;
 
 	INIT(this,
 		.public = {
@@ -71,6 +73,11 @@ plugin_t *sqlite_plugin_create()
 		},
 	);
 
+#if SQLITE_VERSION_NUMBER >= 3005000
+	threadsave = sqlite3_threadsafe();
+#endif
+	DBG2(DBG_LIB, "using SQLite %s, thread safety %d",
+		 sqlite3_libversion(), threadsave);
+
 	return &this->public.plugin;
 }
-
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.am b/src/libstrongswan/plugins/test_vectors/Makefile.am
index 85f8672..bde27b8 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.am
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.am
@@ -40,6 +40,10 @@ libstrongswan_test_vectors_la_SOURCES = \
 	test_vectors/sha2.c \
 	test_vectors/sha2_hmac.c \
 	test_vectors/fips_prf.c \
+	test_vectors/modp.c \
+	test_vectors/modpsub.c \
+	test_vectors/ecp.c \
+	test_vectors/ecpbp.c \
 	test_vectors/rng.c
 
 libstrongswan_test_vectors_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in
index 8980ec4..e98119b 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.in
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.in
@@ -143,7 +143,8 @@ am_libstrongswan_test_vectors_la_OBJECTS = test_vectors_plugin.lo \
 	test_vectors/md5_hmac.lo test_vectors/sha1.lo \
 	test_vectors/sha1_hmac.lo test_vectors/sha2.lo \
 	test_vectors/sha2_hmac.lo test_vectors/fips_prf.lo \
-	test_vectors/rng.lo
+	test_vectors/modp.lo test_vectors/modpsub.lo \
+	test_vectors/ecp.lo test_vectors/ecpbp.lo test_vectors/rng.lo
 libstrongswan_test_vectors_la_OBJECTS =  \
 	$(am_libstrongswan_test_vectors_la_OBJECTS)
 AM_V_lt = $(am__v_lt_ at AM_V@)
@@ -481,6 +482,10 @@ libstrongswan_test_vectors_la_SOURCES = \
 	test_vectors/sha2.c \
 	test_vectors/sha2_hmac.c \
 	test_vectors/fips_prf.c \
+	test_vectors/modp.c \
+	test_vectors/modpsub.c \
+	test_vectors/ecp.c \
+	test_vectors/ecpbp.c \
 	test_vectors/rng.c
 
 libstrongswan_test_vectors_la_LDFLAGS = -module -avoid-version
@@ -626,6 +631,14 @@ test_vectors/sha2_hmac.lo: test_vectors/$(am__dirstamp) \
 	test_vectors/$(DEPDIR)/$(am__dirstamp)
 test_vectors/fips_prf.lo: test_vectors/$(am__dirstamp) \
 	test_vectors/$(DEPDIR)/$(am__dirstamp)
+test_vectors/modp.lo: test_vectors/$(am__dirstamp) \
+	test_vectors/$(DEPDIR)/$(am__dirstamp)
+test_vectors/modpsub.lo: test_vectors/$(am__dirstamp) \
+	test_vectors/$(DEPDIR)/$(am__dirstamp)
+test_vectors/ecp.lo: test_vectors/$(am__dirstamp) \
+	test_vectors/$(DEPDIR)/$(am__dirstamp)
+test_vectors/ecpbp.lo: test_vectors/$(am__dirstamp) \
+	test_vectors/$(DEPDIR)/$(am__dirstamp)
 test_vectors/rng.lo: test_vectors/$(am__dirstamp) \
 	test_vectors/$(DEPDIR)/$(am__dirstamp)
 
@@ -654,12 +667,16 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/camellia_xcbc.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/cast.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/des.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/ecp.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/ecpbp.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/fips_prf.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/idea.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/md2.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/md4.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/md5.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/md5_hmac.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/modp.Plo at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/modpsub.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/null.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/rc2.Plo at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at test_vectors/$(DEPDIR)/rc5.Plo at am__quote@
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors.h b/src/libstrongswan/plugins/test_vectors/test_vectors.h
index 33c13d9..f7450aa 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors.h
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors.h
@@ -86,6 +86,11 @@ TEST_VECTOR_AEAD(aes_ccm8)
 TEST_VECTOR_AEAD(aes_ccm9)
 TEST_VECTOR_AEAD(aes_ccm10)
 TEST_VECTOR_AEAD(aes_ccm11)
+TEST_VECTOR_AEAD(aes_ccm12)
+TEST_VECTOR_AEAD(aes_ccm13)
+TEST_VECTOR_AEAD(aes_ccm14)
+TEST_VECTOR_AEAD(aes_ccm15)
+TEST_VECTOR_AEAD(aes_ccm16)
 TEST_VECTOR_AEAD(aes_gcm1)
 TEST_VECTOR_AEAD(aes_gcm2)
 TEST_VECTOR_AEAD(aes_gcm3_1)
@@ -100,6 +105,13 @@ TEST_VECTOR_AEAD(aes_gcm13)
 TEST_VECTOR_AEAD(aes_gcm14)
 TEST_VECTOR_AEAD(aes_gcm15)
 TEST_VECTOR_AEAD(aes_gcm16)
+TEST_VECTOR_AEAD(aes_gcm17)
+TEST_VECTOR_AEAD(aes_gcm18)
+TEST_VECTOR_AEAD(aes_gcm19)
+TEST_VECTOR_AEAD(aes_gcm20)
+TEST_VECTOR_AEAD(aes_gcm21)
+TEST_VECTOR_AEAD(aes_gcm22)
+TEST_VECTOR_AEAD(aes_gcm23)
 
 TEST_VECTOR_SIGNER(aes_xcbc_s1)
 TEST_VECTOR_SIGNER(aes_xcbc_s2)
@@ -228,3 +240,23 @@ TEST_VECTOR_RNG(rng_runs_1)
 TEST_VECTOR_RNG(rng_runs_2)
 TEST_VECTOR_RNG(rng_runs_3)
 
+TEST_VECTOR_DH(modp768)
+TEST_VECTOR_DH(modp1024)
+TEST_VECTOR_DH(modp1536)
+TEST_VECTOR_DH(modp2048)
+TEST_VECTOR_DH(modp3072)
+TEST_VECTOR_DH(modp4096)
+TEST_VECTOR_DH(modp6144)
+TEST_VECTOR_DH(modp8192)
+TEST_VECTOR_DH(modp1024_160)
+TEST_VECTOR_DH(modp2048_224)
+TEST_VECTOR_DH(modp2048_256)
+TEST_VECTOR_DH(ecp192)
+TEST_VECTOR_DH(ecp224)
+TEST_VECTOR_DH(ecp256)
+TEST_VECTOR_DH(ecp384)
+TEST_VECTOR_DH(ecp521)
+TEST_VECTOR_DH(ecp224bp)
+TEST_VECTOR_DH(ecp256bp)
+TEST_VECTOR_DH(ecp384bp)
+TEST_VECTOR_DH(ecp512bp)
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/aes_ccm.c b/src/libstrongswan/plugins/test_vectors/test_vectors/aes_ccm.c
index 95c41ec..cb45254 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors/aes_ccm.c
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/aes_ccm.c
@@ -166,3 +166,82 @@ aead_test_vector_t aes_ccm11 = {
 			  "\x66\xca\x61\x1e\x96\x7a\x61\xb3\x1c\x16\x45\x52\xba\x04\x9c\x9f"
 			  "\xb1\xd2\x40\xbc\x52\x7c\x6f\xb1",
 };
+
+/**
+ * The vectors below are defined by ourself
+ */
+aead_test_vector_t aes_ccm12 = {
+	.alg = ENCR_AES_CCM_ICV8, .key_size = 24, .salt_size = 3,
+	.len = 32, .alen = 27,
+	.key	= "\x58\x5d\xa0\x96\x65\x1a\x04\xd7\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+			  "\x29\xa0\xba\x9e\x48\x78\xd1\xba\xee\x49\x83",
+	.iv		= "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+	.adata	= "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
+			  "\xa4\xf0\x13\x05\xd1\x77\x99\x67\x11\xc4\xc6",
+	.plain	= "\x85\x34\x66\x42\xc8\x92\x0f\x36\x58\xe0\x6b\x91\x3c\x98\x5c\xbb"
+			  "\x0a\x85\xcc\x02\xad\x7a\x96\xe9\x65\x43\xa4\xc3\x0f\xdc\x55\x81",
+	.cipher	= "\xfb\xe5\x5d\x34\xbe\xe5\xe8\xe7\x5a\xef\x2f\xbf\x1f\x7f\xd4\xb2"
+			  "\x66\xca\x61\x1e\x96\x7a\x61\xb3\x1c\x16\x45\x52\xba\x04\x9c\x9f"
+			  "\x24\x0e\xd1\xa5\x40\x74\xc8\x4e",
+};
+
+aead_test_vector_t aes_ccm13 = {
+	.alg = ENCR_AES_CCM_ICV8, .key_size = 24, .salt_size = 3,
+	.len = 27, .alen = 32,
+	.key	= "\x58\x5d\xa0\x96\x65\x1a\x04\xd7\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+			  "\x29\xa0\xba\x9e\x48\x78\xd1\xba\xee\x49\x83",
+	.iv		= "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+	.adata	= "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
+			  "\xa4\xf0\x13\x05\xd1\x77\x99\x67\x11\xc4\xc6\xdb\x00\x56\x36\x61",
+	.plain	= "\x85\x34\x66\x42\xc8\x92\x0f\x36\x58\xe0\x6b\x91\x3c\x98\x5c\xbb"
+			  "\x0a\x85\xcc\x02\xad\x7a\x96\xe9\x65\x43\xa4",
+	.cipher	= "\xfb\xe5\x5d\x34\xbe\xe5\xe8\xe7\x5a\xef\x2f\xbf\x1f\x7f\xd4\xb2"
+			  "\x66\xca\x61\x1e\x96\x7a\x61\xb3\x1c\x16\x45\xa6\xe9\x3c\xa8\x50"
+			  "\x4e\x62\x97",
+};
+
+aead_test_vector_t aes_ccm14 = {
+	.alg = ENCR_AES_CCM_ICV8, .key_size = 24, .salt_size = 3,
+	.len = 27, .alen = 27,
+	.key	= "\x58\x5d\xa0\x96\x65\x1a\x04\xd7\x96\xe5\xc5\x68\xaa\x95\x35\xe0"
+			  "\x29\xa0\xba\x9e\x48\x78\xd1\xba\xee\x49\x83",
+	.iv		= "\xe9\xa9\xff\xe9\x57\xba\xfd\x9e",
+	.adata	= "\x44\xa6\x2c\x05\xe9\xe1\x43\xb1\x58\x7c\xf2\x5c\x6d\x39\x0a\x64"
+			  "\xa4\xf0\x13\x05\xd1\x77\x99\x67\x11\xc4\xc6",
+	.plain	= "\x85\x34\x66\x42\xc8\x92\x0f\x36\x58\xe0\x6b\x91\x3c\x98\x5c\xbb"
+			  "\x0a\x85\xcc\x02\xad\x7a\x96\xe9\x65\x43\xa4",
+	.cipher	= "\xfb\xe5\x5d\x34\xbe\xe5\xe8\xe7\x5a\xef\x2f\xbf\x1f\x7f\xd4\xb2"
+			  "\x66\xca\x61\x1e\x96\x7a\x61\xb3\x1c\x16\x45\x11\x03\x16\x48\xfb"
+			  "\xb7\xde\xf1",
+};
+
+aead_test_vector_t aes_ccm15 = {
+	.alg = ENCR_AES_CCM_ICV12, .key_size = 16, .salt_size = 3,
+	.len = 32, .alen = 32,
+	.key	= "\x7c\xc8\x18\x3b\x8d\x99\xe0\x7c\x45\x41\xb8\xbd\x5c\xa7\xc2\x32"
+			  "\x8a\xb8\x02\x59\xa4\xfe\xa9\x2c\x09\x75\x9a\x9b\x3c\x9b\x27\x39"
+			  "\xf9\xd9\x4e",
+	.iv		= "\x63\xb5\x3d\x9d\x43\xf6\x1e\x50",
+	.adata	= "\x57\xf5\x6b\x8b\x57\x5c\x3d\x3b\x13\x02\x01\x0c\x83\x4c\x96\x35"
+			  "\x8e\xd6\x39\xcf\x7d\x14\x9b\x94\xb0\x39\x36\xe6\x8f\x57\xe0\x13",
+	.plain	= "\x3b\x6c\x29\x36\xb6\xef\x07\xa6\x83\x72\x07\x4f\xcf\xfa\x66\x89"
+			  "\x5f\xca\xb1\xba\xd5\x8f\x2c\x27\x30\xdb\x75\x09\x93\xd4\x65\xe4",
+	.cipher	= "\x2b\x94\x71\x1a\xd3\x28\x21\xe5\xe2\xeb\x75\xe8\x09\x98\x9c\x0a"
+			  "\xc9\xea\x3e\xe4\x3a\xf9\x71\x4c\x4f\x16\x73\x1d\xa5\x10\x93\x5b"
+			  "\x83\xcd\xdd\x30\xb9\x3f\x86\xb3\x14\xbb\x7d\x81",
+};
+
+aead_test_vector_t aes_ccm16 = {
+	.alg = ENCR_AES_CCM_ICV12, .key_size = 24, .salt_size = 3,
+	.len = 32, .alen = 32,
+	.key	= "\x7c\xc8\x18\x3b\x8d\x99\xe0\x7c\x45\x41\xb8\xbd\x5c\xa7\xc2\x32"
+			  "\x8a\xb8\x02\x59\xa4\xfe\xa9\x2c\xf9\xd9\x4e",
+	.iv		= "\x63\xb5\x3d\x9d\x43\xf6\x1e\x50",
+	.adata	= "\x57\xf5\x6b\x8b\x57\x5c\x3d\x3b\x13\x02\x01\x0c\x83\x4c\x96\x35"
+			  "\x8e\xd6\x39\xcf\x7d\x14\x9b\x94\xb0\x39\x36\xe6\x8f\x57\xe0\x13",
+	.plain	= "\x3b\x6c\x29\x36\xb6\xef\x07\xa6\x83\x72\x07\x4f\xcf\xfa\x66\x89"
+			  "\x5f\xca\xb1\xba\xd5\x8f\x2c\x27\x30\xdb\x75\x09\x93\xd4\x65\xe4",
+	.cipher	= "\x48\x19\x60\xbb\x65\xa8\x00\xb8\x26\xf1\x7f\x16\x1f\x3c\xfc\x6d"
+			  "\x86\x62\x10\xc5\x51\xcf\xef\x74\xac\xc6\xdf\x28\xac\x36\x6f\xa0"
+			  "\x3a\x38\x24\x50\x68\x0f\x40\x1e\xaf\xea\x42\x16",
+};
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/aes_gcm.c b/src/libstrongswan/plugins/test_vectors/test_vectors/aes_gcm.c
index 1f33bcb..f348cd4 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors/aes_gcm.c
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/aes_gcm.c
@@ -220,3 +220,153 @@ aead_test_vector_t aes_gcm16 = {
 			  "\xc5\xf6\x1e\x63\x93\xba\x7a\x0a\xbc\xc9\xf6\x62\x76\xfc\x6e\xce"
 			  "\x0f\x4e\x17\x68\xcd\xdf\x88\x53\xbb\x2d\x55\x1b",
 };
+
+/**
+ * Some self made vectors for AES-192/256 with ICV8/12
+ */
+aead_test_vector_t aes_gcm17 = {
+	.alg = ENCR_AES_GCM_ICV8, .key_size = 24, .salt_size = 4,
+	.len = 70, .alen = 0,
+	.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c\xca\xfe\xba\xbe",
+	.iv		= "\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+	.plain	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\xb1\x6a\xed\xf5\xaa\x0d",
+	.cipher	= "\x39\x80\xca\x0b\x3c\x00\xe8\x41\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
+			  "\x85\x9e\x1c\xea\xa6\xef\xd9\x84\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
+			  "\x7d\x77\x3d\x00\xc1\x44\xc5\x25\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
+			  "\xb5\xb4\xa5\xeb\x10\x86\xcb\xdd\x59\x76\x52\x0d\xff\xa4\x85\x26"
+			  "\x4b\x54\x22\xa0\xc6\x65\x4d\xa8\x46\x73\xec\xc0\x61\x68",
+};
+aead_test_vector_t aes_gcm18 = {
+	.alg = ENCR_AES_GCM_ICV12, .key_size = 24, .salt_size = 4,
+	.len = 70, .alen = 0,
+	.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c\xca\xfe\xba\xbe",
+	.iv		= "\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+	.plain	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\xb1\x6a\xed\xf5\xaa\x0d",
+	.cipher	= "\x39\x80\xca\x0b\x3c\x00\xe8\x41\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
+			  "\x85\x9e\x1c\xea\xa6\xef\xd9\x84\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
+			  "\x7d\x77\x3d\x00\xc1\x44\xc5\x25\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
+			  "\xb5\xb4\xa5\xeb\x10\x86\xcb\xdd\x59\x76\x52\x0d\xff\xa4\x85\x26"
+			  "\x4b\x54\x22\xa0\xc6\x65\x4d\xa8\x46\x73\xec\xc0\x61\x68\x0f\x00"
+			  "\x0c\x32",
+};
+aead_test_vector_t aes_gcm19 = {
+	.alg = ENCR_AES_GCM_ICV8, .key_size = 32, .salt_size = 4,
+	.len = 70, .alen = 0,
+	.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xca\xfe\xba\xbe",
+	.iv		= "\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+	.plain	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\xb1\x6a\xed\xf5\xaa\x0d",
+	.cipher	= "\x52\x2d\xc1\xf0\x99\x56\x7d\x07\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
+			  "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
+			  "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d\xa7\xb0\x8b\x10\x56\x82\x88\x38"
+			  "\x68\xa0\xff\x03\xac\xdf\x95\x0e\x29\x65\x83\x7f\xda\x89\x72\xdd"
+			  "\xd5\xc5\x96\xa3\x4a\xe0\xe6\x2f\x1e\xe2\x04\x80\xd7\xb7",
+};
+aead_test_vector_t aes_gcm20 = {
+	.alg = ENCR_AES_GCM_ICV12, .key_size = 32, .salt_size = 4,
+	.len = 70, .alen = 0,
+	.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xca\xfe\xba\xbe",
+	.iv		= "\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+	.plain	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\xb1\x6a\xed\xf5\xaa\x0d",
+	.cipher	= "\x52\x2d\xc1\xf0\x99\x56\x7d\x07\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
+			  "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
+			  "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d\xa7\xb0\x8b\x10\x56\x82\x88\x38"
+			  "\x68\xa0\xff\x03\xac\xdf\x95\x0e\x29\x65\x83\x7f\xda\x89\x72\xdd"
+			  "\xd5\xc5\x96\xa3\x4a\xe0\xe6\x2f\x1e\xe2\x04\x80\xd7\xb7\x5b\x65"
+			  "\x9a\xad",
+};
+
+/**
+ * Some self-made vectors using more associated data
+ */
+aead_test_vector_t aes_gcm21 = {
+	.alg = ENCR_AES_GCM_ICV16, .key_size = 16, .salt_size = 4,
+	.len = 70, .alen = 69,
+	.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xca\xfe\xba\xbe",
+	.iv		= "\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+	.adata	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef"
+			  "\xab\xad\xda\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce"
+			  "\xde\xad\xbe\xef\xda\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xda"
+			  "\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xda\xd2\xfe\xed\xfa\xce"
+			  "\xde\xad\xbe\xef\xfe",
+	.plain	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\xb1\x6a\xed\xf5\xaa\x0d",
+	.cipher	= "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c"
+			  "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e"
+			  "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05"
+			  "\xb6\xf5\xea\x59\x55\x6f\x43\x93\xa8\xf4\x95\x8c\x14\x36\x3e\xf5"
+			  "\x6c\xc2\x8a\x31\x64\xff\xe9\x24\x77\xc3\xaf\x6b\x64\xc7\x8b\xb9"
+			  "\xec\xb9\x48\x84\xa2\xdb",
+};
+aead_test_vector_t aes_gcm22 = {
+	.alg = ENCR_AES_GCM_ICV16, .key_size = 24, .salt_size = 4,
+	.len = 70, .alen = 69,
+	.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c\xca\xfe\xba\xbe",
+	.iv		= "\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+	.adata	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef"
+			  "\xab\xad\xda\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce"
+			  "\xde\xad\xbe\xef\xda\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xda"
+			  "\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xda\xd2\xfe\xed\xfa\xce"
+			  "\xde\xad\xbe\xef\xfe",
+	.plain	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\xb1\x6a\xed\xf5\xaa\x0d",
+	.cipher	= "\x39\x80\xca\x0b\x3c\x00\xe8\x41\xeb\x06\xfa\xc4\x87\x2a\x27\x57"
+			  "\x85\x9e\x1c\xea\xa6\xef\xd9\x84\x62\x85\x93\xb4\x0c\xa1\xe1\x9c"
+			  "\x7d\x77\x3d\x00\xc1\x44\xc5\x25\xac\x61\x9d\x18\xc8\x4a\x3f\x47"
+			  "\xb5\xb4\xa5\xeb\x10\x86\xcb\xdd\x59\x76\x52\x0d\xff\xa4\x85\x26"
+			  "\x4b\x54\x22\xa0\xc6\x65\x82\x33\xf3\x2d\x00\xe5\x03\x29\x8f\x7f"
+			  "\x70\x74\xe6\xfe\x60\x75",
+};
+aead_test_vector_t aes_gcm23 = {
+	.alg = ENCR_AES_GCM_ICV16, .key_size = 32, .salt_size = 4,
+	.len = 70, .alen = 69,
+	.key	= "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08"
+			  "\xca\xfe\xba\xbe",
+	.iv		= "\xfa\xce\xdb\xad\xde\xca\xf8\x88",
+	.adata	= "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef"
+			  "\xab\xad\xda\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce"
+			  "\xde\xad\xbe\xef\xda\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xda"
+			  "\xd2\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xda\xd2\xfe\xed\xfa\xce"
+			  "\xde\xad\xbe\xef\xfe",
+	.plain	= "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a"
+			  "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25"
+			  "\xb1\x6a\xed\xf5\xaa\x0d",
+	.cipher	= "\x52\x2d\xc1\xf0\x99\x56\x7d\x07\xf4\x7f\x37\xa3\x2a\x84\x42\x7d"
+			  "\x64\x3a\x8c\xdc\xbf\xe5\xc0\xc9\x75\x98\xa2\xbd\x25\x55\xd1\xaa"
+			  "\x8c\xb0\x8e\x48\x59\x0d\xbb\x3d\xa7\xb0\x8b\x10\x56\x82\x88\x38"
+			  "\x68\xa0\xff\x03\xac\xdf\x95\x0e\x29\x65\x83\x7f\xda\x89\x72\xdd"
+			  "\xd5\xc5\x96\xa3\x4a\xe0\xa8\xb6\x0f\xfe\xd5\xe5\x33\xf4\x37\x74"
+			  "\x83\x93\xf8\xaf\x80\x43",
+};
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/ecp.c b/src/libstrongswan/plugins/test_vectors/test_vectors/ecp.c
new file mode 100644
index 0000000..b3c94b2
--- /dev/null
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/ecp.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the Licenseor (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be usefulbut
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <crypto/crypto_tester.h>
+
+/**
+ * Test vectors from RFC5114
+ */
+
+dh_test_vector_t ecp192 = {
+	.group = ECP_192_BIT, .priv_len = 24, .pub_len = 48, .shared_len = 24,
+	.priv_a	= "\x32\x3f\xa3\x16\x9d\x8e\x9c\x65\x93\xf5\x94\x76\xbc\x14\x20\x00"
+			  "\xab\x5b\xe0\xe2\x49\xc4\x34\x26",
+	.priv_b	= "\x63\x1f\x95\xbb\x4a\x67\x63\x2c\x9c\x47\x6e\xee\x9a\xb6\x95\xab"
+			  "\x24\x0a\x04\x99\x30\x7f\xcf\x62",
+	.pub_a	= "\xcd\x46\x48\x9e\xcf\xd6\xc1\x05\xe7\xb3\xd3\x25\x66\xe2\xb1\x22"
+			  "\xe2\x49\xab\xaa\xdd\x87\x06\x12\x68\x88\x7b\x48\x77\xdf\x51\xdd"
+			  "\x4d\xc3\xd6\xfd\x11\xf0\xa2\x6f\x8f\xd3\x84\x43\x17\x91\x6e\x9a",
+	.pub_b	= "\x51\x9a\x12\x16\x80\xe0\x04\x54\x66\xba\x21\xdf\x2e\xee\x47\xf5"
+			  "\x97\x3b\x50\x05\x77\xef\x13\xd5\xff\x61\x3a\xb4\xd6\x4c\xee\x3a"
+			  "\x20\x87\x5b\xdb\x10\xf9\x53\xf6\xb3\x0c\xa0\x72\xc6\x0a\xa5\x7f",
+	.shared	= "\xad\x42\x01\x82\x63\x3f\x85\x26\xbf\xe9\x54\xac\xda\x37\x6f\x05"
+			  "\xe5\xff\x4f\x83\x7f\x54\xfe\xbe",
+};
+
+dh_test_vector_t ecp224 = {
+	.group = ECP_224_BIT, .priv_len = 28, .pub_len = 56, .shared_len = 28,
+	.priv_a	= "\xb5\x58\xeb\x6c\x28\x8d\xa7\x07\xbb\xb4\xf8\xfb\xae\x2a\xb9\xe9"
+			  "\xcb\x62\xe3\xbc\x5c\x75\x73\xe2\x2e\x26\xd3\x7f",
+	.priv_b	= "\xac\x3b\x1a\xdd\x3d\x97\x70\xe6\xf6\xa7\x08\xee\x9f\x3b\x8e\x0a"
+			  "\xb3\xb4\x80\xe9\xf2\x7f\x85\xc8\x8b\x5e\x6d\x18",
+	.pub_a	= "\x49\xdf\xef\x30\x9f\x81\x48\x8c\x30\x4c\xff\x5a\xb3\xee\x5a\x21"
+			  "\x54\x36\x7d\xc7\x83\x31\x50\xe0\xa5\x1f\x3e\xeb\x4f\x2b\x5e\xe4"
+			  "\x57\x62\xc4\xf6\x54\xc1\xa0\xc6\x7f\x54\xcf\x88\xb0\x16\xb5\x1b"
+			  "\xce\x3d\x7c\x22\x8d\x57\xad\xb4",
+	.pub_b	= "\x6b\x3a\xc9\x6a\x8d\x0c\xde\x6a\x55\x99\xbe\x80\x32\xed\xf1\x0c"
+			  "\x16\x2d\x0a\x8a\xd2\x19\x50\x6d\xcd\x42\xa2\x07\xd4\x91\xbe\x99"
+			  "\xc2\x13\xa7\xd1\xca\x37\x06\xde\xbf\xe3\x05\xf3\x61\xaf\xcb\xb3"
+			  "\x3e\x26\x09\xc8\xb1\x61\x8a\xd5",
+	.shared	= "\x52\x27\x2f\x50\xf4\x6f\x4e\xdc\x91\x51\x56\x90\x92\xf4\x6d\xf2"
+			  "\xd9\x6e\xcc\x3b\x6d\xc1\x71\x4a\x4e\xa9\x49\xfa",
+};
+
+dh_test_vector_t ecp256 = {
+	.group = ECP_256_BIT, .priv_len = 32, .pub_len = 64, .shared_len = 32,
+	.priv_a	= "\x81\x42\x64\x14\x5f\x2f\x56\xf2\xe9\x6a\x8e\x33\x7a\x12\x84\x99"
+			  "\x3f\xaf\x43\x2a\x5a\xbc\xe5\x9e\x86\x7b\x72\x91\xd5\x07\xa3\xaf",
+	.priv_b	= "\x2c\xe1\x78\x8e\xc1\x97\xe0\x96\xdb\x95\xa2\x00\xcc\x0a\xb2\x6a"
+			  "\x19\xce\x6b\xcc\xad\x56\x2b\x8e\xee\x1b\x59\x37\x61\xcf\x7f\x41",
+	.pub_a	= "\x2a\xf5\x02\xf3\xbe\x89\x52\xf2\xc9\xb5\xa8\xd4\x16\x0d\x09\xe9"
+			  "\x71\x65\xbe\x50\xbc\x42\xae\x4a\x5e\x8d\x3b\x4b\xa8\x3a\xeb\x15"
+			  "\xeb\x0f\xaf\x4c\xa9\x86\xc4\xd3\x86\x81\xa0\xf9\x87\x2d\x79\xd5"
+			  "\x67\x95\xbd\x4b\xff\x6e\x6d\xe3\xc0\xf5\x01\x5e\xce\x5e\xfd\x85",
+	.pub_b	= "\xb1\x20\xde\x4a\xa3\x64\x92\x79\x53\x46\xe8\xde\x6c\x2c\x86\x46"
+			  "\xae\x06\xaa\xea\x27\x9f\xa7\x75\xb3\xab\x07\x15\xf6\xce\x51\xb0"
+			  "\x9f\x1b\x7e\xec\xe2\x0d\x7b\x5e\xd8\xec\x68\x5f\xa3\xf0\x71\xd8"
+			  "\x37\x27\x02\x70\x92\xa8\x41\x13\x85\xc3\x4d\xde\x57\x08\xb2\xb6",
+	.shared	= "\xdd\x0f\x53\x96\x21\x9d\x1e\xa3\x93\x31\x04\x12\xd1\x9a\x08\xf1"
+			  "\xf5\x81\x1e\x9d\xc8\xec\x8e\xea\x7f\x80\xd2\x1c\x82\x0c\x27\x88",
+};
+
+dh_test_vector_t ecp384 = {
+	.group = ECP_384_BIT, .priv_len = 48, .pub_len = 96, .shared_len = 48,
+	.priv_a	= "\xd2\x73\x35\xea\x71\x66\x4a\xf2\x44\xdd\x14\xe9\xfd\x12\x60\x71"
+			  "\x5d\xfd\x8a\x79\x65\x57\x1c\x48\xd7\x09\xee\x7a\x79\x62\xa1\x56"
+			  "\xd7\x06\xa9\x0c\xbc\xb5\xdf\x29\x86\xf0\x5f\xea\xdb\x93\x76\xf1",
+	.priv_b	= "\x52\xd1\x79\x1f\xdb\x4b\x70\xf8\x9c\x0f\x00\xd4\x56\xc2\xf7\x02"
+			  "\x3b\x61\x25\x26\x2c\x36\xa7\xdf\x1f\x80\x23\x11\x21\xcc\xe3\xd3"
+			  "\x9b\xe5\x2e\x00\xc1\x94\xa4\x13\x2c\x4a\x6c\x76\x8b\xcd\x94\xd2",
+	.pub_a	= "\x79\x31\x48\xf1\x78\x76\x34\xd5\xda\x4c\x6d\x90\x74\x41\x7d\x05"
+			  "\xe0\x57\xab\x62\xf8\x20\x54\xd1\x0e\xe6\xb0\x40\x3d\x62\x79\x54"
+			  "\x7e\x6a\x8e\xa9\xd1\xfd\x77\x42\x7d\x01\x6f\xe2\x7a\x8b\x8c\x66"
+			  "\xc6\xc4\x12\x94\x33\x1d\x23\xe6\xf4\x80\xf4\xfb\x4c\xd4\x05\x04"
+			  "\xc9\x47\x39\x2e\x94\xf4\xc3\xf0\x6b\x8f\x39\x8b\xb2\x9e\x42\x36"
+			  "\x8f\x7a\x68\x59\x23\xde\x3b\x67\xba\xce\xd2\x14\xa1\xa1\xd1\x28",
+	.pub_b	= "\x5c\xd4\x2a\xb9\xc4\x1b\x53\x47\xf7\x4b\x8d\x4e\xfb\x70\x8b\x3d"
+			  "\x5b\x36\xdb\x65\x91\x53\x59\xb4\x4a\xbc\x17\x64\x7b\x6b\x99\x99"
+			  "\x78\x9d\x72\xa8\x48\x65\xae\x2f\x22\x3f\x12\xb5\xa1\xab\xc1\x20"
+			  "\xe1\x71\x45\x8f\xea\xa9\x39\xaa\xa3\xa8\xbf\xac\x46\xb4\x04\xbd"
+			  "\x8f\x6d\x5b\x34\x8c\x0f\xa4\xd8\x0c\xec\xa1\x63\x56\xca\x93\x32"
+			  "\x40\xbd\xe8\x72\x34\x15\xa8\xec\xe0\x35\xb0\xed\xf3\x67\x55\xde",
+	.shared	= "\x5e\xa1\xfc\x4a\xf7\x25\x6d\x20\x55\x98\x1b\x11\x05\x75\xe0\xa8"
+			  "\xca\xe5\x31\x60\x13\x7d\x90\x4c\x59\xd9\x26\xeb\x1b\x84\x56\xe4"
+			  "\x27\xaa\x8a\x45\x40\x88\x4c\x37\xde\x15\x9a\x58\x02\x8a\xbc\x0e",
+};
+
+dh_test_vector_t ecp521 = {
+	.group = ECP_521_BIT, .priv_len = 66, .pub_len = 132, .shared_len = 66,
+	.priv_a	= "\x01\x13\xf8\x2d\xa8\x25\x73\x5e\x3d\x97\x27\x66\x83\xb2\xb7\x42"
+			  "\x77\xba\xd2\x73\x35\xea\x71\x66\x4a\xf2\x43\x0c\xc4\xf3\x34\x59"
+			  "\xb9\x66\x9e\xe7\x8b\x3f\xfb\x9b\x86\x83\x01\x5d\x34\x4d\xcb\xfe"
+			  "\xf6\xfb\x9a\xf4\xc6\xc4\x70\xbe\x25\x45\x16\xcd\x3c\x1a\x1f\xb4"
+			  "\x73\x62",
+	.priv_b	= "\x00\xce\xe3\x48\x0d\x86\x45\xa1\x7d\x24\x9f\x27\x76\xd2\x8b\xae"
+			  "\x61\x69\x52\xd1\x79\x1f\xdb\x4b\x70\xf7\xc3\x37\x87\x32\xaa\x1b"
+			  "\x22\x92\x84\x48\xbc\xd1\xdc\x24\x96\xd4\x35\xb0\x10\x48\x06\x6e"
+			  "\xbe\x4f\x72\x90\x3c\x36\x1b\x1a\x9d\xc1\x19\x3d\xc2\xc9\xd0\x89"
+			  "\x1b\x96",
+	.pub_a	= "\x01\xeb\xb3\x4d\xd7\x57\x21\xab\xf8\xad\xc9\xdb\xed\x17\x88\x9c"
+			  "\xbb\x97\x65\xd9\x0a\x7c\x60\xf2\xce\xf0\x07\xbb\x0f\x2b\x26\xe1"
+			  "\x48\x81\xfd\x44\x42\xe6\x89\xd6\x1c\xb2\xdd\x04\x6e\xe3\x0e\x3f"
+			  "\xfd\x20\xf9\xa4\x5b\xbd\xf6\x41\x3d\x58\x3a\x2d\xbf\x59\x92\x4f"
+			  "\xd3\x5c\x00\xf6\xb6\x32\xd1\x94\xc0\x38\x8e\x22\xd8\x43\x7e\x55"
+			  "\x8c\x55\x2a\xe1\x95\xad\xfd\x15\x3f\x92\xd7\x49\x08\x35\x1b\x2f"
+			  "\x8c\x4e\xda\x94\xed\xb0\x91\x6d\x1b\x53\xc0\x20\xb5\xee\xca\xed"
+			  "\x1a\x5f\xc3\x8a\x23\x3e\x48\x30\x58\x7b\xb2\xee\x34\x89\xb3\xb4"
+			  "\x2a\x5a\x86\xa4",
+	.pub_b	= "\x01\x0e\xbf\xaf\xc6\xe8\x5e\x08\xd2\x4b\xff\xfc\xc1\xa4\x51\x1d"
+			  "\xb0\xe6\x34\xbe\xeb\x1b\x6d\xec\x8c\x59\x39\xae\x44\x76\x62\x01"
+			  "\xaf\x62\x00\x43\x0b\xa9\x7c\x8a\xc6\xa0\xe9\xf0\x8b\x33\xce\x7e"
+			  "\x9f\xee\xb5\xba\x4e\xe5\xe0\xd8\x15\x10\xc2\x42\x95\xb8\xa0\x8d"
+			  "\x02\x35\x00\xa4\xa6\xec\x30\x0d\xf9\xe2\x57\xb0\x37\x2b\x5e\x7a"
+			  "\xbf\xef\x09\x34\x36\x71\x9a\x77\x88\x7e\xbb\x0b\x18\xcf\x80\x99"
+			  "\xb9\xf4\x21\x2b\x6e\x30\xa1\x41\x9c\x18\xe0\x29\xd3\x68\x63\xcc"
+			  "\x9d\x44\x8f\x4d\xba\x4d\x2a\x0e\x60\x71\x1b\xe5\x72\x91\x5f\xbd"
+			  "\x4f\xef\x26\x95",
+	.shared	= "\x00\xcd\xea\x89\x62\x1c\xfa\x46\xb1\x32\xf9\xe4\xcf\xe2\x26\x1c"
+			  "\xde\x2d\x43\x68\xeb\x56\x56\x63\x4c\x7c\xc9\x8c\x7a\x00\xcd\xe5"
+			  "\x4e\xd1\x86\x6a\x0d\xd3\xe6\x12\x6c\x9d\x2f\x84\x5d\xaf\xf8\x2c"
+			  "\xeb\x1d\xa0\x8f\x5d\x87\x52\x1b\xb0\xeb\xec\xa7\x79\x11\x16\x9c"
+			  "\x20\xcc",
+};
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/ecpbp.c b/src/libstrongswan/plugins/test_vectors/test_vectors/ecpbp.c
new file mode 100644
index 0000000..de43998
--- /dev/null
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/ecpbp.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the Licenseor (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be usefulbut
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <crypto/crypto_tester.h>
+
+/**
+ * Test vectors from RFC6923/RFC7027
+ */
+
+dh_test_vector_t ecp224bp = {
+	.group = ECP_224_BP, .priv_len = 28, .pub_len = 56, .shared_len = 28,
+	.priv_a	= "\x7c\x4b\x7a\x2c\x8a\x4b\xad\x1f\xbb\x7d\x79\xcc\x09\x55\xdb\x7c"
+			  "\x6a\x46\x60\xca\x64\xcc\x47\x78\x15\x9b\x49\x5e",
+	.priv_b	= "\x63\x97\x6d\x4a\xae\x6c\xd0\xf6\xdd\x18\xde\xfe\xf5\x5d\x96\x56"
+			  "\x9d\x05\x07\xc0\x3e\x74\xd6\x48\x6f\xfa\x28\xfb",
+	.pub_a	= "\xb1\x04\xa6\x7a\x6f\x6e\x85\xe1\x4e\xc1\x82\x5e\x15\x39\xe8\xec"
+			  "\xdb\xbf\x58\x49\x22\x36\x7d\xd8\x8c\x6b\xdc\xf2\x46\xd7\x82\xe7"
+			  "\xfd\xb5\xf6\x0c\xd8\x40\x43\x01\xac\x59\x49\xc5\x8e\xdb\x26\xbc"
+			  "\x68\xba\x07\x69\x5b\x75\x0a\x94",
+	.pub_b	= "\x2a\x97\x08\x9a\x92\x96\x14\x7b\x71\xb2\x1a\x4b\x57\x4e\x12\x78"
+			  "\x24\x5b\x53\x6f\x14\xd8\xc2\xb9\xd0\x7a\x87\x4e\x9b\x90\x0d\x7c"
+			  "\x77\xa7\x09\xa7\x97\x27\x6b\x8c\xa1\xba\x61\xbb\x95\xb5\x46\xfc"
+			  "\x29\xf8\x62\xe4\x4d\x59\xd2\x5b",
+	.shared	= "\x31\x2d\xfd\x98\x78\x3f\x9f\xb7\x7b\x97\x04\x94\x5a\x73\xbe\xb6"
+			  "\xdc\xcb\xe3\xb6\x5d\x0f\x96\x7d\xca\xb5\x74\xeb",
+};
+
+dh_test_vector_t ecp256bp = {
+	.group = ECP_256_BP, .priv_len = 32, .pub_len = 64, .shared_len = 32,
+	.priv_a	= "\x81\xdb\x1e\xe1\x00\x15\x0f\xf2\xea\x33\x8d\x70\x82\x71\xbe\x38"
+			  "\x30\x0c\xb5\x42\x41\xd7\x99\x50\xf7\x7b\x06\x30\x39\x80\x4f\x1d",
+	.priv_b	= "\x55\xe4\x0b\xc4\x1e\x37\xe3\xe2\xad\x25\xc3\xc6\x65\x45\x11\xff"
+			  "\xa8\x47\x4a\x91\xa0\x03\x20\x87\x59\x38\x52\xd3\xe7\xd7\x6b\xd3",
+	.pub_a	= "\x44\x10\x6e\x91\x3f\x92\xbc\x02\xa1\x70\x5d\x99\x53\xa8\x41\x4d"
+			  "\xb9\x5e\x1a\xaa\x49\xe8\x1d\x9e\x85\xf9\x29\xa8\xe3\x10\x0b\xe5"
+			  "\x8a\xb4\x84\x6f\x11\xca\xcc\xb7\x3c\xe4\x9c\xbd\xd1\x20\xf5\xa9"
+			  "\x00\xa6\x9f\xd3\x2c\x27\x22\x23\xf7\x89\xef\x10\xeb\x08\x9b\xdc",
+	.pub_b	= "\x8d\x2d\x68\x8c\x6c\xf9\x3e\x11\x60\xad\x04\xcc\x44\x29\x11\x7d"
+			  "\xc2\xc4\x18\x25\xe1\xe9\xfc\xa0\xad\xdd\x34\xe6\xf1\xb3\x9f\x7b"
+			  "\x99\x0c\x57\x52\x08\x12\xbe\x51\x26\x41\xe4\x70\x34\x83\x21\x06"
+			  "\xbc\x7d\x3e\x8d\xd0\xe4\xc7\xf1\x13\x6d\x70\x06\x54\x7c\xec\x6a",
+	.shared	= "\x89\xaf\xc3\x9d\x41\xd3\xb3\x27\x81\x4b\x80\x94\x0b\x04\x25\x90"
+			  "\xf9\x65\x56\xec\x91\xe6\xae\x79\x39\xbc\xe3\x1f\x3a\x18\xbf\x2b",
+};
+
+dh_test_vector_t ecp384bp = {
+	.group = ECP_384_BP, .priv_len = 48, .pub_len = 96, .shared_len = 48,
+	.priv_a	= "\x1e\x20\xf5\xe0\x48\xa5\x88\x6f\x1f\x15\x7c\x74\xe9\x1b\xde\x2b"
+			  "\x98\xc8\xb5\x2d\x58\xe5\x00\x3d\x57\x05\x3f\xc4\xb0\xbd\x65\xd6"
+			  "\xf1\x5e\xb5\xd1\xee\x16\x10\xdf\x87\x07\x95\x14\x36\x27\xd0\x42",
+	.priv_b	= "\x03\x26\x40\xbc\x60\x03\xc5\x92\x60\xf7\x25\x0c\x3d\xb5\x8c\xe6"
+			  "\x47\xf9\x8e\x12\x60\xac\xce\x4a\xcd\xa3\xdd\x86\x9f\x74\xe0\x1f"
+			  "\x8b\xa5\xe0\x32\x43\x09\xdb\x6a\x98\x31\x49\x7a\xba\xc9\x66\x70",
+	.pub_a	= "\x68\xb6\x65\xdd\x91\xc1\x95\x80\x06\x50\xcd\xd3\x63\xc6\x25\xf4"
+			  "\xe7\x42\xe8\x13\x46\x67\xb7\x67\xb1\xb4\x76\x79\x35\x88\xf8\x85"
+			  "\xab\x69\x8c\x85\x2d\x4a\x6e\x77\xa2\x52\xd6\x38\x0f\xca\xf0\x68"
+			  "\x55\xbc\x91\xa3\x9c\x9e\xc0\x1d\xee\x36\x01\x7b\x7d\x67\x3a\x93"
+			  "\x12\x36\xd2\xf1\xf5\xc8\x39\x42\xd0\x49\xe3\xfa\x20\x60\x74\x93"
+			  "\xe0\xd0\x38\xff\x2f\xd3\x0c\x2a\xb6\x7d\x15\xc8\x5f\x7f\xaa\x59",
+	.pub_b	= "\x4d\x44\x32\x6f\x26\x9a\x59\x7a\x5b\x58\xbb\xa5\x65\xda\x55\x56"
+			  "\xed\x7f\xd9\xa8\xa9\xeb\x76\xc2\x5f\x46\xdb\x69\xd1\x9d\xc8\xce"
+			  "\x6a\xd1\x8e\x40\x4b\x15\x73\x8b\x20\x86\xdf\x37\xe7\x1d\x1e\xb4"
+			  "\x62\xd6\x92\x13\x6d\xe5\x6c\xbe\x93\xbf\x5f\xa3\x18\x8e\xf5\x8b"
+			  "\xc8\xa3\xa0\xec\x6c\x1e\x15\x1a\x21\x03\x8a\x42\xe9\x18\x53\x29"
+			  "\xb5\xb2\x75\x90\x3d\x19\x2f\x8d\x4e\x1f\x32\xfe\x9c\xc7\x8c\x48",
+	.shared	= "\x0b\xd9\xd3\xa7\xea\x0b\x3d\x51\x9d\x09\xd8\xe4\x8d\x07\x85\xfb"
+			  "\x74\x4a\x6b\x35\x5e\x63\x04\xbc\x51\xc2\x29\xfb\xbc\xe2\x39\xbb"
+			  "\xad\xf6\x40\x37\x15\xc3\x5d\x4f\xb2\xa5\x44\x4f\x57\x5d\x4f\x42",
+};
+
+dh_test_vector_t ecp512bp = {
+	.group = ECP_512_BP, .priv_len = 64, .pub_len = 128, .shared_len = 64,
+	.priv_a	= "\x16\x30\x2f\xf0\xdb\xbb\x5a\x8d\x73\x3d\xab\x71\x41\xc1\xb4\x5a"
+			  "\xcb\xc8\x71\x59\x39\x67\x7f\x6a\x56\x85\x0a\x38\xbd\x87\xbd\x59"
+			  "\xb0\x9e\x80\x27\x96\x09\xff\x33\x3e\xb9\xd4\xc0\x61\x23\x1f\xb2"
+			  "\x6f\x92\xee\xb0\x49\x82\xa5\xf1\xd1\x76\x4c\xad\x57\x66\x54\x22",
+	.priv_b	= "\x23\x0e\x18\xe1\xbc\xc8\x8a\x36\x2f\xa5\x4e\x4e\xa3\x90\x20\x09"
+			  "\x29\x2f\x7f\x80\x33\x62\x4f\xd4\x71\xb5\xd8\xac\xe4\x9d\x12\xcf"
+			  "\xab\xbc\x19\x96\x3d\xab\x8e\x2f\x1e\xba\x00\xbf\xfb\x29\xe4\xd7"
+			  "\x2d\x13\xf2\x22\x45\x62\xf4\x05\xcb\x80\x50\x36\x66\xb2\x54\x29",
+	.pub_a	= "\x0a\x42\x05\x17\xe4\x06\xaa\xc0\xac\xdc\xe9\x0f\xcd\x71\x48\x77"
+			  "\x18\xd3\xb9\x53\xef\xd7\xfb\xec\x5f\x7f\x27\xe2\x8c\x61\x49\x99"
+			  "\x93\x97\xe9\x1e\x02\x9e\x06\x45\x7d\xb2\xd3\xe6\x40\x66\x8b\x39"
+			  "\x2c\x2a\x7e\x73\x7a\x7f\x0b\xf0\x44\x36\xd1\x16\x40\xfd\x09\xfd"
+			  "\x72\xe6\x88\x2e\x8d\xb2\x8a\xad\x36\x23\x7c\xd2\x5d\x58\x0d\xb2"
+			  "\x37\x83\x96\x1c\x8d\xc5\x2d\xfa\x2e\xc1\x38\xad\x47\x2a\x0f\xce"
+			  "\xf3\x88\x7c\xf6\x2b\x62\x3b\x2a\x87\xde\x5c\x58\x83\x01\xea\x3e"
+			  "\x5f\xc2\x69\xb3\x73\xb6\x07\x24\xf5\xe8\x2a\x6a\xd1\x47\xfd\xe7",
+	.pub_b	= "\x9d\x45\xf6\x6d\xe5\xd6\x7e\x2e\x6d\xb6\xe9\x3a\x59\xce\x0b\xb4"
+			  "\x81\x06\x09\x7f\xf7\x8a\x08\x1d\xe7\x81\xcd\xb3\x1f\xce\x8c\xcb"
+			  "\xaa\xea\x8d\xd4\x32\x0c\x41\x19\xf1\xe9\xcd\x43\x7a\x2e\xab\x37"
+			  "\x31\xfa\x96\x68\xab\x26\x8d\x87\x1d\xed\xa5\x5a\x54\x73\x19\x9f"
+			  "\x2f\xdc\x31\x30\x95\xbc\xdd\x5f\xb3\xa9\x16\x36\xf0\x7a\x95\x9c"
+			  "\x8e\x86\xb5\x63\x6a\x1e\x93\x0e\x83\x96\x04\x9c\xb4\x81\x96\x1d"
+			  "\x36\x5c\xc1\x14\x53\xa0\x6c\x71\x98\x35\x47\x5b\x12\xcb\x52\xfc"
+			  "\x3c\x38\x3b\xce\x35\xe2\x7e\xf1\x94\x51\x2b\x71\x87\x62\x85\xfa",
+	.shared	= "\xa7\x92\x70\x98\x65\x5f\x1f\x99\x76\xfa\x50\xa9\xd5\x66\x86\x5d"
+			  "\xc5\x30\x33\x18\x46\x38\x1c\x87\x25\x6b\xaf\x32\x26\x24\x4b\x76"
+			  "\xd3\x64\x03\xc0\x24\xd7\xbb\xf0\xaa\x08\x03\xea\xff\x40\x5d\x3d"
+			  "\x24\xf1\x1a\x9b\x5c\x0b\xef\x67\x9f\xe1\x45\x4b\x21\xc4\xcd\x1f",
+};
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/modp.c b/src/libstrongswan/plugins/test_vectors/test_vectors/modp.c
new file mode 100644
index 0000000..482e41c
--- /dev/null
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/modp.c
@@ -0,0 +1,731 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the Licenseor (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be usefulbut
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <crypto/crypto_tester.h>
+
+/**
+ * As I couldn't find any test vectors for common MODP diffie hellman groups
+ * these have been generated.
+ */
+
+dh_test_vector_t modp768 = {
+	.group = MODP_768_BIT, .priv_len = 32, .pub_len = 96, .shared_len = 96,
+	.priv_a	= "\x60\x91\xff\xc6\xde\x28\xc1\xcc\xc7\xc6\x5d\xa6\x11\xab\xfa\xe8"
+			  "\x6a\x10\x74\xb2\x22\x43\xe3\x70\x6c\xb6\xde\x2f\xe2\x9d\x11\x42",
+	.priv_b	= "\x76\xe0\x2f\xc3\xea\xbe\x6a\x0f\xce\xd6\xc3\x1e\x59\x45\xd1\x67"
+			  "\xfa\xd0\x02\x00\xb4\xaf\x12\xcd\x6f\xc6\xd7\xe3\x81\x48\x62\x78",
+	.pub_a	= "\xd7\xa2\x54\x62\x99\x01\xc8\x89\x53\x2c\x3e\x44\xda\x3d\x0b\x7e"
+			  "\x92\x27\x37\x70\xc6\x26\xc3\x91\x90\x52\x2d\xab\x67\x07\xca\xff"
+			  "\x36\x59\x10\x9f\x2f\x43\x24\xa4\x17\xeb\x7d\xc4\x56\x3a\x09\xba"
+			  "\x04\xcd\x3c\x9b\x27\xd3\xc1\x22\x7e\xb1\x9d\xcb\x69\xfe\xf3\xb6"
+			  "\xe2\xaa\x13\x81\x23\x24\x06\x64\x2d\xd1\x50\x78\x57\x07\xf4\x7c"
+			  "\x3d\x74\x8a\x3d\x6b\x96\xd0\x00\xc5\x2c\x99\xd1\x0b\x65\xf2\xd1",
+	.pub_b	= "\xf0\xe9\xdc\x78\x10\x4c\x97\x99\xb6\x70\x74\xb0\x7d\x8f\x09\x7a"
+			  "\xa8\x82\xbd\xe4\x64\xc8\xeb\x9a\x0a\xcd\xef\x13\x86\x19\x4f\x49"
+			  "\xc0\x63\xc6\x7d\x68\xf1\x4c\x5e\x3b\x04\x19\x57\x67\x8e\xa7\xcb"
+			  "\x39\x7d\x87\x07\x20\x81\x9e\xa1\x08\x5a\x28\xd8\x13\xe3\x73\x9a"
+			  "\x64\x00\x6f\x24\x66\xe8\x6c\x09\xe0\xc6\x9c\x2c\xa4\xf1\x0a\x04"
+			  "\xc4\x9b\xb3\x01\x86\xbd\xfa\xb5\x4d\xf4\x20\x83\x14\xd9\x3c\x52",
+	.shared	= "\x29\xcb\x14\x7d\x2a\x2b\x0d\x02\x59\x4d\xb0\x7b\xf0\x44\x70\x5c"
+			  "\xb1\x44\x89\xd0\xf0\xa9\x32\xcc\x87\xf6\x04\x05\x1d\x1c\xb6\xe2"
+			  "\xbe\x90\x39\x16\xe2\x5c\x65\x39\x93\xc8\x05\x5e\xd4\x37\x6c\xa4"
+			  "\xdb\xa8\x40\x12\x39\x1a\x92\xa3\xf3\x42\x64\xaf\x64\x1f\xd8\x18"
+			  "\xe1\xba\x4e\x99\x34\x30\x09\x97\xd7\x32\xd7\x0d\x0d\x73\x73\xcd"
+			  "\x3d\xaa\xad\x22\xe8\x68\xb7\xe2\x50\x02\x9d\x30\x7e\xe5\x41\x48",
+};
+
+dh_test_vector_t modp1024 = {
+	.group = MODP_1024_BIT, .priv_len = 32, .pub_len = 128, .shared_len = 128,
+	.priv_a	= "\xe5\x3c\x20\x5d\xa0\xd8\xe4\xbf\xb4\x17\x49\x44\x32\x0f\xc6\xe4"
+			  "\xea\x66\xfe\x44\xe3\xc9\x31\xac\x5d\xa1\x45\x0a\xea\x47\xeb\xcf",
+	.priv_b	= "\x7f\x9a\xf7\x21\xeb\x7c\xd2\xa9\x00\xa3\x6e\x39\x9e\xbc\x5c\x65"
+			  "\xee\xcc\xe6\x62\x9c\x8e\x1c\x5a\x7f\xf3\x32\x93\x64\x5f\xd3\xe3",
+	.pub_a	= "\x66\x61\x7c\x9b\xbe\x91\xee\x99\x00\xd8\x06\x41\x5b\x73\x84\xec"
+			  "\xb0\xb6\xb8\x0a\x39\xbd\x5b\x07\x03\x96\xee\x32\x37\x5a\x8f\x68"
+			  "\x37\x6b\x35\x2b\x97\xba\xf3\x2f\x95\xc4\xd1\x8c\x06\xab\x96\xbf"
+			  "\xe3\xf3\x75\x2d\xf1\xe3\xc5\x57\x41\xb6\xf4\x24\x41\x17\xee\xbd"
+			  "\xa1\x01\x59\x83\xc6\xba\x00\x8f\xe8\x9f\xe5\x1c\xf4\xc9\x69\x25"
+			  "\x92\xeb\xf7\x42\x43\x6c\x39\x3d\xf6\x1a\x60\xcc\xc6\x4f\xd7\x90"
+			  "\x7a\x6d\x26\x26\x7c\x0f\x15\x56\x23\x0c\x3e\x33\x2b\x2e\x11\xd1"
+			  "\x18\xa6\x98\x25\x89\x79\x3a\x2f\x6d\x66\xb8\x66\x76\xba\xe4\x7a",
+	.pub_b	= "\x7b\x90\x10\x60\x9e\xbf\x2c\x49\x70\x17\x45\x8a\xfa\xab\x42\x02"
+			  "\x88\x5d\x25\xde\x7b\x5e\x5c\xe9\xb0\x5b\xd4\x42\xa3\xe9\x7b\x52"
+			  "\xce\xa7\x60\xd7\xdb\xcb\x21\xdd\x71\xd8\x0c\xd4\x34\x7c\xaa\x9e"
+			  "\xdf\xbc\x2d\xf4\xc1\xcd\xc1\x66\x9b\x8a\xd2\x44\xeb\x34\x5b\x33"
+			  "\x1d\x87\x54\x92\x88\x3d\xf0\x4a\x3d\x0b\x1a\x8b\x89\x27\xd5\x09"
+			  "\x91\xfe\x03\xe7\x35\x7e\xb6\xbd\xfc\xe3\xd8\xc6\x84\xc9\x86\x1b"
+			  "\xc5\xce\x03\x96\x2f\xfb\x87\xbf\x05\xda\xbd\x5a\x37\x27\x99\x4d"
+			  "\xde\xe5\xd3\xc6\xec\xc5\x89\x85\x99\x91\xb9\x32\x55\x76\x1f\xd5",
+	.shared	= "\x95\x79\x0f\x5c\x46\xae\x7c\xa1\xa4\x71\xdd\x78\x6a\xa8\xe4\x44"
+			  "\x07\x3e\xce\xc9\x69\x5d\x00\x46\x20\xcd\x7c\x9d\x36\x09\xa6\x97"
+			  "\x3c\x89\xa2\x30\x75\x09\x35\x63\x8b\x86\xd1\xe6\x5b\x27\xb7\x84"
+			  "\x88\x81\xf9\x01\x3a\xbd\x03\x62\x80\xd1\x86\x2b\xb0\x3c\xa6\x0b"
+			  "\xa9\x0b\x70\xf9\xae\x7e\xdf\x71\xff\x80\xf5\xa7\xee\xfb\xe2\x67"
+			  "\x29\xb5\xbb\xb1\xbb\x1f\xeb\x0d\x24\x0e\x53\xc9\xd7\x4b\x4f\xe9"
+			  "\xd2\x62\xb5\x3b\xd5\xd8\xa7\x38\x3f\x90\xf0\x1e\x35\x96\x47\xd0"
+			  "\x48\x02\xd7\x4a\x4f\x75\x3b\x29\x4a\x96\x50\x3f\x26\x05\xd3\xf1",
+};
+
+dh_test_vector_t modp1536 = {
+	.group = MODP_1536_BIT, .priv_len = 32, .pub_len = 192, .shared_len = 192,
+	.priv_a	= "\x22\xd9\xdc\xc7\x30\x79\x93\x6a\x85\x8c\x07\xaa\x85\xed\x07\xb3"
+			  "\xd1\xe8\xb6\x70\xe7\xca\xaf\xa1\x92\x83\x76\x96\x07\x0f\xef\x29",
+	.priv_b	= "\x32\x34\x74\xde\x77\x88\xe0\x03\x6b\x30\x95\x49\x56\x0b\x00\x0d"
+			  "\x81\xf8\x2f\xdb\x69\x78\xf3\xc0\x3b\x70\x16\x80\xde\x6e\x28\x10",
+	.pub_a	= "\x3d\x7d\x1d\xd1\xbc\xa7\x13\x7a\x64\x23\x73\xd5\xd9\xb8\x6e\xf9"
+			  "\x95\x84\x9e\xa5\x1c\xb6\xcd\x51\xa6\xb9\x3e\x83\xb3\x4f\x96\x7d"
+			  "\xbf\x7d\x66\xbc\x7c\xe5\xd9\x58\xbf\x01\x90\x2b\x60\xf1\xc3\x07"
+			  "\x6c\xfe\x14\x7b\xeb\x45\xf0\x83\x97\xcf\xf4\xc3\xa8\x02\x7c\xaa"
+			  "\xe1\x84\x78\x8e\xf3\xeb\x0d\xd5\x6e\x14\xc6\xdd\x2c\xe9\x54\xe3"
+			  "\xd5\xcc\x80\xdb\x84\xde\xb5\x34\xce\x38\x24\x45\xe7\xa4\x41\xdb"
+			  "\x97\x12\x30\x02\x0a\x1a\x45\xca\x00\x70\xd6\x94\xf0\x93\xc7\x16"
+			  "\xd8\x07\x68\x33\x6e\x61\xb5\x6f\xf7\x8b\x35\x09\x39\xfe\x4e\x9e"
+			  "\x03\x2c\x85\xbb\x58\x81\xc4\xc8\xd7\xdb\xd5\x30\xa6\xfc\x50\x13"
+			  "\x00\xf7\xe9\xe6\x5b\xff\xb9\x83\x34\x8a\xd0\x5c\xc5\x6e\x2c\x19"
+			  "\xf5\x97\xa9\x9f\xb9\x68\x91\x4b\xe9\xb5\x7a\xcf\x91\x11\xe7\x5b"
+			  "\x57\x6a\x61\x37\x67\x15\x76\x57\x90\x0d\xcf\x22\xf4\x20\x0c\x3d",
+	.pub_b	= "\xd6\x32\x58\xd5\x54\x35\x3d\x6b\x2b\xcc\x0b\x53\x53\xfa\x80\x00"
+			  "\xb3\xa3\x54\xa2\x41\x1d\x7f\x17\xab\xca\x69\x1d\xe8\x22\x7c\xd7"
+			  "\xd4\x3e\x7f\xef\x8b\x3e\xe7\xa0\xa9\x1a\x66\x3d\x30\xc5\x4f\x3c"
+			  "\x5f\x4b\x95\xc9\xfe\x38\xc6\xcf\x19\x39\xb4\x80\x2b\xb6\xf0\xa9"
+			  "\x51\x12\x8f\xdc\x39\x1d\x90\xfa\x8b\x40\x48\x4f\x45\xb6\xda\x02"
+			  "\xc7\x6c\xf9\x1b\x43\x31\xc4\xcf\x78\x51\xe5\x50\xa2\xd1\xc0\x25"
+			  "\x53\x14\x03\xe0\x40\x3a\xf4\x72\xb3\x83\x41\xdc\x56\x2b\xe9\x8d"
+			  "\x1a\xa2\x80\x49\x4d\x62\x64\x31\x6a\x6f\x77\x4c\xe0\xee\xd4\x01"
+			  "\x57\xb6\x37\xc5\x4e\x69\x50\x3b\xec\xb8\xf0\xd7\x57\xb2\x86\xe4"
+			  "\xd8\x43\xc2\x24\x21\x9a\x92\x3f\x73\xab\x57\x83\x15\xaf\x44\x5a"
+			  "\xfa\xd9\x56\x9d\xf2\x5a\xcf\xca\x3a\x9f\x7c\x93\xd3\x03\xf4\xef"
+			  "\x24\x32\xbf\x62\xce\x52\x5c\x8a\x56\xba\xbd\x2f\xfb\x54\x38\x32",
+	.shared	= "\x6e\x3d\xf6\xe2\x52\xba\x11\x53\xca\x45\xe9\xa8\xbb\xe5\x48\x33"
+			  "\x7b\x69\x57\x2a\xff\x4e\x61\xb4\x6e\xc9\x86\xb8\x70\xa8\x63\xd3"
+			  "\x85\x3a\xb9\xa5\x4d\x9c\x63\x2a\x09\x48\xce\x8c\x65\xf1\xa2\x9b"
+			  "\x06\x7a\x14\x51\x19\x8d\xab\x9f\x24\x77\x6e\x86\x42\x5a\x06\xbd"
+			  "\xaa\x9f\x26\xdc\xe9\xe8\x9e\x36\x8d\x0e\x16\x70\x27\x74\x01\x5a"
+			  "\x14\x30\xaa\xa1\xe8\x33\x22\x7f\x9d\xea\x7a\x58\x18\xce\x47\x43"
+			  "\x20\xb3\x9c\xe8\x67\xca\x79\xa4\x9b\x31\xe6\xab\xce\xa6\xc8\xda"
+			  "\xff\x00\xb8\x06\x4e\x2a\x75\x73\x72\xd4\x0d\x58\xa5\x92\xe7\xa2"
+			  "\xde\xb1\xf9\xa0\xd9\xab\xab\x1f\xc0\x81\x2e\xe1\xff\xa6\x2a\x20"
+			  "\xff\x68\xce\x4d\x02\xac\xb8\x4a\x1a\x03\x3d\x03\xe4\xf0\x5e\x97"
+			  "\xa4\xfa\xd8\x9e\xc2\x3a\xee\x34\x9e\x26\x4e\xfa\x61\xae\x59\xe9"
+			  "\x38\x1b\x1e\x5b\x7a\xa5\xd0\x9a\xb6\x6b\x74\x99\x7c\xba\xed\x20",
+};
+
+dh_test_vector_t modp2048 = {
+	.group = MODP_2048_BIT, .priv_len = 48, .pub_len = 256, .shared_len = 256,
+	.priv_a	= "\xaf\x3b\xfd\x38\x62\xca\xa1\x17\x74\xce\x2b\x74\x84\x08\x07\xc1"
+			  "\xde\x5c\xd6\xa7\x61\x9b\xb3\xa0\xc7\xaf\x39\xee\xda\xa6\xeb\x89"
+			  "\xe2\xe9\xc1\x44\xb3\x62\x5b\x27\x31\x87\x9c\xb5\x8f\xa3\x76\x6d",
+	.priv_b	= "\x77\xa4\x8e\x47\x72\xe2\x3e\x28\x4c\xe4\xaf\x81\x39\x9d\xcd\x58"
+			  "\x9b\xeb\x7c\xef\xbc\xc9\xd1\x96\xf0\x6d\xcf\xdf\xc3\xa8\x8e\x3b"
+			  "\x4c\x1c\x82\xbe\xfe\xc0\xe6\x4b\xa4\x95\xcc\xde\x32\x99\x36\xce",
+	.pub_a	= "\x1a\x27\xc5\xa7\x23\x7a\xe8\xfe\x0a\x71\xc0\xaf\x64\x94\xfa\xec"
+			  "\xcd\xd4\xa5\x03\x1d\x47\xa1\xa6\xb7\x16\x2d\xfc\xdf\x03\xbb\x17"
+			  "\xb7\xbb\x08\x9b\xd6\x52\xa5\xf3\x1b\x36\x61\xbb\x11\x4d\x7c\x48"
+			  "\xd8\x3d\x24\x4f\x46\xdb\x64\x87\x0c\x9c\x83\x27\xf1\xa8\x30\xab"
+			  "\xf5\x31\xe5\x18\xdd\x52\x1a\x2e\x94\xe7\x06\x1e\x94\x42\x09\xba"
+			  "\x53\x31\x01\x2b\x3d\xff\x00\x84\x9e\xaa\xb5\x8c\x7c\x7a\xf1\x52"
+			  "\x65\x21\x0f\xbc\xf0\xf8\x7b\x9d\xd9\x32\xf8\xba\x4e\x9a\x9f\x91"
+			  "\xb6\x32\x94\x53\x0a\x12\x00\xb8\x8b\x3a\x03\xe1\xa0\xc7\xfd\x34"
+			  "\xde\xec\x6f\xad\x50\x1e\xde\x06\xce\x7e\xc9\xe2\x91\xd4\x7b\x69"
+			  "\xb3\xa4\xb6\x1b\xb0\x87\x63\xb6\xd4\x6b\xfb\xda\xb9\x7b\xde\xce"
+			  "\xa0\xff\x09\xa8\x72\x22\x1f\xb4\xb6\xcc\xca\x6b\x5c\x6f\xaa\xd8"
+			  "\xeb\x87\x3b\x9a\x2f\x39\xb6\x3e\x62\xcf\xad\xd4\x76\x07\xe6\x8e"
+			  "\x2c\x29\x05\x83\xf7\x26\x8f\xb4\x3f\xc0\x0a\x7d\xc8\x81\x0e\xcd"
+			  "\xac\x1a\x59\xbd\x1b\x47\x7a\xaf\x41\xcb\x4b\x24\xad\xa3\xe5\xf7"
+			  "\xb8\xcb\x98\x6f\x1a\xe4\x76\xaf\xc7\x67\x7a\xa6\x25\x70\xa1\xb1"
+			  "\x83\x8d\xda\x26\xbe\x78\x63\xee\x2f\x40\xb5\xe5\x38\xa4\xe1\x81",
+	.pub_b	= "\x66\x72\x82\x31\x8d\x65\xcb\x05\xcd\x32\x3c\x25\x09\x1e\x66\x4c"
+			  "\xc7\x5a\x3a\x20\xc0\x14\xb2\xf6\x38\x9d\x3b\x27\xf5\xc1\xe9\x08"
+			  "\xe0\xd4\x0f\xf8\x55\x2b\xd5\x87\x75\x25\x50\x30\x22\x85\xb4\x9f"
+			  "\x75\xf8\xff\xae\xc9\x37\xfb\x2e\x69\xc8\x15\x0f\x88\xd6\x50\x8b"
+			  "\xf0\xfb\x1f\x16\xe9\x67\x6f\x5e\xcf\x71\x8f\x87\x4f\x3d\x8d\xe3"
+			  "\xc8\x68\x87\x49\xdb\xcf\x1a\xff\xd4\xd6\x2f\xf9\xea\x5d\x9e\x30"
+			  "\x35\xb2\xce\x4a\x6e\xae\x28\x1c\x40\x8f\xc8\x08\x4a\xe2\x35\xd9"
+			  "\x98\xa0\x37\x61\x0a\x8c\xb4\x8c\x87\x8c\xd0\x63\x5f\xa1\x36\x9f"
+			  "\xc9\x0b\x86\x4c\x53\x23\x67\x38\x45\x97\xfd\xee\xfd\xb6\x74\x2b"
+			  "\x00\x6a\xde\xda\xe2\x01\x5b\xc4\xce\x2f\x9c\x54\x51\xc9\x63\x6a"
+			  "\x16\xed\x7d\x10\xb4\xe4\x0d\x82\x5b\x50\xaa\x76\x33\xa0\xe8\xfb"
+			  "\x81\x3b\xeb\xc0\x49\xf7\xff\x6a\x71\xec\xfb\x14\xe8\x80\xf5\x09"
+			  "\xd3\x8b\x57\x1a\x80\x98\x08\xa4\x96\xb4\x51\xb5\xb5\x56\x7a\x36"
+			  "\x08\xb0\x1a\x22\xe4\x99\x83\x55\xf1\x81\xb8\x79\xde\x26\x23\x04"
+			  "\xf2\x9d\xe1\x42\xff\x5e\x52\xcc\x56\x4f\x3a\x2d\x1e\x84\xa0\xc3"
+			  "\x3d\x8f\x3d\xa7\xbf\x64\x12\xb3\xf0\x18\xe0\x0d\x90\xfa\x5b\x94",
+	.shared	= "\x26\xf9\xe8\x45\x7c\xf2\xd7\xd5\x6d\xd8\x19\xc2\xa8\x67\xd7\xc3"
+			  "\xa9\x0a\xa2\xb9\x44\xe2\x0b\x8b\xde\xd3\xa5\xbf\x91\xaa\x1f\xf8"
+			  "\x1a\x7e\xa8\x9d\x52\x4c\x36\x5f\x38\x23\x51\x08\x35\xcd\x86\x44"
+			  "\xc4\xd5\xda\xcf\x89\x3e\x61\x0d\x2c\x1a\x14\x06\x16\xd1\xc8\xc1"
+			  "\xd3\x5f\x46\xde\x2c\x5f\xaa\xd9\xae\xce\xc6\xb6\x77\xac\xd9\x84"
+			  "\x09\x81\x42\xa8\xaa\x0c\x85\x42\xe9\xac\x98\xb3\xbc\x7b\x57\x7c"
+			  "\x59\xb8\xec\x53\x34\x6e\x15\x67\xa9\x00\x39\xac\x92\xb2\x24\x63"
+			  "\x5a\xb2\x16\x73\x1b\x06\x35\x39\x25\x64\x2c\x33\x0a\x20\x1b\xa4"
+			  "\xb3\x12\x84\xa9\x51\x58\x60\xf3\x5e\x93\x08\xf5\x51\x5a\x77\x99"
+			  "\x84\xfb\xd9\xf5\xce\x41\x77\xdb\x78\xd1\xcb\x03\x84\xb6\x3c\x73"
+			  "\x9c\x6d\x74\x4a\xd7\xa7\x00\xb9\x5a\x53\x1b\x29\xf3\xb7\x44\xed"
+			  "\x38\xe6\x9a\xee\x67\x07\x2c\x45\xa9\x1c\xee\x6b\x14\x21\x5e\x04"
+			  "\xf2\x7c\x31\x35\x8c\x86\xdc\xe4\x48\xd6\x0a\x22\x3b\xdc\x55\x4e"
+			  "\xda\xa3\xe4\x07\x2e\xf6\x03\xa0\xf4\x61\x9f\x8d\xb3\x9c\xec\x29"
+			  "\x1c\x86\x01\x74\x15\x5d\x8a\xbf\x9e\x10\x82\x93\x1d\xf5\x8e\xd9"
+			  "\xee\x9c\x12\x15\xdd\x23\x93\xde\x02\xf5\xc1\x76\x7f\x07\x0e\x28",
+};
+
+dh_test_vector_t modp3072 = {
+	.group = MODP_3072_BIT, .priv_len = 48, .pub_len = 384, .shared_len = 384,
+	.priv_a	= "\x51\xf8\xaa\xb6\x63\x20\x1e\xb2\x86\xba\xd2\x99\x32\xb2\xe5\x8a"
+			  "\x92\x96\xbf\x2a\xa7\x78\x79\xcc\x8c\x64\x29\xd5\xa6\x68\xad\xf7"
+			  "\x60\x57\xad\xc3\x77\xcc\x75\xfd\x86\x47\x96\xb8\xfa\x7b\x42\x8c",
+	.priv_b	= "\xaf\x7f\x44\x29\x0b\xaa\xc8\x81\x5e\x70\x75\x9b\x6b\x27\x42\x27"
+			  "\x12\x22\x50\xea\x8d\x5a\x12\xef\x4b\x0a\x82\xcf\xe9\x1d\x52\x98"
+			  "\x9d\x96\xc1\xa8\x40\x89\x2a\x9f\xfa\x9f\x3a\x65\xc7\x7c\x8c\xd9",
+	.pub_a	= "\xae\x98\x27\xa0\x7a\x37\x2e\x16\x01\x67\x20\x63\x72\xc5\x5b\x61"
+			  "\x5c\xd4\x9e\x8c\x43\xf7\x1a\x6e\x6b\x22\x83\x8c\x0f\x9b\x9d\x90"
+			  "\x3a\xe5\x97\x97\xf3\x95\xc9\xca\x7c\x78\x0f\xa8\x8d\x79\x27\xa3"
+			  "\xac\x48\xf1\xb5\x05\xe6\x7a\x0d\xb1\xeb\xad\x57\x8e\xb1\x57\x2b"
+			  "\x86\x52\x5e\x84\x0c\x4c\xe2\x43\x5e\xd4\xcd\xe1\x75\x68\xa2\xcb"
+			  "\x27\x08\x85\xc9\xd3\xa7\x24\xf8\x73\x46\xe5\x19\xa9\x47\x84\xee"
+			  "\x88\xaf\xec\x27\x86\x68\x9f\x0b\xc1\x23\xe0\xe4\x65\x79\x57\xb4"
+			  "\xf7\x5f\x24\xb5\x2d\xd4\x80\x39\x09\x3a\xe8\xeb\x5d\xa4\x0d\x1e"
+			  "\x31\xfc\x53\xfd\x98\xa0\x58\xb0\x38\x9b\xd5\xc7\xaf\x5b\x0d\xf4"
+			  "\x49\xd6\x13\x90\x1c\xa2\x71\xb5\x8e\x47\x0f\x88\xd3\x45\x93\x1f"
+			  "\x3f\x64\xe8\x1f\x03\x1d\xe9\x5a\xda\xef\x78\xf6\x0e\x64\x5e\xca"
+			  "\x7d\xd5\x61\x8a\xa6\xed\xd3\x9f\xa8\x91\x22\x46\x39\xa9\xae\x42"
+			  "\xa8\xa9\x37\x4d\x68\x3f\xd3\xf4\x82\x6b\x97\x4c\x8d\x00\x39\x2f"
+			  "\x31\x12\x45\xa7\x1c\x86\xdb\x4e\xb5\xef\xc4\x78\x34\xce\x6b\xaf"
+			  "\xb2\x08\xaa\xba\xc6\x8c\x35\xe3\x4f\x79\x15\x78\x40\x1c\x7b\x75"
+			  "\x01\x15\xb1\x6e\x5c\x3a\xc3\x62\x42\xf4\xa9\x0a\x99\x73\x4c\x08"
+			  "\x36\x8d\x48\xab\x5d\x50\xec\x92\xf3\xf1\x26\x7e\x54\xb9\x33\x34"
+			  "\xa5\x0b\x00\xd7\x57\x1d\x1c\xeb\x1e\x66\x21\x58\xd5\x66\x36\x20"
+			  "\xd1\xf0\x22\x8a\x64\xf4\x92\xea\x8e\x1f\xe1\x81\x7e\x35\x83\x57"
+			  "\x7f\x1e\x48\xa5\x84\x91\xc1\x0d\x98\xff\xa0\xea\xa8\x64\x05\xd0"
+			  "\x2c\x94\xb4\x9f\x99\xfd\xdc\x6a\x3b\x7b\xd6\xe3\xbc\xe2\x26\x1e"
+			  "\xa3\xcb\xbd\x82\x1f\x49\x5a\x2a\xa7\x1a\xe9\x09\xb3\xcd\x0d\x2c"
+			  "\x9b\xec\x0b\x06\x8b\xa7\x26\x20\xff\x06\x32\x4c\xdb\x80\x0b\xf8"
+			  "\x56\x5e\x4b\x78\x21\x84\x61\x0e\xf0\x77\xbc\x4e\x8f\xc5\x17\xf7",
+	.pub_b	= "\x2b\x27\x0c\x8e\x66\x74\x09\x31\x45\xef\x84\xab\x0c\x34\x56\x0f"
+			  "\x5c\x4f\x94\x82\xa5\x0f\x2f\x44\x72\xfd\xe9\x87\xb4\x6e\xb8\x40"
+			  "\x34\x02\x03\xd6\x31\x10\x2f\x2c\x7f\x9e\xb4\x8d\x20\x74\x44\xfb"
+			  "\x21\x71\x7d\xaf\x76\xf6\x60\x04\xa7\x9e\xa8\xee\xe7\x7c\xc9\x80"
+			  "\x19\xba\x12\x34\xf1\x6f\xbf\xf7\xdd\xa9\x45\xa4\x46\x81\x1d\x28"
+			  "\x5d\x31\xaf\xd3\x31\xdf\xa8\x0c\x87\x0e\xfb\x19\x96\x68\xbb\x38"
+			  "\x76\x18\xe1\x16\x21\xf5\x32\x92\x90\x8f\xd3\x29\xaa\xdb\x91\x63"
+			  "\x5e\x47\x5f\x33\x00\x4d\x9e\xff\xca\x65\xe7\x3f\xdf\xe5\x58\xf3"
+			  "\x4b\xa9\xee\xf3\xcf\x96\x1d\xab\x56\x5c\x5a\x72\x2a\xfb\x22\x8c"
+			  "\x26\xbf\x38\xd3\x9c\x84\xf7\xca\x70\xf8\x51\xbf\x21\x8a\x7e\x2c"
+			  "\x2d\xb5\xd3\x56\x93\x7a\x01\x5a\x65\x50\x31\x13\xf6\xc0\xd5\x2d"
+			  "\x3b\x2a\x21\x21\xa0\xca\x42\xc6\xcc\xde\xbb\x0b\x2c\xfc\x68\xaa"
+			  "\x66\x2f\x3e\x08\xdd\x69\x82\x42\x7a\x0a\x11\xb2\xe1\x44\xe0\xf1"
+			  "\xa3\x47\xd1\xd2\x7f\xf8\x96\xee\x56\xf5\xd9\xfb\x25\xf7\x40\xb5"
+			  "\xc7\x09\x88\xfc\xdc\x91\x12\xdf\xce\xa2\xde\x11\x7c\x12\x87\xd3"
+			  "\x2d\xa8\x42\x70\x49\xce\xef\x09\x7b\xf4\x57\x81\x84\x6a\x02\x1d"
+			  "\x38\x3e\x73\x1a\xa6\xe5\xc3\xdc\x0a\x46\x22\x6e\x54\xc5\xa6\x36"
+			  "\x7a\xd8\x90\x0b\x8e\xad\xba\x54\x09\x3e\xc6\xf7\x1c\x29\x74\x4a"
+			  "\xdc\x73\x02\xe8\x11\x85\xed\x80\xdb\x14\xb3\xe4\x3f\x29\x36\x1a"
+			  "\xf4\xe6\x1c\x33\x1e\x5d\x77\x4d\x76\x17\xbf\x31\x55\x71\x3b\x0d"
+			  "\x4f\x90\x38\x97\x6f\x2f\xf8\x51\x99\xc1\xd7\x0d\xcb\x3e\xfa\x2b"
+			  "\x63\xe0\xc7\x7c\xee\x78\x9f\xa0\x05\x8f\xdf\x52\x67\xc6\xb1\xbd"
+			  "\xed\xc1\xd1\xef\x47\xca\x08\x22\x2a\x9a\x27\xe6\x5f\x89\x2e\xef"
+			  "\xde\x06\x12\xf4\x6b\x51\xbe\x1a\x14\x77\x4d\x45\x14\xd7\xe7\xca",
+	.shared	= "\x45\x3c\xaf\x89\xd6\xbf\xf3\x9b\xda\xe1\x85\x46\x17\x61\xd6\xde"
+			  "\xf5\x89\xa5\x82\x66\x9c\x1a\xc8\x6b\x0b\x7e\xe4\x69\x56\xc9\xf9"
+			  "\x4d\x74\x77\xdd\xd8\x1c\xde\x12\x75\x76\xda\xeb\xd3\x52\x95\x15"
+			  "\xf0\x6a\xa7\xdf\x5e\xb1\x31\x27\x67\x5c\xe1\xb4\xdc\xa2\xac\xb6"
+			  "\x47\xe3\x55\x76\xb9\x40\x50\xbc\xc3\x85\xb3\xb4\x89\x44\xdd\x1e"
+			  "\xca\xbe\x6c\x76\x70\x45\xcd\xcd\xdd\x3a\x1d\x65\x83\x8c\xcc\xb0"
+			  "\x82\xf5\x44\xf0\xfd\x9b\xe6\xc3\xd4\xff\xe7\x55\xe4\xd5\x6d\xfb"
+			  "\xb4\x20\x93\x52\x3f\x45\xd2\x41\x5e\xad\xf3\x6a\x18\x5c\x87\xa6"
+			  "\xe0\x14\x27\xbb\xcc\x98\x95\x68\xa2\x93\x66\xb1\xc6\x91\x72\x4d"
+			  "\x81\x0e\x99\xfb\x05\x83\x00\x26\x72\xa5\x3e\x49\x9f\xf2\x30\x4a"
+			  "\x4b\xcc\x10\xa3\xb8\x0b\xf4\x8a\x9e\x31\x5b\xe9\x98\xbf\x17\x0c"
+			  "\xe9\x0e\xc4\xeb\x87\x05\x57\x0e\x5e\xc4\x80\xc2\x1c\x4d\xd0\xa5"
+			  "\x3a\x1c\xb2\x06\xa3\x42\x45\x2e\xa8\xa6\x84\xd5\x69\xd8\x10\xf8"
+			  "\xe9\x8f\xea\xd7\x03\x9c\x64\xef\xef\x59\x35\x24\xf5\x07\x5c\xb8"
+			  "\x7e\x75\x63\xa4\x2a\xd1\xb5\x78\x19\xc7\xb0\x19\x96\x3d\x07\x0b"
+			  "\x4c\xef\xe2\x2c\x59\x6b\x3a\x96\xa8\xba\x41\xbd\xab\xe0\x54\xa9"
+			  "\xa9\xb4\xd1\xc4\x27\x8a\x83\x64\xea\xd9\x96\xa0\x39\xe8\xbd\xdc"
+			  "\x00\x60\x1e\xcf\x10\x2d\x20\xd6\xab\xce\xd2\xff\x19\x29\x49\xf5"
+			  "\xf8\x1c\x36\xfb\x47\x96\x44\x39\xcd\x44\x03\x6a\x23\xac\x30\x86"
+			  "\x8c\xa5\x23\x25\x84\x7b\x31\x00\xd3\xd4\x28\x16\x76\xbf\x94\x84"
+			  "\xa0\x05\x66\xf1\x3b\x6a\xe8\x9c\x57\xb7\x73\x2f\x8e\x60\x43\x4e"
+			  "\x8e\x48\x85\xcb\x1b\xf9\x47\xce\xd1\x4d\x31\x53\xe1\xb6\xc8\x1b"
+			  "\x33\x12\x0f\xfb\xd8\x45\x94\x91\xd2\xc5\x78\xaa\xb0\xa9\x7e\x83"
+			  "\xdc\x87\x87\x5b\xe5\x88\xc0\xcd\xee\xee\xfd\x19\xcc\x4f\x1d\x40",
+};
+
+dh_test_vector_t modp4096 = {
+	.group = MODP_4096_BIT, .priv_len = 64, .pub_len = 512, .shared_len = 512,
+	.priv_a	= "\xab\x69\xbc\xe9\x61\xf9\x8a\xa9\xd5\x91\xe3\xfd\x9a\xbc\x46\xc8"
+			  "\x0d\xde\x39\x02\x84\xf1\x91\x42\xe8\x81\x5a\xb0\x80\x54\x72\x2b"
+			  "\xbd\x2e\x14\x1e\x27\x9e\xc7\xfd\x30\xaa\xfa\xca\x66\x40\x93\x73"
+			  "\x1e\xcc\x75\xa2\xbd\x07\xe4\xa5\x88\x3f\x56\x08\x93\xc8\x33\x50",
+	.priv_b	= "\xef\x3e\xcb\x88\xf4\xf9\x88\xf7\x2a\xcd\x5a\xa2\x2e\xbe\xbf\x19"
+			  "\x0f\xde\x7e\x8e\x4d\x0d\x50\xcc\xde\x80\xf9\x41\xb3\xbb\xd6\xa2"
+			  "\xf9\xa1\x2a\xee\x9b\xb3\xe5\xc5\x80\x3f\x67\xaf\xfe\x27\xc8\x0d"
+			  "\x05\x46\x9b\x52\x54\xeb\x1f\x32\x6c\x18\x73\x1f\xd3\x4a\xc2\xcd",
+	.pub_a	= "\x3e\xc6\x3c\x0c\x68\x32\x05\xc3\x9d\x4b\x97\x72\x39\xfe\x7f\x96"
+			  "\x17\x56\x0b\x1a\x56\xc4\x7f\xd9\x07\x02\x6a\xd8\x09\x0a\xa4\x4b"
+			  "\xcc\x29\xd3\xc2\xb3\x8d\x34\xe1\x5c\x9e\x14\xc8\x05\x81\xa5\xc4"
+			  "\x83\x2f\x5c\xd8\x8e\x43\x73\xbf\x59\x0e\xad\x63\x6f\x68\xc8\x99"
+			  "\x59\xdf\xeb\xc4\x33\x03\x48\x97\x4e\xc4\x80\x7c\xa4\x4f\xb7\xd4"
+			  "\x4f\x02\xb7\x97\x70\x9e\x16\x0e\x3c\x0e\xc4\x06\x1f\x75\x9a\xec"
+			  "\x63\xd9\x96\xd2\x37\x7a\x18\xdc\xc5\x94\xc2\x08\xfa\x83\x7a\xeb"
+			  "\xc1\x68\x9d\x5c\x0a\xb4\x30\x5c\x1b\xbe\x86\xb1\xd4\xa1\x6f\x4c"
+			  "\xb5\x25\xfc\xcc\xf1\x00\x6e\x21\x23\xc7\x76\xb1\xff\xd1\xfe\xa2"
+			  "\x97\x7b\x1e\xac\x82\xd1\xee\xec\x4c\x46\x73\xa5\x17\xdb\xc4\x2e"
+			  "\x0f\x89\x30\xdb\x28\xd8\xc8\xe8\xb4\x0f\x8a\x49\x8d\xa5\x83\x05"
+			  "\x5c\x9c\x12\x35\x34\xcc\x2c\x53\x34\xd0\xbe\xbe\xa3\x76\x26\x78"
+			  "\xd1\xf5\x34\xba\x64\x6f\x75\x22\xf2\x68\x57\xa0\xff\x28\x8f\x7e"
+			  "\xfc\x38\xc1\xdf\xa0\xa6\x4c\x3e\xb5\x31\x64\xc1\x8f\x6c\x2a\x4e"
+			  "\x51\x5c\x13\xc1\xb7\x39\x35\xd9\xbd\xb4\x58\x27\x33\x55\x34\x29"
+			  "\x67\xa8\x54\xc7\x8b\x16\x8b\x58\x90\xf7\xfe\x08\xd0\x8c\x2e\x4a"
+			  "\x6f\x16\x63\x32\x2e\x7b\x52\xef\x02\x17\xc8\x15\x13\x72\x2f\x34"
+			  "\xc0\x95\x48\x02\xe4\x2c\xfb\x6c\x9e\xe9\xd2\xc3\x98\x68\x71\x1f"
+			  "\x1a\xfc\x4e\x47\x78\x52\x2d\x9c\x45\x09\x0b\x26\x23\xf4\xaf\xa3"
+			  "\x88\x42\x6b\x89\x75\x64\x05\x93\xbe\x79\x2b\xb8\xa7\x15\xbe\xf2"
+			  "\xc4\x6c\x2c\x50\xa6\x8a\xa6\x30\x13\x8a\xb2\x6d\xf9\xda\xe2\xb0"
+			  "\xe2\xc4\xeb\xc1\x0a\x86\x36\xda\xd9\xbe\x2f\xfb\x79\x19\xcd\x52"
+			  "\x78\x85\x84\x3c\xb7\x6c\x71\xf2\x8e\x71\xf6\xf8\x23\xd9\x9c\x2f"
+			  "\xe3\x1a\xd7\xfb\xcc\x9a\xbb\x24\xef\x26\x66\xa1\x21\xcc\xf2\x1f"
+			  "\x88\x1f\xa6\x6a\xb7\x18\xba\xf9\x2b\xef\x5c\xec\xaa\xcf\x4c\x92"
+			  "\x9c\x9c\xb5\x44\x24\xd1\x7a\xb7\x73\x8c\xa6\x80\x7b\x4e\xfa\x49"
+			  "\x36\x0a\x3d\xb6\x52\x7c\x72\x4c\x45\x31\x62\x9e\x9d\xb1\x84\x5c"
+			  "\x6a\x1e\xb4\x63\x2e\x0c\x07\xab\x6c\x31\x37\x7c\x80\x83\x70\x49"
+			  "\x46\x44\xa3\x5b\xd4\x78\x5f\x49\x5f\x60\x63\x8b\x98\x81\x71\xde"
+			  "\xce\x5d\x5c\x44\x90\x35\x7d\x02\x89\xb3\x94\x4b\xc9\xf7\x85\x4d"
+			  "\xb8\x06\x97\xd5\xf6\x3b\xf3\xe3\x1d\xb4\x4e\xfb\x9a\x43\xe1\xdc"
+			  "\x9d\x17\xee\x47\x01\x2d\xfb\xac\xfd\xaf\x4d\xeb\xfe\xf0\x8b\x5c",
+	.pub_b	= "\x20\xb7\xb4\x5f\x69\xe2\xc3\x0b\xcc\xf8\x41\xca\xe8\x04\x2c\x36"
+			  "\x35\x37\x25\x42\x05\x99\x33\x5f\xa2\xe8\x7b\xbe\x59\xce\xbb\xc7"
+			  "\xa7\xd3\xf6\x1e\xb6\x69\x82\x50\x3a\x75\x76\xc3\x47\x63\xdf\xef"
+			  "\x6a\x6b\x18\x0a\x93\xaf\x66\xe4\xf7\x2f\x12\xd5\x8c\x93\x84\x6d"
+			  "\x16\x05\x58\xb0\xd3\x16\x03\x9f\x6b\xa9\x9e\xa6\x4f\x00\x5b\xa1"
+			  "\x1e\x59\xf3\xa9\xcb\x99\x3d\x28\x27\x1a\x4f\xb8\x30\xc3\xf6\xc4"
+			  "\xce\xb9\xb0\x16\x2c\xcc\xa1\x97\xff\x65\x15\x78\x9d\x43\x6c\x94"
+			  "\x7e\xb5\xd8\x01\x09\x74\xeb\xcd\x36\x6b\xc4\x76\x83\x41\x09\x0a"
+			  "\x6f\xb5\x5c\xa8\x4e\x31\xd2\x48\x9e\x35\x27\xa2\x60\x77\x6f\x9b"
+			  "\x8a\x58\x57\x7b\xdc\xd6\x89\xd8\xe4\xb7\x25\x14\xcf\x15\xee\xa5"
+			  "\xa4\x96\x29\xa2\xf2\xc4\x86\xc5\x1b\x5d\x14\xd4\x9b\x11\x93\x09"
+			  "\xbf\xe9\xc9\x32\xb6\x04\xc6\xf1\xc0\xe9\x2c\x44\x8d\xc1\x9f\x54"
+			  "\xf4\x21\x11\x2f\x28\x87\x23\x8c\x91\x37\xc5\x59\xb6\x9a\x93\xac"
+			  "\xf3\x6c\xc1\xf0\xbd\xfe\x4c\xca\x0b\x60\x47\x71\xee\x2a\xf1\x7c"
+			  "\x34\x04\x5d\x42\x29\xb2\xb8\x0a\xcd\xfb\x7f\x56\xe4\xea\xee\x81"
+			  "\xed\x6c\x88\x5a\x2e\x45\xaf\xc9\x8d\xe1\x21\x2e\x5f\x71\x4f\x5f"
+			  "\x00\x88\x12\xd7\x17\x06\x89\x6d\x2d\x5e\xd8\x59\x0c\xee\x66\x41"
+			  "\x08\x79\xdc\x31\x95\xa9\x21\xef\xe0\x85\xdb\x41\xd6\x87\xec\x2d"
+			  "\xe9\x06\xa8\x10\x33\x6f\xa7\x57\x0d\x43\x11\x2d\xec\xf9\xff\xa4"
+			  "\xae\x50\xf5\x4f\xad\x3e\xec\x2b\xb3\xed\x86\xdd\xa3\x66\x2b\xc0"
+			  "\xfc\x1c\x28\x94\xd4\xde\x7d\xa9\x26\x0f\x74\x73\xbe\x67\x6d\xbf"
+			  "\x60\x90\x33\x32\x0d\xba\xa4\x91\x72\x0c\xe2\xd3\x5d\x07\x8d\xbd"
+			  "\xde\x84\x5b\x4a\x49\x5a\xd2\xec\xc2\xe6\xda\x5f\x1c\x0c\x89\x20"
+			  "\xe4\xea\x0e\xcc\xa0\xe0\x77\xda\xc5\x9b\x97\xf0\xe9\x4b\x6c\xca"
+			  "\xd3\xf4\x2a\x34\xb6\x63\x4e\xde\x83\xb2\x9d\x9c\x76\x15\xf7\x41"
+			  "\x90\xdf\x33\xb2\x0e\x7d\x69\x08\xd6\x63\x69\x8a\xdb\x8a\x2d\xac"
+			  "\xd9\x79\xf1\xca\x13\xf2\xcc\x84\x02\xf8\xf6\xcb\xf9\x11\x92\xf1"
+			  "\x11\xdd\xf5\xad\x29\x39\x05\x95\x54\xac\x47\xb4\x78\x74\x7b\x78"
+			  "\xa2\x71\x92\x97\xae\xda\x20\xe3\xd8\x53\x38\x26\x9b\x30\x80\xfc"
+			  "\x3f\xd7\x8d\xe4\xac\xf3\x4e\x09\x47\x7a\x61\xca\xc7\xc1\xb7\xdc"
+			  "\x76\x94\xed\x14\x1a\x51\x48\x0e\x6b\x2b\x43\xc0\x25\x56\xe8\xa8"
+			  "\x49\x7c\x4f\xca\x56\xf7\xfd\x56\xc8\xeb\x36\xa1\xf8\xc3\xd1\x24",
+	.shared	= "\x23\xb0\x6f\x49\x39\x60\x9b\x0f\x67\x08\x85\x2d\x4f\x87\xb3\x56"
+			  "\x98\x8f\xb4\x5b\x1e\x4c\x95\x1b\x0b\x1d\x59\xbb\xa8\xca\x8b\x60"
+			  "\xc2\x55\xa1\x8f\x37\x55\xa6\xdb\x05\xe4\x28\x5f\xe8\xf1\xf9\xd2"
+			  "\x6a\xdd\x24\x14\x19\xf0\xfc\xa9\x82\x37\xfd\x7a\x5e\x52\x6d\x57"
+			  "\xab\x5a\xd0\x69\xc3\xf1\x89\xf3\xc2\x91\x50\x11\x44\xa6\x55\x14"
+			  "\xa5\x66\xb7\x4d\x0d\xc6\x41\x9c\x13\x06\xcf\xbf\xf3\x5d\xbe\xb4"
+			  "\x3a\xbd\x5e\xd3\x9c\xe1\x37\x53\xb2\x8a\xe5\xe1\x05\xf7\x19\x1b"
+			  "\xc6\xd7\x0a\xc3\x55\x2c\x82\x37\x3c\x6b\xd9\xdb\x8e\xd5\xee\x15"
+			  "\x46\xfd\xb5\x49\x9a\xe7\x0a\x6b\xcb\xd1\x85\x9a\x31\xec\x43\xdc"
+			  "\xcf\x05\x52\x5e\xe4\x0c\x94\x98\x87\xdd\x81\x68\xae\x29\xcc\x53"
+			  "\x7a\x6f\x57\xa5\x26\xf4\x25\xdd\x07\x5f\x39\xd6\xee\x71\xcb\x49"
+			  "\x7a\x57\x1f\xe5\x79\x58\xc7\xde\x32\x1d\x64\xf4\xe4\x89\x22\x43"
+			  "\xe7\x8f\xef\x47\xb3\x31\xa6\x76\x84\x49\x89\x19\x1f\x97\xad\xf7"
+			  "\x91\x32\x60\x7a\x14\x8f\x19\x3c\x7d\xd5\xe6\xd5\x99\x25\x7e\x1b"
+			  "\xf1\x21\x93\x24\x68\xdb\xbe\x21\x60\xc9\x7a\xf0\x3f\x9d\x1b\x19"
+			  "\xb1\x6b\x4f\x8f\xec\x5d\xcb\xc7\x98\x34\x4a\x87\xdb\xd4\x02\xa6"
+			  "\x26\x6e\x10\xc0\xe8\xa7\x22\xfe\x9f\x67\xe8\x63\x6c\xb0\xa7\x3e"
+			  "\x22\x4d\x53\x23\xde\x9b\x7f\xa7\xc6\x6c\x62\xa1\xf4\x00\x42\x04"
+			  "\x1c\xba\xde\xf2\x4b\x4f\xaa\xfd\xa9\x14\x79\xec\x91\x97\x64\xb0"
+			  "\xf4\x8b\x95\x9e\x67\x99\xf0\x94\x96\x6d\x24\x61\x27\xc0\x0e\x9c"
+			  "\xc7\xd8\xf5\xa8\x43\xd1\xa4\xd6\x1c\x5c\x0a\x64\xb6\xb1\x6c\xa7"
+			  "\x32\x44\x93\x75\xd9\xcf\x5d\x32\xd3\x99\xf6\x56\xfd\x51\x4f\xbf"
+			  "\xe6\x6e\xea\x82\xe4\x79\xfc\x73\x18\x0b\x72\x1d\xd4\xc5\xbb\x20"
+			  "\xd4\x50\xc5\xa1\x95\x9e\x1f\x8f\xed\x9d\xd2\x8c\x97\x05\x12\x72"
+			  "\xf6\x64\x00\xcd\xd4\x13\x45\x7d\xdd\xe6\x9a\xc7\x43\x5e\xe4\xa4"
+			  "\xf7\x2a\x37\x02\x49\x82\xb4\xa7\xf6\xf5\x5e\x03\x07\x03\x82\xb8"
+			  "\x3b\x2c\xed\xb7\x75\x25\x17\xf0\x48\xb7\xc6\x91\xd1\xf1\xd7\xb8"
+			  "\x52\xa5\xb7\xcd\x3b\x2b\xde\x97\x62\x0e\x9b\x2c\xd9\xc7\x7f\xd8"
+			  "\xcc\xb6\x92\x5a\xde\xf7\x06\xa6\x77\x0a\x2e\xfb\x62\x1c\x93\xf1"
+			  "\xca\x24\xf0\x9a\x68\x6e\x8b\x86\x05\x81\x49\x47\x39\x92\x15\x33"
+			  "\x9a\x1f\x29\xfb\x57\xac\xf9\xce\x9e\xba\x2c\xbd\x49\x69\xc8\x9e"
+			  "\x4f\xb9\x39\x02\x12\xb9\xb2\xa3\x5d\x4a\xfa\x17\xb3\xee\xc0\x8a",
+};
+
+dh_test_vector_t modp6144 = {
+	.group = MODP_6144_BIT, .priv_len = 64, .pub_len = 768, .shared_len = 768,
+	.priv_a	= "\xab\x36\xf0\x65\x7c\x4f\xba\xdc\x2a\x3b\x07\xed\xd1\xc8\xaf\xcb"
+			  "\x42\xaf\xcd\x7f\xf9\x1c\x57\x01\x37\x25\x50\x0d\x89\x42\x9f\x34"
+			  "\x79\x8f\x99\xf5\xde\x53\xd1\x08\x8f\xd9\xf6\x60\xa1\xa5\x2b\xe4"
+			  "\x54\xf9\x63\x4d\x15\xbb\x4e\x4c\xe0\x9e\x5a\x69\xe0\xf9\x9d\x59",
+	.priv_b	= "\x59\xa5\x52\xa4\x0d\x17\x80\xaf\x64\x33\xbc\x9e\x8a\x9b\x6d\x48"
+			  "\x30\xdd\xd3\x57\x53\x07\x40\x9a\x90\xc9\x2b\xda\x40\x4b\xb7\x99"
+			  "\xf0\x09\x3e\xfe\x21\xbe\xad\x85\xf1\x6a\x23\x7b\x05\x90\xc3\x35"
+			  "\x6d\x96\x8c\xc0\x9d\xcd\x5b\x2d\x96\x86\x07\xd6\xd1\xbf\x70\xc2",
+	.pub_a	= "\x0a\x78\x01\x5c\x3e\x0d\x36\x2a\xff\xe5\xd9\x3a\x9c\x2d\xf2\xdf"
+			  "\x5b\xb9\x6b\x7f\xf2\xfc\xc2\xdd\x96\x6c\x53\x9d\x1d\x4c\xdb\xac"
+			  "\xec\xe2\x6d\x16\xab\x6d\x3d\xe8\x24\xe0\x75\x87\x29\x12\xeb\xa0"
+			  "\x44\x33\x66\x11\x0e\x0d\x7e\x17\x27\x4b\x95\x78\xaf\x12\x46\x63"
+			  "\xe6\x55\x17\x0b\xf7\xb7\xb2\xbd\xb4\xbf\xe4\x7a\x88\x97\x68\x95"
+			  "\x6a\x98\xf1\xce\x1a\xc8\xc6\xc7\xc4\x8e\x13\xa3\x6c\x16\x1c\x82"
+			  "\x00\x7c\x98\x35\xb2\x2e\x7b\x47\x99\x38\x92\xa1\x71\x2b\x27\x5d"
+			  "\xdc\x84\x54\xf4\x33\x0b\xd1\xfc\x08\xab\xfc\x48\x8e\x71\x8b\x43"
+			  "\xa6\x21\x3a\x09\xc5\x68\x74\xce\xef\xb3\xa9\xfa\xe7\xe1\x11\xc0"
+			  "\x0a\x10\x43\x3f\x4b\x23\x75\xef\xab\x04\x2b\xd5\xc1\xc2\x9a\xaf"
+			  "\x97\x0c\xeb\xae\xb5\x7f\x10\xf0\x10\x6e\xa6\x3d\x25\x72\x59\x93"
+			  "\x0a\xf5\xb3\x3b\xc2\x64\x27\xe6\xef\x47\x32\xde\x43\xdc\xea\x0a"
+			  "\x88\x72\x9b\x93\x7e\x6a\x9a\xfc\xf2\x92\xa2\x9f\x8b\xe9\x9b\x71"
+			  "\x88\xd8\x2d\xfc\x13\x7e\x69\x19\x9a\x53\x5d\x92\xdc\x61\x37\x60"
+			  "\x03\x38\x67\x1e\x6d\x46\x76\x31\xff\xc2\xbd\x69\x59\x42\xcd\x7e"
+			  "\xbb\x40\x2c\x54\xea\x39\x1b\x9a\x02\xde\x1f\x28\x99\xfe\xd5\xbd"
+			  "\xb7\x1f\x27\xab\x71\x0b\xba\xaa\x32\xb2\xc2\xe0\xec\x8d\x4b\xd4"
+			  "\xca\x6c\xc5\x07\xd9\x72\x0b\x20\xaf\x9c\xce\xcd\x7f\x4e\x88\xed"
+			  "\x55\x0a\xea\xbc\x43\xdd\x0b\x3d\xc0\x20\xdb\x3e\x14\x89\x76\xc7"
+			  "\x61\xf5\x44\x21\x8a\x79\xb7\x3b\x37\x77\x24\x99\xf3\x61\xba\x0b"
+			  "\x1d\x3c\xf2\x10\x23\x75\x36\xfb\x89\xd8\x57\x86\x51\xed\x67\x51"
+			  "\xd1\xe8\x10\x95\x61\x2b\x0f\xcf\x65\x36\xbc\xb0\xff\x17\x2c\x3d"
+			  "\x54\xdc\x07\x13\x19\x99\xd4\x11\x98\xf9\x7e\xa8\x32\x9a\xbb\x04"
+			  "\xc3\x75\x3f\x83\xe1\xfd\x3b\x92\x78\x72\x3c\x98\x67\xf4\xc1\xff"
+			  "\x19\xe1\xd2\xad\x7d\x34\x65\xf0\xb8\xc2\xdd\x9d\x4c\xcd\x36\x1a"
+			  "\xbd\xf8\x56\x66\xd6\xfe\x04\x2c\x98\x04\x2b\xec\xa9\x4b\x66\x4b"
+			  "\x71\xcf\x78\x07\x56\xe5\xba\x9c\x8a\x72\xb8\xc9\xe4\x82\xd6\x59"
+			  "\x22\x59\x39\x75\xd6\xdd\x00\xf3\x16\xc7\xb2\x0c\x81\xeb\x67\x4f"
+			  "\x0b\xbe\xa8\x1e\xed\xe6\x7b\xbf\xf1\x17\x38\x3f\xf4\x86\x0b\x97"
+			  "\x75\xa7\x81\x86\x14\xb8\x6d\x48\x5e\x88\x98\xa9\x2f\x54\xfd\x7f"
+			  "\x05\x45\xb4\x32\xcd\x5f\xab\xec\x2e\xa8\x42\xd8\x3b\x51\xc2\x18"
+			  "\x91\x7a\xb6\x10\x5e\x26\x8b\xc8\x50\x08\x2c\x79\xa1\xd0\x74\x12"
+			  "\xce\xc4\xd2\x3c\xb0\x04\x54\xa8\x87\x2b\x9f\xb3\x05\x4a\x89\x64"
+			  "\xb5\xaf\x7f\x64\x4b\x45\xcd\xd7\xf2\xb8\xa8\x8c\xd8\x7c\x6e\xe6"
+			  "\x19\xd9\xaf\x59\xb5\x2b\x07\x37\x1b\x8f\xb0\x57\xe7\x05\x9f\x21"
+			  "\x52\x6d\xc4\x89\x4a\xff\xce\xda\xc8\x5b\x73\xf3\xd4\x07\xc7\x29"
+			  "\x02\x7e\xa6\x79\x82\xd3\x01\xba\x93\x0e\x37\x17\x3d\xfc\x38\xd3"
+			  "\x25\x7e\x52\xd2\x53\xba\x20\xe8\xe9\xef\xa2\x96\x38\x49\x14\xd2"
+			  "\x83\x8b\x2c\x62\xb0\x27\xc6\x5d\x36\x34\xd4\x58\x14\x25\x6e\xc1"
+			  "\xcf\xd0\x2d\x21\xa3\xc0\x9c\x9b\x14\x20\x83\xec\x1a\xeb\x14\x2a"
+			  "\xd3\x97\x40\xad\xd0\xeb\x51\x8f\xa2\x10\x62\xb4\x50\x94\xff\x35"
+			  "\x43\xc2\x29\x88\x0e\xf6\xb9\x4c\x85\x80\x13\xed\x2f\x56\x15\xdc"
+			  "\x0f\x09\xd2\xe5\x40\x11\x70\x34\x76\x2c\xed\xb1\xac\xe5\x82\x77"
+			  "\x45\x42\x3e\x8e\x8d\x08\x6e\x5b\xbe\x34\xf9\x93\x0f\x8a\x43\xec"
+			  "\xa6\x9f\x7c\x56\xe6\x95\x31\x85\x9d\xb1\x97\xaf\x2d\xac\x76\x81"
+			  "\x1f\xfb\x4d\x53\xfe\x04\xe2\x48\xbe\xac\x50\xe2\xb3\x74\x77\x5f"
+			  "\x48\xec\x26\xd0\x9b\xb9\xa3\x28\x23\xa9\x2c\xc2\x0a\xb7\xd3\x80"
+			  "\x87\x03\xa2\x3b\x74\x07\xaf\xa5\x5f\x2b\x9b\x90\xa2\xf8\x89\x3c",
+	.pub_b	= "\x75\x3a\x06\x23\x48\x41\x6e\x90\x3b\x5b\x3b\x25\x89\x38\xf1\xa4"
+			  "\x3f\xe0\x96\x2a\xcb\x3c\xd2\x7a\x71\xb3\xed\x8a\xd4\xa5\x62\x77"
+			  "\x4b\x6f\xf4\xf2\x29\x31\x2a\xfc\xb4\x7b\x34\xfe\x9c\xb0\x83\x62"
+			  "\xe7\x45\xc9\x93\x19\x89\xdb\x90\x99\xc5\x77\x85\x06\x97\xa6\x2f"
+			  "\xde\x6d\x98\x01\xbc\x4f\x51\x92\x94\x6f\x10\x3a\x7a\x56\x14\x48"
+			  "\xad\x7d\x1d\x15\x0c\x8c\xda\xc9\x01\xf1\x3b\xfd\x27\x09\x2e\xf7"
+			  "\xec\x0f\x82\x1e\x0e\xa6\xb9\x1b\x63\x90\xc3\x3e\x7e\xf1\xad\x5c"
+			  "\xaf\x6f\x6d\x9d\x3f\x25\x4f\xe9\x53\xaf\x03\x6e\xdc\x24\xf3\x2c"
+			  "\x65\x67\xc7\x08\x61\x80\x18\x7c\x19\x97\x44\x56\x5e\xf0\xa2\x94"
+			  "\x7c\x59\x01\x94\x5b\x46\xa8\x0b\x28\x6c\xa0\xfc\xa0\xad\xe4\x4a"
+			  "\x2c\x87\x77\x7b\x44\x28\x25\xd4\xa2\x24\x70\x69\x9a\x83\xf7\x65"
+			  "\xde\xe3\xeb\x03\x14\x00\x4c\xba\x87\x87\xf2\x47\x4c\x3e\x44\x67"
+			  "\x66\x85\x48\xb4\x12\xa6\x15\x22\x0d\x39\x02\x07\x66\x59\x07\x3a"
+			  "\x64\x9e\xba\x6e\xc4\xdc\x29\x07\x5b\x67\xff\x42\xca\xe0\x1d\xcd"
+			  "\x39\x08\xff\x63\x03\xb1\x76\xc4\xa3\xdc\x81\x33\xfb\x4c\x28\xa1"
+			  "\xe4\x7e\xbe\x5f\x73\x24\x92\x7a\x40\x8d\x75\xc5\x94\x13\x26\x91"
+			  "\xef\x9a\xee\x45\xaa\xff\xfc\xae\x61\x34\xdb\x20\x96\x99\xe9\x18"
+			  "\x30\x95\x37\x23\xaf\x3d\x2f\x3b\x03\x69\x4b\xfa\x92\x92\x57\x8e"
+			  "\x66\xe2\x89\xf0\x62\xe5\x2b\x2c\x23\xca\xcd\x8d\xdd\x88\x92\xb4"
+			  "\xc9\x8e\x9d\x57\x62\x69\x3e\xd1\xd7\xc8\x7e\x99\xac\x4e\x7c\x65"
+			  "\xaf\xea\x99\xfa\x69\xd8\x46\xb2\xc7\x1f\x76\xf1\x3e\x99\xb7\x23"
+			  "\x2c\x7c\x80\x8b\x3a\x5e\x86\x2c\x50\x5a\x36\x48\x0a\x23\x23\xdf"
+			  "\x69\x95\xa0\x1b\xfd\x1f\x4e\x06\xc5\x0b\x17\x3c\x62\xce\x5a\x63"
+			  "\x82\xcd\x14\x64\xb8\x60\x36\xb9\x74\x9c\xa4\xe1\xa5\x0c\xc0\x77"
+			  "\x05\x41\x46\xac\x16\xdb\xb5\x16\x71\x71\x6e\x62\x93\x17\xd6\xdc"
+			  "\xbb\xbd\xb3\x01\x5f\x08\xa9\x71\x91\x97\x92\xb1\x1d\xa8\x0a\xf9"
+			  "\xc3\xaa\x4c\xc2\x63\x48\xd1\xae\x21\xbb\xf3\xb7\xda\x04\x5e\x6e"
+			  "\x82\x89\x5d\xdc\xfb\xae\x76\xaf\x50\x42\x71\x06\x8b\x0c\xfd\xb9"
+			  "\x0f\x00\x24\x97\xe0\x0c\x9f\xf2\x95\x11\x63\x6f\xcf\x59\xfb\xd2"
+			  "\xcc\x10\xec\xaa\xef\x89\xff\x1b\x48\xc9\xce\x78\x22\x50\xf6\x31"
+			  "\x47\x78\x38\x3b\xae\x32\xed\xf6\xaa\xa9\x7a\x53\x71\xc6\xbd\x10"
+			  "\xcf\x17\xf4\x1b\x1e\xb0\x90\x4d\xd1\xd2\xa2\x9b\x5c\x37\xd3\x9c"
+			  "\x31\xb2\xb8\x5b\x8c\xa2\xde\x11\xf7\x97\x03\xea\x45\x38\xc5\x5c"
+			  "\x22\x8e\x3d\x60\x4a\xc7\x32\xaa\xee\x7a\x67\x9a\xa5\x85\x1f\x64"
+			  "\xb1\x45\xe7\xe1\x69\x68\x5c\x65\x1e\x0a\xf3\xf3\x11\x26\x98\x7b"
+			  "\xf8\x27\x23\xad\xf4\x25\x6f\xab\x83\x48\xc4\x5e\xba\xea\x73\x6a"
+			  "\x2b\x82\x66\x02\xf5\x21\x5a\xbc\xf5\xbf\xf1\xa4\x72\x1c\xd9\x9d"
+			  "\xb6\x46\xe9\xb5\x61\xbe\xe5\x59\x8a\xf9\x8e\xfa\x79\x2e\xa6\x02"
+			  "\xad\x22\xea\x06\x2c\x42\x66\xb9\x0c\x6d\x4b\x2b\x8b\xd9\xa3\x8b"
+			  "\x60\xe2\x63\xe0\x44\x54\x02\x2f\x75\xb7\x41\x81\x9c\xe7\xce\xc4"
+			  "\x3e\x82\x05\x5e\x0e\x4c\x16\x0a\x59\xfa\xb1\x13\x02\x87\xb8\xd8"
+			  "\xa7\xbc\x15\xb2\x5a\xb5\xea\x50\x76\x76\x73\xa1\xf4\xc2\x71\x88"
+			  "\x5d\x0c\x8c\xbe\x32\x3d\x60\x15\xdb\xad\xde\x37\xf8\x8e\xb8\xd2"
+			  "\x24\xc3\x3c\x97\xe7\x9c\xc6\xdc\xcd\xcd\x43\x93\x06\xd8\x64\x9f"
+			  "\xca\x07\x15\x47\xca\x13\x39\x8d\xd6\x75\xe0\x61\x7f\x7f\x15\x28"
+			  "\x8f\xe8\x4d\x19\xb6\x41\x20\x93\x17\x03\xaf\x1b\x16\x13\x07\xc7"
+			  "\x50\xfe\xeb\x97\x7c\xe3\x72\x32\x9b\x87\xab\xab\x2d\x47\xa0\x93"
+			  "\xc3\xc9\x17\x58\xc6\x2c\x8a\xa8\x78\x6e\x6c\x30\x6c\xbf\x3f\x66",
+	.shared	= "\xfc\xe8\xe5\xeb\xf2\xb0\x07\xfc\x46\x60\x17\xa8\xed\xf0\xf1\xa6"
+			  "\x9f\x5a\xf2\xea\x49\x2a\x09\xd8\x08\xd2\x84\xc2\x2d\x9b\x3d\x07"
+			  "\x2b\x9f\x89\x1b\x0c\x0f\x09\xe4\x67\xd1\x6e\x33\x8d\x2e\x6d\xd1"
+			  "\xf5\x1b\xdb\xc4\xe8\x64\x61\xf5\x49\x47\xd0\x07\x0f\xbe\xc1\xfc"
+			  "\xe3\xe4\xf3\xd8\xa6\xeb\x73\x8c\xb1\xd5\xcf\xc6\x54\x6d\xe2\x07"
+			  "\xba\x55\x17\xe8\x2b\x39\xc2\xab\x30\x8d\x2d\x48\xe1\xe7\x3f\x7f"
+			  "\x5c\xf8\x4a\xfa\x7b\x71\xb3\xf2\x4c\x52\x45\x5d\xfd\xa0\x94\x98"
+			  "\xe9\xde\x3f\x14\x52\x7f\xa5\xd6\xf7\xa4\x67\x27\x4d\x84\x4e\xaf"
+			  "\x7f\x20\xef\xc6\xaf\x5d\xac\xaf\xd7\xe1\x52\x02\x6f\xd4\x84\x73"
+			  "\x15\x7b\x74\x89\x65\xcd\xa7\xb8\xd5\x8d\x54\x94\x44\x88\xf6\xd2"
+			  "\xa9\x7f\xa9\x12\xd1\x19\xa7\x75\x2f\xcf\x3c\xb9\xc2\xc7\x66\x18"
+			  "\x91\x83\xd9\xa1\x69\xe2\x09\xc0\x38\x7f\x7b\xff\x5e\x44\x9d\x34"
+			  "\x3c\xef\xb3\xbc\x86\x57\xaa\x28\x22\x09\x7a\xa1\x64\xad\xf0\x16"
+			  "\xcb\x15\x8f\xaf\x9e\xb8\x0f\x9f\x53\x1c\x8a\xf9\xf3\x2d\xee\xf7"
+			  "\x31\xa8\xcd\x44\x6a\x5f\xea\x66\x95\x81\x96\x49\x83\xd7\x1d\x54"
+			  "\xaf\x34\x81\x5d\x3c\x4e\x4e\xc5\xe6\x5c\x04\x4d\x7a\x5c\x4b\x7b"
+			  "\x54\x14\xa1\x19\x31\xe3\xda\x28\x4f\x8a\x3a\x99\x12\x3c\x22\xb5"
+			  "\xce\xe7\x8b\x1c\xf0\x3a\xdf\x88\x5b\xe5\xdb\x0a\x88\xcd\x84\x9d"
+			  "\x41\xdd\xf1\x63\x00\xf3\x6c\x23\xa4\x4b\x81\x04\x74\xd1\x35\x8f"
+			  "\xef\x99\x9d\xf9\x46\x7f\x96\x98\x15\xbc\xa6\x25\x39\x6e\x32\xd1"
+			  "\x7f\xa0\xcc\xe9\x60\x41\xc7\xcf\x0d\xd3\x16\x99\xee\xb7\x63\xbb"
+			  "\xb2\x4c\x93\x7f\x50\xd0\xfe\x90\x39\x33\x87\xc6\x17\x97\x44\x83"
+			  "\xad\x3c\x20\x2f\xd5\xc0\x30\xf4\xfa\xde\xdf\x42\x43\x16\x46\x6a"
+			  "\x6b\x36\x59\xcd\xf1\x8c\x39\x82\xba\x54\xf6\x34\x3f\x6b\xf2\xf2"
+			  "\x1f\x58\x58\xea\xdb\x8f\x80\xa2\x4d\x01\xe8\x2d\x70\x0c\x58\xf9"
+			  "\x56\x4f\x6e\xea\xe2\x98\x0c\xc7\x01\x74\x40\x25\x24\xcc\x87\x16"
+			  "\x98\x67\x5a\x7e\x95\x87\xa1\x41\x0e\xa6\x22\x89\x13\x26\x0f\x6f"
+			  "\x81\xdc\xd5\x3d\x75\xe0\xd6\x71\xe7\xde\x0a\x6c\x62\x3b\x64\xab"
+			  "\x2f\x67\xa0\xad\xdc\x32\x70\x1c\xa1\xfa\xe9\x08\xed\x5d\x90\x09"
+			  "\xad\x42\x74\x5d\xcd\x12\x24\xfb\x14\xe8\xb9\x89\xa4\x4f\x0b\x07"
+			  "\xa9\x4a\x7a\x27\xce\x19\x8d\x32\x6f\x74\x9a\xc5\x10\x91\xf1\xfc"
+			  "\x03\xfa\x1c\x87\xe8\x70\x5c\x36\xa8\xef\x2c\xc7\xb6\xe4\x47\xac"
+			  "\xb7\x3d\x0e\x44\x12\xbd\xa2\xf9\xdb\x49\x5f\xc5\xe6\xdf\x7a\x37"
+			  "\x87\x32\x73\xb3\x6d\x08\xac\xef\xb8\xa3\x0a\x14\xb6\xd7\x7f\x76"
+			  "\x0f\x02\x9b\x93\x45\x7b\xee\xd4\x92\x53\x40\x6c\x9e\xe1\x52\xe4"
+			  "\x22\x31\xcf\xcb\xc5\x30\x11\xe0\xb6\xe4\x17\xad\x03\xe9\x8d\xaf"
+			  "\x2e\xc8\x5a\x2c\x89\x49\x9d\xde\x67\xc4\x03\x1d\x91\x8f\x30\x7d"
+			  "\x11\xd1\x93\x8c\x7b\xb9\x17\x71\x7c\x3b\x14\x34\x03\xba\x76\x8a"
+			  "\x4b\xe0\xd0\x93\xc9\x25\x59\xce\x3f\xcc\x5d\x38\xfe\x18\xfa\xbb"
+			  "\x0d\xde\xe0\xd4\x17\x3e\x18\x27\x58\x73\x86\x89\x71\xa0\x7f\xcd"
+			  "\xd4\x8e\x54\xcc\x3f\x63\x1e\x44\x3d\xb9\x39\x77\x4c\xb8\xaa\x57"
+			  "\x5f\x7b\xd2\xa9\x86\x9c\x15\xbe\xa7\xf1\xea\xa9\xdf\x95\x32\x2c"
+			  "\xbf\x93\xb0\x31\xaf\x6e\x74\xe0\x37\x7c\x94\xf0\x4f\x6c\x44\x3c"
+			  "\xd9\x1c\x3b\x48\x24\x8b\x28\x2f\x65\x54\xce\x69\xf4\x5b\xb6\x11"
+			  "\xef\xab\xec\x45\x4d\x10\x58\xa7\xf2\xa7\xc7\x1a\x9f\xfa\xdc\xcd"
+			  "\x54\xfa\x0d\xe8\x96\xbc\x0d\x55\x0a\x49\xf1\x2a\x31\x28\x15\x26"
+			  "\x56\xf2\xa0\x6c\x84\x51\xbd\x6b\xee\x20\xc5\xd6\x4b\x36\x5f\x7b"
+			  "\xb8\xd0\xeb\x41\xb6\x7c\xfb\x9d\x9d\xfd\x62\x0e\xb7\x99\xca\x17",
+};
+
+dh_test_vector_t modp8192 = {
+	.group = MODP_8192_BIT, .priv_len = 64, .pub_len = 1024, .shared_len = 1024,
+	.priv_a	= "\xa6\x48\x81\x47\x45\xfe\x1e\xd1\x98\x9b\x75\xba\x6d\xd5\x01\xe4"
+			  "\x4e\x77\x6d\xc9\x97\xa0\xae\x27\x37\x64\x61\xb0\xee\x79\x65\x94"
+			  "\xc2\xe6\xdb\x07\xe5\xf9\xd8\x7d\x94\x4d\x37\x01\x22\x38\xe5\x70"
+			  "\xaf\x52\x3a\x47\xf3\xe8\x6e\x2a\x4c\xd0\xdb\x3a\x49\x40\xcf\x0b",
+	.priv_b	= "\xd8\xf2\xb0\x9f\x17\xbe\x6f\x13\x64\x5c\xb4\x57\xbe\x0a\xa8\x02"
+			  "\x02\xe8\x43\xf5\x10\xd2\x93\xf9\x32\x55\x98\x2f\x89\x87\x26\x61"
+			  "\x79\xd6\x01\x90\x95\x70\xa3\xf9\xcc\x58\x50\x8b\x62\xf8\x8d\x64"
+			  "\xe0\xd0\x59\xf1\xa2\xed\xea\xd4\x42\x82\x04\xcc\x09\x2a\x2d\x82",
+	.pub_a	= "\x1f\x6d\x66\x0a\xfb\x04\x87\x42\x55\xe6\x83\xee\x89\x9a\xd2\xfd"
+			  "\xbc\xf7\x35\x7f\xdf\xe2\x47\xef\x3b\x2f\xf9\x41\x19\x48\x45\x26"
+			  "\x44\x53\x41\xc5\xdf\xea\x28\xa7\x45\xa0\xff\x56\x95\x13\x24\x72"
+			  "\x34\x1b\x11\xb2\xe6\x9b\xd8\xe9\x98\x18\xf0\x5c\x22\x74\x26\x65"
+			  "\x9c\xf0\x34\x81\x55\x50\x1d\xce\x5a\x7b\x5d\x11\xae\xaf\xfb\xd0"
+			  "\x52\xb5\xff\x8a\xc8\xe3\x5e\x78\x50\x29\x79\x53\x9e\xf4\xe4\xa7"
+			  "\xa9\x51\x55\x1a\xcc\x10\x02\x72\x6b\xa8\xee\x95\x95\x70\x19\x92"
+			  "\x34\x15\xd8\xec\x61\x27\xbe\x25\x2c\x44\x65\xb0\xef\xae\x8a\xee"
+			  "\xcd\x39\x0f\x33\x55\xcf\x94\x52\x5e\xef\x38\xdb\x92\x62\x79\xb8"
+			  "\xfd\xce\xe1\x3c\x43\x8e\xdd\xb2\xa5\x22\x44\xa7\x1b\xda\x1e\x85"
+			  "\x30\x91\x82\xfa\x8c\x57\xff\x0c\xd4\x06\x9d\x4f\xfb\xcc\x42\xe5"
+			  "\xe6\x60\xc1\xf0\x07\x3c\x85\x6a\xc6\x11\xcb\xf7\xf9\xf3\x2c\x95"
+			  "\x67\xa1\x8e\x44\x94\xed\xe7\x42\x7b\x1a\x18\x16\x55\xdb\xc7\x91"
+			  "\xc7\x9d\x54\x7d\x88\xfd\x49\x45\x9b\xd3\x56\xee\x47\x26\xa9\x5c"
+			  "\xd3\x7b\xf2\x42\xe4\x8a\x94\xd9\x22\xcc\x06\x66\xce\x4f\x29\x91"
+			  "\x2a\x1e\x4e\xc8\x8e\x3e\x40\xde\xdc\x95\xe1\x2c\xe2\x50\x47\x2e"
+			  "\x58\x37\x49\x32\xe4\x64\x81\xe7\x03\x11\x81\x13\xb7\xdd\x6f\xef"
+			  "\xae\xf5\xc5\xe6\x1c\x13\x6b\x76\xa1\xb0\xbf\x4d\xf0\x01\xc3\x09"
+			  "\xd8\x59\xff\x13\x34\x6d\x52\x11\x9b\xa6\xc9\xca\x38\xe6\x71\x80"
+			  "\x39\xae\x37\x4b\x1c\xe1\x13\xfb\xc6\x91\x8f\x32\xc3\x6a\x04\xd8"
+			  "\xc6\x80\x08\x4e\xef\xf6\x80\xf9\x8f\xda\xaf\x27\x79\x9b\x21\x2d"
+			  "\x2d\xea\x87\x4b\x4d\xeb\x5a\x87\xfb\x72\x36\xe2\x3e\x9b\x42\xcf"
+			  "\xa9\xeb\x49\x41\xe6\xc2\xb8\xc0\xad\xbd\xb3\x61\xc1\x61\x5f\x9c"
+			  "\xb6\xbd\x8f\x99\x3a\xe8\xca\x86\xb8\xd8\x7f\x2f\xb2\x33\xc0\x9f"
+			  "\xd3\x8e\x44\xdc\x6d\x0c\x19\x89\xb9\x05\xc6\x36\xf4\x7a\xc3\x06"
+			  "\x46\xa4\x22\x6e\xef\x76\xba\x92\xfd\xaf\xce\x71\xbc\x0c\x05\xfe"
+			  "\xec\x8f\x8d\xfb\x59\x46\xf9\x7c\xc1\x1f\x1c\x52\x62\x4d\x01\x57"
+			  "\x4e\x86\x03\x94\x8b\xba\xf7\xbd\xca\xbb\x15\xaa\x61\xdd\xbc\x32"
+			  "\xdf\x9e\x5f\xad\x3b\xf8\xf6\xfb\x4d\x1e\x9c\x86\x9e\x7e\x0f\xaf"
+			  "\xf6\x91\x7e\x08\xf4\xfb\x55\xd8\xe0\x4b\xd9\xcd\x23\x57\x83\x58"
+			  "\x59\xd7\x56\x93\xee\x14\x2f\x2b\xd2\x83\xa4\xce\x45\xa2\x90\xba"
+			  "\x15\x4d\xca\x0c\x8b\x29\x7a\xe5\xbc\xba\xa0\x45\xd0\x08\x27\x75"
+			  "\x61\x3a\x83\x99\x2f\x39\xc6\x41\x03\xc0\xb7\xd6\xfb\x5b\x94\x64"
+			  "\xc3\xfe\xca\x32\x1c\xe3\x66\xc8\xb4\x49\x44\x1c\x63\xb0\xaa\x18"
+			  "\x31\x4b\x15\x8a\xda\x77\xc5\xfd\xea\x33\x6c\x9a\x45\x4c\x24\xb5"
+			  "\x1c\xd2\x5d\x56\x98\x3c\xdf\xb1\x5f\x10\xee\xc1\x17\xec\xbe\x7c"
+			  "\xdb\x24\xdd\xdb\x22\xf6\x47\x8a\xfc\xc5\xb5\xa8\x9a\x8f\xb8\x27"
+			  "\x72\xa1\xd4\x5e\x43\xcd\x7b\x33\x2e\xe3\x09\x94\x77\x20\xfe\xba"
+			  "\xae\x2e\x9b\xc1\x43\xdd\x9d\x44\xd8\xd6\xfe\xff\xe3\x0f\xf6\xd3"
+			  "\x71\xa1\xf8\xda\x1c\xff\x41\x21\x6f\x07\xc9\x55\x99\x6f\x0a\xef"
+			  "\xd6\x5a\x6c\xa5\xdd\xba\x98\x46\x30\x43\xad\x27\xe4\xf1\x1e\x3a"
+			  "\x89\x4a\xb3\xc8\x6d\xf7\xe9\x2f\x48\xd0\xd7\x29\x38\x5c\xe7\xac"
+			  "\xbc\x3f\x65\x5e\x23\xdd\xc1\xad\x73\xed\x1a\xee\x81\xf3\x63\x29"
+			  "\x7e\x72\x8f\x1a\xfc\x2d\x03\xf9\xbb\x3c\x38\x42\xc2\xfb\x53\x2f"
+			  "\x56\xd6\xca\xb9\xeb\xa4\x17\x46\xdb\x53\x56\xf0\xdd\x1d\x8a\xfc"
+			  "\x03\x06\x4d\x8c\x97\x7e\xf0\xc6\x5d\x6d\x5a\x23\xed\xee\xf9\x11"
+			  "\xed\x04\x34\x0c\x04\xa0\x60\xf9\xa8\xfe\x8f\xfa\xd6\xf3\x27\x3d"
+			  "\x32\x48\xbe\x3b\x56\x3a\xe8\x76\xe9\x54\xe7\x81\xef\xe3\x8f\xd9"
+			  "\x03\x42\x5b\xa7\xd2\x69\x96\x39\x05\x8f\x41\x25\x35\x3a\x56\x66"
+			  "\x5a\xc8\x36\xda\x84\xc5\xe9\x2e\x55\xac\xe9\xeb\xdc\x8f\xd8\x26"
+			  "\x06\x3b\x61\x7f\xd7\x78\x4e\x5b\xe5\xd7\xca\x76\xf0\xd0\x71\xf6"
+			  "\x45\x21\x30\xdf\xfc\x69\x82\xcf\xc3\x02\xda\x4f\x4e\x51\x59\x4f"
+			  "\x56\xd1\x60\x5a\xd9\x12\x21\x7a\xa9\x99\x81\x5a\xa8\xa8\x10\x94"
+			  "\xd7\x3e\x58\x7e\xd9\xde\xbc\xf5\x83\xf0\x92\x4f\xe6\xdd\x17\xb3"
+			  "\x9c\xdd\xd5\x7b\xc0\xb4\xb5\x8c\xae\x7b\x63\x1a\xaa\xd0\x93\x55"
+			  "\x31\x28\xd7\x8e\xec\x8c\x28\x64\x81\x9e\x2e\x47\xa9\xb3\xa0\x06"
+			  "\x2a\x3d\xfe\x27\x40\x9c\x13\x96\xa0\xff\x65\xd9\x05\xd8\x92\xa2"
+			  "\x63\x0e\xbf\xe2\xc5\xe3\x51\xbf\x20\x74\xdc\xbe\x5a\xfb\xd5\x5c"
+			  "\x1b\x8f\x41\x21\x43\xaf\xdf\x35\xd1\x46\x80\x16\xf0\x28\x5d\x55"
+			  "\x52\x0c\x05\x24\x63\x68\x5d\x50\x7a\x50\xde\x2d\xfa\xae\xd0\x71"
+			  "\x9a\xad\x2a\x56\xb6\xa2\x52\xbc\xe1\x93\xc4\x93\x36\xc6\x08\xec"
+			  "\xf3\x26\x14\x0b\xa5\x4c\x9e\x15\xf3\x48\xf6\xd1\xd4\x45\x41\xd7"
+			  "\xb7\x5c\xd9\x89\x89\xe6\x62\xe6\x4b\x9f\x3a\xf7\xc7\x77\xd7\xc3"
+			  "\xae\x18\x3c\x5c\xee\x2a\xf1\x80\x8a\x73\x83\xa4\x0e\x63\x12\x04",
+	.pub_b	= "\x8e\x2b\x1b\xac\x90\x76\x05\x3f\xf4\xd5\xde\xa3\xad\xf0\xe9\x40"
+			  "\x27\x69\xb2\x65\x1a\x54\x5c\x89\x0a\x82\xbd\x59\xc3\x4f\x55\x02"
+			  "\x77\xdd\xac\x4c\x3b\x43\xb5\x34\xf5\xa2\x15\x85\xba\xa2\x40\x6f"
+			  "\xb7\x37\x6c\xdb\x3d\xd1\xc0\xc9\xa0\x6c\x17\x3c\xa3\xc1\xcf\x7f"
+			  "\x86\x86\xcb\xaf\x9a\x5c\x27\x36\x8e\x47\xac\x3f\x30\x46\xe7\xd9"
+			  "\xd9\x56\x54\x22\xfe\x43\xb6\xc9\x04\xf9\xd0\x63\x02\x02\xcd\x7d"
+			  "\x77\xcc\x21\x1b\x7b\xea\x4a\xc1\x9c\xdb\x68\x0e\x34\x00\x43\x4b"
+			  "\xd1\x66\x03\x07\x42\xc9\x79\x7f\x81\x0f\xcc\xff\x4b\x2c\x00\xf9"
+			  "\xb9\xd4\x70\xde\x92\x65\x45\x32\xac\x64\x76\x49\xe6\xc0\x26\x77"
+			  "\xbc\xb8\x09\xa6\xbd\xa1\x22\x73\x13\x4b\x1c\x7c\xa8\x88\xe1\x69"
+			  "\xb1\xe2\x64\x48\x3f\x4b\x2f\xd8\xa3\xb4\xf6\x4e\x5a\x79\x06\xf0"
+			  "\xcb\x72\x9c\x72\x0e\xe6\x39\xa6\x69\x7b\xa3\x32\x9e\xa0\x81\xb0"
+			  "\xd6\xa2\x10\xee\xbb\x5b\xd5\x51\xd0\xd6\xbf\x28\x80\x0c\x67\xf4"
+			  "\x38\xf4\xc3\x16\x3b\x83\xd2\x6c\xd3\xf3\x02\x34\x64\xeb\xa1\x6c"
+			  "\xb3\xa5\x13\x6a\x64\xb5\xa6\x3a\x1b\x63\x5e\xe7\x03\x96\xdb\x37"
+			  "\x4f\xc8\xb8\x60\x86\x45\x30\x61\x97\xfa\x8e\x3d\xae\x48\xa4\x7d"
+			  "\xfe\x72\x6a\xe9\x98\xeb\x77\x13\x4a\x4e\x6a\xae\x24\xf2\xd2\xad"
+			  "\xa6\xca\x7e\x98\x38\x53\x24\xea\x98\x09\x2c\x5b\x0f\x46\x9c\x6a"
+			  "\x50\x0c\x46\x27\x98\x51\x56\x06\x6e\xca\xe9\xb8\x47\xe7\x20\xd7"
+			  "\x71\x38\xdc\x17\x74\x4e\x0b\x9d\xa6\xe3\x8e\x69\x28\x2a\x90\x45"
+			  "\x3e\x72\xdf\x62\x88\x3a\x8a\x04\x59\x05\x43\x2a\xa3\x22\x90\x1f"
+			  "\x62\xa2\x46\x03\x90\x81\xd8\x1a\x12\x77\x37\x08\x34\x58\x0d\x0b"
+			  "\x5d\x02\x5f\xa3\x66\xfb\x6e\xeb\x22\x5c\xe3\xbc\xcc\x8d\xa5\x94"
+			  "\xe8\x14\xd5\x08\xfe\x8b\x75\x6a\xf1\x9a\xde\x32\x26\x10\xb4\xb9"
+			  "\x9f\x5d\x60\x83\x66\xdf\xfc\xfe\x4d\xdc\xd9\x95\xcf\xa9\x89\xc4"
+			  "\xe6\x92\x8a\xd5\x99\x35\x7e\xc5\x5b\x42\x62\x92\x3f\x7e\x2a\x32"
+			  "\xd0\x64\x8b\x0a\x61\x0f\x3d\xa8\x83\xb8\x95\x77\x34\x3c\xd0\x31"
+			  "\xe6\xf9\x01\x69\x2f\x3f\xb4\xa1\x03\x18\x1b\xf1\xbd\xac\xe1\x8d"
+			  "\x61\xb8\xd0\xf6\x7f\xd9\x7a\x3f\x26\xc1\x81\x16\x80\x93\xe6\x65"
+			  "\x56\x5b\xc1\x56\xfb\xf1\x65\xd9\x5a\x21\xe9\xf2\xd2\xde\x7d\x89"
+			  "\x12\xa2\x4f\x8f\xd9\x61\x0c\x51\xbf\xfc\x36\x65\x36\x5b\x51\x20"
+			  "\x90\x42\x3a\x99\xd1\x88\x21\xf1\xd7\x1a\xe1\xed\xca\xdd\x08\x4e"
+			  "\xb5\x29\xa3\x72\x83\xed\x85\x15\xe5\x20\x5c\x6e\xbb\x39\x2a\x38"
+			  "\x12\xde\xe0\x5a\x1c\x10\x7b\xb2\x5b\x46\xa2\x80\xb4\x3e\x59\x1a"
+			  "\x7d\x09\x70\x9d\xbc\x6f\x76\x8a\xf4\xb4\xc9\x35\x26\xfb\xcc\x7a"
+			  "\xb5\x52\x8b\x06\xe3\x6f\x50\xb1\xf6\x4d\xf4\xbd\xa9\x1e\x39\x37"
+			  "\x56\x1b\x25\x62\x0f\x7a\x4a\xfb\xe1\xff\xf5\x28\xf8\x40\xd4\xf2"
+			  "\x99\xd1\xad\xd9\x23\x5b\x4e\x3b\x8a\x57\x87\x54\x23\xd7\x73\x54"
+			  "\xf9\xa0\x0e\xa5\x49\x5f\x8e\x93\x8e\x41\xeb\x69\x7b\xef\x48\xeb"
+			  "\x1b\xb6\x6b\x48\x29\xff\x4e\x89\xb1\xf2\xbd\xef\x77\x7a\x92\x71"
+			  "\x97\xac\x21\x76\x6e\x54\xd3\x89\xe2\xca\x07\xbe\x00\xe8\xb4\xd4"
+			  "\xd5\x63\xf1\x4b\xbb\x76\x16\xc8\xdb\xf1\x14\x18\x4b\xbe\x39\x00"
+			  "\x75\xf2\x85\x2b\x8e\xd8\xc0\x81\x12\x9b\xe4\x9f\x98\x74\x6f\x70"
+			  "\xa8\xa4\x7f\x14\x66\x21\x91\x61\x86\x2b\xa6\x01\xf5\xd1\x00\x6c"
+			  "\x7b\x3a\x39\xb8\x3b\x6c\xe8\x4b\x16\xd0\x99\xcc\x2a\x9f\x63\xdd"
+			  "\x77\xc1\x1d\x14\x98\x38\xca\x3f\x5a\xdf\xc4\x9d\xf5\xe6\xa8\x2a"
+			  "\x4b\xfb\x53\x68\x6e\x31\x39\x12\x07\x2b\x7e\xe3\x78\x3d\x23\x79"
+			  "\xc4\x2b\xc1\xac\x29\x20\x59\x91\xf0\xd8\xfb\x9d\x20\x5b\x21\x70"
+			  "\x0e\xa8\x46\xca\xfc\x09\x38\x12\x1c\x2c\xa4\x67\xa8\x94\x04\x87"
+			  "\xa4\xaa\x2c\x25\xea\x57\x35\xc2\x4e\xa9\x15\x0e\x7c\x46\xe3\xdf"
+			  "\x40\x77\x81\xd6\xf3\x9c\xee\xd4\x22\x3b\xe9\x20\x98\x1a\x18\x4e"
+			  "\xd3\x3d\xe6\xd0\xfc\xcc\x2d\x5c\x72\x69\xe7\xc4\xca\x12\xe9\xb7"
+			  "\xbe\x84\x31\x9e\x5d\x6f\xcf\x91\x37\x15\xeb\xf8\x08\xba\x50\xc3"
+			  "\xb4\xad\x36\x09\xe0\xd3\x61\xea\x9b\xe6\x28\x56\x33\x73\x2b\xe7"
+			  "\x51\x52\xc5\x40\x66\x34\x47\x03\xe4\xd9\xff\x4b\x23\xaf\x80\x63"
+			  "\xbd\x30\xe0\x2d\xe2\x08\x4a\x09\xd3\x04\x0a\x4d\xbc\x7b\xac\x80"
+			  "\x94\x8c\x4d\xd7\x4a\x35\x72\xa4\x18\x66\xf2\x0e\x01\x6a\x0f\x31"
+			  "\x17\x31\x07\xb9\x65\x68\xd6\xac\x2f\x53\x36\x01\x3f\x06\x18\x77"
+			  "\xae\xbe\xb4\xac\x60\x9a\x73\x3d\x7d\x40\xdc\xed\x19\x27\x03\x57"
+			  "\x0a\xca\xe4\xcc\xc6\xfe\x3b\x7a\x9d\x73\xb2\xa4\xf1\x21\x32\x11"
+			  "\x21\x86\x77\x1e\x25\x96\xc8\xb0\xce\xd5\x1e\x4c\xea\xd0\x04\xde"
+			  "\x67\xa8\x36\x23\x89\x85\x7b\xa9\x2a\x0c\x52\xd5\x63\xbe\x17\xdb"
+			  "\x82\xd5\xf6\x51\xc3\x9a\x9f\xab\x58\x46\x87\x0c\xb3\xc1\x23\x87"
+			  "\x61\xac\x00\xed\x46\xe5\x79\x2c\x5b\xd6\x6e\xaa\xee\x4b\x08\xb2",
+	.shared	= "\x7d\xc5\xc9\x35\xc9\x62\x79\x93\x1d\xfc\x55\xc6\x20\x36\x95\x7c"
+			  "\xa1\x5d\x9c\x0f\xdf\x95\xa7\x1f\x59\xae\xb7\xa6\x39\x0f\xd1\x7e"
+			  "\x93\x34\x7f\xb6\x72\x96\xf2\xe3\x20\x30\x40\xe7\x77\x51\xc1\x0a"
+			  "\x08\xf3\xad\x86\x40\xec\xf0\xd2\x9d\x88\xba\xff\x50\xf7\x4e\x88"
+			  "\x1f\xf0\xdd\x12\x17\x05\x97\x1e\x3c\xe3\x91\x65\x10\xd9\x16\x32"
+			  "\x21\x44\xd8\x81\xed\x17\x9a\x60\x34\xee\x4d\x81\x03\xbc\x05\x56"
+			  "\xba\x7f\xa7\x31\xc9\x3b\x57\x5e\x38\x1c\x45\xbf\xfc\x51\x48\xf3"
+			  "\x05\xa9\x74\x39\xdf\xa1\x34\x48\x62\x31\x5d\x58\x45\x16\xc1\x9e"
+			  "\x26\x38\xb4\x59\x95\xdd\x92\x52\x1e\x26\x20\xed\xd2\xb2\xb3\x98"
+			  "\x6b\xde\xbe\xf1\xa0\xbc\x52\xc9\xfe\x97\x65\x78\xd6\xce\x91\xb1"
+			  "\x8e\x9b\x04\xfc\x74\xb9\x1d\x52\x7d\x0b\xf0\x1d\x2a\x3c\xde\x2e"
+			  "\x4c\x49\xee\x62\x9c\x59\x09\x12\xd7\x4a\xd7\x0d\x03\x72\x3d\x04"
+			  "\x58\xd5\x19\x9e\x42\x97\x2c\x32\xb9\xda\x5c\xee\xaf\x40\x44\xc9"
+			  "\xfd\x69\xcf\x6e\x81\x6b\x2b\xa4\x21\x3b\xde\x2d\xc3\xb7\x03\xe3"
+			  "\xa3\xf2\x77\xd8\x70\xf5\x6f\x24\x48\xbf\x48\xb5\xa5\xff\x86\x06"
+			  "\x0c\x23\xc2\xc9\x8e\xfa\x0f\xa6\xaa\x77\x95\x1a\x1a\x91\xfe\x30"
+			  "\x6b\x18\xc5\xfb\x13\x76\x7a\xa5\x29\xa3\x02\xce\x2b\x46\x74\x5a"
+			  "\x1c\xe6\x7c\x3a\xb7\x43\xea\xf9\x3f\x53\xa9\xfb\x63\x94\x26\x42"
+			  "\x82\xdc\x9a\x4a\xd6\xbb\xa9\xd1\x6e\xc2\xc7\x92\x28\x3b\x33\xc3"
+			  "\x58\xf6\xfb\x44\x5c\x5d\xea\xe0\x62\xaa\x30\x97\x30\x38\x36\x47"
+			  "\xb1\xae\x3b\x99\x35\xab\xc9\x45\x2a\x07\xec\x34\x88\x61\x70\xb0"
+			  "\x47\xf9\xd6\x61\x23\x48\x71\x6f\x85\x3b\xf1\x8a\x17\x72\xc1\x99"
+			  "\x6d\x4f\x94\x2b\x11\xf2\x75\x33\x08\x67\x08\xba\xa6\x50\x2a\x1f"
+			  "\x6b\x0e\x38\x0e\x52\xea\xe0\xd8\xcd\xd0\x11\x80\xa7\xb9\x97\xd9"
+			  "\x68\x1b\x21\x7c\xe2\x69\x8e\x14\x61\x39\x49\x65\xbb\xc2\x7c\x2e"
+			  "\x8e\xb1\x83\x28\x7b\xf0\xf0\x62\xdc\x35\x33\xea\xc9\x14\x3f\x83"
+			  "\x60\xd3\xec\x37\xd4\xe3\x87\x86\x2c\x43\x53\x80\x3f\x39\x36\x4d"
+			  "\x1e\x73\x2a\x5c\x8c\xfb\x2d\x2e\x78\xd1\xf1\xe5\x8c\x89\x35\x1e"
+			  "\x0a\xd3\x07\x3c\x05\x0d\x4e\xa0\x81\x6a\xee\xb5\x27\xef\xa6\x2e"
+			  "\x04\x07\x01\xf7\x40\x9b\xbf\x7b\xf8\x3d\x0f\x68\x79\xc6\x96\x16"
+			  "\x53\x5b\xb0\x8f\xb1\xbd\xd4\x28\xa7\x73\x37\x7b\x06\xbf\x9c\xd2"
+			  "\xb4\x28\x82\xb4\xd2\x63\xf9\xb2\x56\x7c\x28\x02\x4b\x91\x63\x03"
+			  "\xdc\x58\x6e\xb5\x88\x2e\x76\x3a\x53\x4a\xd4\x22\x7c\xa5\xca\xdc"
+			  "\x96\x14\xa6\xfb\x64\xe9\xa5\x09\xf2\x3e\x4d\x7e\x40\x01\x93\x05"
+			  "\xe0\xad\x2e\x20\x7c\x4e\x17\x45\xa8\x70\x7e\xd1\xc7\xbb\x10\x94"
+			  "\x81\x36\x22\x62\x3f\x44\xe2\xfa\x36\x9e\x4e\x37\x75\xdf\x8d\x6f"
+			  "\x15\x73\x41\xf0\x6f\x32\xce\xa9\xfc\x06\x8f\x39\xcf\xfb\x34\x16"
+			  "\xba\x74\x7d\xe6\x02\x18\xd3\xe4\x8c\xee\xd1\xef\xdc\xd4\x59\x8d"
+			  "\xeb\x25\x7a\x09\xc8\xcc\x38\x7b\xcb\x8b\x3c\xb8\x77\xb4\xad\x1a"
+			  "\x9e\x78\x20\x58\x6b\x36\x4d\x5d\xbb\x07\x38\xba\x65\xf4\xfe\x4d"
+			  "\x86\x94\xdf\x77\x52\x08\xb1\x75\x07\x85\xaf\x77\xe9\xb3\xab\x3a"
+			  "\x35\x30\x8a\xfd\x34\x99\x3b\x8f\xfc\x9a\x9e\xe1\x46\xcb\xbf\xf3"
+			  "\xbd\xb9\x9c\x8c\x4e\x29\x6d\xa3\x29\x5a\x1f\x88\x23\xdf\x89\xa7"
+			  "\x88\x7c\x90\x75\x5a\xd5\x97\x60\x17\xdf\x5e\x96\x04\xf8\xae\x24"
+			  "\xd8\xf1\xa3\x3a\xa1\x40\x40\xd1\x45\x8e\xa5\xe5\x32\x32\xcc\xcc"
+			  "\x1c\x8a\x9f\x6d\xa0\xa8\x89\x9d\x75\x2b\xd2\xc2\x07\xb2\xe1\x1a"
+			  "\xcd\x4f\x31\x80\xb2\x19\x5f\x06\x9d\x8e\x7a\xf1\x2e\x15\x1d\xbc"
+			  "\x4c\xb4\x75\x6f\x7b\xb7\xe4\x70\xd6\x0c\xe1\x27\x93\xce\x4a\x63"
+			  "\xde\xe7\x48\x87\x5c\x75\xae\x34\x82\x5a\x71\xda\x1f\x93\x72\x64"
+			  "\x7c\x7b\xda\x6a\xd7\xf9\xe8\x1f\x72\x67\x71\x68\x6f\x85\x64\x53"
+			  "\x72\x80\x8f\x1f\x7a\x15\x1c\x11\xfd\x11\xf7\x8c\xc4\x43\x41\x60"
+			  "\x03\xf2\x79\x19\x27\xdf\x98\x37\xaf\x07\xb3\x8d\x0b\xee\x01\x85"
+			  "\x6f\x6d\xa9\xbd\x0e\x1f\x79\xdf\x21\x78\x24\xbf\xc5\x09\x29\x9e"
+			  "\x64\x0d\x8e\xff\xc9\xe7\xe8\x51\xd3\xe8\xfe\xa5\xe0\xa9\x8d\x54"
+			  "\x17\x3a\x34\xaf\xd9\xbd\xfd\xaa\x8c\x81\x79\xfb\x65\x85\x67\x73"
+			  "\x32\x2d\x32\x00\xcb\x3b\xe2\x0e\x43\xe8\x40\xf6\x42\xf2\x74\x00"
+			  "\xa0\xfd\xe6\x96\x4a\x2b\xbb\xa9\xd9\x95\xc4\x42\x75\x12\x3f\xbb"
+			  "\x79\x35\x9c\x91\xb5\x24\x10\xc4\xc5\xbd\x4a\x4c\x47\xd8\x89\x92"
+			  "\x70\xa5\xe6\xc9\xed\x2e\xbd\x98\xc0\x17\xb0\xad\x8c\x31\x95\x81"
+			  "\x84\x86\xb1\xaa\x42\xf6\x2e\x10\x92\x2f\x67\x73\x33\xb9\x02\x43"
+			  "\x52\x24\x05\xdb\x9c\xec\xc5\xf1\x3e\x78\x05\xcb\x04\xd6\x91\xa8"
+			  "\x51\x9e\x48\xa8\xae\xa8\x8d\x13\x2d\xcd\xa1\xbe\x23\x9e\x00\x4c"
+			  "\x0a\x59\xf8\x18\xb0\x0a\x06\xe2\x0a\xb4\x16\x02\xa7\x21\x4c\xac"
+			  "\x9a\x80\x62\x7f\xb6\xd6\xa0\x3b\x11\xd3\x30\xf9\x3d\xfd\x26\x27",
+};
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/modpsub.c b/src/libstrongswan/plugins/test_vectors/test_vectors/modpsub.c
new file mode 100644
index 0000000..bb64e2d
--- /dev/null
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/modpsub.c
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the Licenseor (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be usefulbut
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <crypto/crypto_tester.h>
+
+/**
+ * Test vectors from RFC5114
+ */
+
+dh_test_vector_t modp1024_160 = {
+	.group = MODP_1024_160, .priv_len = 20, .pub_len = 128, .shared_len = 128,
+	.priv_a	= "\xB9\xA3\xB3\xAE\x8F\xEF\xC1\xA2\x93\x04\x96\x50\x70\x86\xF8\x45"
+			  "\x5D\x48\x94\x3E",
+	.priv_b	= "\x93\x92\xC9\xF9\xEB\x6A\x7A\x6A\x90\x22\xF7\xD8\x3E\x72\x23\xC6"
+			  "\x83\x5B\xBD\xDA",
+	.pub_a	= "\x2A\x85\x3B\x3D\x92\x19\x75\x01\xB9\x01\x5B\x2D\xEB\x3E\xD8\x4F"
+			  "\x5E\x02\x1D\xCC\x3E\x52\xF1\x09\xD3\x27\x3D\x2B\x75\x21\x28\x1C"
+			  "\xBA\xBE\x0E\x76\xFF\x57\x27\xFA\x8A\xCC\xE2\x69\x56\xBA\x9A\x1F"
+			  "\xCA\x26\xF2\x02\x28\xD8\x69\x3F\xEB\x10\x84\x1D\x84\xA7\x36\x00"
+			  "\x54\xEC\xE5\xA7\xF5\xB7\xA6\x1A\xD3\xDF\xB3\xC6\x0D\x2E\x43\x10"
+			  "\x6D\x87\x27\xDA\x37\xDF\x9C\xCE\x95\xB4\x78\x75\x5D\x06\xBC\xEA"
+			  "\x8F\x9D\x45\x96\x5F\x75\xA5\xF3\xD1\xDF\x37\x01\x16\x5F\xC9\xE5"
+			  "\x0C\x42\x79\xCE\xB0\x7F\x98\x95\x40\xAE\x96\xD5\xD8\x8E\xD7\x76",
+	.pub_b	= "\x71\x7A\x6C\xB0\x53\x37\x1F\xF4\xA3\xB9\x32\x94\x1C\x1E\x56\x63"
+			  "\xF8\x61\xA1\xD6\xAD\x34\xAE\x66\x57\x6D\xFB\x98\xF6\xC6\xCB\xF9"
+			  "\xDD\xD5\xA5\x6C\x78\x33\xF6\xBC\xFD\xFF\x09\x55\x82\xAD\x86\x8E"
+			  "\x44\x0E\x8D\x09\xFD\x76\x9E\x3C\xEC\xCD\xC3\xD3\xB1\xE4\xCF\xA0"
+			  "\x57\x77\x6C\xAA\xF9\x73\x9B\x6A\x9F\xEE\x8E\x74\x11\xF8\xD6\xDA"
+			  "\xC0\x9D\x6A\x4E\xDB\x46\xCC\x2B\x5D\x52\x03\x09\x0E\xAE\x61\x26"
+			  "\x31\x1E\x53\xFD\x2C\x14\xB5\x74\xE6\xA3\x10\x9A\x3D\xA1\xBE\x41"
+			  "\xBD\xCE\xAA\x18\x6F\x5C\xE0\x67\x16\xA2\xB6\xA0\x7B\x3C\x33\xFE",
+	.shared	= "\x5C\x80\x4F\x45\x4D\x30\xD9\xC4\xDF\x85\x27\x1F\x93\x52\x8C\x91"
+			  "\xDF\x6B\x48\xAB\x5F\x80\xB3\xB5\x9C\xAA\xC1\xB2\x8F\x8A\xCB\xA9"
+			  "\xCD\x3E\x39\xF3\xCB\x61\x45\x25\xD9\x52\x1D\x2E\x64\x4C\x53\xB8"
+			  "\x07\xB8\x10\xF3\x40\x06\x2F\x25\x7D\x7D\x6F\xBF\xE8\xD5\xE8\xF0"
+			  "\x72\xE9\xB6\xE9\xAF\xDA\x94\x13\xEA\xFB\x2E\x8B\x06\x99\xB1\xFB"
+			  "\x5A\x0C\xAC\xED\xDE\xAE\xAD\x7E\x9C\xFB\xB3\x6A\xE2\xB4\x20\x83"
+			  "\x5B\xD8\x3A\x19\xFB\x0B\x5E\x96\xBF\x8F\xA4\xD0\x9E\x34\x55\x25"
+			  "\x16\x7E\xCD\x91\x55\x41\x6F\x46\xF4\x08\xED\x31\xB6\x3C\x6E\x6D",
+};
+
+dh_test_vector_t modp2048_224 = {
+	.group = MODP_2048_224, .priv_len = 28, .pub_len = 256, .shared_len = 256,
+	.priv_a	= "\x22\xe6\x26\x01\xdb\xff\xd0\x67\x08\xa6\x80\xf7\x47\xf3\x61\xf7"
+			  "\x6d\x8f\x4f\x72\x1a\x05\x48\xe4\x83\x29\x4b\x0c",
+	.priv_b	= "\x4f\xf3\xbc\x96\xc7\xfc\x6a\x6d\x71\xd3\xb3\x63\x80\x0a\x7c\xdf"
+			  "\xef\x6f\xc4\x1b\x44\x17\xea\x15\x35\x3b\x75\x90",
+	.pub_a	= "\x1b\x3a\x63\x45\x1b\xd8\x86\xe6\x99\xe6\x7b\x49\x4e\x28\x8b\xd7"
+			  "\xf8\xe0\xd3\x70\xba\xdd\xa7\xa0\xef\xd2\xfd\xe7\xd8\xf6\x61\x45"
+			  "\xcc\x9f\x28\x04\x19\x97\x5e\xb8\x08\x87\x7c\x8a\x4c\x0c\x8e\x0b"
+			  "\xd4\x8d\x4a\x54\x01\xeb\x1e\x87\x76\xbf\xee\xe1\x34\xc0\x38\x31"
+			  "\xac\x27\x3c\xd9\xd6\x35\xab\x0c\xe0\x06\xa4\x2a\x88\x7e\x3f\x52"
+			  "\xfb\x87\x66\xb6\x50\xf3\x80\x78\xbc\x8e\xe8\x58\x0c\xef\xe2\x43"
+			  "\x96\x8c\xfc\x4f\x8d\xc3\xdb\x08\x45\x54\x17\x1d\x41\xbf\x2e\x86"
+			  "\x1b\x7b\xb4\xd6\x9d\xd0\xe0\x1e\xa3\x87\xcb\xaa\x5c\xa6\x72\xaf"
+			  "\xcb\xe8\xbd\xb9\xd6\x2d\x4c\xe1\x5f\x17\xdd\x36\xf9\x1e\xd1\xee"
+			  "\xdd\x65\xca\x4a\x06\x45\x5c\xb9\x4c\xd4\x0a\x52\xec\x36\x0e\x84"
+			  "\xb3\xc9\x26\xe2\x2c\x43\x80\xa3\xbf\x30\x9d\x56\x84\x97\x68\xb7"
+			  "\xf5\x2c\xfd\xf6\x55\xfd\x05\x3a\x7e\xf7\x06\x97\x9e\x7e\x58\x06"
+			  "\xb1\x7d\xfa\xe5\x3a\xd2\xa5\xbc\x56\x8e\xbb\x52\x9a\x7a\x61\xd6"
+			  "\x8d\x25\x6f\x8f\xc9\x7c\x07\x4a\x86\x1d\x82\x7e\x2e\xbc\x8c\x61"
+			  "\x34\x55\x31\x15\xb7\x0e\x71\x03\x92\x0a\xa1\x6d\x85\xe5\x2b\xcb"
+			  "\xab\x8d\x78\x6a\x68\x17\x8f\xa8\xff\x7c\x2f\x5c\x71\x64\x8d\x6f",
+	.pub_b	= "\x4d\xce\xe9\x92\xa9\x76\x2a\x13\xf2\xf8\x38\x44\xad\x3d\x77\xee"
+			  "\x0e\x31\xc9\x71\x8b\x3d\xb6\xc2\x03\x5d\x39\x61\x18\x2c\x3e\x0b"
+			  "\xa2\x47\xec\x41\x82\xd7\x60\xcd\x48\xd9\x95\x99\x97\x06\x22\xa1"
+			  "\x88\x1b\xba\x2d\xc8\x22\x93\x9c\x78\xc3\x91\x2c\x66\x61\xfa\x54"
+			  "\x38\xb2\x07\x66\x22\x2b\x75\xe2\x4c\x2e\x3a\xd0\xc7\x28\x72\x36"
+			  "\x12\x95\x25\xee\x15\xb5\xdd\x79\x98\xaa\x04\xc4\xa9\x69\x6c\xac"
+			  "\xd7\x17\x20\x83\xa9\x7a\x81\x66\x4e\xad\x2c\x47\x9e\x44\x4e\x4c"
+			  "\x06\x54\xcc\x19\xe2\x8d\x77\x03\xce\xe8\xda\xcd\x61\x26\xf5\xd6"
+			  "\x65\xec\x52\xc6\x72\x55\xdb\x92\x01\x4b\x03\x7e\xb6\x21\xa2\xac"
+			  "\x8e\x36\x5d\xe0\x71\xff\xc1\x40\x0a\xcf\x07\x7a\x12\x91\x3d\xd8"
+			  "\xde\x89\x47\x34\x37\xab\x7b\xa3\x46\x74\x3c\x1b\x21\x5d\xd9\xc1"
+			  "\x21\x64\xa7\xe4\x05\x31\x18\xd1\x99\xbe\xc8\xef\x6f\xc5\x61\x17"
+			  "\x0c\x84\xc8\x7d\x10\xee\x9a\x67\x4a\x1f\xa8\xff\xe1\x3b\xdf\xba"
+			  "\x1d\x44\xde\x48\x94\x6d\x68\xdc\x0c\xdd\x77\x76\x35\xa7\xab\x5b"
+			  "\xfb\x1e\x4b\xb7\xb8\x56\xf9\x68\x27\x73\x4c\x18\x41\x38\xe9\x15"
+			  "\xd9\xc3\x00\x2e\xbc\xe5\x31\x20\x54\x6a\x7e\x20\x02\x14\x2b\x6c",
+	.shared	= "\x34\xd9\xbd\xdc\x1b\x42\x17\x6c\x31\x3f\xea\x03\x4c\x21\x03\x4d"
+			  "\x07\x4a\x63\x13\xbb\x4e\xcd\xb3\x70\x3f\xff\x42\x45\x67\xa4\x6b"
+			  "\xdf\x75\x53\x0e\xde\x0a\x9d\xa5\x22\x9d\xe7\xd7\x67\x32\x28\x6c"
+			  "\xbc\x0f\x91\xda\x4c\x3c\x85\x2f\xc0\x99\xc6\x79\x53\x1d\x94\xc7"
+			  "\x8a\xb0\x3d\x9d\xec\xb0\xa4\xe4\xca\x8b\x2b\xb4\x59\x1c\x40\x21"
+			  "\xcf\x8c\xe3\xa2\x0a\x54\x1d\x33\x99\x40\x17\xd0\x20\x0a\xe2\xc9"
+			  "\x51\x6e\x2f\xf5\x14\x57\x79\x26\x9e\x86\x2b\x0f\xb4\x74\xa2\xd5"
+			  "\x6d\xc3\x1e\xd5\x69\xa7\x70\x0b\x4c\x4a\xb1\x6b\x22\xa4\x55\x13"
+			  "\x53\x1e\xf5\x23\xd7\x12\x12\x07\x7b\x5a\x16\x9b\xde\xff\xad\x7a"
+			  "\xd9\x60\x82\x84\xc7\x79\x5b\x6d\x5a\x51\x83\xb8\x70\x66\xde\x17"
+			  "\xd8\xd6\x71\xc9\xeb\xd8\xec\x89\x54\x4d\x45\xec\x06\x15\x93\xd4"
+			  "\x42\xc6\x2a\xb9\xce\x3b\x1c\xb9\x94\x3a\x1d\x23\xa5\xea\x3b\xcf"
+			  "\x21\xa0\x14\x71\xe6\x7e\x00\x3e\x7f\x8a\x69\xc7\x28\xbe\x49\x0b"
+			  "\x2f\xc8\x8c\xfe\xb9\x2d\xb6\xa2\x15\xe5\xd0\x3c\x17\xc4\x64\xc9"
+			  "\xac\x1a\x46\xe2\x03\xe1\x3f\x95\x29\x95\xfb\x03\xc6\x9d\x3c\xc4"
+			  "\x7f\xcb\x51\x0b\x69\x98\xff\xd3\xaa\x6d\xe7\x3c\xf9\xf6\x38\x69",
+};
+
+dh_test_vector_t modp2048_256 = {
+	.group = MODP_2048_256, .priv_len = 32, .pub_len = 256, .shared_len = 256,
+	.priv_a	= "\x08\x81\x38\x2c\xdb\x87\x66\x0c\x6d\xc1\x3e\x61\x49\x38\xd5\xb9"
+			  "\xc8\xb2\xf2\x48\x58\x1c\xc5\xe3\x1b\x35\x45\x43\x97\xfc\xe5\x0e",
+	.priv_b	= "\x7d\x62\xa7\xe3\xef\x36\xde\x61\x7b\x13\xd1\xaf\xb8\x2c\x78\x0d"
+			  "\x83\xa2\x3b\xd4\xee\x67\x05\x64\x51\x21\xf3\x71\xf5\x46\xa5\x3d",
+	.pub_a	= "\x2e\x93\x80\xc8\x32\x3a\xf9\x75\x45\xbc\x49\x41\xde\xb0\xec\x37"
+			  "\x42\xc6\x2f\xe0\xec\xe8\x24\xa6\xab\xdb\xe6\x6c\x59\xbe\xe0\x24"
+			  "\x29\x11\xbf\xb9\x67\x23\x5c\xeb\xa3\x5a\xe1\x3e\x4e\xc7\x52\xbe"
+			  "\x63\x0b\x92\xdc\x4b\xde\x28\x47\xa9\xc6\x2c\xb8\x15\x27\x45\x42"
+			  "\x1f\xb7\xeb\x60\xa6\x3c\x0f\xe9\x15\x9f\xcc\xe7\x26\xce\x7c\xd8"
+			  "\x52\x3d\x74\x50\x66\x7e\xf8\x40\xe4\x91\x91\x21\xeb\x5f\x01\xc8"
+			  "\xc9\xb0\xd3\xd6\x48\xa9\x3b\xfb\x75\x68\x9e\x82\x44\xac\x13\x4a"
+			  "\xf5\x44\x71\x1c\xe7\x9a\x02\xdc\xc3\x42\x26\x68\x47\x80\xdd\xdc"
+			  "\xb4\x98\x59\x41\x06\xc3\x7f\x5b\xc7\x98\x56\x48\x7a\xf5\xab\x02"
+			  "\x2a\x2e\x5e\x42\xf0\x98\x97\xc1\xa8\x5a\x11\xea\x02\x12\xaf\x04"
+			  "\xd9\xb4\xce\xbc\x93\x7c\x3c\x1a\x3e\x15\xa8\xa0\x34\x2e\x33\x76"
+			  "\x15\xc8\x4e\x7f\xe3\xb8\xb9\xb8\x7f\xb1\xe7\x3a\x15\xaf\x12\xa3"
+			  "\x0d\x74\x6e\x06\xdf\xc3\x4f\x29\x0d\x79\x7c\xe5\x1a\xa1\x3a\xa7"
+			  "\x85\xbf\x66\x58\xaf\xf5\xe4\xb0\x93\x00\x3c\xbe\xaf\x66\x5b\x3c"
+			  "\x2e\x11\x3a\x3a\x4e\x90\x52\x69\x34\x1d\xc0\x71\x14\x26\x68\x5f"
+			  "\x4e\xf3\x7e\x86\x8a\x81\x26\xff\x3f\x22\x79\xb5\x7c\xa6\x7e\x29",
+	.pub_b	= "\x57\x5f\x03\x51\xbd\x2b\x1b\x81\x74\x48\xbd\xf8\x7a\x6c\x36\x2c"
+			  "\x1e\x28\x9d\x39\x03\xa3\x0b\x98\x32\xc5\x74\x1f\xa2\x50\x36\x3e"
+			  "\x7a\xcb\xc7\xf7\x7f\x3d\xac\xbc\x1f\x13\x1a\xdd\x8e\x03\x36\x7e"
+			  "\xff\x8f\xbb\xb3\xe1\xc5\x78\x44\x24\x80\x9b\x25\xaf\xe4\xd2\x26"
+			  "\x2a\x1a\x6f\xd2\xfa\xb6\x41\x05\xca\x30\xa6\x74\xe0\x7f\x78\x09"
+			  "\x85\x20\x88\x63\x2f\xc0\x49\x23\x37\x91\xad\x4e\xdd\x08\x3a\x97"
+			  "\x8b\x88\x3e\xe6\x18\xbc\x5e\x0d\xd0\x47\x41\x5f\x2d\x95\xe6\x83"
+			  "\xcf\x14\x82\x6b\x5f\xbe\x10\xd3\xce\x41\xc6\xc1\x20\xc7\x8a\xb2"
+			  "\x00\x08\xc6\x98\xbf\x7f\x0b\xca\xb9\xd7\xf4\x07\xbe\xd0\xf4\x3a"
+			  "\xfb\x29\x70\xf5\x7f\x8d\x12\x04\x39\x63\xe6\x6d\xdd\x32\x0d\x59"
+			  "\x9a\xd9\x93\x6c\x8f\x44\x13\x7c\x08\xb1\x80\xec\x5e\x98\x5c\xeb"
+			  "\xe1\x86\xf3\xd5\x49\x67\x7e\x80\x60\x73\x31\xee\x17\xaf\x33\x80"
+			  "\xa7\x25\xb0\x78\x23\x17\xd7\xdd\x43\xf5\x9d\x7a\xf9\x56\x8a\x9b"
+			  "\xb6\x3a\x84\xd3\x65\xf9\x22\x44\xed\x12\x09\x88\x21\x93\x02\xf4"
+			  "\x29\x24\xc7\xca\x90\xb8\x9d\x24\xf7\x1b\x0a\xb6\x97\x82\x3d\x7d"
+			  "\xeb\x1a\xff\x5b\x0e\x8e\x4a\x45\xd4\x9f\x7f\x53\x75\x7e\x19\x13",
+	.shared	= "\x86\xc7\x0b\xf8\xd0\xbb\x81\xbb\x01\x07\x8a\x17\x21\x9c\xb7\xd2"
+			  "\x72\x03\xdb\x2a\x19\xc8\x77\xf1\xd1\xf1\x9f\xd7\xd7\x7e\xf2\x25"
+			  "\x46\xa6\x8f\x00\x5a\xd5\x2d\xc8\x45\x53\xb7\x8f\xc6\x03\x30\xbe"
+			  "\x51\xea\x7c\x06\x72\xca\xc1\x51\x5e\x4b\x35\xc0\x47\xb9\xa5\x51"
+			  "\xb8\x8f\x39\xdc\x26\xda\x14\xa0\x9e\xf7\x47\x74\xd4\x7c\x76\x2d"
+			  "\xd1\x77\xf9\xed\x5b\xc2\xf1\x1e\x52\xc8\x79\xbd\x95\x09\x85\x04"
+			  "\xcd\x9e\xec\xd8\xa8\xf9\xb3\xef\xbd\x1f\x00\x8a\xc5\x85\x30\x97"
+			  "\xd9\xd1\x83\x7f\x2b\x18\xf7\x7c\xd7\xbe\x01\xaf\x80\xa7\xc7\xb5"
+			  "\xea\x3c\xa5\x4c\xc0\x2d\x0c\x11\x6f\xee\x3f\x95\xbb\x87\x39\x93"
+			  "\x85\x87\x5d\x7e\x86\x74\x7e\x67\x6e\x72\x89\x38\xac\xbf\xf7\x09"
+			  "\x8e\x05\xbe\x4d\xcf\xb2\x40\x52\xb8\x3a\xef\xfb\x14\x78\x3f\x02"
+			  "\x9a\xdb\xde\x7f\x53\xfa\xe9\x20\x84\x22\x40\x90\xe0\x07\xce\xe9"
+			  "\x4d\x4b\xf2\xba\xce\x9f\xfd\x4b\x57\xd2\xaf\x7c\x72\x4d\x0c\xaa"
+			  "\x19\xbf\x05\x01\xf6\xf1\x7b\x4a\xa1\x0f\x42\x5e\x3e\xa7\x60\x80"
+			  "\xb4\xb9\xd6\xb3\xce\xfe\xa1\x15\xb2\xce\xb8\x78\x9b\xb8\xa3\xb0"
+			  "\xea\x87\xfe\xbe\x63\xb6\xc8\xf8\x46\xec\x6d\xb0\xc2\x6c\x5d\x7c",
+};
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c
index cd0a12a..0505e2c 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors_plugin.c
@@ -19,12 +19,13 @@
 #include <crypto/crypto_tester.h>
 
 /* define symbols of all test vectors */
-#define TEST_VECTOR_CRYPTER(x) crypter_test_vector_t x;
-#define TEST_VECTOR_AEAD(x) aead_test_vector_t x;
-#define TEST_VECTOR_SIGNER(x) signer_test_vector_t x;
-#define TEST_VECTOR_HASHER(x) hasher_test_vector_t x;
-#define TEST_VECTOR_PRF(x) prf_test_vector_t x;
-#define TEST_VECTOR_RNG(x) rng_test_vector_t x;
+#define TEST_VECTOR_CRYPTER(x) extern crypter_test_vector_t x;
+#define TEST_VECTOR_AEAD(x) extern aead_test_vector_t x;
+#define TEST_VECTOR_SIGNER(x) extern signer_test_vector_t x;
+#define TEST_VECTOR_HASHER(x) extern hasher_test_vector_t x;
+#define TEST_VECTOR_PRF(x) extern prf_test_vector_t x;
+#define TEST_VECTOR_RNG(x) extern rng_test_vector_t x;
+#define TEST_VECTOR_DH(x) extern dh_test_vector_t x;
 
 #include "test_vectors.h"
 
@@ -34,6 +35,7 @@
 #undef TEST_VECTOR_HASHER
 #undef TEST_VECTOR_PRF
 #undef TEST_VECTOR_RNG
+#undef TEST_VECTOR_DH
 
 #define TEST_VECTOR_CRYPTER(x)
 #define TEST_VECTOR_AEAD(x)
@@ -41,6 +43,7 @@
 #define TEST_VECTOR_HASHER(x)
 #define TEST_VECTOR_PRF(x)
 #define TEST_VECTOR_RNG(x)
+#define TEST_VECTOR_DH(x)
 
 /* create test vector arrays */
 #undef TEST_VECTOR_CRYPTER
@@ -91,6 +94,14 @@ static rng_test_vector_t *rng[] = {
 #undef TEST_VECTOR_RNG
 #define TEST_VECTOR_RNG(x)
 
+#undef TEST_VECTOR_DH
+#define TEST_VECTOR_DH(x) &x,
+static dh_test_vector_t *dh[] = {
+#include "test_vectors.h"
+};
+#undef TEST_VECTOR_DH
+#define TEST_VECTOR_DH(x)
+
 typedef struct private_test_vectors_plugin_t private_test_vectors_plugin_t;
 
 /**
@@ -175,7 +186,11 @@ plugin_t *test_vectors_plugin_create()
 		lib->crypto->add_test_vector(lib->crypto,
 									 RANDOM_NUMBER_GENERATOR, rng[i]);
 	}
+	for (i = 0; i < countof(dh); i++)
+	{
+		lib->crypto->add_test_vector(lib->crypto,
+									 DIFFIE_HELLMAN_GROUP, dh[i]);
+	}
 
 	return &this->public.plugin;
 }
-
diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c
index b5d2365..312a187 100644
--- a/src/libstrongswan/tests/suites/test_chunk.c
+++ b/src/libstrongswan/tests/suites/test_chunk.c
@@ -61,6 +61,32 @@ START_TEST(test_chunk_equals)
 END_TEST
 
 /*******************************************************************************
+ * equals_const
+ */
+
+START_TEST(test_chunk_equals_const)
+{
+	chunk_t chunk = chunk_from_str("chunk");
+	chunk_t chunk_a, chunk_b;
+
+	chunk_a = chunk_empty;
+	chunk_b = chunk_empty;
+	ck_assert(!chunk_equals_const(chunk_a, chunk_b));
+
+	chunk_a = chunk;
+	ck_assert(!chunk_equals_const(chunk_a, chunk_b));
+	chunk_b = chunk;
+	ck_assert(chunk_equals_const(chunk_a, chunk_b));
+
+	chunk_b = chunk_from_str("asdf");
+	ck_assert(!chunk_equals_const(chunk_a, chunk_b));
+
+	chunk_b = chunk_from_str("chunk");
+	ck_assert(chunk_equals_const(chunk_a, chunk_b));
+}
+END_TEST
+
+/*******************************************************************************
  * chunk_compare test
  */
 
@@ -1013,6 +1039,7 @@ Suite *chunk_suite_create()
 
 	tc = tcase_create("equals");
 	tcase_add_test(tc, test_chunk_equals);
+	tcase_add_test(tc, test_chunk_equals_const);
 	suite_add_tcase(s, tc);
 
 	tc = tcase_create("chunk_compare");
diff --git a/src/libstrongswan/tests/suites/test_enum.c b/src/libstrongswan/tests/suites/test_enum.c
index 53ebd29..70bfdb2 100644
--- a/src/libstrongswan/tests/suites/test_enum.c
+++ b/src/libstrongswan/tests/suites/test_enum.c
@@ -291,6 +291,15 @@ START_TEST(test_enum_printf_hook_split)
 }
 END_TEST
 
+START_TEST(test_enum_printf_hook_null)
+{
+	char buf[16];
+
+	snprintf(buf, sizeof(buf), "%N", NULL, 7);
+	ck_assert_str_eq("(7)", buf);
+}
+END_TEST
+
 START_TEST(test_enum_printf_hook_flags)
 {
 	char buf[1024];
@@ -406,6 +415,7 @@ Suite *enum_suite_create()
 	tc = tcase_create("enum_printf_hook");
 	tcase_add_loop_test(tc, test_enum_printf_hook_cont, 0, countof(printf_tests_cont));
 	tcase_add_loop_test(tc, test_enum_printf_hook_split, 0, countof(printf_tests_split));
+	tcase_add_test(tc, test_enum_printf_hook_null);
 	tcase_add_loop_test(tc, test_enum_printf_hook_flags, 0, countof(printf_tests_flags));
 	tcase_add_loop_test(tc, test_enum_printf_hook_flags_incomplete, 0, countof(printf_tests_flags_incomplete));
 	tcase_add_loop_test(tc, test_enum_printf_hook_flags_null, 0, countof(printf_tests_flags_null));
diff --git a/src/libstrongswan/tests/suites/test_threading.c b/src/libstrongswan/tests/suites/test_threading.c
index 55a4cd7..9a9fdd8 100644
--- a/src/libstrongswan/tests/suites/test_threading.c
+++ b/src/libstrongswan/tests/suites/test_threading.c
@@ -1517,6 +1517,36 @@ START_TEST(test_cleanup_pop)
 }
 END_TEST
 
+static void *cleanup_popall_run(void *data)
+{
+	thread_cleanup_push(cleanup3, data);
+	thread_cleanup_push(cleanup2, data);
+	thread_cleanup_push(cleanup1, data);
+
+	thread_cleanup_popall();
+	return NULL;
+}
+
+START_TEST(test_cleanup_popall)
+{
+	thread_t *threads[THREADS];
+	uintptr_t values[THREADS];
+	int i;
+
+	for (i = 0; i < THREADS; i++)
+	{
+		values[i] = 1;
+		threads[i] = thread_create(cleanup_popall_run, &values[i]);
+	}
+	for (i = 0; i < THREADS; i++)
+	{
+		threads[i]->join(threads[i]);
+		ck_assert_int_eq(values[i], 4);
+	}
+}
+END_TEST
+
+
 static thread_value_t *tls[10];
 
 static void *tls_run(void *data)
@@ -1697,6 +1727,7 @@ Suite *threading_suite_create()
 	tcase_add_test(tc, test_cleanup_exit);
 	tcase_add_test(tc, test_cleanup_cancel);
 	tcase_add_test(tc, test_cleanup_pop);
+	tcase_add_test(tc, test_cleanup_popall);
 	suite_add_tcase(s, tc);
 
 	tc = tcase_create("thread local storage");
diff --git a/src/libstrongswan/tests/suites/test_utils.c b/src/libstrongswan/tests/suites/test_utils.c
index 85a8544..b38f2cb 100644
--- a/src/libstrongswan/tests/suites/test_utils.c
+++ b/src/libstrongswan/tests/suites/test_utils.c
@@ -229,6 +229,41 @@ START_TEST(test_strpfx)
 END_TEST
 
 /*******************************************************************************
+ * mallac_align/free_align
+ */
+
+START_TEST(test_malloc_align)
+{
+	void *ptr[128][256];
+	int size, align;
+
+	for (size = 0; size < countof(ptr); size++)
+	{
+		for (align = 0; align < countof(ptr[0]); align++)
+		{
+			ptr[size][align] = malloc_align(size, align);
+			if (align)
+			{
+				ck_assert((uintptr_t)ptr[size][align] % align == 0);
+			}
+			if (size)
+			{
+				ck_assert(ptr[size][align]);
+				memset(ptr[size][align], 0xEF, size);
+			}
+		}
+	}
+	for (size = 0; size < countof(ptr); size++)
+	{
+		for (align = 0; align < countof(ptr[0]); align++)
+		{
+			free_align(ptr[size][align]);
+		}
+	}
+}
+END_TEST
+
+/*******************************************************************************
  * memxor
  */
 
@@ -307,6 +342,48 @@ START_TEST(test_memxor_aligned)
 END_TEST
 
 /*******************************************************************************
+ * memeq/const
+ */
+
+static struct {
+	char *a;
+	char *b;
+	size_t n;
+	bool res;
+} memeq_data[] = {
+	{NULL, NULL, 0, TRUE},
+	{"a", "b", 0, TRUE},
+	{"", "", 1, TRUE},
+	{"abcdefgh", "abcdefgh", 8, TRUE},
+	{"a", "b", 1, FALSE},
+	{"A", "a", 1, FALSE},
+	{"\0a", "\0b", 2, FALSE},
+	{"abc", "abd", 3, FALSE},
+	{"abc", "dbd", 3, FALSE},
+	{"abcdefgh", "abcdffgh", 8, FALSE},
+	{"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+	 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 52, TRUE},
+	{"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+	 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyy", 52, FALSE},
+	{"bbcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz",
+	 "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 52, FALSE},
+};
+
+START_TEST(test_memeq)
+{
+	ck_assert(memeq(memeq_data[_i].a, memeq_data[_i].b,
+					memeq_data[_i].n) == memeq_data[_i].res);
+}
+END_TEST
+
+START_TEST(test_memeq_const)
+{
+	ck_assert(memeq_const(memeq_data[_i].a, memeq_data[_i].b,
+						  memeq_data[_i].n) == memeq_data[_i].res);
+}
+END_TEST
+
+/*******************************************************************************
  * memstr
  */
 
@@ -774,11 +851,20 @@ Suite *utils_suite_create()
 	tcase_add_loop_test(tc, test_strpfx, 0, countof(strpfx_data));
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("malloc_align");
+	tcase_add_test(tc, test_malloc_align);
+	suite_add_tcase(s, tc);
+
 	tc = tcase_create("memxor");
 	tcase_add_test(tc, test_memxor);
 	tcase_add_test(tc, test_memxor_aligned);
 	suite_add_tcase(s, tc);
 
+	tc = tcase_create("memeq");
+	tcase_add_loop_test(tc, test_memeq, 0, countof(memeq_data));
+	tcase_add_loop_test(tc, test_memeq_const, 0, countof(memeq_data));
+	suite_add_tcase(s, tc);
+
 	tc = tcase_create("memstr");
 	tcase_add_loop_test(tc, test_memstr, 0, countof(memstr_data));
 	suite_add_tcase(s, tc);
diff --git a/src/libstrongswan/tests/suites/test_vectors.c b/src/libstrongswan/tests/suites/test_vectors.c
index a1205d0..a353428 100644
--- a/src/libstrongswan/tests/suites/test_vectors.c
+++ b/src/libstrongswan/tests/suites/test_vectors.c
@@ -19,15 +19,34 @@
 #include "test_suite.h"
 
 #include <utils/test.h>
+#include <threading/thread.h>
+#include <crypto/transform.h>
 
-IMPORT_FUNCTION_FOR_TESTS(crypto, verify_registered_algorithms, u_int,
-						  crypto_factory_t *factory);
+static transform_type_t tfs[] = {
+	ENCRYPTION_ALGORITHM,
+	AEAD_ALGORITHM,
+	INTEGRITY_ALGORITHM,
+	HASH_ALGORITHM,
+	PSEUDO_RANDOM_FUNCTION,
+	RANDOM_NUMBER_GENERATOR,
+	DIFFIE_HELLMAN_GROUP,
+};
 
 START_TEST(test_vectors)
 {
-	u_int failed = TEST_FUNCTION(crypto, verify_registered_algorithms,
-								 lib->crypto);
-	fail_if(failed > 0, "%u test vectors failed", failed);
+	enumerator_t *enumerator;
+	char *plugin;
+	bool success;
+	u_int alg;
+
+	enumerator = lib->crypto->create_verify_enumerator(lib->crypto, tfs[_i]);
+	thread_cleanup_push((void*)enumerator->destroy, enumerator);
+	while (enumerator->enumerate(enumerator, &alg, &plugin, &success))
+	{
+		ck_assert_msg(success, "test vector for %N from '%s' plugin failed",
+					  transform_get_enum_names(tfs[_i]), alg, plugin);
+	}
+	thread_cleanup_pop(TRUE);
 }
 END_TEST
 
@@ -39,8 +58,9 @@ Suite *vectors_suite_create()
 
 	s = suite_create("vectors");
 
-	tc = tcase_create("failures");
-	tcase_add_test(tc, test_vectors);
+	tc = tcase_create("transforms");
+	tcase_add_loop_test(tc, test_vectors, 0, countof(tfs));
+	tcase_set_timeout(tc, 20);
 	suite_add_tcase(s, tc);
 
 	return s;
diff --git a/src/libstrongswan/tests/test_runner.c b/src/libstrongswan/tests/test_runner.c
index b773028..0bae9c8 100644
--- a/src/libstrongswan/tests/test_runner.c
+++ b/src/libstrongswan/tests/test_runner.c
@@ -185,6 +185,7 @@ static bool run_test(test_function_t *tfun, int i)
 		tfun->cb(i);
 		return TRUE;
 	}
+	thread_cleanup_popall();
 	return FALSE;
 }
 
@@ -219,6 +220,7 @@ static bool call_fixture(test_case_t *tcase, bool up)
 		}
 		else
 		{
+			thread_cleanup_popall();
 			failure = TRUE;
 			break;
 		}
@@ -233,9 +235,6 @@ static bool call_fixture(test_case_t *tcase, bool up)
  */
 static bool pre_test(test_runner_init_t init, char *cfg)
 {
-	level_t level = LEVEL_SILENT;
-	char *verbosity;
-
 	library_init(cfg, "test-runner");
 
 	/* use non-blocking RNG to generate keys fast */
@@ -258,12 +257,6 @@ static bool pre_test(test_runner_init_t init, char *cfg)
 		library_deinit();
 		return FALSE;
 	}
-	verbosity = getenv("TESTS_VERBOSITY");
-	if (verbosity)
-	{
-		level = atoi(verbosity);
-	}
-	dbg_default_set_level(level);
 	return TRUE;
 }
 
@@ -336,6 +329,7 @@ static bool post_test(test_runner_init_t init, bool check_leaks,
 		}
 		else
 		{
+			thread_cleanup_popall();
 			library_deinit();
 			return FALSE;
 		}
@@ -529,7 +523,8 @@ int test_runner_run(const char *name, test_configuration_t configs[],
 	test_suite_t *suite;
 	enumerator_t *enumerator;
 	int passed = 0, result;
-	char *cfg;
+	level_t level = LEVEL_SILENT;
+	char *cfg, *verbosity;
 
 	/* redirect all output to stderr (to redirect make's stdout to /dev/null) */
 	dup2(2, 1);
@@ -542,6 +537,13 @@ int test_runner_run(const char *name, test_configuration_t configs[],
 		return EXIT_FAILURE;
 	}
 
+	verbosity = getenv("TESTS_VERBOSITY");
+	if (verbosity)
+	{
+		level = atoi(verbosity);
+	}
+	dbg_default_set_level(level);
+
 	fprintf(stderr, "Running %u '%s' test suites:\n", array_count(suites), name);
 
 	enumerator = array_create_enumerator(suites);
diff --git a/src/libstrongswan/tests/test_runner.h b/src/libstrongswan/tests/test_runner.h
index 7250f8a..5c30570 100644
--- a/src/libstrongswan/tests/test_runner.h
+++ b/src/libstrongswan/tests/test_runner.h
@@ -69,10 +69,14 @@ struct test_configuration_t {
  *
  * - TESTS_VERBOSITY: Numerical loglevel for debug log
  * - TESTS_STRONGSWAN_CONF: Specify a path to a custom strongswan.conf
+ * - TESTS_PLUGINS: Specify an explicit list of plugins to load
  * - TESTS_SUITES: Run specific test suites only
  * - TESTS_SUITES_EXCLUDE: Don't run specific test suites
  * - TESTS_REDUCED_KEYLENGTHS: Test minimal keylengths for public key tests only
  *
+ * Please note that TESTS_PLUGINS actually must be implemented by the init
+ * callback function, as plugin loading is delegated.
+ *
  * @param name			name of test runner
  * @param config		test suite constructors with dependencies
  * @param init_cb		init/deinit callback
diff --git a/src/libstrongswan/tests/test_suite.h b/src/libstrongswan/tests/test_suite.h
index da57ab4..aedd8c0 100644
--- a/src/libstrongswan/tests/test_suite.h
+++ b/src/libstrongswan/tests/test_suite.h
@@ -313,7 +313,7 @@ void test_fail_if_worker_failed();
 	test_fail_if_worker_failed(); \
 	if (!(x)) \
 	{ \
-		test_fail_msg(__FILE__, __LINE__, #x); \
+		test_fail_msg(__FILE__, __LINE__, "%s", #x); \
 	} \
 })
 
@@ -329,7 +329,7 @@ void test_fail_if_worker_failed();
 	test_fail_if_worker_failed(); \
 	if (!(x)) \
 	{ \
-		test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
+		test_fail_msg(__FILE__, __LINE__, "%s: " fmt, #x, ##__VA_ARGS__); \
 	} \
 })
 
@@ -349,7 +349,7 @@ void test_fail_if_worker_failed();
 	test_fail_if_worker_failed(); \
 	if (x) \
 	{ \
-		test_fail_msg(__FILE__, __LINE__, #x ": " fmt, ##__VA_ARGS__); \
+		test_fail_msg(__FILE__, __LINE__, "%s : " fmt, #x, ##__VA_ARGS__); \
 	} \
 })
 #define fail_unless test_assert_msg
diff --git a/src/libstrongswan/tests/tests.c b/src/libstrongswan/tests/tests.c
index d95ddd9..aed600f 100644
--- a/src/libstrongswan/tests/tests.c
+++ b/src/libstrongswan/tests/tests.c
@@ -37,7 +37,8 @@ static bool test_runner_init(bool init)
 	{
 		char *plugins, *plugindir;
 
-		plugins = lib->settings->get_str(lib->settings,
+		plugins = getenv("TESTS_PLUGINS") ?:
+					lib->settings->get_str(lib->settings,
 										"tests.load", PLUGINS);
 		plugindir = lib->settings->get_str(lib->settings,
 										"tests.plugindir", PLUGINDIR);
diff --git a/src/libstrongswan/threading/thread.c b/src/libstrongswan/threading/thread.c
index 593f44a..7a243e8 100644
--- a/src/libstrongswan/threading/thread.c
+++ b/src/libstrongswan/threading/thread.c
@@ -16,7 +16,6 @@
 #define _GNU_SOURCE
 #include <pthread.h>
 #include <signal.h>
-#include <semaphore.h>
 
 #ifdef HAVE_GETTID
 #include <sys/types.h>
@@ -79,11 +78,6 @@ struct private_thread_t {
 	mutex_t *mutex;
 
 	/**
-	 * Semaphore used to sync the creation/start of the thread.
-	 */
-	sem_t created;
-
-	/**
 	 * TRUE if this thread has been detached or joined, i.e. can be cleaned
 	 * up after terminating.
 	 */
@@ -160,7 +154,6 @@ static void thread_destroy(private_thread_t *this)
 	this->cleanup_handlers->destroy(this->cleanup_handlers);
 	this->mutex->unlock(this->mutex);
 	this->mutex->destroy(this->mutex);
-	sem_destroy(&this->created);
 	free(this);
 }
 
@@ -263,7 +256,6 @@ static private_thread_t *thread_create_internal()
 		.cleanup_handlers = linked_list_create(),
 		.mutex = mutex_create(MUTEX_TYPE_DEFAULT),
 	);
-	sem_init(&this->created, FALSE, 0);
 
 	return this;
 }
@@ -292,7 +284,6 @@ static void *thread_main(private_thread_t *this)
 {
 	void *res;
 
-	sem_wait(&this->created);
 	current_thread->set(current_thread, this);
 	pthread_cleanup_push((thread_cleanup_t)thread_cleanup, this);
 
@@ -324,6 +315,10 @@ thread_t *thread_create(thread_main_t main, void *arg)
 
 	this->main = main;
 	this->arg = arg;
+	id_mutex->lock(id_mutex);
+	this->id = next_id++;
+	id_mutex->unlock(id_mutex);
+
 	if (pthread_create(&this->thread_id, NULL, (void*)thread_main, this) != 0)
 	{
 		DBG1(DBG_LIB, "failed to create thread!");
@@ -331,10 +326,6 @@ thread_t *thread_create(thread_main_t main, void *arg)
 		thread_destroy(this);
 		return NULL;
 	}
-	id_mutex->lock(id_mutex);
-	this->id = next_id++;
-	id_mutex->unlock(id_mutex);
-	sem_post(&this->created);
 
 	return &this->public;
 }
@@ -383,9 +374,7 @@ void thread_cleanup_push(thread_cleanup_t cleanup, void *arg)
 		.arg = arg,
 	);
 
-	this->mutex->lock(this->mutex);
 	this->cleanup_handlers->insert_last(this->cleanup_handlers, handler);
-	this->mutex->unlock(this->mutex);
 }
 
 /**
@@ -396,15 +385,12 @@ void thread_cleanup_pop(bool execute)
 	private_thread_t *this = (private_thread_t*)thread_current();
 	cleanup_handler_t *handler;
 
-	this->mutex->lock(this->mutex);
 	if (this->cleanup_handlers->remove_last(this->cleanup_handlers,
 											(void**)&handler) != SUCCESS)
 	{
-		this->mutex->unlock(this->mutex);
 		DBG1(DBG_LIB, "!!! THREAD CLEANUP ERROR !!!");
 		return;
 	}
-	this->mutex->unlock(this->mutex);
 
 	if (execute)
 	{
@@ -416,6 +402,23 @@ void thread_cleanup_pop(bool execute)
 /**
  * Described in header.
  */
+void thread_cleanup_popall()
+{
+	private_thread_t *this = (private_thread_t*)thread_current();
+	cleanup_handler_t *handler;
+
+	while (this->cleanup_handlers->get_count(this->cleanup_handlers))
+	{
+		this->cleanup_handlers->remove_last(this->cleanup_handlers,
+											(void**)&handler);
+		handler->cleanup(handler->arg);
+		free(handler);
+	}
+}
+
+/**
+ * Described in header.
+ */
 bool thread_cancelability(bool enable)
 {
 #ifdef HAVE_PTHREAD_CANCEL
diff --git a/src/libstrongswan/threading/thread.h b/src/libstrongswan/threading/thread.h
index 3827554..c247728 100644
--- a/src/libstrongswan/threading/thread.h
+++ b/src/libstrongswan/threading/thread.h
@@ -124,6 +124,16 @@ void thread_cleanup_push(thread_cleanup_t cleanup, void *arg);
 void thread_cleanup_pop(bool execute);
 
 /**
+ * Pop and execute all cleanup handlers in reverse order of registration.
+ *
+ * This function is for very special purposes only, where the caller exactly
+ * knows which cleanup handlers have been pushed. For regular use, a caller
+ * should thread_cleanup_pop() exactly the number of handlers it pushed
+ * using thread_cleanup_push().
+ */
+void thread_cleanup_popall();
+
+/**
  * Enable or disable the cancelability of the current thread. The current
  * value is returned.
  *
diff --git a/src/libstrongswan/threading/windows/thread.c b/src/libstrongswan/threading/windows/thread.c
index e76758f..6105247 100644
--- a/src/libstrongswan/threading/windows/thread.c
+++ b/src/libstrongswan/threading/windows/thread.c
@@ -562,6 +562,26 @@ void thread_cleanup_pop(bool execute)
 /**
  * Described in header.
  */
+void thread_cleanup_popall()
+{
+	private_thread_t *this;
+	cleanup_t cleanup = {};
+	bool old;
+
+	this = get_current_thread();
+	while (array_count(this->cleanup))
+	{
+		old = set_leak_detective(FALSE);
+		array_remove(this->cleanup, -1, &cleanup);
+		set_leak_detective(old);
+
+		cleanup.cb(cleanup.arg);
+	}
+}
+
+/**
+ * Described in header.
+ */
 bool thread_cancelability(bool enable)
 {
 	private_thread_t *this;
diff --git a/src/libstrongswan/utils/chunk.h b/src/libstrongswan/utils/chunk.h
index 48405b7..2ec7f75 100644
--- a/src/libstrongswan/utils/chunk.h
+++ b/src/libstrongswan/utils/chunk.h
@@ -310,6 +310,19 @@ static inline bool chunk_equals(chunk_t a, chunk_t b)
 }
 
 /**
+ * Compare two chunks for equality, constant time for cryptographic purposes.
+ *
+ * Note that this function is constant time only for chunks with the same
+ * length, i.e. it does not protect against guessing the length of one of the
+ * chunks.
+ */
+static inline bool chunk_equals_const(chunk_t a, chunk_t b)
+{
+	return a.ptr != NULL  && b.ptr != NULL &&
+			a.len == b.len && memeq_const(a.ptr, b.ptr, a.len);
+}
+
+/**
  * Compare two chunks (given as pointers) for equality (useful as callback),
  * NULL chunks are never equal.
  */
diff --git a/src/libstrongswan/utils/cpu_feature.c b/src/libstrongswan/utils/cpu_feature.c
new file mode 100644
index 0000000..d86ca6b
--- /dev/null
+++ b/src/libstrongswan/utils/cpu_feature.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "cpu_feature.h"
+
+#if defined __i386__ || defined(__x86_64__)
+
+typedef enum {
+	/* Generic CPUID(1) flags */
+	CPUID1_EDX_MMX =				(1 << 23),
+	CPUID1_EDX_SSE =				(1 << 25),
+	CPUID1_EDX_SSE2 =				(1 << 26),
+	CPUID1_ECX_SSE3 =				(1 <<  0),
+	CPUID1_ECX_PCLMULQDQ =			(1 <<  1),
+	CPUID1_ECX_SSSE3 =				(1 <<  9),
+	CPUID1_ECX_SSE41 =				(1 << 19),
+	CPUID1_ECX_SSE42 =				(1 << 20),
+	CPUID1_ECX_AESNI =				(1 << 25),
+	CPUID1_ECX_AVX =				(1 << 28),
+	CPUID1_ECX_RDRAND =				(1 << 30),
+
+	/* For CentaurHauls cpuid(0xC0000001) */
+	CPUIDC1_EDX_RNG_AVAILABLE =		(1 <<  2),
+	CPUIDC1_EDX_RNG_ENABLED =		(1 <<  3),
+	CPUIDC1_EDX_ACE_AVAILABLE =		(1 <<  6),
+	CPUIDC1_EDX_ACE_ENABLED =		(1 <<  7),
+	CPUIDC1_EDX_ACE2_AVAILABLE =	(1 <<  8),
+	CPUIDC1_EDX_ACE2_ENABLED =		(1 <<  9),
+	CPUIDC1_EDX_PHE_AVAILABLE =		(1 << 10),
+	CPUIDC1_EDX_PHE_ENABLED =		(1 << 11),
+	CPUIDC1_EDX_PMM_AVAILABLE =		(1 << 12),
+	CPUIDC1_EDX_PMM_ENABLED =		(1 << 13),
+} cpuid_flag_t;
+
+/**
+ * Get cpuid for info, return eax, ebx, ecx and edx.
+ * -fPIC requires to save ebx on IA-32.
+ */
+static void cpuid(u_int op, u_int *a, u_int *b, u_int *c, u_int *d)
+{
+#ifdef __x86_64__
+	asm("cpuid" : "=a" (*a), "=b" (*b), "=c" (*c), "=d" (*d) : "a" (op));
+#else /* __i386__ */
+	asm("pushl %%ebx;"
+		"cpuid;"
+		"movl %%ebx, %1;"
+		"popl %%ebx;"
+		: "=a" (*a), "=r" (*b), "=c" (*c), "=d" (*d) : "a" (op));
+#endif /* __x86_64__ / __i386__*/
+}
+
+/**
+ * Return feature if flag in reg, flag-to-feature
+ */
+static inline cpu_feature_t f2f(u_int reg, cpuid_flag_t flag, cpu_feature_t f)
+{
+	if (reg & flag)
+	{
+		return f;
+	}
+	return 0;
+}
+
+/**
+ * Get features for a Via "CentaurHauls" CPU
+ */
+static cpu_feature_t get_via_features()
+{
+	cpu_feature_t f = 0;
+	u_int a, b, c, d;
+
+	cpuid(0xc0000001, &a, &b, &c, &d);
+
+	f |= f2f(d, CPUIDC1_EDX_RNG_AVAILABLE, CPU_FEATURE_PADLOCK_RNG_AVAILABLE);
+	f |= f2f(d, CPUIDC1_EDX_RNG_ENABLED, CPU_FEATURE_PADLOCK_RNG_ENABLED);
+	f |= f2f(d, CPUIDC1_EDX_ACE_AVAILABLE, CPU_FEATURE_PADLOCK_ACE_AVAILABLE);
+	f |= f2f(d, CPUIDC1_EDX_ACE_ENABLED, CPU_FEATURE_PADLOCK_ACE_ENABLED);
+	f |= f2f(d, CPUIDC1_EDX_ACE2_AVAILABLE, CPU_FEATURE_PADLOCK_ACE2_AVAILABLE);
+	f |= f2f(d, CPUIDC1_EDX_ACE2_ENABLED, CPU_FEATURE_PADLOCK_ACE2_ENABLED);
+	f |= f2f(d, CPUIDC1_EDX_PHE_AVAILABLE, CPU_FEATURE_PADLOCK_PHE_AVAILABLE);
+	f |= f2f(d, CPUIDC1_EDX_PHE_ENABLED, CPU_FEATURE_PADLOCK_PHE_ENABLED);
+	f |= f2f(d, CPUIDC1_EDX_PMM_AVAILABLE, CPU_FEATURE_PADLOCK_PMM_AVAILABLE);
+	f |= f2f(d, CPUIDC1_EDX_PMM_ENABLED, CPU_FEATURE_PADLOCK_PMM_ENABLED);
+
+	return f;
+}
+
+/**
+ * See header.
+ */
+cpu_feature_t cpu_feature_get_all()
+{
+	char vendor[3 * sizeof(u_int32_t) + 1];
+	cpu_feature_t f = 0;
+	u_int a, b, c, d;
+
+	cpuid(0, &a, &b, &c, &d);
+	/* VendorID string is in b-d-c (yes, in this order) */
+	snprintf(vendor, sizeof(vendor), "%.4s%.4s%.4s", &b, &d, &c);
+
+	cpuid(1, &a, &b, &c, &d);
+
+	/* check common x86 features for CPUID(1) */
+	f |= f2f(d, CPUID1_EDX_MMX, CPU_FEATURE_MMX);
+	f |= f2f(d, CPUID1_EDX_SSE, CPU_FEATURE_SSE);
+	f |= f2f(d, CPUID1_EDX_SSE2, CPU_FEATURE_SSE2);
+	f |= f2f(c, CPUID1_ECX_SSE3, CPU_FEATURE_SSE3);
+	f |= f2f(c, CPUID1_ECX_PCLMULQDQ, CPU_FEATURE_PCLMULQDQ);
+	f |= f2f(c, CPUID1_ECX_SSSE3, CPU_FEATURE_SSSE3);
+	f |= f2f(c, CPUID1_ECX_SSE41, CPU_FEATURE_SSE41);
+	f |= f2f(c, CPUID1_ECX_SSE42, CPU_FEATURE_SSE42);
+	f |= f2f(c, CPUID1_ECX_AESNI, CPU_FEATURE_AESNI);
+	f |= f2f(c, CPUID1_ECX_AVX, CPU_FEATURE_AVX);
+	f |= f2f(c, CPUID1_ECX_RDRAND, CPU_FEATURE_RDRAND);
+
+	if (streq(vendor, "CentaurHauls"))
+	{
+		cpuid(0xc0000000, &a, &b, &c, &d);
+		/* check Centaur Extended Feature Flags */
+		if (a >= 0xc0000001)
+		{
+			f |= get_via_features();
+		}
+	}
+	return f;
+}
+
+#else /* !x86 */
+
+/**
+ * See header.
+ */
+cpu_feature_t cpu_feature_get_all()
+{
+	return 0;
+}
+
+#endif
+
+/**
+ * See header.
+ */
+bool cpu_feature_available(cpu_feature_t feature)
+{
+	return (cpu_feature_get_all() & feature) == feature;
+}
diff --git a/src/libstrongswan/utils/cpu_feature.h b/src/libstrongswan/utils/cpu_feature.h
new file mode 100644
index 0000000..3a807fa
--- /dev/null
+++ b/src/libstrongswan/utils/cpu_feature.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup cpu_feature cpu_feature
+ * @{ @ingroup utils
+ */
+
+#ifndef CPU_FEATURE_H_
+#define CPU_FEATURE_H_
+
+#include <library.h>
+
+typedef enum {
+	/** x86/x64 extensions */
+	CPU_FEATURE_MMX =							(1 <<  0),
+	CPU_FEATURE_SSE =							(1 <<  1),
+	CPU_FEATURE_SSE2 =							(1 <<  2),
+	CPU_FEATURE_SSE3 =							(1 <<  3),
+	CPU_FEATURE_SSSE3 =							(1 <<  4),
+	CPU_FEATURE_SSE41 =							(1 <<  5),
+	CPU_FEATURE_SSE42 =							(1 <<  6),
+	CPU_FEATURE_AVX =							(1 <<  7),
+	CPU_FEATURE_RDRAND =						(1 <<  8),
+	CPU_FEATURE_AESNI =							(1 <<  9),
+	CPU_FEATURE_PCLMULQDQ =						(1 << 10),
+	/** Via Padlock Security features */
+	CPU_FEATURE_PADLOCK_RNG_AVAILABLE =			(1 << 22),
+	CPU_FEATURE_PADLOCK_RNG_ENABLED =			(1 << 23),
+	CPU_FEATURE_PADLOCK_ACE_AVAILABLE =			(1 << 24),
+	CPU_FEATURE_PADLOCK_ACE_ENABLED =			(1 << 25),
+	CPU_FEATURE_PADLOCK_ACE2_AVAILABLE =		(1 << 26),
+	CPU_FEATURE_PADLOCK_ACE2_ENABLED =			(1 << 27),
+	CPU_FEATURE_PADLOCK_PHE_AVAILABLE =			(1 << 28),
+	CPU_FEATURE_PADLOCK_PHE_ENABLED =			(1 << 29),
+	CPU_FEATURE_PADLOCK_PMM_AVAILABLE =			(1 << 30),
+	CPU_FEATURE_PADLOCK_PMM_ENABLED =			(1 << 31),
+} cpu_feature_t;
+
+/**
+ * Get a bitmask for all supported CPU features
+ */
+cpu_feature_t cpu_feature_get_all();
+
+/**
+ * Check if a given set of CPU features is available.
+ */
+bool cpu_feature_available(cpu_feature_t feature);
+
+#endif /** CPU_FEATURE_H_ @}*/
diff --git a/src/libstrongswan/utils/enum.c b/src/libstrongswan/utils/enum.c
index 089bebb..1cead77 100644
--- a/src/libstrongswan/utils/enum.c
+++ b/src/libstrongswan/utils/enum.c
@@ -26,6 +26,10 @@
  */
 char *enum_to_name(enum_name_t *e, int val)
 {
+	if (!e)
+	{
+		return NULL;
+	}
 	do
 	{
 		if (val >= e->first && val <= e->last)
@@ -140,7 +144,7 @@ int enum_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
 	int val = *((int*)(args[1]));
 	char *name, buf[512];
 
-	if (ed->next == ENUM_FLAG_MAGIC)
+	if (ed && ed->next == ENUM_FLAG_MAGIC)
 	{
 		name = enum_flags_to_string(ed, val, buf, sizeof(buf));
 		if (name == NULL)
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index bc8432a..99f4843 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -552,6 +552,7 @@ char *whitelist[] = {
 	/* ClearSilver */
 	"nerr_init",
 	/* libgcrypt */
+	"gcrypt_plugin_create",
 	"gcry_control",
 	"gcry_check_version",
 	"gcry_randomize",
@@ -690,8 +691,8 @@ static int print_traces(private_leak_detective_t *this,
 			{
 				if (!thresh_count || entry->count >= thresh_count)
 				{
-					this->report_cb(this->report_data, entry->count,
-									entry->bytes, entry->backtrace, detailed);
+					cb(user, entry->count, entry->bytes, entry->backtrace,
+					   detailed);
 				}
 			}
 		}
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
index 02a7209..9b516ac 100644
--- a/src/libstrongswan/utils/utils.c
+++ b/src/libstrongswan/utils/utils.c
@@ -14,221 +14,22 @@
  * for more details.
  */
 
-#define _GNU_SOURCE /* for memrchr */
-#ifdef WIN32
-/* for GetTickCount64, Windows 7 */
-# define _WIN32_WINNT 0x0601
-#endif
-
 #include "utils.h"
 
-#include <sys/stat.h>
-#include <string.h>
-#include <stdio.h>
 #include <unistd.h>
-#include <inttypes.h>
-#include <stdint.h>
 #include <limits.h>
-#include <dirent.h>
-#include <time.h>
 #ifndef WIN32
 # include <signal.h>
 #endif
 
 #include <library.h>
-#include <utils/debug.h>
-#include <utils/chunk.h>
 #include <collections/enumerator.h>
-#include <threading/spinlock.h>
-#include <threading/mutex.h>
-#include <threading/condvar.h>
-
-ENUM(status_names, SUCCESS, NEED_MORE,
-	"SUCCESS",
-	"FAILED",
-	"OUT_OF_RES",
-	"ALREADY_DONE",
-	"NOT_SUPPORTED",
-	"INVALID_ARG",
-	"NOT_FOUND",
-	"PARSE_ERROR",
-	"VERIFY_ERROR",
-	"INVALID_STATE",
-	"DESTROY_ME",
-	"NEED_MORE",
-);
-
-/**
- * Described in header.
- */
-void memxor(u_int8_t dst[], u_int8_t src[], size_t n)
-{
-	int m, i;
-
-	/* byte wise XOR until dst aligned */
-	for (i = 0; (uintptr_t)&dst[i] % sizeof(long) && i < n; i++)
-	{
-		dst[i] ^= src[i];
-	}
-	/* try to use words if src shares an aligment with dst */
-	switch (((uintptr_t)&src[i] % sizeof(long)))
-	{
-		case 0:
-			for (m = n - sizeof(long); i <= m; i += sizeof(long))
-			{
-				*(long*)&dst[i] ^= *(long*)&src[i];
-			}
-			break;
-		case sizeof(int):
-			for (m = n - sizeof(int); i <= m; i += sizeof(int))
-			{
-				*(int*)&dst[i] ^= *(int*)&src[i];
-			}
-			break;
-		case sizeof(short):
-			for (m = n - sizeof(short); i <= m; i += sizeof(short))
-			{
-				*(short*)&dst[i] ^= *(short*)&src[i];
-			}
-			break;
-		default:
-			break;
-	}
-	/* byte wise XOR of the rest */
-	for (; i < n; i++)
-	{
-		dst[i] ^= src[i];
-	}
-}
-
-/**
- * Described in header.
- */
-void memwipe_noinline(void *ptr, size_t n)
-{
-	memwipe_inline(ptr, n);
-}
-
-/**
- * Described in header.
- */
-void *memstr(const void *haystack, const char *needle, size_t n)
-{
-	const u_char *pos = haystack;
-	size_t l;
-
-	if (!haystack || !needle || (l = strlen(needle)) == 0)
-	{
-		return NULL;
-	}
-	for (; n >= l; ++pos, --n)
-	{
-		if (memeq(pos, needle, l))
-		{
-			return (void*)pos;
-		}
-	}
-	return NULL;
-}
-
-/**
- * Described in header.
- */
-void *utils_memrchr(const void *s, int c, size_t n)
-{
-	const u_char *pos;
-
-	if (!s || !n)
-	{
-		return NULL;
-	}
-
-	for (pos = s + n - 1; pos >= (u_char*)s; pos--)
-	{
-		if (*pos == (u_char)c)
-		{
-			return (void*)pos;
-		}
-	}
-	return NULL;
-}
-
-/**
- * Described in header.
- */
-char* translate(char *str, const char *from, const char *to)
-{
-	char *pos = str;
-	if (strlen(from) != strlen(to))
-	{
-		return str;
-	}
-	while (pos && *pos)
-	{
-		char *match;
-		if ((match = strchr(from, *pos)) != NULL)
-		{
-			*pos = to[match - from];
-		}
-		pos++;
-	}
-	return str;
-}
-
-/**
- * Described in header.
- */
-char* strreplace(const char *str, const char *search, const char *replace)
-{
-	size_t len, slen, rlen, count = 0;
-	char *res, *pos, *found, *dst;
-
-	if (!str || !*str || !search || !*search || !replace)
-	{
-		return (char*)str;
-	}
-	slen = strlen(search);
-	rlen = strlen(replace);
-	if (slen != rlen)
-	{
-		for (pos = (char*)str; (pos = strstr(pos, search)); pos += slen)
-		{
-			found = pos;
-			count++;
-		}
-		if (!count)
-		{
-			return (char*)str;
-		}
-		len = (found - str) + strlen(found) + count * (rlen - slen);
-	}
-	else
-	{
-		len = strlen(str);
-	}
-	found = strstr(str, search);
-	if (!found)
-	{
-		return (char*)str;
-	}
-	dst = res = malloc(len + 1);
-	pos = (char*)str;
-	do
-	{
-		len = found - pos;
-		memcpy(dst, pos, len);
-		dst += len;
-		memcpy(dst, replace, rlen);
-		dst += rlen;
-		pos = found + slen;
-	}
-	while ((found = strstr(pos, search)));
-	strcpy(dst, pos);
-	return res;
-}
 
 #ifdef WIN32
 
+#include <threading/mutex.h>
+#include <threading/condvar.h>
+
 /**
  * Flag to indicate signaled wait_sigint()
  */
@@ -305,216 +106,6 @@ void wait_sigint()
 
 #endif
 
-/**
- * Described in header.
- */
-char* path_dirname(const char *path)
-{
-	char *pos;
-
-	pos = path ? strrchr(path, DIRECTORY_SEPARATOR[0]) : NULL;
-
-	if (pos && !pos[1])
-	{	/* if path ends with slashes we have to look beyond them */
-		while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
-		{	/* skip trailing slashes */
-			pos--;
-		}
-		pos = memrchr(path, DIRECTORY_SEPARATOR[0], pos - path + 1);
-	}
-	if (!pos)
-	{
-#ifdef WIN32
-		if (path && strlen(path))
-		{
-			if ((isalpha(path[0]) && path[1] == ':'))
-			{	/* if just a drive letter given, return that as dirname */
-				return chunk_clone(chunk_from_chars(path[0], ':', 0)).ptr;
-			}
-		}
-#endif
-		return strdup(".");
-	}
-	while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
-	{	/* skip superfluous slashes */
-		pos--;
-	}
-	return strndup(path, pos - path + 1);
-}
-
-/**
- * Described in header.
- */
-char* path_basename(const char *path)
-{
-	char *pos, *trail = NULL;
-
-	if (!path || !*path)
-	{
-		return strdup(".");
-	}
-	pos = strrchr(path, DIRECTORY_SEPARATOR[0]);
-	if (pos && !pos[1])
-	{	/* if path ends with slashes we have to look beyond them */
-		while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
-		{	/* skip trailing slashes */
-			pos--;
-		}
-		if (pos == path && *pos == DIRECTORY_SEPARATOR[0])
-		{	/* contains only slashes */
-			return strdup(DIRECTORY_SEPARATOR);
-		}
-		trail = pos + 1;
-		pos = memrchr(path, DIRECTORY_SEPARATOR[0], trail - path);
-	}
-	pos = pos ? pos + 1 : (char*)path;
-	return trail ? strndup(pos, trail - pos) : strdup(pos);
-}
-
-/**
- * Described in header.
- */
-bool path_absolute(const char *path)
-{
-	if (!path)
-	{
-		return FALSE;
-	}
-#ifdef WIN32
-	if (strpfx(path, "\\\\"))
-	{	/* UNC */
-		return TRUE;
-	}
-	if (strlen(path) && isalpha(path[0]) && path[1] == ':')
-	{	/* drive letter */
-		return TRUE;
-	}
-#else /* !WIN32 */
-	if (path[0] == DIRECTORY_SEPARATOR[0])
-	{
-		return TRUE;
-	}
-#endif
-	return FALSE;
-}
-
-/**
- * Described in header.
- */
-bool mkdir_p(const char *path, mode_t mode)
-{
-	int len;
-	char *pos, full[PATH_MAX];
-	pos = full;
-	if (!path || *path == '\0')
-	{
-		return TRUE;
-	}
-	len = snprintf(full, sizeof(full)-1, "%s", path);
-	if (len < 0 || len >= sizeof(full)-1)
-	{
-		DBG1(DBG_LIB, "path string %s too long", path);
-		return FALSE;
-	}
-	/* ensure that the path ends with a '/' */
-	if (full[len-1] != '/')
-	{
-		full[len++] = '/';
-		full[len] = '\0';
-	}
-	/* skip '/' at the beginning */
-	while (*pos == '/')
-	{
-		pos++;
-	}
-	while ((pos = strchr(pos, '/')))
-	{
-		*pos = '\0';
-		if (access(full, F_OK) < 0)
-		{
-#ifdef WIN32
-			if (_mkdir(full) < 0)
-#else
-			if (mkdir(full, mode) < 0)
-#endif
-			{
-				DBG1(DBG_LIB, "failed to create directory %s", full);
-				return FALSE;
-			}
-		}
-		*pos = '/';
-		pos++;
-	}
-	return TRUE;
-}
-
-ENUM(tty_color_names, TTY_RESET, TTY_BG_DEF,
-	"\e[0m",
-	"\e[1m",
-	"\e[4m",
-	"\e[5m",
-	"\e[30m",
-	"\e[31m",
-	"\e[32m",
-	"\e[33m",
-	"\e[34m",
-	"\e[35m",
-	"\e[36m",
-	"\e[37m",
-	"\e[39m",
-	"\e[40m",
-	"\e[41m",
-	"\e[42m",
-	"\e[43m",
-	"\e[44m",
-	"\e[45m",
-	"\e[46m",
-	"\e[47m",
-	"\e[49m",
-);
-
-/**
- * Get the escape string for a given TTY color, empty string on non-tty FILE
- */
-char* tty_escape_get(int fd, tty_escape_t escape)
-{
-	if (!isatty(fd))
-	{
-		return "";
-	}
-	switch (escape)
-	{
-		case TTY_RESET:
-		case TTY_BOLD:
-		case TTY_UNDERLINE:
-		case TTY_BLINKING:
-#ifdef WIN32
-			return "";
-#endif
-		case TTY_FG_BLACK:
-		case TTY_FG_RED:
-		case TTY_FG_GREEN:
-		case TTY_FG_YELLOW:
-		case TTY_FG_BLUE:
-		case TTY_FG_MAGENTA:
-		case TTY_FG_CYAN:
-		case TTY_FG_WHITE:
-		case TTY_FG_DEF:
-		case TTY_BG_BLACK:
-		case TTY_BG_RED:
-		case TTY_BG_GREEN:
-		case TTY_BG_YELLOW:
-		case TTY_BG_BLUE:
-		case TTY_BG_MAGENTA:
-		case TTY_BG_CYAN:
-		case TTY_BG_WHITE:
-		case TTY_BG_DEF:
-			return enum_to_name(tty_color_names, escape);
-		/* warn if a escape code is missing */
-	}
-	return "";
-}
-
 #ifndef HAVE_CLOSEFROM
 /**
  * Described in header.
@@ -563,58 +154,6 @@ void closefrom(int lowfd)
 #endif /* HAVE_CLOSEFROM */
 
 /**
- * Return monotonic time
- */
-time_t time_monotonic(timeval_t *tv)
-{
-#ifdef WIN32
-	ULONGLONG ms;
-	time_t s;
-
-	ms = GetTickCount64();
-	s = ms / 1000;
-	if (tv)
-	{
-		tv->tv_sec = s;
-		tv->tv_usec = (ms - (s * 1000)) * 1000;
-	}
-	return s;
-#else /* !WIN32 */
-#if defined(HAVE_CLOCK_GETTIME) && \
-	(defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
-	 defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
-	/* as we use time_monotonic() for condvar operations, we use the
-	 * monotonic time source only if it is also supported by pthread. */
-	timespec_t ts;
-
-	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
-	{
-		if (tv)
-		{
-			tv->tv_sec = ts.tv_sec;
-			tv->tv_usec = ts.tv_nsec / 1000;
-		}
-		return ts.tv_sec;
-	}
-#endif /* HAVE_CLOCK_GETTIME && (...) */
-	/* Fallback to non-monotonic timestamps:
-	 * On MAC OS X, creating monotonic timestamps is rather difficult. We
-	 * could use mach_absolute_time() and catch sleep/wakeup notifications.
-	 * We stick to the simpler (non-monotonic) gettimeofday() for now.
-	 * But keep in mind: we need the same time source here as in condvar! */
-	if (!tv)
-	{
-		return time(NULL);
-	}
-	if (gettimeofday(tv, NULL) != 0)
-	{	/* should actually never fail if passed pointers are valid */
-		return -1;
-	}
-	return tv->tv_sec;
-#endif /* !WIN32 */
-}
-
-/**
  * return null
  */
 void *return_null()
@@ -639,144 +178,12 @@ bool return_false()
 }
 
 /**
- * returns FAILED
- */
-status_t return_failed()
-{
-	return FAILED;
-}
-
-/**
- * returns SUCCESS
- */
-status_t return_success()
-{
-	return SUCCESS;
-}
-
-/**
  * nop operation
  */
 void nop()
 {
 }
 
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
-
-/**
- * Spinlock for ref_get/put
- */
-static spinlock_t *ref_lock;
-
-/**
- * Increase refcount
- */
-refcount_t ref_get(refcount_t *ref)
-{
-	refcount_t current;
-
-	ref_lock->lock(ref_lock);
-	current = ++(*ref);
-	ref_lock->unlock(ref_lock);
-
-	return current;
-}
-
-/**
- * Decrease refcount
- */
-bool ref_put(refcount_t *ref)
-{
-	bool more_refs;
-
-	ref_lock->lock(ref_lock);
-	more_refs = --(*ref) > 0;
-	ref_lock->unlock(ref_lock);
-	return !more_refs;
-}
-
-/**
- * Current refcount
- */
-refcount_t ref_cur(refcount_t *ref)
-{
-	refcount_t current;
-
-	ref_lock->lock(ref_lock);
-	current = *ref;
-	ref_lock->unlock(ref_lock);
-
-	return current;
-}
-
-/**
- * Spinlock for all compare and swap operations.
- */
-static spinlock_t *cas_lock;
-
-/**
- * Compare and swap if equal to old value
- */
-#define _cas_impl(name, type) \
-bool cas_##name(type *ptr, type oldval, type newval) \
-{ \
-	bool swapped; \
-	cas_lock->lock(cas_lock); \
-	if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
-	cas_lock->unlock(cas_lock); \
-	return swapped; \
-}
-
-_cas_impl(bool, bool)
-_cas_impl(ptr, void*)
-
-#endif /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
-
-
-#ifdef HAVE_FMEMOPEN_FALLBACK
-
-static int fmemread(chunk_t *cookie, char *buf, int size)
-{
-	int len;
-
-	len = min(size, cookie->len);
-	memcpy(buf, cookie->ptr, len);
-	*cookie = chunk_skip(*cookie, len);
-
-	return len;
-}
-
-static int fmemwrite(chunk_t *cookie, const char *buf, int size)
-{
-	int len;
-
-	len = min(size, cookie->len);
-	memcpy(cookie->ptr, buf, len);
-	*cookie = chunk_skip(*cookie, len);
-
-	return len;
-}
-
-static int fmemclose(void *cookie)
-{
-	free(cookie);
-	return 0;
-}
-
-FILE *fmemopen(void *buf, size_t size, const char *mode)
-{
-	chunk_t *cookie;
-
-	INIT(cookie,
-		.ptr = buf,
-		.len = size,
-	);
-
-	return funopen(cookie, (void*)fmemread, (void*)fmemwrite, NULL, fmemclose);
-}
-
-#endif /* FMEMOPEN fallback*/
-
 /**
  * See header
  */
@@ -785,12 +192,7 @@ void utils_init()
 #ifdef WIN32
 	windows_init();
 #endif
-
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
-	ref_lock = spinlock_create();
-	cas_lock = spinlock_create();
-#endif
-
+	atomics_init();
 	strerror_init();
 }
 
@@ -802,137 +204,6 @@ void utils_deinit()
 #ifdef WIN32
 	windows_deinit();
 #endif
-
-#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
-	ref_lock->destroy(ref_lock);
-	cas_lock->destroy(cas_lock);
-#endif
-
+	atomics_deinit();
 	strerror_deinit();
 }
-
-/**
- * Described in header.
- */
-int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
-					 const void *const *args)
-{
-	static const char* months[] = {
-		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-	};
-	time_t *time = *((time_t**)(args[0]));
-	bool utc = *((int*)(args[1]));
-	struct tm t, *ret = NULL;
-
-	if (*time != UNDEFINED_TIME)
-	{
-		if (utc)
-		{
-			ret = gmtime_r(time, &t);
-		}
-		else
-		{
-			ret = localtime_r(time, &t);
-		}
-	}
-	if (ret == NULL)
-	{
-		return print_in_hook(data, "--- -- --:--:--%s----",
-							 utc ? " UTC " : " ");
-	}
-	return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
-						 months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
-						 t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
-}
-
-/**
- * Described in header.
- */
-int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
-						   const void *const *args)
-{
-	char* unit = "second";
-	time_t *arg1 = *((time_t**)(args[0]));
-	time_t *arg2 = *((time_t**)(args[1]));
-	u_int64_t delta = llabs(*arg1 - *arg2);
-
-	if (delta > 2 * 60 * 60 * 24)
-	{
-		delta /= 60 * 60 * 24;
-		unit = "day";
-	}
-	else if (delta > 2 * 60 * 60)
-	{
-		delta /= 60 * 60;
-		unit = "hour";
-	}
-	else if (delta > 2 * 60)
-	{
-		delta /= 60;
-		unit = "minute";
-	}
-	return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
-						 (delta == 1) ? "" : "s");
-}
-
-/**
- * Number of bytes per line to dump raw data
- */
-#define BYTES_PER_LINE 16
-
-static char hexdig_upper[] = "0123456789ABCDEF";
-
-/**
- * Described in header.
- */
-int mem_printf_hook(printf_hook_data_t *data,
-					printf_hook_spec_t *spec, const void *const *args)
-{
-	char *bytes = *((void**)(args[0]));
-	u_int len = *((int*)(args[1]));
-
-	char buffer[BYTES_PER_LINE * 3];
-	char ascii_buffer[BYTES_PER_LINE + 1];
-	char *buffer_pos = buffer;
-	char *bytes_pos  = bytes;
-	char *bytes_roof = bytes + len;
-	int line_start = 0;
-	int i = 0;
-	int written = 0;
-
-	written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
-
-	while (bytes_pos < bytes_roof)
-	{
-		*buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
-		*buffer_pos++ = hexdig_upper[ *bytes_pos       & 0xF];
-
-		ascii_buffer[i++] =
-				(*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
-
-		if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
-		{
-			int padding = 3 * (BYTES_PER_LINE - i);
-
-			while (padding--)
-			{
-				*buffer_pos++ = ' ';
-			}
-			*buffer_pos++ = '\0';
-			ascii_buffer[i] = '\0';
-
-			written += print_in_hook(data, "\n%4d: %s  %s",
-									 line_start, buffer, ascii_buffer);
-
-			buffer_pos = buffer;
-			line_start += BYTES_PER_LINE;
-			i = 0;
-		}
-		else
-		{
-			*buffer_pos++ = ' ';
-		}
-	}
-	return written;
-}
diff --git a/src/libstrongswan/utils/utils.h b/src/libstrongswan/utils/utils.h
index 7c48d94..acc15c4 100644
--- a/src/libstrongswan/utils/utils.h
+++ b/src/libstrongswan/utils/utils.h
@@ -40,6 +40,33 @@
 # include <poll.h>
 #endif
 
+#include "utils/types.h"
+#include "enum.h"
+#include "utils/atomics.h"
+#include "utils/align.h"
+#include "utils/byteorder.h"
+#include "utils/string.h"
+#include "utils/memory.h"
+#include "utils/strerror.h"
+#include "utils/status.h"
+#include "utils/object.h"
+#include "utils/path.h"
+#include "utils/time.h"
+#include "utils/tty.h"
+#ifdef __APPLE__
+# include "compat/apple.h"
+#endif
+
+/**
+ * Initialize utility functions
+ */
+void utils_init();
+
+/**
+ * Deinitialize utility functions
+ */
+void utils_deinit();
+
 /**
  * strongSwan program return codes
  */
@@ -75,236 +102,11 @@
 		BUILD_ASSERT(!__builtin_types_compatible_p(typeof(a), typeof(&(a)[0])))
 
 /**
- * General purpose boolean type.
- */
-#ifdef HAVE_STDBOOL_H
-# include <stdbool.h>
-#else
-# ifndef HAVE__BOOL
-#  define _Bool signed char
-# endif /* HAVE__BOOL */
-# define bool _Bool
-# define false 0
-# define true 1
-# define __bool_true_false_are_defined 1
-#endif /* HAVE_STDBOOL_H */
-#ifndef FALSE
-# define FALSE false
-#endif /* FALSE */
-#ifndef TRUE
-# define TRUE  true
-#endif /* TRUE */
-
-#include "enum.h"
-#include "utils/strerror.h"
-#ifdef __APPLE__
-# include "compat/apple.h"
-#endif
-
-/**
- * Directory separator character in paths on this platform
- */
-#ifdef WIN32
-# define DIRECTORY_SEPARATOR "\\"
-#else
-# define DIRECTORY_SEPARATOR "/"
-#endif
-
-/**
- * Initialize utility functions
- */
-void utils_init();
-
-/**
- * Deinitialize utility functions
- */
-void utils_deinit();
-
-/**
- * Helper function that compares two strings for equality
- */
-static inline bool streq(const char *x, const char *y)
-{
-	return strcmp(x, y) == 0;
-}
-
-/**
- * Helper function that compares two strings for equality, length limited
- */
-static inline bool strneq(const char *x, const char *y, size_t len)
-{
-	return strncmp(x, y, len) == 0;
-}
-
-/**
- * Helper function that checks if a string starts with a given prefix
- */
-static inline bool strpfx(const char *x, const char *prefix)
-{
-	return strneq(x, prefix, strlen(prefix));
-}
-
-/**
- * Helper function that compares two strings for equality ignoring case
- */
-static inline bool strcaseeq(const char *x, const char *y)
-{
-	return strcasecmp(x, y) == 0;
-}
-
-/**
- * Helper function that compares two strings for equality ignoring case, length limited
- */
-static inline bool strncaseeq(const char *x, const char *y, size_t len)
-{
-	return strncasecmp(x, y, len) == 0;
-}
-
-/**
- * Helper function that checks if a string starts with a given prefix
- */
-static inline bool strcasepfx(const char *x, const char *prefix)
-{
-	return strncaseeq(x, prefix, strlen(prefix));
-}
-
-/**
- * NULL-safe strdup variant
- */
-static inline char *strdupnull(const char *s)
-{
-	return s ? strdup(s) : NULL;
-}
-
-/**
- * Helper function that compares two binary blobs for equality
- */
-static inline bool memeq(const void *x, const void *y, size_t len)
-{
-	return memcmp(x, y, len) == 0;
-}
-
-/**
- * Calling memcpy() with NULL pointers, even with n == 0, results in undefined
- * behavior according to the C standard.  This version is guaranteed to not
- * access the pointers if n is 0.
- */
-static inline void *memcpy_noop(void *dst, const void *src, size_t n)
-{
-	return n ? memcpy(dst, src, n) : dst;
-}
-#ifdef memcpy
-# undef memcpy
-#endif
-#define memcpy(d,s,n) memcpy_noop(d,s,n)
-
-/**
- * Calling memmove() with NULL pointers, even with n == 0, results in undefined
- * behavior according to the C standard.  This version is guaranteed to not
- * access the pointers if n is 0.
- */
-static inline void *memmove_noop(void *dst, const void *src, size_t n)
-{
-	return n ? memmove(dst, src, n) : dst;
-}
-#ifdef memmove
-# undef memmove
-#endif
-#define memmove(d,s,n) memmove_noop(d,s,n)
-
-/**
- * Calling memset() with a NULL pointer, even with n == 0, results in undefined
- * behavior according to the C standard.  This version is guaranteed to not
- * access the pointer if n is 0.
- */
-static inline void *memset_noop(void *s, int c, size_t n)
-{
-	return n ? memset(s, c, n) : s;
-}
-#ifdef memset
-# undef memset
-#endif
-#define memset(s,c,n) memset_noop(s,c,n)
-
-/**
- * Macro gives back larger of two values.
- */
-#define max(x,y) ({ \
-	typeof(x) _x = (x); \
-	typeof(y) _y = (y); \
-	_x > _y ? _x : _y; })
-
-/**
- * Macro gives back smaller of two values.
- */
-#define min(x,y) ({ \
-	typeof(x) _x = (x); \
-	typeof(y) _y = (y); \
-	_x < _y ? _x : _y; })
-
-/**
- * Call destructor of an object, if object != NULL
- */
-#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
-
-/**
- * Call offset destructor of an object, if object != NULL
- */
-#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
-
-/**
- * Call function destructor of an object, if object != NULL
- */
-#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
-
-/**
  * Debug macro to follow control flow
  */
 #define POS printf("%s, line %d\n", __FILE__, __LINE__)
 
 /**
- * Object allocation/initialization macro, using designated initializer.
- */
-#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
-						   *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
-
-/**
- * Method declaration/definition macro, providing private and public interface.
- *
- * Defines a method name with this as first parameter and a return value ret,
- * and an alias for this method with a _ prefix, having the this argument
- * safely casted to the public interface iface.
- * _name is provided a function pointer, but will get optimized out by GCC.
- */
-#define METHOD(iface, name, ret, this, ...) \
-	static ret name(union {iface *_public; this;} \
-	__attribute__((transparent_union)), ##__VA_ARGS__); \
-	static typeof(name) *_##name = (typeof(name)*)name; \
-	static ret name(this, ##__VA_ARGS__)
-
-/**
- * Same as METHOD(), but is defined for two public interfaces.
- */
-#define METHOD2(iface1, iface2, name, ret, this, ...) \
-	static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
-	__attribute__((transparent_union)), ##__VA_ARGS__); \
-	static typeof(name) *_##name = (typeof(name)*)name; \
-	static ret name(this, ##__VA_ARGS__)
-
-/**
- * Callback declaration/definition macro, allowing casted first parameter.
- *
- * This is very similar to METHOD, but instead of casting the first parameter
- * to a public interface, it uses a void*. This allows type safe definition
- * of a callback function, while using the real type for the first parameter.
- */
-#define CALLBACK(name, ret, param1, ...) \
-	static ret _cb_##name(union {void *_generic; param1;} \
-	__attribute__((transparent_union)), ##__VA_ARGS__); \
-	static typeof(_cb_##name) *name = (typeof(_cb_##name)*)_cb_##name; \
-	static ret _cb_##name(param1, ##__VA_ARGS__)
-
-/**
  * This macro allows counting the number of arguments passed to a macro.
  * Combined with the VA_ARGS_DISPATCH() macro this can be used to implement
  * macro overloading based on the number of arguments.
@@ -331,28 +133,6 @@ static inline void *memset_noop(void *s, int c, size_t n)
 #define __VA_ARGS_DISPATCH(func, num) func ## num
 
 /**
- * Architecture independent bitfield definition helpers (at least with GCC).
- *
- * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
- * BITFIELD2(u_int8_t,
- *     low: 4,
- *     high: 4,
- * ) flags;
- * The member defined first placed at bit 0.
- */
-#if BYTE_ORDER == LITTLE_ENDIAN
-#define BITFIELD2(t, a, b,...)			struct { t a; t b; __VA_ARGS__}
-#define BITFIELD3(t, a, b, c,...)		struct { t a; t b; t c; __VA_ARGS__}
-#define BITFIELD4(t, a, b, c, d,...)	struct { t a; t b; t c; t d; __VA_ARGS__}
-#define BITFIELD5(t, a, b, c, d, e,...)	struct { t a; t b; t c; t d; t e; __VA_ARGS__}
-#elif BYTE_ORDER == BIG_ENDIAN
-#define BITFIELD2(t, a, b,...)			struct { t b; t a; __VA_ARGS__}
-#define BITFIELD3(t, a, b, c,...)		struct { t c; t b; t a; __VA_ARGS__}
-#define BITFIELD4(t, a, b, c, d,...)	struct { t d; t c; t b; t a; __VA_ARGS__}
-#define BITFIELD5(t, a, b, c, d, e,...)	struct { t e; t d; t c; t b; t a; __VA_ARGS__}
-#endif
-
-/**
  * Macro to allocate a sized type.
  */
 #define malloc_thing(thing) ((thing*)malloc(sizeof(thing)))
@@ -369,313 +149,10 @@ static inline void *memset_noop(void *s, int c, size_t n)
 #define ignore_result(call) { if(call){}; }
 
 /**
- * Assign a function as a class method
- */
-#define ASSIGN(method, function) (method = (typeof(method))function)
-
-/**
- * time_t not defined
- */
-#define UNDEFINED_TIME 0
-
-/**
- * Maximum time since epoch causing wrap-around on Jan 19 03:14:07 UTC 2038
- */
-#define TIME_32_BIT_SIGNED_MAX	0x7fffffff
-
-/**
- * define some missing fixed width int types on OpenSolaris.
- * TODO: since the uintXX_t types are defined by the C99 standard we should
- * probably use those anyway
- */
-#if defined __sun || defined WIN32
-        #include <stdint.h>
-        typedef uint8_t         u_int8_t;
-        typedef uint16_t        u_int16_t;
-        typedef uint32_t        u_int32_t;
-        typedef uint64_t        u_int64_t;
-#endif
-
-typedef enum status_t status_t;
-
-/**
- * Return values of function calls.
- */
-enum status_t {
-	/**
-	 * Call succeeded.
-	 */
-	SUCCESS,
-
-	/**
-	 * Call failed.
-	 */
-	FAILED,
-
-	/**
-	 * Out of resources.
-	 */
-	OUT_OF_RES,
-
-	/**
-	 * The suggested operation is already done
-	 */
-	ALREADY_DONE,
-
-	/**
-	 * Not supported.
-	 */
-	NOT_SUPPORTED,
-
-	/**
-	 * One of the arguments is invalid.
-	 */
-	INVALID_ARG,
-
-	/**
-	 * Something could not be found.
-	 */
-	NOT_FOUND,
-
-	/**
-	 * Error while parsing.
-	 */
-	PARSE_ERROR,
-
-	/**
-	 * Error while verifying.
-	 */
-	VERIFY_ERROR,
-
-	/**
-	 * Object in invalid state.
-	 */
-	INVALID_STATE,
-
-	/**
-	 * Destroy object which called method belongs to.
-	 */
-	DESTROY_ME,
-
-	/**
-	 * Another call to the method is required.
-	 */
-	NEED_MORE,
-};
-
-/**
- * enum_names for type status_t.
- */
-extern enum_name_t *status_names;
-
-typedef enum tty_escape_t tty_escape_t;
-
-/**
- * Excape codes for tty colors
- */
-enum tty_escape_t {
-	/** text properties */
-	TTY_RESET,
-	TTY_BOLD,
-	TTY_UNDERLINE,
-	TTY_BLINKING,
-
-	/** foreground colors */
-	TTY_FG_BLACK,
-	TTY_FG_RED,
-	TTY_FG_GREEN,
-	TTY_FG_YELLOW,
-	TTY_FG_BLUE,
-	TTY_FG_MAGENTA,
-	TTY_FG_CYAN,
-	TTY_FG_WHITE,
-	TTY_FG_DEF,
-
-	/** background colors */
-	TTY_BG_BLACK,
-	TTY_BG_RED,
-	TTY_BG_GREEN,
-	TTY_BG_YELLOW,
-	TTY_BG_BLUE,
-	TTY_BG_MAGENTA,
-	TTY_BG_CYAN,
-	TTY_BG_WHITE,
-	TTY_BG_DEF,
-};
-
-/**
- * Get the escape string for a given TTY color, empty string on non-tty fd
- */
-char* tty_escape_get(int fd, tty_escape_t escape);
-
-/**
- * deprecated pluto style return value:
- * error message, NULL for success
- */
-typedef const char *err_t;
-
-/**
- * Handle struct timeval like an own type.
- */
-typedef struct timeval timeval_t;
-
-/**
- * Handle struct timespec like an own type.
- */
-typedef struct timespec timespec_t;
-
-/**
- * Handle struct chunk_t like an own type.
- */
-typedef struct sockaddr sockaddr_t;
-
-/**
- * Same as memcpy, but XORs src into dst instead of copy
- */
-void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
-
-/**
- * Safely overwrite n bytes of memory at ptr with zero, non-inlining variant.
- */
-void memwipe_noinline(void *ptr, size_t n);
-
-/**
- * Safely overwrite n bytes of memory at ptr with zero, inlining variant.
- */
-static inline void memwipe_inline(void *ptr, size_t n)
-{
-	volatile char *c = (volatile char*)ptr;
-	size_t m, i;
-
-	/* byte wise until long aligned */
-	for (i = 0; (uintptr_t)&c[i] % sizeof(long) && i < n; i++)
-	{
-		c[i] = 0;
-	}
-	/* word wise */
-	if (n >= sizeof(long))
-	{
-		for (m = n - sizeof(long); i <= m; i += sizeof(long))
-		{
-			*(volatile long*)&c[i] = 0;
-		}
-	}
-	/* byte wise of the rest */
-	for (; i < n; i++)
-	{
-		c[i] = 0;
-	}
-}
-
-/**
- * Safely overwrite n bytes of memory at ptr with zero, auto-inlining variant.
- */
-static inline void memwipe(void *ptr, size_t n)
-{
-	if (!ptr)
-	{
-		return;
-	}
-	if (__builtin_constant_p(n))
-	{
-		memwipe_inline(ptr, n);
-	}
-	else
-	{
-		memwipe_noinline(ptr, n);
-	}
-}
-
-/**
- * A variant of strstr with the characteristics of memchr, where haystack is not
- * a null-terminated string but simply a memory area of length n.
- */
-void *memstr(const void *haystack, const char *needle, size_t n);
-
-/**
- * Replacement for memrchr(3) if it is not provided by the C library.
- *
- * @param s		start of the memory area to search
- * @param c		character to search
- * @param n		length of memory area to search
- * @return		pointer to the found character or NULL
- */
-void *utils_memrchr(const void *s, int c, size_t n);
-
-#ifndef HAVE_MEMRCHR
-#define memrchr(s,c,n) utils_memrchr(s,c,n)
-#endif
-
-/**
- * Translates the characters in the given string, searching for characters
- * in 'from' and mapping them to characters in 'to'.
- * The two characters sets 'from' and 'to' must contain the same number of
- * characters.
- */
-char *translate(char *str, const char *from, const char *to);
-
-/**
- * Replaces all occurrences of search in the given string with replace.
- *
- * Allocates memory only if anything is replaced in the string.  The original
- * string is also returned if any of the arguments are invalid (e.g. if search
- * is empty or any of them are NULL).
- *
- * @param str		original string
- * @param search	string to search for and replace
- * @param replace	string to replace found occurrences with
- * @return			allocated string, if anything got replaced, str otherwise
- */
-char *strreplace(const char *str, const char *search, const char *replace);
-
-/**
  * Portable function to wait for SIGINT/SIGTERM (or equivalent).
  */
 void wait_sigint();
 
-/**
- * Like dirname(3) returns the directory part of the given null-terminated
- * pathname, up to but not including the final '/' (or '.' if no '/' is found).
- * Trailing '/' are not counted as part of the pathname.
- *
- * The difference is that it does this in a thread-safe manner (i.e. it does not
- * use static buffers) and does not modify the original path.
- *
- * @param path		original pathname
- * @return			allocated directory component
- */
-char *path_dirname(const char *path);
-
-/**
- * Like basename(3) returns the filename part of the given null-terminated path,
- * i.e. the part following the final '/' (or '.' if path is empty or NULL).
- * Trailing '/' are not counted as part of the pathname.
- *
- * The difference is that it does this in a thread-safe manner (i.e. it does not
- * use static buffers) and does not modify the original path.
- *
- * @param path		original pathname
- * @return			allocated filename component
- */
-char *path_basename(const char *path);
-
-/**
- * Check if a given path is absolute.
- *
- * @param path		path to check
- * @return			TRUE if absolute, FALSE if relative
- */
-bool path_absolute(const char *path);
-
-/**
- * Creates a directory and all required parent directories.
- *
- * @param path		path to the new directory
- * @param mode		permissions of the new directory/directories
- * @return			TRUE on success
- */
-bool mkdir_p(const char *path, mode_t mode);
-
 #ifndef HAVE_CLOSEFROM
 /**
  * Close open file descriptors greater than or equal to lowfd.
@@ -686,34 +163,6 @@ void closefrom(int lowfd);
 #endif
 
 /**
- * Get a timestamp from a monotonic time source.
- *
- * While the time()/gettimeofday() functions are affected by leap seconds
- * and system time changes, this function returns ever increasing monotonic
- * time stamps.
- *
- * @param tv		timeval struct receiving monotonic timestamps, or NULL
- * @return			monotonic timestamp in seconds
- */
-time_t time_monotonic(timeval_t *tv);
-
-/**
- * Add the given number of milliseconds to the given timeval struct
- *
- * @param tv		timeval struct to modify
- * @param ms		number of milliseconds
- */
-static inline void timeval_add_ms(timeval_t *tv, u_int ms)
-{
-	tv->tv_usec += ms * 1000;
-	while (tv->tv_usec >= 1000000 /* 1s */)
-	{
-		tv->tv_usec -= 1000000;
-		tv->tv_sec++;
-	}
-}
-
-/**
  * returns null
  */
 void *return_null();
@@ -733,294 +182,4 @@ bool return_true();
  */
 bool return_false();
 
-/**
- * returns FAILED
- */
-status_t return_failed();
-
-/**
- * returns SUCCESS
- */
-status_t return_success();
-
-/**
- * Write a 16-bit host order value in network order to an unaligned address.
- *
- * @param host		host order 16-bit value
- * @param network	unaligned address to write network order value to
- */
-static inline void htoun16(void *network, u_int16_t host)
-{
-	char *unaligned = (char*)network;
-
-	host = htons(host);
-	memcpy(unaligned, &host, sizeof(host));
-}
-
-/**
- * Write a 32-bit host order value in network order to an unaligned address.
- *
- * @param host		host order 32-bit value
- * @param network	unaligned address to write network order value to
- */
-static inline void htoun32(void *network, u_int32_t host)
-{
-	char *unaligned = (char*)network;
-
-	host = htonl(host);
-	memcpy((char*)unaligned, &host, sizeof(host));
-}
-
-/**
- * Write a 64-bit host order value in network order to an unaligned address.
- *
- * @param host		host order 64-bit value
- * @param network	unaligned address to write network order value to
- */
-static inline void htoun64(void *network, u_int64_t host)
-{
-	char *unaligned = (char*)network;
-
-#ifdef be64toh
-	host = htobe64(host);
-	memcpy((char*)unaligned, &host, sizeof(host));
-#else
-	u_int32_t high_part, low_part;
-
-	high_part = host >> 32;
-	high_part = htonl(high_part);
-	low_part  = host & 0xFFFFFFFFLL;
-	low_part  = htonl(low_part);
-
-	memcpy(unaligned, &high_part, sizeof(high_part));
-	unaligned += sizeof(high_part);
-	memcpy(unaligned, &low_part, sizeof(low_part));
-#endif
-}
-
-/**
- * Read a 16-bit value in network order from an unaligned address to host order.
- *
- * @param network	unaligned address to read network order value from
- * @return			host order value
- */
-static inline u_int16_t untoh16(void *network)
-{
-	char *unaligned = (char*)network;
-	u_int16_t tmp;
-
-	memcpy(&tmp, unaligned, sizeof(tmp));
-	return ntohs(tmp);
-}
-
-/**
- * Read a 32-bit value in network order from an unaligned address to host order.
- *
- * @param network	unaligned address to read network order value from
- * @return			host order value
- */
-static inline u_int32_t untoh32(void *network)
-{
-	char *unaligned = (char*)network;
-	u_int32_t tmp;
-
-	memcpy(&tmp, unaligned, sizeof(tmp));
-	return ntohl(tmp);
-}
-
-/**
- * Read a 64-bit value in network order from an unaligned address to host order.
- *
- * @param network	unaligned address to read network order value from
- * @return			host order value
- */
-static inline u_int64_t untoh64(void *network)
-{
-	char *unaligned = (char*)network;
-
-#ifdef be64toh
-	u_int64_t tmp;
-
-	memcpy(&tmp, unaligned, sizeof(tmp));
-	return be64toh(tmp);
-#else
-	u_int32_t high_part, low_part;
-
-	memcpy(&high_part, unaligned, sizeof(high_part));
-	unaligned += sizeof(high_part);
-	memcpy(&low_part, unaligned, sizeof(low_part));
-
-	high_part = ntohl(high_part);
-	low_part  = ntohl(low_part);
-
-	return (((u_int64_t)high_part) << 32) + low_part;
-#endif
-}
-
-/**
- * Get the padding required to make size a multiple of alignment
- */
-static inline size_t pad_len(size_t size, size_t alignment)
-{
-	size_t remainder;
-
-	remainder = size % alignment;
-	return remainder ? alignment - remainder : 0;
-}
-
-/**
- * Round up size to be multiple of alignment
- */
-static inline size_t round_up(size_t size, size_t alignment)
-{
-	return size + pad_len(size, alignment);
-}
-
-/**
- * Round down size to be a multiple of alignment
- */
-static inline size_t round_down(size_t size, size_t alignment)
-{
-	return size - (size % alignment);
-}
-
-/**
- * Special type to count references
- */
-typedef u_int refcount_t;
-
-/* use __atomic* built-ins with GCC 4.7 and newer */
-#ifdef __GNUC__
-# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
-#  define HAVE_GCC_ATOMIC_OPERATIONS
-# endif
-#endif
-
-#ifdef HAVE_GCC_ATOMIC_OPERATIONS
-
-#define ref_get(ref) __atomic_add_fetch(ref, 1, __ATOMIC_RELAXED)
-/* The relaxed memory model works fine for increments as these (usually) don't
- * change the state of refcounted objects.  But here we have to ensure that we
- * free the right stuff if ref counted objects are mutable.  So we have to sync
- * with other threads that call ref_put().  It would be sufficient to use
- * __ATOMIC_RELEASE here and then call __atomic_thread_fence() with
- * __ATOMIC_ACQUIRE if we reach 0, but since we don't have control over the use
- * of ref_put() we have to make sure. */
-#define ref_put(ref) (!__atomic_sub_fetch(ref, 1, __ATOMIC_ACQ_REL))
-#define ref_cur(ref) __atomic_load_n(ref, __ATOMIC_RELAXED)
-
-#define _cas_impl(ptr, oldval, newval) ({ typeof(oldval) _old = oldval; \
-			__atomic_compare_exchange_n(ptr, &_old, newval, FALSE, \
-										__ATOMIC_SEQ_CST, __ATOMIC_RELAXED); })
-#define cas_bool(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
-#define cas_ptr(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
-
-#elif defined(HAVE_GCC_SYNC_OPERATIONS)
-
-#define ref_get(ref) __sync_add_and_fetch(ref, 1)
-#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
-#define ref_cur(ref) __sync_fetch_and_add(ref, 0)
-
-#define cas_bool(ptr, oldval, newval) \
-					(__sync_bool_compare_and_swap(ptr, oldval, newval))
-#define cas_ptr(ptr, oldval, newval) \
-					(__sync_bool_compare_and_swap(ptr, oldval, newval))
-
-#else /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
-
-/**
- * Get a new reference.
- *
- * Increments the reference counter atomically.
- *
- * @param ref	pointer to ref counter
- * @return		new value of ref
- */
-refcount_t ref_get(refcount_t *ref);
-
-/**
- * Put back a unused reference.
- *
- * Decrements the reference counter atomically and
- * says if more references available.
- *
- * @param ref	pointer to ref counter
- * @return		TRUE if no more references counted
- */
-bool ref_put(refcount_t *ref);
-
-/**
- * Get the current value of the reference counter.
- *
- * @param ref	pointer to ref counter
- * @return		current value of ref
- */
-refcount_t ref_cur(refcount_t *ref);
-
-/**
- * Atomically replace value of ptr with newval if it currently equals oldval.
- *
- * @param ptr		pointer to variable
- * @param oldval	old value of the variable
- * @param newval	new value set if possible
- * @return			TRUE if value equaled oldval and newval was written
- */
-bool cas_bool(bool *ptr, bool oldval, bool newval);
-
-/**
- * Atomically replace value of ptr with newval if it currently equals oldval.
- *
- * @param ptr		pointer to variable
- * @param oldval	old value of the variable
- * @param newval	new value set if possible
- * @return			TRUE if value equaled oldval and newval was written
- */
-bool cas_ptr(void **ptr, void *oldval, void *newval);
-
-#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
-
-#ifndef HAVE_FMEMOPEN
-# ifdef HAVE_FUNOPEN
-#  define HAVE_FMEMOPEN
-#  define HAVE_FMEMOPEN_FALLBACK
-#  include <stdio.h>
-/**
- * fmemopen(3) fallback using BSD funopen.
- *
- * We could also provide one using fopencookie(), but should we have it we
- * most likely have fmemopen().
- *
- * fseek() is currently not supported.
- */
-FILE *fmemopen(void *buf, size_t size, const char *mode);
-# endif /* FUNOPEN */
-#endif /* FMEMOPEN */
-
-/**
- * printf hook for time_t.
- *
- * Arguments are:
- *	time_t* time, bool utc
- */
-int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
-					 const void *const *args);
-
-/**
- * printf hook for time_t deltas.
- *
- * Arguments are:
- *	time_t* begin, time_t* end
- */
-int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
-						   const void *const *args);
-
-/**
- * printf hook for memory areas.
- *
- * Arguments are:
- *	u_char *ptr, u_int len
- */
-int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
-					const void *const *args);
-
 #endif /** UTILS_H_ @}*/
diff --git a/src/libstrongswan/utils/utils/align.c b/src/libstrongswan/utils/utils/align.c
new file mode 100644
index 0000000..29f110f
--- /dev/null
+++ b/src/libstrongswan/utils/utils/align.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+#include <utils/debug.h>
+
+/**
+ * Described in header.
+ */
+void* malloc_align(size_t size, u_int8_t align)
+{
+	u_int8_t pad;
+	void *ptr;
+
+	if (align == 0)
+	{
+		align = 1;
+	}
+	ptr = malloc(align + sizeof(pad) + size);
+	if (!ptr)
+	{
+		return NULL;
+	}
+	/* store padding length just before data, down to the allocation boundary
+	 * to do some verification during free_align() */
+	pad = align - ((uintptr_t)ptr % align);
+	memset(ptr, pad, pad);
+	return ptr + pad;
+}
+
+/**
+ * Described in header.
+ */
+void free_align(void *ptr)
+{
+	u_int8_t pad, *pos;
+
+	pos = ptr - 1;
+	/* verify padding to check any corruption */
+	for (pad = *pos; (void*)pos >= ptr - pad; pos--)
+	{
+		if (*pos != pad)
+		{
+			DBG1(DBG_LIB, "!!!! invalid free_align() !!!!");
+			return;
+		}
+	}
+	free(ptr - pad);
+}
diff --git a/src/libstrongswan/utils/utils/align.h b/src/libstrongswan/utils/utils/align.h
new file mode 100644
index 0000000..39cde10
--- /dev/null
+++ b/src/libstrongswan/utils/utils/align.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup align_i align
+ * @{ @ingroup utils_i
+ */
+
+#ifndef ALIGN_H_
+#define ALIGN_H_
+
+/**
+ * Macro gives back larger of two values.
+ */
+#define max(x,y) ({ \
+	typeof(x) _x = (x); \
+	typeof(y) _y = (y); \
+	_x > _y ? _x : _y; })
+
+/**
+ * Macro gives back smaller of two values.
+ */
+#define min(x,y) ({ \
+	typeof(x) _x = (x); \
+	typeof(y) _y = (y); \
+	_x < _y ? _x : _y; })
+
+/**
+ * Get the padding required to make size a multiple of alignment
+ */
+static inline size_t pad_len(size_t size, size_t alignment)
+{
+	size_t remainder;
+
+	remainder = size % alignment;
+	return remainder ? alignment - remainder : 0;
+}
+
+/**
+ * Round up size to be multiple of alignment
+ */
+static inline size_t round_up(size_t size, size_t alignment)
+{
+	return size + pad_len(size, alignment);
+}
+
+/**
+ * Round down size to be a multiple of alignment
+ */
+static inline size_t round_down(size_t size, size_t alignment)
+{
+	return size - (size % alignment);
+}
+
+/**
+ * malloc(), but returns aligned memory.
+ *
+ * The returned pointer must be freed using free_align(), not free().
+ *
+ * @param size			size of allocated data
+ * @param align			alignment, up to 255 bytes, usually a power of 2
+ * @return				allocated hunk, aligned to align bytes
+ */
+void* malloc_align(size_t size, u_int8_t align);
+
+/**
+ * Free a hunk allocated by malloc_align().
+ *
+ * @param ptr			hunk to free
+ */
+void free_align(void *ptr);
+
+#endif /** ALIGN_H_ @} */
diff --git a/src/libstrongswan/utils/utils/atomics.c b/src/libstrongswan/utils/utils/atomics.c
new file mode 100644
index 0000000..17e823e
--- /dev/null
+++ b/src/libstrongswan/utils/utils/atomics.c
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
+
+#include <threading/spinlock.h>
+
+/**
+ * Spinlock for ref_get/put
+ */
+static spinlock_t *ref_lock;
+
+/**
+ * Increase refcount
+ */
+refcount_t ref_get(refcount_t *ref)
+{
+	refcount_t current;
+
+	ref_lock->lock(ref_lock);
+	current = ++(*ref);
+	ref_lock->unlock(ref_lock);
+
+	return current;
+}
+
+/**
+ * Decrease refcount
+ */
+bool ref_put(refcount_t *ref)
+{
+	bool more_refs;
+
+	ref_lock->lock(ref_lock);
+	more_refs = --(*ref) > 0;
+	ref_lock->unlock(ref_lock);
+	return !more_refs;
+}
+
+/**
+ * Current refcount
+ */
+refcount_t ref_cur(refcount_t *ref)
+{
+	refcount_t current;
+
+	ref_lock->lock(ref_lock);
+	current = *ref;
+	ref_lock->unlock(ref_lock);
+
+	return current;
+}
+
+/**
+ * Spinlock for all compare and swap operations.
+ */
+static spinlock_t *cas_lock;
+
+/**
+ * Compare and swap if equal to old value
+ */
+#define _cas_impl(name, type) \
+bool cas_##name(type *ptr, type oldval, type newval) \
+{ \
+	bool swapped; \
+	cas_lock->lock(cas_lock); \
+	if ((swapped = (*ptr == oldval))) { *ptr = newval; } \
+	cas_lock->unlock(cas_lock); \
+	return swapped; \
+}
+
+_cas_impl(bool, bool)
+_cas_impl(ptr, void*)
+
+#endif /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
+
+/**
+ * See header
+ */
+void atomics_init()
+{
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
+	ref_lock = spinlock_create();
+	cas_lock = spinlock_create();
+#endif
+}
+
+/**
+ * See header
+ */
+void atomics_deinit()
+{
+#if !defined(HAVE_GCC_ATOMIC_OPERATIONS) && !defined(HAVE_GCC_SYNC_OPERATIONS)
+	ref_lock->destroy(ref_lock);
+	cas_lock->destroy(cas_lock);
+#endif
+}
diff --git a/src/libstrongswan/utils/utils/atomics.h b/src/libstrongswan/utils/utils/atomics.h
new file mode 100644
index 0000000..e5db0a1
--- /dev/null
+++ b/src/libstrongswan/utils/utils/atomics.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup atomics_i atomics
+ * @{ @ingroup utils_i
+ */
+
+#ifndef ATOMICS_H_
+#define ATOMICS_H_
+
+/**
+ * Special type to count references
+ */
+typedef u_int refcount_t;
+
+/* use __atomic* built-ins with GCC 4.7 and newer */
+#ifdef __GNUC__
+# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+#  define HAVE_GCC_ATOMIC_OPERATIONS
+# endif
+#endif
+
+#ifdef HAVE_GCC_ATOMIC_OPERATIONS
+
+#define ref_get(ref) __atomic_add_fetch(ref, 1, __ATOMIC_RELAXED)
+/* The relaxed memory model works fine for increments as these (usually) don't
+ * change the state of refcounted objects.  But here we have to ensure that we
+ * free the right stuff if ref counted objects are mutable.  So we have to sync
+ * with other threads that call ref_put().  It would be sufficient to use
+ * __ATOMIC_RELEASE here and then call __atomic_thread_fence() with
+ * __ATOMIC_ACQUIRE if we reach 0, but since we don't have control over the use
+ * of ref_put() we have to make sure. */
+#define ref_put(ref) (!__atomic_sub_fetch(ref, 1, __ATOMIC_ACQ_REL))
+#define ref_cur(ref) __atomic_load_n(ref, __ATOMIC_RELAXED)
+
+#define _cas_impl(ptr, oldval, newval) ({ typeof(oldval) _old = oldval; \
+			__atomic_compare_exchange_n(ptr, &_old, newval, FALSE, \
+										__ATOMIC_SEQ_CST, __ATOMIC_RELAXED); })
+#define cas_bool(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
+#define cas_ptr(ptr, oldval, newval) _cas_impl(ptr, oldval, newval)
+
+#elif defined(HAVE_GCC_SYNC_OPERATIONS)
+
+#define ref_get(ref) __sync_add_and_fetch(ref, 1)
+#define ref_put(ref) (!__sync_sub_and_fetch(ref, 1))
+#define ref_cur(ref) __sync_fetch_and_add(ref, 0)
+
+#define cas_bool(ptr, oldval, newval) \
+					(__sync_bool_compare_and_swap(ptr, oldval, newval))
+#define cas_ptr(ptr, oldval, newval) \
+					(__sync_bool_compare_and_swap(ptr, oldval, newval))
+
+#else /* !HAVE_GCC_ATOMIC_OPERATIONS && !HAVE_GCC_SYNC_OPERATIONS */
+
+/**
+ * Get a new reference.
+ *
+ * Increments the reference counter atomically.
+ *
+ * @param ref	pointer to ref counter
+ * @return		new value of ref
+ */
+refcount_t ref_get(refcount_t *ref);
+
+/**
+ * Put back a unused reference.
+ *
+ * Decrements the reference counter atomically and
+ * says if more references available.
+ *
+ * @param ref	pointer to ref counter
+ * @return		TRUE if no more references counted
+ */
+bool ref_put(refcount_t *ref);
+
+/**
+ * Get the current value of the reference counter.
+ *
+ * @param ref	pointer to ref counter
+ * @return		current value of ref
+ */
+refcount_t ref_cur(refcount_t *ref);
+
+/**
+ * Atomically replace value of ptr with newval if it currently equals oldval.
+ *
+ * @param ptr		pointer to variable
+ * @param oldval	old value of the variable
+ * @param newval	new value set if possible
+ * @return			TRUE if value equaled oldval and newval was written
+ */
+bool cas_bool(bool *ptr, bool oldval, bool newval);
+
+/**
+ * Atomically replace value of ptr with newval if it currently equals oldval.
+ *
+ * @param ptr		pointer to variable
+ * @param oldval	old value of the variable
+ * @param newval	new value set if possible
+ * @return			TRUE if value equaled oldval and newval was written
+ */
+bool cas_ptr(void **ptr, void *oldval, void *newval);
+
+#endif /* HAVE_GCC_ATOMIC_OPERATIONS */
+
+/**
+ * Initialize atomics utility functions
+ */
+void atomics_init();
+
+/**
+ * Clean up atomics utility functions
+ */
+void atomics_deinit();
+
+#endif /** ATOMICS_H_ @} */
diff --git a/src/libstrongswan/utils/utils/byteorder.h b/src/libstrongswan/utils/utils/byteorder.h
new file mode 100644
index 0000000..48cf1d5
--- /dev/null
+++ b/src/libstrongswan/utils/utils/byteorder.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup byteorder_i byteorder
+ * @{ @ingroup utils_i
+ */
+
+#ifndef BYTEORDER_H_
+#define BYTEORDER_H_
+
+/**
+ * Architecture independent bitfield definition helpers (at least with GCC).
+ *
+ * Defines a bitfield with a type t and a fixed size of bitfield members, e.g.:
+ * BITFIELD2(u_int8_t,
+ *     low: 4,
+ *     high: 4,
+ * ) flags;
+ * The member defined first placed at bit 0.
+ */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define BITFIELD2(t, a, b,...)			struct { t a; t b; __VA_ARGS__}
+#define BITFIELD3(t, a, b, c,...)		struct { t a; t b; t c; __VA_ARGS__}
+#define BITFIELD4(t, a, b, c, d,...)	struct { t a; t b; t c; t d; __VA_ARGS__}
+#define BITFIELD5(t, a, b, c, d, e,...)	struct { t a; t b; t c; t d; t e; __VA_ARGS__}
+#elif BYTE_ORDER == BIG_ENDIAN
+#define BITFIELD2(t, a, b,...)			struct { t b; t a; __VA_ARGS__}
+#define BITFIELD3(t, a, b, c,...)		struct { t c; t b; t a; __VA_ARGS__}
+#define BITFIELD4(t, a, b, c, d,...)	struct { t d; t c; t b; t a; __VA_ARGS__}
+#define BITFIELD5(t, a, b, c, d, e,...)	struct { t e; t d; t c; t b; t a; __VA_ARGS__}
+#endif
+
+/**
+ * Write a 16-bit host order value in network order to an unaligned address.
+ *
+ * @param host		host order 16-bit value
+ * @param network	unaligned address to write network order value to
+ */
+static inline void htoun16(void *network, u_int16_t host)
+{
+	char *unaligned = (char*)network;
+
+	host = htons(host);
+	memcpy(unaligned, &host, sizeof(host));
+}
+
+/**
+ * Write a 32-bit host order value in network order to an unaligned address.
+ *
+ * @param host		host order 32-bit value
+ * @param network	unaligned address to write network order value to
+ */
+static inline void htoun32(void *network, u_int32_t host)
+{
+	char *unaligned = (char*)network;
+
+	host = htonl(host);
+	memcpy((char*)unaligned, &host, sizeof(host));
+}
+
+/**
+ * Write a 64-bit host order value in network order to an unaligned address.
+ *
+ * @param host		host order 64-bit value
+ * @param network	unaligned address to write network order value to
+ */
+static inline void htoun64(void *network, u_int64_t host)
+{
+	char *unaligned = (char*)network;
+
+#ifdef be64toh
+	host = htobe64(host);
+	memcpy((char*)unaligned, &host, sizeof(host));
+#else
+	u_int32_t high_part, low_part;
+
+	high_part = host >> 32;
+	high_part = htonl(high_part);
+	low_part  = host & 0xFFFFFFFFLL;
+	low_part  = htonl(low_part);
+
+	memcpy(unaligned, &high_part, sizeof(high_part));
+	unaligned += sizeof(high_part);
+	memcpy(unaligned, &low_part, sizeof(low_part));
+#endif
+}
+
+/**
+ * Read a 16-bit value in network order from an unaligned address to host order.
+ *
+ * @param network	unaligned address to read network order value from
+ * @return			host order value
+ */
+static inline u_int16_t untoh16(void *network)
+{
+	char *unaligned = (char*)network;
+	u_int16_t tmp;
+
+	memcpy(&tmp, unaligned, sizeof(tmp));
+	return ntohs(tmp);
+}
+
+/**
+ * Read a 32-bit value in network order from an unaligned address to host order.
+ *
+ * @param network	unaligned address to read network order value from
+ * @return			host order value
+ */
+static inline u_int32_t untoh32(void *network)
+{
+	char *unaligned = (char*)network;
+	u_int32_t tmp;
+
+	memcpy(&tmp, unaligned, sizeof(tmp));
+	return ntohl(tmp);
+}
+
+/**
+ * Read a 64-bit value in network order from an unaligned address to host order.
+ *
+ * @param network	unaligned address to read network order value from
+ * @return			host order value
+ */
+static inline u_int64_t untoh64(void *network)
+{
+	char *unaligned = (char*)network;
+
+#ifdef be64toh
+	u_int64_t tmp;
+
+	memcpy(&tmp, unaligned, sizeof(tmp));
+	return be64toh(tmp);
+#else
+	u_int32_t high_part, low_part;
+
+	memcpy(&high_part, unaligned, sizeof(high_part));
+	unaligned += sizeof(high_part);
+	memcpy(&low_part, unaligned, sizeof(low_part));
+
+	high_part = ntohl(high_part);
+	low_part  = ntohl(low_part);
+
+	return (((u_int64_t)high_part) << 32) + low_part;
+#endif
+}
+
+#endif /** BYTEORDER_H_ @} */
diff --git a/src/libstrongswan/utils/utils/memory.c b/src/libstrongswan/utils/utils/memory.c
new file mode 100644
index 0000000..a153715
--- /dev/null
+++ b/src/libstrongswan/utils/utils/memory.c
@@ -0,0 +1,237 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+#include <utils/chunk.h>
+
+/**
+ * Described in header.
+ */
+void memxor(u_int8_t dst[], u_int8_t src[], size_t n)
+{
+	int m, i;
+
+	/* byte wise XOR until dst aligned */
+	for (i = 0; (uintptr_t)&dst[i] % sizeof(long) && i < n; i++)
+	{
+		dst[i] ^= src[i];
+	}
+	/* try to use words if src shares an aligment with dst */
+	switch (((uintptr_t)&src[i] % sizeof(long)))
+	{
+		case 0:
+			for (m = n - sizeof(long); i <= m; i += sizeof(long))
+			{
+				*(long*)&dst[i] ^= *(long*)&src[i];
+			}
+			break;
+		case sizeof(int):
+			for (m = n - sizeof(int); i <= m; i += sizeof(int))
+			{
+				*(int*)&dst[i] ^= *(int*)&src[i];
+			}
+			break;
+		case sizeof(short):
+			for (m = n - sizeof(short); i <= m; i += sizeof(short))
+			{
+				*(short*)&dst[i] ^= *(short*)&src[i];
+			}
+			break;
+		default:
+			break;
+	}
+	/* byte wise XOR of the rest */
+	for (; i < n; i++)
+	{
+		dst[i] ^= src[i];
+	}
+}
+
+/**
+ * Described in header.
+ */
+void memwipe_noinline(void *ptr, size_t n)
+{
+	memwipe_inline(ptr, n);
+}
+
+/**
+ * Described in header.
+ */
+bool memeq_const(const void *x, const void *y, size_t len)
+{
+	const u_char *a, *b;
+	u_int bad = 0;
+	size_t i;
+
+	a = (const u_char*)x;
+	b = (const u_char*)y;
+
+	for (i = 0; i < len; i++)
+	{
+		bad |= a[i] != b[i];
+	}
+	return !bad;
+}
+
+/**
+ * Described in header.
+ */
+void *memstr(const void *haystack, const char *needle, size_t n)
+{
+	const u_char *pos = haystack;
+	size_t l;
+
+	if (!haystack || !needle || (l = strlen(needle)) == 0)
+	{
+		return NULL;
+	}
+	for (; n >= l; ++pos, --n)
+	{
+		if (memeq(pos, needle, l))
+		{
+			return (void*)pos;
+		}
+	}
+	return NULL;
+}
+
+/**
+ * Described in header.
+ */
+void *utils_memrchr(const void *s, int c, size_t n)
+{
+	const u_char *pos;
+
+	if (!s || !n)
+	{
+		return NULL;
+	}
+
+	for (pos = s + n - 1; pos >= (u_char*)s; pos--)
+	{
+		if (*pos == (u_char)c)
+		{
+			return (void*)pos;
+		}
+	}
+	return NULL;
+}
+
+#ifdef HAVE_FMEMOPEN_FALLBACK
+
+static int fmemread(chunk_t *cookie, char *buf, int size)
+{
+	int len;
+
+	len = min(size, cookie->len);
+	memcpy(buf, cookie->ptr, len);
+	*cookie = chunk_skip(*cookie, len);
+
+	return len;
+}
+
+static int fmemwrite(chunk_t *cookie, const char *buf, int size)
+{
+	int len;
+
+	len = min(size, cookie->len);
+	memcpy(cookie->ptr, buf, len);
+	*cookie = chunk_skip(*cookie, len);
+
+	return len;
+}
+
+static int fmemclose(void *cookie)
+{
+	free(cookie);
+	return 0;
+}
+
+FILE *fmemopen(void *buf, size_t size, const char *mode)
+{
+	chunk_t *cookie;
+
+	INIT(cookie,
+		.ptr = buf,
+		.len = size,
+	);
+
+	return funopen(cookie, (void*)fmemread, (void*)fmemwrite, NULL, fmemclose);
+}
+
+#endif /* FMEMOPEN fallback*/
+
+/**
+ * Number of bytes per line to dump raw data
+ */
+#define BYTES_PER_LINE 16
+
+static char hexdig_upper[] = "0123456789ABCDEF";
+
+/**
+ * Described in header.
+ */
+int mem_printf_hook(printf_hook_data_t *data,
+					printf_hook_spec_t *spec, const void *const *args)
+{
+	char *bytes = *((void**)(args[0]));
+	u_int len = *((int*)(args[1]));
+
+	char buffer[BYTES_PER_LINE * 3];
+	char ascii_buffer[BYTES_PER_LINE + 1];
+	char *buffer_pos = buffer;
+	char *bytes_pos  = bytes;
+	char *bytes_roof = bytes + len;
+	int line_start = 0;
+	int i = 0;
+	int written = 0;
+
+	written += print_in_hook(data, "=> %u bytes @ %p", len, bytes);
+
+	while (bytes_pos < bytes_roof)
+	{
+		*buffer_pos++ = hexdig_upper[(*bytes_pos >> 4) & 0xF];
+		*buffer_pos++ = hexdig_upper[ *bytes_pos       & 0xF];
+
+		ascii_buffer[i++] =
+				(*bytes_pos > 31 && *bytes_pos < 127) ? *bytes_pos : '.';
+
+		if (++bytes_pos == bytes_roof || i == BYTES_PER_LINE)
+		{
+			int padding = 3 * (BYTES_PER_LINE - i);
+
+			while (padding--)
+			{
+				*buffer_pos++ = ' ';
+			}
+			*buffer_pos++ = '\0';
+			ascii_buffer[i] = '\0';
+
+			written += print_in_hook(data, "\n%4d: %s  %s",
+									 line_start, buffer, ascii_buffer);
+
+			buffer_pos = buffer;
+			line_start += BYTES_PER_LINE;
+			i = 0;
+		}
+		else
+		{
+			*buffer_pos++ = ' ';
+		}
+	}
+	return written;
+}
diff --git a/src/libstrongswan/utils/utils/memory.h b/src/libstrongswan/utils/utils/memory.h
new file mode 100644
index 0000000..aef318f
--- /dev/null
+++ b/src/libstrongswan/utils/utils/memory.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup memory_i memory
+ * @{ @ingroup utils_i
+ */
+
+#ifndef MEMORY_H_
+#define MEMORY_H_
+
+/**
+ * Helper function that compares two binary blobs for equality
+ */
+static inline bool memeq(const void *x, const void *y, size_t len)
+{
+	return memcmp(x, y, len) == 0;
+}
+
+/**
+ * Same as memeq(), but with a constant runtime, safe for cryptographic use.
+ */
+bool memeq_const(const void *x, const void *y, size_t len);
+
+/**
+ * Calling memcpy() with NULL pointers, even with n == 0, results in undefined
+ * behavior according to the C standard.  This version is guaranteed to not
+ * access the pointers if n is 0.
+ */
+static inline void *memcpy_noop(void *dst, const void *src, size_t n)
+{
+	return n ? memcpy(dst, src, n) : dst;
+}
+#ifdef memcpy
+# undef memcpy
+#endif
+#define memcpy(d,s,n) memcpy_noop(d,s,n)
+
+/**
+ * Calling memmove() with NULL pointers, even with n == 0, results in undefined
+ * behavior according to the C standard.  This version is guaranteed to not
+ * access the pointers if n is 0.
+ */
+static inline void *memmove_noop(void *dst, const void *src, size_t n)
+{
+	return n ? memmove(dst, src, n) : dst;
+}
+#ifdef memmove
+# undef memmove
+#endif
+#define memmove(d,s,n) memmove_noop(d,s,n)
+
+/**
+ * Calling memset() with a NULL pointer, even with n == 0, results in undefined
+ * behavior according to the C standard.  This version is guaranteed to not
+ * access the pointer if n is 0.
+ */
+static inline void *memset_noop(void *s, int c, size_t n)
+{
+	return n ? memset(s, c, n) : s;
+}
+#ifdef memset
+# undef memset
+#endif
+#define memset(s,c,n) memset_noop(s,c,n)
+
+/**
+ * Same as memcpy, but XORs src into dst instead of copy
+ */
+void memxor(u_int8_t dest[], u_int8_t src[], size_t n);
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, non-inlining variant.
+ */
+void memwipe_noinline(void *ptr, size_t n);
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, inlining variant.
+ */
+static inline void memwipe_inline(void *ptr, size_t n)
+{
+	volatile char *c = (volatile char*)ptr;
+	size_t m, i;
+
+	/* byte wise until long aligned */
+	for (i = 0; (uintptr_t)&c[i] % sizeof(long) && i < n; i++)
+	{
+		c[i] = 0;
+	}
+	/* word wise */
+	if (n >= sizeof(long))
+	{
+		for (m = n - sizeof(long); i <= m; i += sizeof(long))
+		{
+			*(volatile long*)&c[i] = 0;
+		}
+	}
+	/* byte wise of the rest */
+	for (; i < n; i++)
+	{
+		c[i] = 0;
+	}
+}
+
+/**
+ * Safely overwrite n bytes of memory at ptr with zero, auto-inlining variant.
+ */
+static inline void memwipe(void *ptr, size_t n)
+{
+	if (!ptr)
+	{
+		return;
+	}
+	if (__builtin_constant_p(n))
+	{
+		memwipe_inline(ptr, n);
+	}
+	else
+	{
+		memwipe_noinline(ptr, n);
+	}
+}
+
+/**
+ * A variant of strstr with the characteristics of memchr, where haystack is not
+ * a null-terminated string but simply a memory area of length n.
+ */
+void *memstr(const void *haystack, const char *needle, size_t n);
+
+/**
+ * Replacement for memrchr(3) if it is not provided by the C library.
+ *
+ * @param s		start of the memory area to search
+ * @param c		character to search
+ * @param n		length of memory area to search
+ * @return		pointer to the found character or NULL
+ */
+void *utils_memrchr(const void *s, int c, size_t n);
+
+#ifndef HAVE_MEMRCHR
+#define memrchr(s,c,n) utils_memrchr(s,c,n)
+#endif
+
+#ifndef HAVE_FMEMOPEN
+# ifdef HAVE_FUNOPEN
+#  define HAVE_FMEMOPEN
+#  define HAVE_FMEMOPEN_FALLBACK
+#  include <stdio.h>
+/**
+ * fmemopen(3) fallback using BSD funopen.
+ *
+ * We could also provide one using fopencookie(), but should we have it we
+ * most likely have fmemopen().
+ *
+ * fseek() is currently not supported.
+ */
+FILE *fmemopen(void *buf, size_t size, const char *mode);
+# endif /* FUNOPEN */
+#endif /* FMEMOPEN */
+
+/**
+ * printf hook for memory areas.
+ *
+ * Arguments are:
+ *	u_char *ptr, u_int len
+ */
+int mem_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+					const void *const *args);
+
+#endif /** MEMORY_H_ @} */
diff --git a/src/libstrongswan/utils/utils/object.h b/src/libstrongswan/utils/utils/object.h
new file mode 100644
index 0000000..301fb66
--- /dev/null
+++ b/src/libstrongswan/utils/utils/object.h
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup object_i object
+ * @{ @ingroup utils_i
+ */
+
+#ifndef OBJECT_H_
+#define OBJECT_H_
+
+/**
+ * Call destructor of an object, if object != NULL
+ */
+#define DESTROY_IF(obj) if (obj) (obj)->destroy(obj)
+
+/**
+ * Call offset destructor of an object, if object != NULL
+ */
+#define DESTROY_OFFSET_IF(obj, offset) if (obj) obj->destroy_offset(obj, offset);
+
+/**
+ * Call function destructor of an object, if object != NULL
+ */
+#define DESTROY_FUNCTION_IF(obj, fn) if (obj) obj->destroy_function(obj, fn);
+
+/**
+ * Object allocation/initialization macro, using designated initializer.
+ */
+#define INIT(this, ...) { (this) = malloc(sizeof(*(this))); \
+						   *(this) = (typeof(*(this))){ __VA_ARGS__ }; }
+
+/**
+ * Aligning version of INIT().
+ *
+ * The returned pointer must be freed using free_align(), not free().
+ *
+ * @param this		object to allocate/initialize
+ * @param align		alignment for allocation, in bytes
+ * @param ...		initializer
+ */
+#define INIT_ALIGN(this, align, ...) { \
+						(this) = malloc_align(sizeof(*(this)), align); \
+						*(this) = (typeof(*(this))){ __VA_ARGS__ }; }
+
+/**
+ * Object allocation/initialization macro, with extra allocated bytes at tail.
+ *
+ * The extra space gets zero-initialized.
+ *
+ * @param this		pointer to object to allocate memory for
+ * @param extra		number of bytes to allocate at end of this
+ * @param ...		initializer
+ */
+#define INIT_EXTRA(this, extra, ...) { \
+						typeof(extra) _extra = (extra); \
+						(this) = malloc(sizeof(*(this)) + _extra); \
+						*(this) = (typeof(*(this))){ __VA_ARGS__ }; \
+						memset((this) + 1, 0, _extra); }
+
+/**
+ * Aligning version of INIT_EXTRA().
+ *
+ * The returned pointer must be freed using free_align(), not free().
+ *
+ * @param this		object to allocate/initialize
+ * @param extra		number of bytes to allocate at end of this
+ * @param align		alignment for allocation, in bytes
+ * @param ...		initializer
+ */
+#define INIT_EXTRA_ALIGN(this, extra, align, ...) { \
+						typeof(extra) _extra = (extra); \
+						(this) = malloc_align(sizeof(*(this)) + _extra, align); \
+						*(this) = (typeof(*(this))){ __VA_ARGS__ }; \
+						memset((this) + 1, 0, _extra); }
+
+/**
+ * Method declaration/definition macro, providing private and public interface.
+ *
+ * Defines a method name with this as first parameter and a return value ret,
+ * and an alias for this method with a _ prefix, having the this argument
+ * safely casted to the public interface iface.
+ * _name is provided a function pointer, but will get optimized out by GCC.
+ */
+#define METHOD(iface, name, ret, this, ...) \
+	static ret name(union {iface *_public; this;} \
+	__attribute__((transparent_union)), ##__VA_ARGS__); \
+	static typeof(name) *_##name = (typeof(name)*)name; \
+	static ret name(this, ##__VA_ARGS__)
+
+/**
+ * Same as METHOD(), but is defined for two public interfaces.
+ */
+#define METHOD2(iface1, iface2, name, ret, this, ...) \
+	static ret name(union {iface1 *_public1; iface2 *_public2; this;} \
+	__attribute__((transparent_union)), ##__VA_ARGS__); \
+	static typeof(name) *_##name = (typeof(name)*)name; \
+	static ret name(this, ##__VA_ARGS__)
+
+/**
+ * Callback declaration/definition macro, allowing casted first parameter.
+ *
+ * This is very similar to METHOD, but instead of casting the first parameter
+ * to a public interface, it uses a void*. This allows type safe definition
+ * of a callback function, while using the real type for the first parameter.
+ */
+#define CALLBACK(name, ret, param1, ...) \
+	static ret _cb_##name(union {void *_generic; param1;} \
+	__attribute__((transparent_union)), ##__VA_ARGS__); \
+	static typeof(_cb_##name) *name = (typeof(_cb_##name)*)_cb_##name; \
+	static ret _cb_##name(param1, ##__VA_ARGS__)
+
+#endif /** OBJECT_H_ @} */
diff --git a/src/libstrongswan/utils/utils/path.c b/src/libstrongswan/utils/utils/path.c
new file mode 100644
index 0000000..3abbe77
--- /dev/null
+++ b/src/libstrongswan/utils/utils/path.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#define _GNU_SOURCE /* for memrchr */
+#include <utils/utils.h>
+#include <utils/debug.h>
+#include <utils/chunk.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+/**
+ * Described in header.
+ */
+char* path_dirname(const char *path)
+{
+	char *pos;
+
+	pos = path ? strrchr(path, DIRECTORY_SEPARATOR[0]) : NULL;
+
+	if (pos && !pos[1])
+	{	/* if path ends with slashes we have to look beyond them */
+		while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
+		{	/* skip trailing slashes */
+			pos--;
+		}
+		pos = memrchr(path, DIRECTORY_SEPARATOR[0], pos - path + 1);
+	}
+	if (!pos)
+	{
+#ifdef WIN32
+		if (path && strlen(path))
+		{
+			if ((isalpha(path[0]) && path[1] == ':'))
+			{	/* if just a drive letter given, return that as dirname */
+				return chunk_clone(chunk_from_chars(path[0], ':', 0)).ptr;
+			}
+		}
+#endif
+		return strdup(".");
+	}
+	while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
+	{	/* skip superfluous slashes */
+		pos--;
+	}
+	return strndup(path, pos - path + 1);
+}
+
+/**
+ * Described in header.
+ */
+char* path_basename(const char *path)
+{
+	char *pos, *trail = NULL;
+
+	if (!path || !*path)
+	{
+		return strdup(".");
+	}
+	pos = strrchr(path, DIRECTORY_SEPARATOR[0]);
+	if (pos && !pos[1])
+	{	/* if path ends with slashes we have to look beyond them */
+		while (pos > path && *pos == DIRECTORY_SEPARATOR[0])
+		{	/* skip trailing slashes */
+			pos--;
+		}
+		if (pos == path && *pos == DIRECTORY_SEPARATOR[0])
+		{	/* contains only slashes */
+			return strdup(DIRECTORY_SEPARATOR);
+		}
+		trail = pos + 1;
+		pos = memrchr(path, DIRECTORY_SEPARATOR[0], trail - path);
+	}
+	pos = pos ? pos + 1 : (char*)path;
+	return trail ? strndup(pos, trail - pos) : strdup(pos);
+}
+
+/**
+ * Described in header.
+ */
+bool path_absolute(const char *path)
+{
+	if (!path)
+	{
+		return FALSE;
+	}
+#ifdef WIN32
+	if (strpfx(path, "\\\\"))
+	{	/* UNC */
+		return TRUE;
+	}
+	if (strlen(path) && isalpha(path[0]) && path[1] == ':')
+	{	/* drive letter */
+		return TRUE;
+	}
+#else /* !WIN32 */
+	if (path[0] == DIRECTORY_SEPARATOR[0])
+	{
+		return TRUE;
+	}
+#endif
+	return FALSE;
+}
+
+/**
+ * Described in header.
+ */
+bool mkdir_p(const char *path, mode_t mode)
+{
+	int len;
+	char *pos, full[PATH_MAX];
+	pos = full;
+	if (!path || *path == '\0')
+	{
+		return TRUE;
+	}
+	len = snprintf(full, sizeof(full)-1, "%s", path);
+	if (len < 0 || len >= sizeof(full)-1)
+	{
+		DBG1(DBG_LIB, "path string %s too long", path);
+		return FALSE;
+	}
+	/* ensure that the path ends with a '/' */
+	if (full[len-1] != '/')
+	{
+		full[len++] = '/';
+		full[len] = '\0';
+	}
+	/* skip '/' at the beginning */
+	while (*pos == '/')
+	{
+		pos++;
+	}
+	while ((pos = strchr(pos, '/')))
+	{
+		*pos = '\0';
+		if (access(full, F_OK) < 0)
+		{
+#ifdef WIN32
+			if (_mkdir(full) < 0)
+#else
+			if (mkdir(full, mode) < 0)
+#endif
+			{
+				DBG1(DBG_LIB, "failed to create directory %s", full);
+				return FALSE;
+			}
+		}
+		*pos = '/';
+		pos++;
+	}
+	return TRUE;
+}
diff --git a/src/libstrongswan/utils/utils/path.h b/src/libstrongswan/utils/utils/path.h
new file mode 100644
index 0000000..838ce73
--- /dev/null
+++ b/src/libstrongswan/utils/utils/path.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup path_i path
+ * @{ @ingroup utils_i
+ */
+
+#ifndef PATH_H_
+#define PATH_H_
+
+/**
+ * Directory separator character in paths on this platform
+ */
+#ifdef WIN32
+# define DIRECTORY_SEPARATOR "\\"
+#else
+# define DIRECTORY_SEPARATOR "/"
+#endif
+
+/**
+ * Like dirname(3) returns the directory part of the given null-terminated
+ * pathname, up to but not including the final '/' (or '.' if no '/' is found).
+ * Trailing '/' are not counted as part of the pathname.
+ *
+ * The difference is that it does this in a thread-safe manner (i.e. it does not
+ * use static buffers) and does not modify the original path.
+ *
+ * @param path		original pathname
+ * @return			allocated directory component
+ */
+char *path_dirname(const char *path);
+
+/**
+ * Like basename(3) returns the filename part of the given null-terminated path,
+ * i.e. the part following the final '/' (or '.' if path is empty or NULL).
+ * Trailing '/' are not counted as part of the pathname.
+ *
+ * The difference is that it does this in a thread-safe manner (i.e. it does not
+ * use static buffers) and does not modify the original path.
+ *
+ * @param path		original pathname
+ * @return			allocated filename component
+ */
+char *path_basename(const char *path);
+
+/**
+ * Check if a given path is absolute.
+ *
+ * @param path		path to check
+ * @return			TRUE if absolute, FALSE if relative
+ */
+bool path_absolute(const char *path);
+
+/**
+ * Creates a directory and all required parent directories.
+ *
+ * @param path		path to the new directory
+ * @param mode		permissions of the new directory/directories
+ * @return			TRUE on success
+ */
+bool mkdir_p(const char *path, mode_t mode);
+
+#endif /** PATH_H_ @} */
diff --git a/src/libstrongswan/crypto/iv/iv_gen_seq.h b/src/libstrongswan/utils/utils/status.c
similarity index 57%
copy from src/libstrongswan/crypto/iv/iv_gen_seq.h
copy to src/libstrongswan/utils/utils/status.c
index 329dcca..4a97d84 100644
--- a/src/libstrongswan/crypto/iv/iv_gen_seq.h
+++ b/src/libstrongswan/utils/utils/status.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -13,20 +14,35 @@
  * for more details.
  */
 
-/**
- * @{ @ingroup iv
- */
-
-#ifndef IV_GEN_SEQ_H_
-#define IV_GEN_SEQ_H_
+#include <utils/utils.h>
 
-#include <crypto/iv/iv_gen.h>
+ENUM(status_names, SUCCESS, NEED_MORE,
+	"SUCCESS",
+	"FAILED",
+	"OUT_OF_RES",
+	"ALREADY_DONE",
+	"NOT_SUPPORTED",
+	"INVALID_ARG",
+	"NOT_FOUND",
+	"PARSE_ERROR",
+	"VERIFY_ERROR",
+	"INVALID_STATE",
+	"DESTROY_ME",
+	"NEED_MORE",
+);
 
 /**
- * Create an IV generator that generates sequential IVs (counter).
- *
- * @return		IV generator
+ * returns FAILED
  */
-iv_gen_t *iv_gen_seq_create();
+status_t return_failed()
+{
+	return FAILED;
+}
 
-#endif /** IV_GEN_SEQ_H_ @}*/
+/**
+ * returns SUCCESS
+ */
+status_t return_success()
+{
+	return SUCCESS;
+}
diff --git a/src/libstrongswan/utils/utils/status.h b/src/libstrongswan/utils/utils/status.h
new file mode 100644
index 0000000..c96eebd
--- /dev/null
+++ b/src/libstrongswan/utils/utils/status.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup status_i status
+ * @{ @ingroup utils_i
+ */
+
+#ifndef STATUS_H_
+#define STATUS_H_
+
+typedef enum status_t status_t;
+
+/**
+ * Return values of function calls.
+ */
+enum status_t {
+	/** Call succeeded */
+	SUCCESS,
+	/** Call failed */
+	FAILED,
+	/** Out of resources */
+	OUT_OF_RES,
+	/** The suggested operation is already done */
+	ALREADY_DONE,
+	/** Not supported */
+	NOT_SUPPORTED,
+	/** One of the arguments is invalid */
+	INVALID_ARG,
+	/** Something could not be found */
+	NOT_FOUND,
+	/** Error while parsing */
+	PARSE_ERROR,
+	/** Error while verifying */
+	VERIFY_ERROR,
+	/** Object in invalid state */
+	INVALID_STATE,
+	/** Destroy object which called method belongs to */
+	DESTROY_ME,
+	/** Another call to the method is required */
+	NEED_MORE,
+};
+
+/**
+ * enum_names for type status_t.
+ */
+extern enum_name_t *status_names;
+
+/**
+ * returns FAILED
+ */
+status_t return_failed();
+
+/**
+ * returns SUCCESS
+ */
+status_t return_success();
+
+#endif /** STATUS_H_ @} */
diff --git a/src/libstrongswan/utils/utils/strerror.h b/src/libstrongswan/utils/utils/strerror.h
index e1b0638..f59649c 100644
--- a/src/libstrongswan/utils/utils/strerror.h
+++ b/src/libstrongswan/utils/utils/strerror.h
@@ -14,7 +14,8 @@
  */
 
 /**
- * @{ @ingroup utils
+ * @defgroup strerror_i strerror
+ * @{ @ingroup utils_i
  */
 
 #ifndef STRERROR_H_
diff --git a/src/libstrongswan/utils/utils/string.c b/src/libstrongswan/utils/utils/string.c
new file mode 100644
index 0000000..14087e7
--- /dev/null
+++ b/src/libstrongswan/utils/utils/string.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+
+/**
+ * Described in header.
+ */
+char* translate(char *str, const char *from, const char *to)
+{
+	char *pos = str;
+	if (strlen(from) != strlen(to))
+	{
+		return str;
+	}
+	while (pos && *pos)
+	{
+		char *match;
+		if ((match = strchr(from, *pos)) != NULL)
+		{
+			*pos = to[match - from];
+		}
+		pos++;
+	}
+	return str;
+}
+
+/**
+ * Described in header.
+ */
+char* strreplace(const char *str, const char *search, const char *replace)
+{
+	size_t len, slen, rlen, count = 0;
+	char *res, *pos, *found, *dst;
+
+	if (!str || !*str || !search || !*search || !replace)
+	{
+		return (char*)str;
+	}
+	slen = strlen(search);
+	rlen = strlen(replace);
+	if (slen != rlen)
+	{
+		for (pos = (char*)str; (pos = strstr(pos, search)); pos += slen)
+		{
+			found = pos;
+			count++;
+		}
+		if (!count)
+		{
+			return (char*)str;
+		}
+		len = (found - str) + strlen(found) + count * (rlen - slen);
+	}
+	else
+	{
+		len = strlen(str);
+	}
+	found = strstr(str, search);
+	if (!found)
+	{
+		return (char*)str;
+	}
+	dst = res = malloc(len + 1);
+	pos = (char*)str;
+	do
+	{
+		len = found - pos;
+		memcpy(dst, pos, len);
+		dst += len;
+		memcpy(dst, replace, rlen);
+		dst += rlen;
+		pos = found + slen;
+	}
+	while ((found = strstr(pos, search)));
+	strcpy(dst, pos);
+	return res;
+}
diff --git a/src/libstrongswan/utils/utils/string.h b/src/libstrongswan/utils/utils/string.h
new file mode 100644
index 0000000..60eaaae
--- /dev/null
+++ b/src/libstrongswan/utils/utils/string.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup string_i string
+ * @{ @ingroup utils_i
+ */
+
+#ifndef STRING_H_
+#define STRING_H_
+
+/**
+ * Helper function that compares two strings for equality
+ */
+static inline bool streq(const char *x, const char *y)
+{
+	return strcmp(x, y) == 0;
+}
+
+/**
+ * Helper function that compares two strings for equality, length limited
+ */
+static inline bool strneq(const char *x, const char *y, size_t len)
+{
+	return strncmp(x, y, len) == 0;
+}
+
+/**
+ * Helper function that checks if a string starts with a given prefix
+ */
+static inline bool strpfx(const char *x, const char *prefix)
+{
+	return strneq(x, prefix, strlen(prefix));
+}
+
+/**
+ * Helper function that compares two strings for equality ignoring case
+ */
+static inline bool strcaseeq(const char *x, const char *y)
+{
+	return strcasecmp(x, y) == 0;
+}
+
+/**
+ * Helper function that compares two strings for equality ignoring case, length limited
+ */
+static inline bool strncaseeq(const char *x, const char *y, size_t len)
+{
+	return strncasecmp(x, y, len) == 0;
+}
+
+/**
+ * Helper function that checks if a string starts with a given prefix
+ */
+static inline bool strcasepfx(const char *x, const char *prefix)
+{
+	return strncaseeq(x, prefix, strlen(prefix));
+}
+
+/**
+ * NULL-safe strdup variant
+ */
+static inline char *strdupnull(const char *s)
+{
+	return s ? strdup(s) : NULL;
+}
+
+/**
+ * Translates the characters in the given string, searching for characters
+ * in 'from' and mapping them to characters in 'to'.
+ * The two characters sets 'from' and 'to' must contain the same number of
+ * characters.
+ */
+char *translate(char *str, const char *from, const char *to);
+
+/**
+ * Replaces all occurrences of search in the given string with replace.
+ *
+ * Allocates memory only if anything is replaced in the string.  The original
+ * string is also returned if any of the arguments are invalid (e.g. if search
+ * is empty or any of them are NULL).
+ *
+ * @param str		original string
+ * @param search	string to search for and replace
+ * @param replace	string to replace found occurrences with
+ * @return			allocated string, if anything got replaced, str otherwise
+ */
+char *strreplace(const char *str, const char *search, const char *replace);
+
+#endif /** STRING_H_ @} */
diff --git a/src/libstrongswan/utils/utils/time.c b/src/libstrongswan/utils/utils/time.c
new file mode 100644
index 0000000..c67ae93
--- /dev/null
+++ b/src/libstrongswan/utils/utils/time.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#ifdef WIN32
+/* for GetTickCount64, Windows 7 */
+# define _WIN32_WINNT 0x0601
+#endif
+
+#define _GNU_SOURCE
+#include <utils/utils.h>
+
+#include <inttypes.h>
+#include <time.h>
+
+/**
+ * Return monotonic time
+ */
+time_t time_monotonic(timeval_t *tv)
+{
+#ifdef WIN32
+	ULONGLONG ms;
+	time_t s;
+
+	ms = GetTickCount64();
+	s = ms / 1000;
+	if (tv)
+	{
+		tv->tv_sec = s;
+		tv->tv_usec = (ms - (s * 1000)) * 1000;
+	}
+	return s;
+#else /* !WIN32 */
+#if defined(HAVE_CLOCK_GETTIME) && \
+	(defined(HAVE_CONDATTR_CLOCK_MONOTONIC) || \
+	 defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC))
+	/* as we use time_monotonic() for condvar operations, we use the
+	 * monotonic time source only if it is also supported by pthread. */
+	timespec_t ts;
+
+	if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+	{
+		if (tv)
+		{
+			tv->tv_sec = ts.tv_sec;
+			tv->tv_usec = ts.tv_nsec / 1000;
+		}
+		return ts.tv_sec;
+	}
+#endif /* HAVE_CLOCK_GETTIME && (...) */
+	/* Fallback to non-monotonic timestamps:
+	 * On MAC OS X, creating monotonic timestamps is rather difficult. We
+	 * could use mach_absolute_time() and catch sleep/wakeup notifications.
+	 * We stick to the simpler (non-monotonic) gettimeofday() for now.
+	 * But keep in mind: we need the same time source here as in condvar! */
+	if (!tv)
+	{
+		return time(NULL);
+	}
+	if (gettimeofday(tv, NULL) != 0)
+	{	/* should actually never fail if passed pointers are valid */
+		return -1;
+	}
+	return tv->tv_sec;
+#endif /* !WIN32 */
+}
+
+/**
+ * Described in header.
+ */
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+					 const void *const *args)
+{
+	static const char* months[] = {
+		"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+	};
+	time_t *time = *((time_t**)(args[0]));
+	bool utc = *((int*)(args[1]));
+	struct tm t, *ret = NULL;
+
+	if (*time != UNDEFINED_TIME)
+	{
+		if (utc)
+		{
+			ret = gmtime_r(time, &t);
+		}
+		else
+		{
+			ret = localtime_r(time, &t);
+		}
+	}
+	if (ret == NULL)
+	{
+		return print_in_hook(data, "--- -- --:--:--%s----",
+							 utc ? " UTC " : " ");
+	}
+	return print_in_hook(data, "%s %02d %02d:%02d:%02d%s%04d",
+						 months[t.tm_mon], t.tm_mday, t.tm_hour, t.tm_min,
+						 t.tm_sec, utc ? " UTC " : " ", t.tm_year + 1900);
+}
+
+/**
+ * Described in header.
+ */
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+						   const void *const *args)
+{
+	char* unit = "second";
+	time_t *arg1 = *((time_t**)(args[0]));
+	time_t *arg2 = *((time_t**)(args[1]));
+	u_int64_t delta = llabs(*arg1 - *arg2);
+
+	if (delta > 2 * 60 * 60 * 24)
+	{
+		delta /= 60 * 60 * 24;
+		unit = "day";
+	}
+	else if (delta > 2 * 60 * 60)
+	{
+		delta /= 60 * 60;
+		unit = "hour";
+	}
+	else if (delta > 2 * 60)
+	{
+		delta /= 60;
+		unit = "minute";
+	}
+	return print_in_hook(data, "%" PRIu64 " %s%s", delta, unit,
+						 (delta == 1) ? "" : "s");
+}
diff --git a/src/libstrongswan/utils/utils/time.h b/src/libstrongswan/utils/utils/time.h
new file mode 100644
index 0000000..2626d9a
--- /dev/null
+++ b/src/libstrongswan/utils/utils/time.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup time_i time
+ * @{ @ingroup utils_i
+ */
+
+#ifndef TIME_H_
+#define TIME_H_
+
+/**
+ * time_t not defined
+ */
+#define UNDEFINED_TIME 0
+
+/**
+ * Maximum time since epoch causing wrap-around on Jan 19 03:14:07 UTC 2038
+ */
+#define TIME_32_BIT_SIGNED_MAX	0x7fffffff
+
+/**
+ * Handle struct timeval like an own type.
+ */
+typedef struct timeval timeval_t;
+
+/**
+ * Handle struct timespec like an own type.
+ */
+typedef struct timespec timespec_t;
+
+/**
+ * Get a timestamp from a monotonic time source.
+ *
+ * While the time()/gettimeofday() functions are affected by leap seconds
+ * and system time changes, this function returns ever increasing monotonic
+ * time stamps.
+ *
+ * @param tv		timeval struct receiving monotonic timestamps, or NULL
+ * @return			monotonic timestamp in seconds
+ */
+time_t time_monotonic(timeval_t *tv);
+
+/**
+ * Add the given number of milliseconds to the given timeval struct
+ *
+ * @param tv		timeval struct to modify
+ * @param ms		number of milliseconds
+ */
+static inline void timeval_add_ms(timeval_t *tv, u_int ms)
+{
+	tv->tv_usec += ms * 1000;
+	while (tv->tv_usec >= 1000000 /* 1s */)
+	{
+		tv->tv_usec -= 1000000;
+		tv->tv_sec++;
+	}
+}
+
+/**
+ * printf hook for time_t.
+ *
+ * Arguments are:
+ *	time_t* time, bool utc
+ */
+int time_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+					 const void *const *args);
+
+/**
+ * printf hook for time_t deltas.
+ *
+ * Arguments are:
+ *	time_t* begin, time_t* end
+ */
+int time_delta_printf_hook(printf_hook_data_t *data, printf_hook_spec_t *spec,
+						   const void *const *args);
+
+#endif /** TIME_H_ @} */
diff --git a/src/libstrongswan/utils/utils/tty.c b/src/libstrongswan/utils/utils/tty.c
new file mode 100644
index 0000000..7cce71d
--- /dev/null
+++ b/src/libstrongswan/utils/utils/tty.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2005-2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <utils/utils.h>
+
+#include <unistd.h>
+
+ENUM(tty_color_names, TTY_RESET, TTY_BG_DEF,
+	"\e[0m",
+	"\e[1m",
+	"\e[4m",
+	"\e[5m",
+	"\e[30m",
+	"\e[31m",
+	"\e[32m",
+	"\e[33m",
+	"\e[34m",
+	"\e[35m",
+	"\e[36m",
+	"\e[37m",
+	"\e[39m",
+	"\e[40m",
+	"\e[41m",
+	"\e[42m",
+	"\e[43m",
+	"\e[44m",
+	"\e[45m",
+	"\e[46m",
+	"\e[47m",
+	"\e[49m",
+);
+
+/**
+ * Get the escape string for a given TTY color, empty string on non-tty FILE
+ */
+char* tty_escape_get(int fd, tty_escape_t escape)
+{
+	if (!isatty(fd))
+	{
+		return "";
+	}
+	switch (escape)
+	{
+		case TTY_RESET:
+		case TTY_BOLD:
+		case TTY_UNDERLINE:
+		case TTY_BLINKING:
+#ifdef WIN32
+			return "";
+#endif
+		case TTY_FG_BLACK:
+		case TTY_FG_RED:
+		case TTY_FG_GREEN:
+		case TTY_FG_YELLOW:
+		case TTY_FG_BLUE:
+		case TTY_FG_MAGENTA:
+		case TTY_FG_CYAN:
+		case TTY_FG_WHITE:
+		case TTY_FG_DEF:
+		case TTY_BG_BLACK:
+		case TTY_BG_RED:
+		case TTY_BG_GREEN:
+		case TTY_BG_YELLOW:
+		case TTY_BG_BLUE:
+		case TTY_BG_MAGENTA:
+		case TTY_BG_CYAN:
+		case TTY_BG_WHITE:
+		case TTY_BG_DEF:
+			return enum_to_name(tty_color_names, escape);
+		/* warn if a escape code is missing */
+	}
+	return "";
+}
diff --git a/src/libstrongswan/utils/utils/tty.h b/src/libstrongswan/utils/utils/tty.h
new file mode 100644
index 0000000..6cd285a
--- /dev/null
+++ b/src/libstrongswan/utils/utils/tty.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup tty_i tty
+ * @{ @ingroup utils_i
+ */
+
+#ifndef TTY_H_
+#define TTY_H_
+
+typedef enum tty_escape_t tty_escape_t;
+
+/**
+ * Excape codes for tty colors
+ */
+enum tty_escape_t {
+	/** text properties */
+	TTY_RESET,
+	TTY_BOLD,
+	TTY_UNDERLINE,
+	TTY_BLINKING,
+
+	/** foreground colors */
+	TTY_FG_BLACK,
+	TTY_FG_RED,
+	TTY_FG_GREEN,
+	TTY_FG_YELLOW,
+	TTY_FG_BLUE,
+	TTY_FG_MAGENTA,
+	TTY_FG_CYAN,
+	TTY_FG_WHITE,
+	TTY_FG_DEF,
+
+	/** background colors */
+	TTY_BG_BLACK,
+	TTY_BG_RED,
+	TTY_BG_GREEN,
+	TTY_BG_YELLOW,
+	TTY_BG_BLUE,
+	TTY_BG_MAGENTA,
+	TTY_BG_CYAN,
+	TTY_BG_WHITE,
+	TTY_BG_DEF,
+};
+
+/**
+ * Get the escape string for a given TTY color, empty string on non-tty fd
+ */
+char* tty_escape_get(int fd, tty_escape_t escape);
+
+#endif /** TTY_H_ @} */
diff --git a/src/libstrongswan/utils/utils/types.h b/src/libstrongswan/utils/utils/types.h
new file mode 100644
index 0000000..056c2e0
--- /dev/null
+++ b/src/libstrongswan/utils/utils/types.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup types_i types
+ * @{ @ingroup utils_i
+ */
+
+#ifndef TYPES_H_
+#define TYPES_H_
+
+/**
+ * General purpose boolean type.
+ */
+#ifdef HAVE_STDBOOL_H
+# include <stdbool.h>
+#else
+# ifndef HAVE__BOOL
+#  define _Bool signed char
+# endif /* HAVE__BOOL */
+# define bool _Bool
+# define false 0
+# define true 1
+# define __bool_true_false_are_defined 1
+#endif /* HAVE_STDBOOL_H */
+#ifndef FALSE
+# define FALSE false
+#endif /* FALSE */
+#ifndef TRUE
+# define TRUE  true
+#endif /* TRUE */
+
+/**
+ * define some missing fixed width int types on OpenSolaris.
+ * TODO: since the uintXX_t types are defined by the C99 standard we should
+ * probably use those anyway
+ */
+#if defined __sun || defined WIN32
+#include <stdint.h>
+typedef uint8_t  u_int8_t;
+typedef uint16_t u_int16_t;
+typedef uint32_t u_int32_t;
+typedef uint64_t u_int64_t;
+#endif
+
+#ifdef HAVE_INT128
+/**
+ * 128 bit wide signed integer, if supported
+ */
+typedef __int128 int128_t;
+/**
+ * 128 bit wide unsigned integer, if supported
+ */
+typedef unsigned __int128 u_int128_t;
+
+# define MAX_INT_TYPE int128_t
+# define MAX_UINT_TYPE u_int128_t
+#else
+# define MAX_INT_TYPE int64_t
+# define MAX_UINT_TYPE u_int64_t
+#endif
+
+/**
+ * deprecated pluto style return value:
+ * error message, NULL for success
+ */
+typedef const char *err_t;
+
+/**
+ * Handle struct sockaddr as a simpler sockaddr_t type.
+ */
+typedef struct sockaddr sockaddr_t;
+
+#endif /** TYPES_H_ @} */
diff --git a/src/libtls/tls_peer.c b/src/libtls/tls_peer.c
index e6be36b..000dda4 100644
--- a/src/libtls/tls_peer.c
+++ b/src/libtls/tls_peer.c
@@ -354,6 +354,13 @@ static status_t process_modp_key_exchange(private_tls_peer_t *this,
 		this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
 		return NEED_MORE;
 	}
+	/* reject (export) DH groups using primes smaller than 1024 bit */
+	if (prime.len < 1024 / 8)
+	{
+		DBG1(DBG_TLS, "short DH prime received (%zu bytes)", prime.len);
+		this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
+		return NEED_MORE;
+	}
 	public = find_public_key(this);
 	if (!public)
 	{
@@ -641,7 +648,7 @@ static status_t process_finished(private_tls_peer_t *this, bio_reader_t *reader)
 		this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
 		return NEED_MORE;
 	}
-	if (!chunk_equals(received, chunk_from_thing(buf)))
+	if (!chunk_equals_const(received, chunk_from_thing(buf)))
 	{
 		DBG1(DBG_TLS, "received server finished invalid");
 		this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
diff --git a/src/libtls/tls_server.c b/src/libtls/tls_server.c
index b1a214f..f9295a1 100644
--- a/src/libtls/tls_server.c
+++ b/src/libtls/tls_server.c
@@ -607,7 +607,7 @@ static status_t process_finished(private_tls_server_t *this,
 		this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
 		return NEED_MORE;
 	}
-	if (!chunk_equals(received, chunk_from_thing(buf)))
+	if (!chunk_equals_const(received, chunk_from_thing(buf)))
 	{
 		DBG1(DBG_TLS, "received client finished invalid");
 		this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
diff --git a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
index faad02b..b239c20 100644
--- a/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
+++ b/src/libtnccs/plugins/tnccs_20/batch/pb_tnc_batch.c
@@ -283,7 +283,7 @@ METHOD(pb_tnc_batch_t, process_header, status_t,
 
 	if (directionality & (*from_server == is_server))
 	{
-		DBG1(DBG_TNC, "wrong Directionality: batch is from a PB %s",
+		DBG1(DBG_TNC, "wrong Directionality: batch is from a PB-TNC %s",
 					   is_server ? "server" : "client");
 		msg = pb_error_msg_create_with_offset(TRUE, PEN_IETF,
 					   PB_ERROR_INVALID_PARAMETER, 1);
diff --git a/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h
index 35b0b7c..3952843 100644
--- a/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h
+++ b/src/libtnccs/plugins/tnccs_20/messages/pb_tnc_msg.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-213 Andreas Steffen
+ * Copyright (C) 2010-2013 Andreas Steffen
  * HSR Hochschule fuer Technik Rapperswil
  *
  * This program is free software; you can redistribute it and/or modify it
diff --git a/src/starter/Android.mk b/src/starter/Android.mk
index c37fc1a..8c5d1a9 100644
--- a/src/starter/Android.mk
+++ b/src/starter/Android.mk
@@ -19,7 +19,7 @@ LOCAL_C_INCLUDES += \
 	$(strongswan_PATH)/src/starter \
 	$(strongswan_PATH)/src/stroke
 
-LOCAL_CFLAGS := $(strongswan_CFLAGS) -DSTART_CHARON \
+LOCAL_CFLAGS := $(strongswan_CFLAGS) \
 	-DIPSEC_SCRIPT='"ipsec"' \
 	-DPLUGINS='"$(strongswan_STARTER_PLUGINS)"'
 
diff --git a/src/starter/Makefile.am b/src/starter/Makefile.am
index f0a2be8..7f5d1ca 100644
--- a/src/starter/Makefile.am
+++ b/src/starter/Makefile.am
@@ -40,10 +40,6 @@ EXTRA_DIST = keywords.txt ipsec.conf Android.mk
 MAINTAINERCLEANFILES = keywords.c
 BUILT_SOURCES = keywords.c parser/parser.h
 
-if USE_CHARON
-  AM_CPPFLAGS += -DSTART_CHARON
-endif
-
 if USE_LOAD_WARNING
   AM_CPPFLAGS += -DLOAD_WARNING
 endif
diff --git a/src/starter/Makefile.in b/src/starter/Makefile.in
index ee68adc..3166cc5 100644
--- a/src/starter/Makefile.in
+++ b/src/starter/Makefile.in
@@ -80,9 +80,8 @@ POST_UNINSTALL = :
 build_triplet = @build@
 host_triplet = @host@
 ipsec_PROGRAMS = starter$(EXEEXT)
- at USE_CHARON_TRUE@am__append_1 = -DSTART_CHARON
- at USE_LOAD_WARNING_TRUE@am__append_2 = -DLOAD_WARNING
- at USE_SCEPCLIENT_TRUE@am__append_3 = -DGENERATE_SELFCERT
+ at USE_LOAD_WARNING_TRUE@am__append_1 = -DLOAD_WARNING
+ at USE_SCEPCLIENT_TRUE@am__append_2 = -DGENERATE_SELFCERT
 subdir = src/starter
 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
 	parser/parser.h parser/parser.c parser/lexer.c \
@@ -493,7 +492,7 @@ AM_CPPFLAGS = -I${linux_headers} -I$(top_srcdir)/src/libstrongswan \
 	-DDEV_RANDOM=\"${random_device}\" \
 	-DDEV_URANDOM=\"${urandom_device}\" \
 	-DPLUGINS=\""${starter_plugins}\"" -DDEBUG $(am__append_1) \
-	$(am__append_2) $(am__append_3)
+	$(am__append_2)
 AM_YFLAGS = -v -d
 starter_LDADD = \
 	$(top_builddir)/src/libstrongswan/libstrongswan.la \
diff --git a/src/starter/confread.c b/src/starter/confread.c
index de9099a..c3a0ac0 100644
--- a/src/starter/confread.c
+++ b/src/starter/confread.c
@@ -50,17 +50,6 @@ static const char firewall_defaults[] = IPSEC_SCRIPT " _updown iptables";
  */
 extern kw_entry_t *in_word_set (char *str, unsigned int len);
 
-static bool daemon_exists(char *daemon, char *path)
-{
-	struct stat st;
-	if (stat(path, &st) != 0)
-	{
-		DBG1(DBG_APP, "Disabling %sstart option, '%s' not found", daemon, path);
-		return FALSE;
-	}
-	return TRUE;
-}
-
 /**
  * Process deprecated keywords
  */
@@ -147,14 +136,6 @@ static void load_setup(starter_config_t *cfg, conf_parser_t *parser)
 	}
 	enumerator->destroy(enumerator);
 	dict->destroy(dict);
-
-	/* verify the executables are actually available */
-#ifdef START_CHARON
-	cfg->setup.charonstart = cfg->setup.charonstart &&
-							 daemon_exists(daemon_name, cmd);
-#else
-	cfg->setup.charonstart = FALSE;
-#endif
 }
 
 /*
@@ -722,12 +703,8 @@ starter_config_t* confread_load(const char *file)
 	INIT(cfg,
 		.setup = {
 			.uniqueids = TRUE,
-
 		}
 	);
-#ifdef START_CHARON
-	cfg->setup.charonstart = TRUE;
-#endif
 
 	/* load config setup section */
 	load_setup(cfg, parser);
diff --git a/src/starter/confread.h b/src/starter/confread.h
index 0eea988..457327f 100644
--- a/src/starter/confread.h
+++ b/src/starter/confread.h
@@ -193,7 +193,6 @@ typedef struct starter_config starter_config_t;
 
 struct starter_config {
 		struct {
-				bool     charonstart;
 				char     *charondebug;
 				bool     uniqueids;
 				bool     cachecrls;
diff --git a/src/starter/starter.c b/src/starter/starter.c
index 74b5b52..a192989 100644
--- a/src/starter/starter.c
+++ b/src/starter/starter.c
@@ -517,6 +517,13 @@ int main (int argc, char **argv)
 		exit(status);
 	}
 
+	if (stat(cmd, &stb) != 0)
+	{
+		DBG1(DBG_APP, "IKE daemon '%s' not found", cmd);
+		cleanup();
+		exit(LSB_RC_FAILURE);
+	}
+
 	DBG1(DBG_APP, "Starting %sSwan "VERSION" IPsec [starter]...",
 		lib->settings->get_bool(lib->settings,
 			"charon.i_dont_care_about_security_and_use_aggressive_mode_psk",
@@ -836,7 +843,7 @@ int main (int argc, char **argv)
 		 */
 		if (_action_ & FLAG_ACTION_START_CHARON)
 		{
-			if (cfg->setup.charonstart && !starter_charon_pid())
+			if (!starter_charon_pid())
 			{
 				DBG2(DBG_APP, "Attempting to start %s...", daemon_name);
 				if (starter_start_charon(cfg, no_fork, attach_gdb))
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 6e1f160..79a92cd 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -31,37 +32,57 @@
 #define IPV4_LEN	 4
 #define IPV6_LEN	16
 
-static char* push_string(stroke_msg_t *msg, char *string)
+static stroke_msg_t *create_stroke_msg(int type)
 {
-	unsigned long string_start = msg->length;
+	stroke_msg_t *msg;
 
-	if (string == NULL)
+	INIT(msg,
+		.type = type,
+		.length = offsetof(stroke_msg_t, buffer),
+	);
+	return msg;
+}
+
+#define push_string(msg, field, str) \
+	push_string_impl(msg, offsetof(stroke_msg_t, field), str)
+#define push_string_end(msg, offset, field, str) \
+	push_string_impl(msg, offset + offsetof(stroke_end_t, field), str)
+
+static void push_string_impl(stroke_msg_t **msg, size_t offset, char *string)
+{
+	size_t cur_len = (*msg)->length, str_len;
+
+	if (!string)
 	{
-		return NULL;
+		return;
 	}
-	else if ((size_t)msg->length + strlen(string) >= sizeof(stroke_msg_t))
+	str_len = strlen(string) + 1;
+	if (cur_len + str_len >= UINT16_MAX)
 	{
-		/* set invalid length to fail during message send */
-		msg->length = ~0;
-		return NULL;
+		(*msg)->length = UINT16_MAX;
+		return;
 	}
-	else
+	while (cur_len + str_len > sizeof(stroke_msg_t) + (*msg)->buflen)
 	{
-		msg->length += strlen(string) + 1;
-		strcpy((char*)msg + string_start, string);
-		return (char*)string_start;
+		*msg = realloc(*msg, sizeof(stroke_msg_t) + (*msg)->buflen +
+					   STROKE_BUF_LEN_INC);
+		(*msg)->buflen += STROKE_BUF_LEN_INC;
 	}
+	(*msg)->length += str_len;
+	strcpy((char*)*msg + cur_len, string);
+	*(char**)((char*)*msg + offset) = (char*)cur_len;
 }
 
-static int send_stroke_msg (stroke_msg_t *msg)
+static int send_stroke_msg(stroke_msg_t *msg)
 {
 	stream_t *stream;
 	char *uri, buffer[64];
 	int count;
 
-	if (msg->length > sizeof(stroke_msg_t))
+	if (msg->length == UINT16_MAX)
 	{
-		DBG1(DBG_APP, "stroke message exceeds buffer size");
+		DBG1(DBG_APP, "stroke message exceeds maximum buffer size");
+		free(msg);
 		return -1;
 	}
 
@@ -74,6 +95,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
 	if (!stream)
 	{
 		DBG1(DBG_APP, "failed to connect to stroke socket '%s'", uri);
+		free(msg);
 		return -1;
 	}
 
@@ -81,6 +103,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
 	{
 		DBG1(DBG_APP, "sending stroke message failed");
 		stream->destroy(stream);
+		free(msg);
 		return -1;
 	}
 	while ((count = stream->read(stream, buffer, sizeof(buffer)-1, TRUE)) > 0)
@@ -93,6 +116,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
 		DBG1(DBG_APP, "reading stroke response failed");
 	}
 	stream->destroy(stream);
+	free(msg);
 	return 0;
 }
 
@@ -109,33 +133,38 @@ static char* connection_name(starter_conn_t *conn)
 	return conn->name;
 }
 
-static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, starter_end_t *conn_end)
+static void add_end(stroke_msg_t **msg, size_t offset, starter_end_t *conn_end)
 {
-	msg_end->auth = push_string(msg, conn_end->auth);
-	msg_end->auth2 = push_string(msg, conn_end->auth2);
-	msg_end->id = push_string(msg, conn_end->id);
-	msg_end->id2 = push_string(msg, conn_end->id2);
-	msg_end->rsakey = push_string(msg, conn_end->rsakey);
-	msg_end->cert = push_string(msg, conn_end->cert);
-	msg_end->cert2 = push_string(msg, conn_end->cert2);
-	msg_end->cert_policy = push_string(msg, conn_end->cert_policy);
-	msg_end->ca = push_string(msg, conn_end->ca);
-	msg_end->ca2 = push_string(msg, conn_end->ca2);
-	msg_end->groups = push_string(msg, conn_end->groups);
-	msg_end->groups2 = push_string(msg, conn_end->groups2);
-	msg_end->updown = push_string(msg, conn_end->updown);
+	stroke_end_t *msg_end;
+
+	push_string_end(msg, offset, auth, conn_end->auth);
+	push_string_end(msg, offset, auth2, conn_end->auth2);
+	push_string_end(msg, offset, id, conn_end->id);
+	push_string_end(msg, offset, id2, conn_end->id2);
+	push_string_end(msg, offset, rsakey, conn_end->rsakey);
+	push_string_end(msg, offset, cert, conn_end->cert);
+	push_string_end(msg, offset, cert2, conn_end->cert2);
+	push_string_end(msg, offset, cert_policy, conn_end->cert_policy);
+	push_string_end(msg, offset, ca, conn_end->ca);
+	push_string_end(msg, offset, ca2, conn_end->ca2);
+	push_string_end(msg, offset, groups, conn_end->groups);
+	push_string_end(msg, offset, groups2, conn_end->groups2);
+	push_string_end(msg, offset, updown, conn_end->updown);
 	if (conn_end->host)
 	{
-		msg_end->address = push_string(msg, conn_end->host);
+		push_string_end(msg, offset, address, conn_end->host);
 	}
 	else
 	{
-		msg_end->address = push_string(msg, "%any");
+		push_string_end(msg, offset, address, "%any");
 	}
+	push_string_end(msg, offset, subnets, conn_end->subnet);
+	push_string_end(msg, offset, sourceip, conn_end->sourceip);
+	push_string_end(msg, offset, dns, conn_end->dns);
+
+	/* we can't assign it earlier as msg might change */
+	msg_end = (stroke_end_t*)((char*)(*msg) + offset);
 	msg_end->ikeport = conn_end->ikeport;
-	msg_end->subnets = push_string(msg, conn_end->subnet);
-	msg_end->sourceip = push_string(msg, conn_end->sourceip);
-	msg_end->dns = push_string(msg, conn_end->dns);
 	msg_end->sendcert = conn_end->sendcert;
 	msg_end->hostaccess = conn_end->hostaccess;
 	msg_end->tohost = !conn_end->subnet;
@@ -147,187 +176,178 @@ static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, sta
 
 int starter_stroke_add_conn(starter_config_t *cfg, starter_conn_t *conn)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	memset(&msg, 0, sizeof(msg));
-	msg.type = STR_ADD_CONN;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.add_conn.version = conn->keyexchange;
-	msg.add_conn.name = push_string(&msg, connection_name(conn));
-	msg.add_conn.eap_identity = push_string(&msg, conn->eap_identity);
-	msg.add_conn.aaa_identity = push_string(&msg, conn->aaa_identity);
-	msg.add_conn.xauth_identity = push_string(&msg, conn->xauth_identity);
+	msg = create_stroke_msg(STR_ADD_CONN);
+	msg->add_conn.version = conn->keyexchange;
+	push_string(&msg, add_conn.name, connection_name(conn));
+	push_string(&msg, add_conn.eap_identity, conn->eap_identity);
+	push_string(&msg, add_conn.aaa_identity, conn->aaa_identity);
+	push_string(&msg, add_conn.xauth_identity, conn->xauth_identity);
 
-	msg.add_conn.mode = conn->mode;
-	msg.add_conn.proxy_mode = conn->proxy_mode;
+	msg->add_conn.mode = conn->mode;
+	msg->add_conn.proxy_mode = conn->proxy_mode;
 
 	if (!(conn->options & SA_OPTION_DONT_REKEY))
 	{
-		msg.add_conn.rekey.reauth = !(conn->options & SA_OPTION_DONT_REAUTH);
-		msg.add_conn.rekey.ipsec_lifetime = conn->sa_ipsec_life_seconds;
-		msg.add_conn.rekey.ike_lifetime = conn->sa_ike_life_seconds;
-		msg.add_conn.rekey.margin = conn->sa_rekey_margin;
-		msg.add_conn.rekey.life_bytes = conn->sa_ipsec_life_bytes;
-		msg.add_conn.rekey.margin_bytes = conn->sa_ipsec_margin_bytes;
-		msg.add_conn.rekey.life_packets = conn->sa_ipsec_life_packets;
-		msg.add_conn.rekey.margin_packets = conn->sa_ipsec_margin_packets;
-		msg.add_conn.rekey.fuzz = conn->sa_rekey_fuzz;
+		msg->add_conn.rekey.reauth = !(conn->options & SA_OPTION_DONT_REAUTH);
+		msg->add_conn.rekey.ipsec_lifetime = conn->sa_ipsec_life_seconds;
+		msg->add_conn.rekey.ike_lifetime = conn->sa_ike_life_seconds;
+		msg->add_conn.rekey.margin = conn->sa_rekey_margin;
+		msg->add_conn.rekey.life_bytes = conn->sa_ipsec_life_bytes;
+		msg->add_conn.rekey.margin_bytes = conn->sa_ipsec_margin_bytes;
+		msg->add_conn.rekey.life_packets = conn->sa_ipsec_life_packets;
+		msg->add_conn.rekey.margin_packets = conn->sa_ipsec_margin_packets;
+		msg->add_conn.rekey.fuzz = conn->sa_rekey_fuzz;
 	}
-	msg.add_conn.rekey.tries = conn->sa_keying_tries;
-
-	msg.add_conn.mobike = conn->options & SA_OPTION_MOBIKE;
-	msg.add_conn.force_encap = conn->options & SA_OPTION_FORCE_ENCAP;
-	msg.add_conn.fragmentation = conn->fragmentation;
-	msg.add_conn.ikedscp = conn->ikedscp;
-	msg.add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS;
-	msg.add_conn.install_policy = conn->install_policy;
-	msg.add_conn.aggressive = conn->aggressive;
-	msg.add_conn.pushmode = conn->options & SA_OPTION_MODECFG_PUSH;
-	msg.add_conn.crl_policy = (crl_policy_t)cfg->setup.strictcrlpolicy;
-	msg.add_conn.unique = cfg->setup.uniqueids;
-	msg.add_conn.algorithms.ike = push_string(&msg, conn->ike);
-	msg.add_conn.algorithms.esp = push_string(&msg, conn->esp);
-	msg.add_conn.algorithms.ah = push_string(&msg, conn->ah);
-	msg.add_conn.dpd.delay = conn->dpd_delay;
-	msg.add_conn.dpd.timeout = conn->dpd_timeout;
-	msg.add_conn.dpd.action = conn->dpd_action;
-	msg.add_conn.close_action = conn->close_action;
-	msg.add_conn.inactivity = conn->inactivity;
-	msg.add_conn.ikeme.mediation = conn->me_mediation;
-	msg.add_conn.ikeme.mediated_by = push_string(&msg, conn->me_mediated_by);
-	msg.add_conn.ikeme.peerid = push_string(&msg, conn->me_peerid);
-	msg.add_conn.reqid = conn->reqid;
-	msg.add_conn.replay_window = conn->replay_window;
-	msg.add_conn.mark_in.value = conn->mark_in.value;
-	msg.add_conn.mark_in.mask = conn->mark_in.mask;
-	msg.add_conn.mark_out.value = conn->mark_out.value;
-	msg.add_conn.mark_out.mask = conn->mark_out.mask;
-	msg.add_conn.tfc = conn->tfc;
-
-	starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->left);
-	starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->right);
-
-	if (!msg.add_conn.me.auth && !msg.add_conn.other.auth &&
+	msg->add_conn.rekey.tries = conn->sa_keying_tries;
+
+	msg->add_conn.mobike = conn->options & SA_OPTION_MOBIKE;
+	msg->add_conn.force_encap = conn->options & SA_OPTION_FORCE_ENCAP;
+	msg->add_conn.fragmentation = conn->fragmentation;
+	msg->add_conn.ikedscp = conn->ikedscp;
+	msg->add_conn.ipcomp = conn->options & SA_OPTION_COMPRESS;
+	msg->add_conn.install_policy = conn->install_policy;
+	msg->add_conn.aggressive = conn->aggressive;
+	msg->add_conn.pushmode = conn->options & SA_OPTION_MODECFG_PUSH;
+	msg->add_conn.crl_policy = (crl_policy_t)cfg->setup.strictcrlpolicy;
+	msg->add_conn.unique = cfg->setup.uniqueids;
+	push_string(&msg, add_conn.algorithms.ike, conn->ike);
+	push_string(&msg, add_conn.algorithms.esp, conn->esp);
+	push_string(&msg, add_conn.algorithms.ah, conn->ah);
+	msg->add_conn.dpd.delay = conn->dpd_delay;
+	msg->add_conn.dpd.timeout = conn->dpd_timeout;
+	msg->add_conn.dpd.action = conn->dpd_action;
+	msg->add_conn.close_action = conn->close_action;
+	msg->add_conn.inactivity = conn->inactivity;
+	msg->add_conn.ikeme.mediation = conn->me_mediation;
+	push_string(&msg, add_conn.ikeme.mediated_by, conn->me_mediated_by);
+	push_string(&msg, add_conn.ikeme.peerid, conn->me_peerid);
+	msg->add_conn.reqid = conn->reqid;
+	msg->add_conn.replay_window = conn->replay_window;
+	msg->add_conn.mark_in.value = conn->mark_in.value;
+	msg->add_conn.mark_in.mask = conn->mark_in.mask;
+	msg->add_conn.mark_out.value = conn->mark_out.value;
+	msg->add_conn.mark_out.mask = conn->mark_out.mask;
+	msg->add_conn.tfc = conn->tfc;
+
+	add_end(&msg, offsetof(stroke_msg_t, add_conn.me), &conn->left);
+	add_end(&msg, offsetof(stroke_msg_t, add_conn.other), &conn->right);
+
+	if (!msg->add_conn.me.auth && !msg->add_conn.other.auth &&
 		 conn->authby)
 	{	/* leftauth/rightauth not set, use legacy options */
 		if (streq(conn->authby, "rsa")   || streq(conn->authby, "rsasig")   ||
 			streq(conn->authby, "ecdsa") || streq(conn->authby, "ecdsasig") ||
 			streq(conn->authby, "pubkey"))
 		{
-			msg.add_conn.me.auth = push_string(&msg, "pubkey");
-			msg.add_conn.other.auth = push_string(&msg, "pubkey");
+			push_string(&msg, add_conn.me.auth, "pubkey");
+			push_string(&msg, add_conn.other.auth, "pubkey");
 		}
 		else if (streq(conn->authby, "secret") || streq(conn->authby, "psk"))
 		{
-			msg.add_conn.me.auth = push_string(&msg, "psk");
-			msg.add_conn.other.auth = push_string(&msg, "psk");
+			push_string(&msg, add_conn.me.auth, "psk");
+			push_string(&msg, add_conn.other.auth, "psk");
 		}
 		else if (streq(conn->authby, "xauthrsasig"))
 		{
-			msg.add_conn.me.auth = push_string(&msg, "pubkey");
-			msg.add_conn.other.auth = push_string(&msg, "pubkey");
+			push_string(&msg, add_conn.me.auth, "pubkey");
+			push_string(&msg, add_conn.other.auth, "pubkey");
 			if (conn->options & SA_OPTION_XAUTH_SERVER)
 			{
-				msg.add_conn.other.auth2 = push_string(&msg, "xauth");
+				push_string(&msg, add_conn.other.auth2, "xauth");
 			}
 			else
 			{
-				msg.add_conn.me.auth2 = push_string(&msg, "xauth");
+				push_string(&msg, add_conn.me.auth2, "xauth");
 			}
 		}
 		else if (streq(conn->authby, "xauthpsk"))
 		{
-			msg.add_conn.me.auth = push_string(&msg, "psk");
-			msg.add_conn.other.auth = push_string(&msg, "psk");
+			push_string(&msg, add_conn.me.auth, "psk");
+			push_string(&msg, add_conn.other.auth, "psk");
 			if (conn->options & SA_OPTION_XAUTH_SERVER)
 			{
-				msg.add_conn.other.auth2 = push_string(&msg, "xauth");
+				push_string(&msg, add_conn.other.auth2, "xauth");
 			}
 			else
 			{
-				msg.add_conn.me.auth2 = push_string(&msg, "xauth");
+				push_string(&msg, add_conn.me.auth2, "xauth");
 			}
 		}
 	}
-	return send_stroke_msg(&msg);
+	return send_stroke_msg(msg);
 }
 
 int starter_stroke_del_conn(starter_conn_t *conn)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_DEL_CONN;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.del_conn.name = push_string(&msg, connection_name(conn));
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_DEL_CONN);
+	push_string(&msg, del_conn.name, connection_name(conn));
+	return send_stroke_msg(msg);
 }
 
 int starter_stroke_route_conn(starter_conn_t *conn)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_ROUTE;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.route.name = push_string(&msg, connection_name(conn));
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_ROUTE);
+	push_string(&msg, route.name, connection_name(conn));
+	return send_stroke_msg(msg);
 }
 
 int starter_stroke_unroute_conn(starter_conn_t *conn)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_UNROUTE;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.route.name = push_string(&msg, connection_name(conn));
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_UNROUTE);
+	push_string(&msg, route.name, connection_name(conn));
+	return send_stroke_msg(msg);
 }
 
 int starter_stroke_initiate_conn(starter_conn_t *conn)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_INITIATE;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.initiate.name = push_string(&msg, connection_name(conn));
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_INITIATE);
+	push_string(&msg, initiate.name, connection_name(conn));
+	return send_stroke_msg(msg);
 }
 
 int starter_stroke_add_ca(starter_ca_t *ca)
 {
-	stroke_msg_t msg;
-
-	msg.type = STR_ADD_CA;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.add_ca.name =        push_string(&msg, ca->name);
-	msg.add_ca.cacert =      push_string(&msg, ca->cacert);
-	msg.add_ca.crluri =      push_string(&msg, ca->crluri);
-	msg.add_ca.crluri2 =     push_string(&msg, ca->crluri2);
-	msg.add_ca.ocspuri =     push_string(&msg, ca->ocspuri);
-	msg.add_ca.ocspuri2 =    push_string(&msg, ca->ocspuri2);
-	msg.add_ca.certuribase = push_string(&msg, ca->certuribase);
-	return send_stroke_msg(&msg);
+	stroke_msg_t *msg;
+
+	msg = create_stroke_msg(STR_ADD_CA);
+	push_string(&msg, add_ca.name, ca->name);
+	push_string(&msg, add_ca.cacert, ca->cacert);
+	push_string(&msg, add_ca.crluri, ca->crluri);
+	push_string(&msg, add_ca.crluri2, ca->crluri2);
+	push_string(&msg, add_ca.ocspuri, ca->ocspuri);
+	push_string(&msg, add_ca.ocspuri2, ca->ocspuri2);
+	push_string(&msg, add_ca.certuribase, ca->certuribase);
+	return send_stroke_msg(msg);
 }
 
 int starter_stroke_del_ca(starter_ca_t *ca)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_DEL_CA;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.del_ca.name = push_string(&msg, ca->name);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_DEL_CA);
+	push_string(&msg, del_ca.name, ca->name);
+	return send_stroke_msg(msg);
 }
 
 int starter_stroke_configure(starter_config_t *cfg)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
 	if (cfg->setup.cachecrls)
 	{
-		msg.type = STR_CONFIG;
-		msg.length = offsetof(stroke_msg_t, buffer);
-		msg.config.cachecrl = 1;
-		return send_stroke_msg(&msg);
+		msg = create_stroke_msg(STR_CONFIG);
+		msg->config.cachecrl = 1;
+		return send_stroke_msg(msg);
 	}
 	return 0;
 }
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index ae20b0c..07911d2 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2014 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -33,28 +33,58 @@ struct stroke_token {
 static char *daemon_name = "charon";
 static int output_verbosity = 1; /* CONTROL */
 
-static char* push_string(stroke_msg_t *msg, char *string)
+static stroke_msg_t *create_stroke_msg(int type)
 {
-	unsigned long string_start = msg->length;
+	stroke_msg_t *msg;
 
-	if (string == NULL ||  msg->length + strlen(string) >= sizeof(stroke_msg_t))
+	INIT(msg,
+		.type = type,
+		.length = offsetof(stroke_msg_t, buffer),
+	);
+	return msg;
+}
+
+#define push_string(msg, field, str) \
+	push_string_impl(msg, offsetof(stroke_msg_t, field), str)
+
+static void push_string_impl(stroke_msg_t **msg, size_t offset, char *string)
+{
+	size_t cur_len = (*msg)->length, str_len;
+
+	if (!string)
+	{
+		return;
+	}
+	str_len = strlen(string) + 1;
+	if (cur_len + str_len >= UINT16_MAX)
 	{
-		return NULL;
+		(*msg)->length = UINT16_MAX;
+		return;
 	}
-	else
+	while (cur_len + str_len > sizeof(stroke_msg_t) + (*msg)->buflen)
 	{
-		msg->length += strlen(string) + 1;
-		strcpy((char*)msg + string_start, string);
-		return (char*)string_start;
+		*msg = realloc(*msg, sizeof(stroke_msg_t) + (*msg)->buflen +
+					   STROKE_BUF_LEN_INC);
+		(*msg)->buflen += STROKE_BUF_LEN_INC;
 	}
+	(*msg)->length += str_len;
+	strcpy((char*)*msg + cur_len, string);
+	*(char**)((char*)*msg + offset) = (char*)cur_len;
 }
 
-static int send_stroke_msg (stroke_msg_t *msg)
+static int send_stroke_msg(stroke_msg_t *msg)
 {
 	stream_t *stream;
 	char *uri, buffer[512], *pass;
 	int count;
 
+	if (msg->length == UINT16_MAX)
+	{
+		fprintf(stderr, "stroke message exceeds maximum buffer size");
+		free(msg);
+		return -1;
+	}
+
 	msg->output_verbosity = output_verbosity;
 
 	uri = lib->settings->get_str(lib->settings, "%s.plugins.stroke.socket",
@@ -63,6 +93,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
 	if (!stream)
 	{
 		fprintf(stderr, "failed to connect to stroke socket '%s'\n", uri);
+		free(msg);
 		return -1;
 	}
 
@@ -70,6 +101,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
 	{
 		fprintf(stderr, "sending stroke message failed\n");
 		stream->destroy(stream);
+		free(msg);
 		return -1;
 	}
 
@@ -109,6 +141,7 @@ static int send_stroke_msg (stroke_msg_t *msg)
 		fprintf(stderr, "reading stroke response failed\n");
 	}
 	stream->destroy(stream);
+	free(msg);
 	return 0;
 }
 
@@ -117,126 +150,116 @@ static int add_connection(char *name,
 						  char *my_addr, char *other_addr,
 						  char *my_nets, char *other_nets)
 {
-	stroke_msg_t msg;
-
-	memset(&msg, 0, sizeof(msg));
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.type = STR_ADD_CONN;
-
-	msg.add_conn.name = push_string(&msg, name);
-	msg.add_conn.version = 2;
-	msg.add_conn.mode = 1;
-	msg.add_conn.mobike = 1;
-	msg.add_conn.dpd.action = 1;
-	msg.add_conn.install_policy = 1;
-
-	msg.add_conn.me.id = push_string(&msg, my_id);
-	msg.add_conn.me.address = push_string(&msg, my_addr);
-	msg.add_conn.me.ikeport = 500;
-	msg.add_conn.me.subnets = push_string(&msg, my_nets);
-	msg.add_conn.me.sendcert = 1;
-	msg.add_conn.me.to_port = 65535;
-
-	msg.add_conn.other.id = push_string(&msg, other_id);
-	msg.add_conn.other.address = push_string(&msg, other_addr);
-	msg.add_conn.other.ikeport = 500;
-	msg.add_conn.other.subnets = push_string(&msg, other_nets);
-	msg.add_conn.other.sendcert = 1;
-	msg.add_conn.other.to_port = 65535;
-
-	return send_stroke_msg(&msg);
+	stroke_msg_t *msg;
+
+	msg = create_stroke_msg(STR_ADD_CONN);
+
+	push_string(&msg, add_conn.name, name);
+	msg->add_conn.version = 2;
+	msg->add_conn.mode = 1;
+	msg->add_conn.mobike = 1;
+	msg->add_conn.dpd.action = 1;
+	msg->add_conn.install_policy = 1;
+
+	push_string(&msg, add_conn.me.id, my_id);
+	push_string(&msg, add_conn.me.address, my_addr);
+	msg->add_conn.me.ikeport = 500;
+	push_string(&msg, add_conn.me.subnets, my_nets);
+	msg->add_conn.me.sendcert = 1;
+	msg->add_conn.me.to_port = 65535;
+
+	push_string(&msg, add_conn.other.id, other_id);
+	push_string(&msg, add_conn.other.address, other_addr);
+	msg->add_conn.other.ikeport = 500;
+	push_string(&msg, add_conn.other.subnets, other_nets);
+	msg->add_conn.other.sendcert = 1;
+	msg->add_conn.other.to_port = 65535;
+
+	return send_stroke_msg(msg);
 }
 
 static int del_connection(char *name)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.type = STR_DEL_CONN;
-	msg.initiate.name = push_string(&msg, name);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_DEL_CONN);
+	push_string(&msg, initiate.name, name);
+	return send_stroke_msg(msg);
 }
 
 static int initiate_connection(char *name)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.type = STR_INITIATE;
-	msg.initiate.name = push_string(&msg, name);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_INITIATE);
+	push_string(&msg, initiate.name, name);
+	return send_stroke_msg(msg);
 }
 
 static int terminate_connection(char *name)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_TERMINATE;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.initiate.name = push_string(&msg, name);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_TERMINATE);
+	push_string(&msg, initiate.name, name);
+	return send_stroke_msg(msg);
 }
 
 static int terminate_connection_srcip(char *start, char *end)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_TERMINATE_SRCIP;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.terminate_srcip.start = push_string(&msg, start);
-	msg.terminate_srcip.end = push_string(&msg, end);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_TERMINATE_SRCIP);
+	push_string(&msg, terminate_srcip.start, start);
+	push_string(&msg, terminate_srcip.end, end);
+	return send_stroke_msg(msg);
 }
 
 static int rekey_connection(char *name)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_REKEY;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.rekey.name = push_string(&msg, name);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_REKEY);
+	push_string(&msg, rekey.name, name);
+	return send_stroke_msg(msg);
 }
 
 static int route_connection(char *name)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_ROUTE;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.route.name = push_string(&msg, name);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_ROUTE);
+	push_string(&msg, route.name, name);
+	return send_stroke_msg(msg);
 }
 
 static int unroute_connection(char *name)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_UNROUTE;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.unroute.name = push_string(&msg, name);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_UNROUTE);
+	push_string(&msg, unroute.name, name);
+	return send_stroke_msg(msg);
 }
 
 static int show_status(stroke_keyword_t kw, char *connection)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
 	switch (kw)
 	{
 		case STROKE_STATUSALL:
-			msg.type = STR_STATUS_ALL;
+			msg = create_stroke_msg(STR_STATUS_ALL);
 			break;
 		case STROKE_STATUSALL_NOBLK:
-			msg.type = STR_STATUS_ALL_NOBLK;
+			msg = create_stroke_msg(STR_STATUS_ALL_NOBLK);
 			break;
 		default:
-			msg.type = STR_STATUS;
+			msg = create_stroke_msg(STR_STATUS);
 			break;
 	}
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.status.name = push_string(&msg, connection);
-	return send_stroke_msg(&msg);
+	push_string(&msg, status.name, connection);
+	return send_stroke_msg(msg);
 }
 
 static int list_flags[] = {
@@ -257,13 +280,12 @@ static int list_flags[] = {
 
 static int list(stroke_keyword_t kw, int utc)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_LIST;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.list.utc = utc;
-	msg.list.flags = list_flags[kw - STROKE_LIST_FIRST];
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_LIST);
+	msg->list.utc = utc;
+	msg->list.flags = list_flags[kw - STROKE_LIST_FIRST];
+	return send_stroke_msg(msg);
 }
 
 static int reread_flags[] = {
@@ -278,12 +300,11 @@ static int reread_flags[] = {
 
 static int reread(stroke_keyword_t kw)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_REREAD;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.reread.flags = reread_flags[kw - STROKE_REREAD_FIRST];
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_REREAD);
+	msg->reread.flags = reread_flags[kw - STROKE_REREAD_FIRST];
+	return send_stroke_msg(msg);
 }
 
 static int purge_flags[] = {
@@ -295,12 +316,11 @@ static int purge_flags[] = {
 
 static int purge(stroke_keyword_t kw)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_PURGE;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.purge.flags = purge_flags[kw - STROKE_PURGE_FIRST];
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_PURGE);
+	msg->purge.flags = purge_flags[kw - STROKE_PURGE_FIRST];
+	return send_stroke_msg(msg);
 }
 
 static int export_flags[] = {
@@ -311,68 +331,61 @@ static int export_flags[] = {
 
 static int export(stroke_keyword_t kw, char *selector)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_EXPORT;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.export.selector = push_string(&msg, selector);
-	msg.export.flags = export_flags[kw - STROKE_EXPORT_FIRST];
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_EXPORT);
+	push_string(&msg, export.selector, selector);
+	msg->export.flags = export_flags[kw - STROKE_EXPORT_FIRST];
+	return send_stroke_msg(msg);
 }
 
 static int leases(stroke_keyword_t kw, char *pool, char *address)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_LEASES;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.leases.pool = push_string(&msg, pool);
-	msg.leases.address = push_string(&msg, address);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_LEASES);
+	push_string(&msg, leases.pool, pool);
+	push_string(&msg, leases.address, address);
+	return send_stroke_msg(msg);
 }
 
 static int memusage()
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_MEMUSAGE;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_MEMUSAGE);
+	return send_stroke_msg(msg);
 }
 
 static int user_credentials(char *name, char *user, char *pass)
 {
-	stroke_msg_t msg;
-
-	msg.type = STR_USER_CREDS;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.user_creds.name = push_string(&msg, name);
-	msg.user_creds.username = push_string(&msg, user);
-	msg.user_creds.password = push_string(&msg, pass);
-	return send_stroke_msg(&msg);
+	stroke_msg_t *msg;
+
+	msg = create_stroke_msg(STR_USER_CREDS);
+	push_string(&msg, user_creds.name, name);
+	push_string(&msg, user_creds.username, user);
+	push_string(&msg, user_creds.password, pass);
+	return send_stroke_msg(msg);
 }
 
 static int counters(int reset, char *name)
 {
-	stroke_msg_t msg;
-
-	msg.type = STR_COUNTERS;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.counters.name = push_string(&msg, name);
-	msg.counters.reset = reset;
+	stroke_msg_t *msg;
 
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_COUNTERS);
+	push_string(&msg, counters.name, name);
+	msg->counters.reset = reset;
+	return send_stroke_msg(msg);
 }
 
 static int set_loglevel(char *type, u_int level)
 {
-	stroke_msg_t msg;
+	stroke_msg_t *msg;
 
-	msg.type = STR_LOGLEVEL;
-	msg.length = offsetof(stroke_msg_t, buffer);
-	msg.loglevel.type = push_string(&msg, type);
-	msg.loglevel.level = level;
-	return send_stroke_msg(&msg);
+	msg = create_stroke_msg(STR_LOGLEVEL);
+	push_string(&msg, loglevel.type, type);
+	msg->loglevel.level = level;
+	return send_stroke_msg(msg);
 }
 
 static int usage(char *error)
diff --git a/src/stroke/stroke_msg.h b/src/stroke/stroke_msg.h
index c2b923f..17f8a43 100644
--- a/src/stroke/stroke_msg.h
+++ b/src/stroke/stroke_msg.h
@@ -1,11 +1,5 @@
-/**
- * @file stroke_msg.h
- *
- * @brief Definition of stroke_msg_t.
- *
- */
-
 /*
+ * Copyright (C) 2015 Tobias Brunner
  * Copyright (C) 2006 Martin Willi
  * Hochschule fuer Technik Rapperswil
  *
@@ -32,7 +26,10 @@
  */
 #define STROKE_SOCKET IPSEC_PIDDIR "/charon.ctl"
 
-#define STROKE_BUF_LEN		4096
+/**
+ * Number of bytes by which the buffer is increased as needed
+ */
+#define STROKE_BUF_LEN_INC     1024
 
 typedef enum list_flag_t list_flag_t;
 
@@ -371,7 +368,10 @@ struct stroke_msg_t {
 			char *name;
 		} counters;
 	};
-	char buffer[STROKE_BUF_LEN];
+	/* length of the string buffer */
+	u_int16_t buflen;
+	/* string buffer */
+	char buffer[];
 };
 
 #endif /* STROKE_MSG_H_ */
diff --git a/src/swanctl/command.c b/src/swanctl/command.c
index 1c079ec..03cd8b9 100644
--- a/src/swanctl/command.c
+++ b/src/swanctl/command.c
@@ -124,17 +124,8 @@ int command_getopt(char **arg)
 		switch (op)
 		{
 			case '+':
-				if (!options->from(options, optarg, &argc, &argv, optind))
-				{
-					/* a error value */
-					return 255;
-				}
-				continue;
 			case 'v':
-				dbg_default_set_level(atoi(optarg));
-				continue;
 			case 'u':
-				uri = optarg;
 				continue;
 			default:
 				*arg = optarg;
@@ -257,6 +248,37 @@ static void cleanup()
 }
 
 /**
+ * Process options common for all commands
+ */
+static bool process_common_opts()
+{
+	while (TRUE)
+	{
+		switch (getopt_long(argc, argv, command_optstring, command_opts, NULL))
+		{
+			case '+':
+				if (!options->from(options, optarg, &argc, &argv, optind))
+				{
+					return FALSE;
+				}
+				continue;
+			case 'v':
+				dbg_default_set_level(atoi(optarg));
+				continue;
+			case 'u':
+				uri = optarg;
+				continue;
+			default:
+				continue;
+			case '?':
+				return FALSE;
+			case EOF:
+				return TRUE;
+		}
+	}
+}
+
+/**
  * Open vici connection, call a command
  */
 static int call_command(command_t *cmd)
@@ -303,6 +325,11 @@ int command_dispatch(int c, char *v[])
 			{
 				return command_usage(NULL);
 			}
+			if (!process_common_opts())
+			{
+				return command_usage("invalid options");
+			}
+			optind = 2;
 			return call_command(&cmds[i]);
 		}
 	}
diff --git a/src/swanctl/command.h b/src/swanctl/command.h
index 2d78a24..ffc3190 100644
--- a/src/swanctl/command.h
+++ b/src/swanctl/command.h
@@ -27,7 +27,7 @@
 /**
  * Maximum number of commands (+1).
  */
-#define MAX_COMMANDS 18
+#define MAX_COMMANDS 19
 
 /**
  * Maximum number of options in a command (+3)
diff --git a/src/swanctl/commands/list_sas.c b/src/swanctl/commands/list_sas.c
index 81e1b7c..1aca6d2 100644
--- a/src/swanctl/commands/list_sas.c
+++ b/src/swanctl/commands/list_sas.c
@@ -13,6 +13,28 @@
  * for more details.
  */
 
+/*
+ * Copyright (C) 2014 Timo Teräs <timo.teras at iki.fi>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <errno.h>
@@ -126,7 +148,7 @@ CALLBACK(child_sas, int,
 		}
 		printf("\n");
 
-		printf("    installed %s ago", child->get(child, "install-time"));
+		printf("    installed %ss ago", child->get(child, "install-time"));
 		if (child->get(child, "rekey-time"))
 		{
 			printf(", rekeying in %ss", child->get(child, "rekey-time"));
@@ -262,9 +284,12 @@ CALLBACK(ike_sas, int,
 CALLBACK(list_cb, void,
 	command_format_options_t *format, char *name, vici_res_t *res)
 {
+	char buf[256];
+
 	if (*format & COMMAND_FORMAT_RAW)
 	{
-		vici_dump(res, "list-sa event", *format & COMMAND_FORMAT_PRETTY,
+		snprintf(buf, sizeof(buf), "%s event", name);
+		vici_dump(res, buf, *format & COMMAND_FORMAT_PRETTY,
 				  stdout);
 	}
 	else
@@ -348,6 +373,50 @@ static int list_sas(vici_conn_t *conn)
 	return 0;
 }
 
+static int monitor_sas(vici_conn_t *conn)
+{
+	command_format_options_t format = COMMAND_FORMAT_NONE;
+	char *arg;
+
+	while (TRUE)
+	{
+		switch (command_getopt(&arg))
+		{
+			case 'h':
+				return command_usage(NULL);
+			case 'P':
+				format |= COMMAND_FORMAT_PRETTY;
+				/* fall through to raw */
+			case 'r':
+				format |= COMMAND_FORMAT_RAW;
+				continue;
+			case EOF:
+				break;
+			default:
+				return command_usage("invalid --monitor-sa option");
+		}
+		break;
+	}
+	if (vici_register(conn, "ike-updown", list_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for IKE_SAs failed: %s\n",
+				strerror(errno));
+		return errno;
+	}
+	if (vici_register(conn, "child-updown", list_cb, &format) != 0)
+	{
+		fprintf(stderr, "registering for CHILD_SAs failed: %s\n",
+				strerror(errno));
+		return errno;
+	}
+
+	wait_sigint();
+
+	fprintf(stderr, "disconnecting...\n");
+
+	return 0;
+}
+
 /**
  * Register the command.
  */
@@ -366,3 +435,16 @@ static void __attribute__ ((constructor))reg()
 		}
 	});
 }
+
+static void __attribute__ ((constructor))reg_monitor_sa()
+{
+	command_register((command_t) {
+		monitor_sas, 'm', "monitor-sa", "monitor for IKE_SA and CHILD_SA changes",
+		{"[--raw|--pretty]"},
+		{
+			{"help",		'h', 0, "show usage information"},
+			{"raw",			'r', 0, "dump raw response message"},
+			{"pretty",		'P', 0, "dump raw response message in pretty print"},
+		}
+	});
+}
diff --git a/testing/config/kernel/config-4.0 b/testing/config/kernel/config-4.0
new file mode 100644
index 0000000..33771a2
--- /dev/null
+++ b/testing/config/kernel/config-4.0
@@ -0,0 +1,2202 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/x86 4.0.0 Kernel Configuration
+#
+CONFIG_64BIT=y
+CONFIG_X86_64=y
+CONFIG_X86=y
+CONFIG_INSTRUCTION_DECODER=y
+CONFIG_PERF_EVENTS_INTEL_UNCORE=y
+CONFIG_OUTPUT_FORMAT="elf64-x86-64"
+CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_MMU=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_ARCH_MAY_HAVE_PC_FDC=y
+CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_HAS_CPU_RELAX=y
+CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
+CONFIG_HAVE_SETUP_PER_CPU_AREA=y
+CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
+CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y
+CONFIG_ARCH_WANT_GENERAL_HUGETLB=y
+CONFIG_ZONE_DMA32=y
+CONFIG_AUDIT_ARCH=y
+CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
+CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
+CONFIG_ARCH_HWEIGHT_CFLAGS="-fcall-saved-rdi -fcall-saved-rsi -fcall-saved-rdx -fcall-saved-rcx -fcall-saved-r8 -fcall-saved-r9 -fcall-saved-r10 -fcall-saved-r11"
+CONFIG_ARCH_SUPPORTS_UPROBES=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+CONFIG_CROSS_MEMORY_ATTACH=y
+# CONFIG_FHANDLE is not set
+CONFIG_USELIB=y
+# CONFIG_AUDIT is not set
+CONFIG_HAVE_ARCH_AUDITSYSCALL=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_CLOCKSOURCE_WATCHDOG=y
+CONFIG_ARCH_CLOCKSOURCE_DATA=y
+CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ_COMMON=y
+# CONFIG_HZ_PERIODIC is not set
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_BSD_PROCESS_ACCT=y
+# CONFIG_BSD_PROCESS_ACCT_V3 is not set
+# CONFIG_TASKSTATS is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_RCU_KTHREAD_PRIO=0
+CONFIG_BUILD_BIN2C=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
+CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y
+CONFIG_ARCH_SUPPORTS_INT128=y
+# CONFIG_CGROUPS is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_IPC_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+# CONFIG_NET_NS is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
+# CONFIG_BLK_DEV_INITRD is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_HAVE_PCSPKR_PLATFORM=y
+CONFIG_BPF=y
+# CONFIG_EXPERT is not set
+CONFIG_SGETMASK_SYSCALL=y
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_PCSPKR_PLATFORM=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_COMPAT_BRK=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_OPROFILE_NMI_TIMER=y
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set
+CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
+CONFIG_ARCH_USE_BUILTIN_BSWAP=y
+CONFIG_HAVE_IOREMAP_PROT=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_OPTPROBES=y
+CONFIG_HAVE_KPROBES_ON_FTRACE=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_HW_BREAKPOINT=y
+CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y
+CONFIG_HAVE_USER_RETURN_NOTIFIER=y
+CONFIG_HAVE_PERF_EVENTS_NMI=y
+CONFIG_HAVE_PERF_REGS=y
+CONFIG_HAVE_PERF_USER_STACK_DUMP=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y
+CONFIG_HAVE_CMPXCHG_LOCAL=y
+CONFIG_HAVE_CMPXCHG_DOUBLE=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_SECCOMP_FILTER=y
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+CONFIG_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR_NONE is not set
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_ARCH_SOFT_DIRTY=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y
+
+#
+# GCOV-based kernel profiling
+#
+CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y
+# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_BSGLIB is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+# CONFIG_PARTITION_ADVANCED is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_EFI_PARTITION=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_DEFAULT_DEADLINE is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y
+CONFIG_ARCH_USE_QUEUE_RWLOCK=y
+CONFIG_FREEZER=y
+
+#
+# Processor type and features
+#
+CONFIG_ZONE_DMA=y
+# CONFIG_SMP is not set
+CONFIG_X86_FEATURE_NAMES=y
+CONFIG_X86_MPPARSE=y
+CONFIG_X86_EXTENDED_PLATFORM=y
+# CONFIG_X86_GOLDFISH is not set
+# CONFIG_X86_INTEL_LPSS is not set
+# CONFIG_X86_AMD_PLATFORM_DEVICE is not set
+CONFIG_IOSF_MBI=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+# CONFIG_HYPERVISOR_GUEST is not set
+CONFIG_NO_BOOTMEM=y
+# CONFIG_MEMTEST is not set
+# CONFIG_MK8 is not set
+# CONFIG_MPSC is not set
+CONFIG_MCORE2=y
+# CONFIG_MATOM is not set
+# CONFIG_GENERIC_CPU is not set
+CONFIG_X86_INTERNODE_CACHE_SHIFT=6
+CONFIG_X86_L1_CACHE_SHIFT=6
+CONFIG_X86_INTEL_USERCOPY=y
+CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_P6_NOP=y
+CONFIG_X86_TSC=y
+CONFIG_X86_CMPXCHG64=y
+CONFIG_X86_CMOV=y
+CONFIG_X86_MINIMUM_CPU_FAMILY=64
+CONFIG_X86_DEBUGCTLMSR=y
+CONFIG_CPU_SUP_INTEL=y
+CONFIG_CPU_SUP_AMD=y
+CONFIG_CPU_SUP_CENTAUR=y
+CONFIG_HPET_TIMER=y
+CONFIG_DMI=y
+CONFIG_GART_IOMMU=y
+# CONFIG_CALGARY_IOMMU is not set
+CONFIG_SWIOTLB=y
+CONFIG_IOMMU_HELPER=y
+CONFIG_NR_CPUS=1
+CONFIG_PREEMPT_NONE=y
+# CONFIG_PREEMPT_VOLUNTARY is not set
+# CONFIG_PREEMPT is not set
+CONFIG_UP_LATE_INIT=y
+CONFIG_X86_UP_APIC_MSI=y
+CONFIG_X86_LOCAL_APIC=y
+CONFIG_X86_IO_APIC=y
+# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
+# CONFIG_X86_MCE is not set
+CONFIG_X86_16BIT=y
+CONFIG_X86_ESPFIX64=y
+CONFIG_X86_VSYSCALL_EMULATION=y
+# CONFIG_I8K is not set
+# CONFIG_MICROCODE is not set
+# CONFIG_MICROCODE_INTEL_EARLY is not set
+# CONFIG_MICROCODE_AMD_EARLY is not set
+# CONFIG_X86_MSR is not set
+# CONFIG_X86_CPUID is not set
+CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_DIRECT_GBPAGES=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_SPARSEMEM_DEFAULT=y
+CONFIG_ARCH_SELECT_MEMORY_MODEL=y
+CONFIG_ARCH_MEMORY_PROBE=y
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_SPARSEMEM_MANUAL=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+CONFIG_MEMORY_ISOLATION=y
+CONFIG_HAVE_BOOTMEM_INFO_NODE=y
+CONFIG_MEMORY_HOTPLUG=y
+CONFIG_MEMORY_HOTPLUG_SPARSE=y
+CONFIG_MEMORY_HOTREMOVE=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y
+CONFIG_MEMORY_BALLOON=y
+# CONFIG_COMPACTION is not set
+CONFIG_MIGRATION=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+CONFIG_GENERIC_EARLY_IOREMAP=y
+# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
+CONFIG_X86_RESERVE_LOW=64
+CONFIG_MTRR=y
+CONFIG_MTRR_SANITIZER=y
+CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
+CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
+CONFIG_X86_PAT=y
+CONFIG_ARCH_USES_PG_UNCACHED=y
+CONFIG_ARCH_RANDOM=y
+CONFIG_X86_SMAP=y
+# CONFIG_X86_INTEL_MPX is not set
+# CONFIG_EFI is not set
+CONFIG_SECCOMP=y
+# CONFIG_HZ_100 is not set
+CONFIG_HZ_250=y
+# CONFIG_HZ_300 is not set
+# CONFIG_HZ_1000 is not set
+CONFIG_HZ=250
+CONFIG_SCHED_HRTICK=y
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+CONFIG_PHYSICAL_START=0x1000000
+CONFIG_RELOCATABLE=y
+# CONFIG_RANDOMIZE_BASE is not set
+CONFIG_PHYSICAL_ALIGN=0x1000000
+# CONFIG_CMDLINE_BOOL is not set
+CONFIG_HAVE_LIVEPATCH=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
+CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y
+
+#
+# Power management and ACPI options
+#
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+# CONFIG_HIBERNATION is not set
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_ACPI=y
+CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y
+CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y
+CONFIG_ACPI_SLEEP=y
+# CONFIG_ACPI_PROCFS_POWER is not set
+# CONFIG_ACPI_EC_DEBUGFS is not set
+CONFIG_ACPI_AC=y
+CONFIG_ACPI_BATTERY=y
+CONFIG_ACPI_BUTTON=y
+CONFIG_ACPI_FAN=y
+# CONFIG_ACPI_DOCK is not set
+CONFIG_ACPI_PROCESSOR=y
+# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set
+CONFIG_ACPI_THERMAL=y
+# CONFIG_ACPI_CUSTOM_DSDT is not set
+# CONFIG_ACPI_DEBUG is not set
+# CONFIG_ACPI_PCI_SLOT is not set
+CONFIG_X86_PM_TIMER=y
+# CONFIG_ACPI_CONTAINER is not set
+# CONFIG_ACPI_HOTPLUG_MEMORY is not set
+CONFIG_ACPI_HOTPLUG_IOAPIC=y
+# CONFIG_ACPI_SBS is not set
+# CONFIG_ACPI_HED is not set
+# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set
+CONFIG_HAVE_ACPI_APEI=y
+CONFIG_HAVE_ACPI_APEI_NMI=y
+# CONFIG_ACPI_APEI is not set
+# CONFIG_PMIC_OPREGION is not set
+# CONFIG_SFI is not set
+
+#
+# CPU Frequency scaling
+#
+# CONFIG_CPU_FREQ is not set
+
+#
+# CPU Idle
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+# CONFIG_INTEL_IDLE is not set
+
+#
+# Memory power savings
+#
+# CONFIG_I7300_IDLE is not set
+
+#
+# Bus options (PCI etc.)
+#
+CONFIG_PCI=y
+CONFIG_PCI_DIRECT=y
+# CONFIG_PCI_MMCONFIG is not set
+CONFIG_PCI_DOMAINS=y
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_PCI_MSI=y
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+CONFIG_HT_IRQ=y
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+CONFIG_PCI_LABEL=y
+
+#
+# PCI host controller drivers
+#
+CONFIG_ISA_DMA_API=y
+CONFIG_AMD_NB=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
+# CONFIG_X86_SYSFB is not set
+
+#
+# Executable file formats / Emulations
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+CONFIG_COREDUMP=y
+# CONFIG_IA32_EMULATION is not set
+CONFIG_X86_DEV_DMA_OPS=y
+CONFIG_PMC_ATOM=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_SUB_POLICY=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_XFRM_IPCOMP=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IP_ROUTE_CLASSID=y
+# CONFIG_IP_PNP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=y
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_NET_IPVTI is not set
+CONFIG_NET_UDP_TUNNEL=y
+# CONFIG_NET_FOU is not set
+# CONFIG_GENEVE is not set
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=y
+# CONFIG_IPV6_ROUTER_PREF is not set
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_INET6_XFRM_TUNNEL=y
+CONFIG_INET6_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_TRANSPORT=y
+CONFIG_INET6_XFRM_MODE_TUNNEL=y
+CONFIG_INET6_XFRM_MODE_BEET=y
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+# CONFIG_IPV6_VTI is not set
+# CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_GRE=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=y
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE=y
+CONFIG_NETFILTER_NETLINK_LOG=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_LOG_COMMON=y
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_ZONES is not set
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+# CONFIG_NF_CT_PROTO_DCCP is not set
+# CONFIG_NF_CT_PROTO_SCTP is not set
+CONFIG_NF_CT_PROTO_UDPLITE=y
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+# CONFIG_NF_CONNTRACK_FTP is not set
+# CONFIG_NF_CONNTRACK_H323 is not set
+# CONFIG_NF_CONNTRACK_IRC is not set
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+CONFIG_NF_CONNTRACK_SANE=y
+# CONFIG_NF_CONNTRACK_SIP is not set
+# CONFIG_NF_CONNTRACK_TFTP is not set
+CONFIG_NF_CT_NETLINK=y
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set
+CONFIG_NF_NAT=y
+CONFIG_NF_NAT_NEEDED=y
+CONFIG_NF_NAT_PROTO_UDPLITE=y
+# CONFIG_NF_NAT_AMANDA is not set
+# CONFIG_NF_NAT_FTP is not set
+# CONFIG_NF_NAT_IRC is not set
+# CONFIG_NF_NAT_SIP is not set
+# CONFIG_NF_NAT_TFTP is not set
+CONFIG_NF_NAT_REDIRECT=y
+# CONFIG_NF_TABLES is not set
+CONFIG_NETFILTER_XTABLES=y
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=y
+CONFIG_NETFILTER_XT_CONNMARK=y
+CONFIG_NETFILTER_XT_SET=y
+
+#
+# Xtables targets
+#
+# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CT=y
+CONFIG_NETFILTER_XT_TARGET_DSCP=y
+CONFIG_NETFILTER_XT_TARGET_HL=y
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_NAT=y
+CONFIG_NETFILTER_XT_TARGET_NETMAP=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set
+CONFIG_NETFILTER_XT_TARGET_REDIRECT=y
+# CONFIG_NETFILTER_XT_TARGET_TEE is not set
+# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set
+
+#
+# Xtables matches
+#
+CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+CONFIG_NETFILTER_XT_MATCH_CLUSTER=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=y
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+# CONFIG_NETFILTER_XT_MATCH_CPU is not set
+CONFIG_NETFILTER_XT_MATCH_DCCP=y
+CONFIG_NETFILTER_XT_MATCH_DEVGROUP=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ECN=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_HL=y
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set
+CONFIG_NETFILTER_XT_MATCH_L2TP=y
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+# CONFIG_NETFILTER_XT_MATCH_OWNER is not set
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set
+CONFIG_NETFILTER_XT_MATCH_REALM=y
+# CONFIG_NETFILTER_XT_MATCH_RECENT is not set
+CONFIG_NETFILTER_XT_MATCH_SCTP=y
+# CONFIG_NETFILTER_XT_MATCH_SOCKET is not set
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=y
+# CONFIG_NETFILTER_XT_MATCH_TIME is not set
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_IP_SET=y
+CONFIG_IP_SET_MAX=256
+CONFIG_IP_SET_BITMAP_IP=y
+CONFIG_IP_SET_BITMAP_IPMAC=y
+CONFIG_IP_SET_BITMAP_PORT=y
+CONFIG_IP_SET_HASH_IP=y
+# CONFIG_IP_SET_HASH_IPMARK is not set
+CONFIG_IP_SET_HASH_IPPORT=y
+CONFIG_IP_SET_HASH_IPPORTIP=y
+CONFIG_IP_SET_HASH_IPPORTNET=y
+# CONFIG_IP_SET_HASH_MAC is not set
+# CONFIG_IP_SET_HASH_NETPORTNET is not set
+CONFIG_IP_SET_HASH_NET=y
+# CONFIG_IP_SET_HASH_NETNET is not set
+CONFIG_IP_SET_HASH_NETPORT=y
+# CONFIG_IP_SET_HASH_NETIFACE is not set
+CONFIG_IP_SET_LIST_SET=y
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_NF_LOG_ARP is not set
+CONFIG_NF_LOG_IPV4=y
+CONFIG_NF_REJECT_IPV4=y
+CONFIG_NF_NAT_IPV4=y
+CONFIG_NF_NAT_MASQUERADE_IPV4=y
+# CONFIG_NF_NAT_PPTP is not set
+# CONFIG_NF_NAT_H323 is not set
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_TARGET_CLUSTERIP=y
+CONFIG_IP_NF_TARGET_ECN=y
+CONFIG_IP_NF_TARGET_TTL=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_NF_REJECT_IPV6=y
+CONFIG_NF_LOG_IPV6=y
+CONFIG_NF_NAT_IPV6=y
+CONFIG_NF_NAT_MASQUERADE_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_AH=y
+CONFIG_IP6_NF_MATCH_EUI64=y
+CONFIG_IP6_NF_MATCH_FRAG=y
+CONFIG_IP6_NF_MATCH_OPTS=y
+CONFIG_IP6_NF_MATCH_HL=y
+CONFIG_IP6_NF_MATCH_IPV6HEADER=y
+CONFIG_IP6_NF_MATCH_MH=y
+# CONFIG_IP6_NF_MATCH_RPFILTER is not set
+CONFIG_IP6_NF_MATCH_RT=y
+CONFIG_IP6_NF_TARGET_HL=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+# CONFIG_IP6_NF_TARGET_SYNPROXY is not set
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+# CONFIG_IP6_NF_NAT is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+CONFIG_L2TP=y
+# CONFIG_L2TP_V3 is not set
+# CONFIG_BRIDGE is not set
+CONFIG_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_NET_MPLS_GSO is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+# CONFIG_CFG80211 is not set
+# CONFIG_LIB80211 is not set
+
+#
+# CFG80211 needs to be enabled for MAC80211
+#
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+CONFIG_NET_9P=y
+CONFIG_NET_9P_VIRTIO=y
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+# CONFIG_DEVTMPFS is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_CONNECTOR is not set
+# CONFIG_MTD is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_PNP=y
+CONFIG_PNP_DEBUG_MESSAGES=y
+
+#
+# Protocols
+#
+CONFIG_PNPACPI=y
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_FD is not set
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+CONFIG_BLK_DEV_NBD=y
+# CONFIG_BLK_DEV_NVME is not set
+# CONFIG_BLK_DEV_SKD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_VIRTIO_BLK=y
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_BLK_DEV_RSXX is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_IBM_ASM is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+
+#
+# Altera FPGA firmware download module
+#
+# CONFIG_VMWARE_VMCI is not set
+
+#
+# Intel MIC Bus Driver
+#
+# CONFIG_INTEL_MIC_BUS is not set
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+# CONFIG_GENWQE is not set
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+# CONFIG_SCSI is not set
+# CONFIG_SCSI_DMA is not set
+# CONFIG_SCSI_NETLINK is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+# CONFIG_MACINTOSH_DRIVERS is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+CONFIG_DUMMY=y
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_IPVLAN is not set
+# CONFIG_VXLAN is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+CONFIG_TUN=y
+# CONFIG_VETH is not set
+CONFIG_VIRTIO_NET=y
+# CONFIG_NLMON is not set
+# CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+# CONFIG_VHOST_NET is not set
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6060 is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+# CONFIG_NET_DSA_MV88E6131 is not set
+# CONFIG_NET_DSA_MV88E6123_61_65 is not set
+# CONFIG_NET_DSA_MV88E6171 is not set
+# CONFIG_NET_DSA_MV88E6352 is not set
+# CONFIG_NET_DSA_BCM_SF2 is not set
+CONFIG_ETHERNET=y
+CONFIG_NET_VENDOR_3COM=y
+# CONFIG_VORTEX is not set
+# CONFIG_TYPHOON is not set
+CONFIG_NET_VENDOR_ADAPTEC=y
+# CONFIG_ADAPTEC_STARFIRE is not set
+CONFIG_NET_VENDOR_AGERE=y
+# CONFIG_ET131X is not set
+CONFIG_NET_VENDOR_ALTEON=y
+# CONFIG_ACENIC is not set
+# CONFIG_ALTERA_TSE is not set
+CONFIG_NET_VENDOR_AMD=y
+# CONFIG_AMD8111_ETH is not set
+# CONFIG_PCNET32 is not set
+# CONFIG_AMD_XGBE is not set
+# CONFIG_NET_XGENE is not set
+# CONFIG_NET_VENDOR_ARC is not set
+CONFIG_NET_VENDOR_ATHEROS=y
+# CONFIG_ATL2 is not set
+# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_ALX is not set
+CONFIG_NET_VENDOR_BROADCOM=y
+# CONFIG_B44 is not set
+# CONFIG_BCMGENET is not set
+# CONFIG_BNX2 is not set
+# CONFIG_CNIC is not set
+# CONFIG_TIGON3 is not set
+# CONFIG_BNX2X is not set
+CONFIG_NET_VENDOR_BROCADE=y
+# CONFIG_BNA is not set
+CONFIG_NET_VENDOR_CHELSIO=y
+# CONFIG_CHELSIO_T1 is not set
+# CONFIG_CHELSIO_T3 is not set
+# CONFIG_CHELSIO_T4 is not set
+# CONFIG_CHELSIO_T4VF is not set
+CONFIG_NET_VENDOR_CISCO=y
+# CONFIG_ENIC is not set
+# CONFIG_CX_ECAT is not set
+# CONFIG_DNET is not set
+CONFIG_NET_VENDOR_DEC=y
+# CONFIG_NET_TULIP is not set
+CONFIG_NET_VENDOR_DLINK=y
+# CONFIG_DL2K is not set
+# CONFIG_SUNDANCE is not set
+CONFIG_NET_VENDOR_EMULEX=y
+# CONFIG_BE2NET is not set
+CONFIG_NET_VENDOR_EXAR=y
+# CONFIG_S2IO is not set
+# CONFIG_VXGE is not set
+CONFIG_NET_VENDOR_HP=y
+# CONFIG_HP100 is not set
+CONFIG_NET_VENDOR_INTEL=y
+# CONFIG_E100 is not set
+# CONFIG_E1000 is not set
+# CONFIG_E1000E is not set
+# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
+# CONFIG_IXGB is not set
+# CONFIG_IXGBE is not set
+# CONFIG_IXGBEVF is not set
+# CONFIG_I40E is not set
+# CONFIG_I40EVF is not set
+# CONFIG_FM10K is not set
+CONFIG_NET_VENDOR_I825XX=y
+# CONFIG_IP1000 is not set
+# CONFIG_JME is not set
+CONFIG_NET_VENDOR_MARVELL=y
+# CONFIG_MVMDIO is not set
+# CONFIG_SKGE is not set
+# CONFIG_SKY2 is not set
+CONFIG_NET_VENDOR_MELLANOX=y
+# CONFIG_MLX4_EN is not set
+# CONFIG_MLX4_CORE is not set
+# CONFIG_MLX5_CORE is not set
+CONFIG_NET_VENDOR_MICREL=y
+# CONFIG_KS8851_MLL is not set
+# CONFIG_KSZ884X_PCI is not set
+CONFIG_NET_VENDOR_MYRI=y
+# CONFIG_MYRI10GE is not set
+# CONFIG_FEALNX is not set
+CONFIG_NET_VENDOR_NATSEMI=y
+# CONFIG_NATSEMI is not set
+# CONFIG_NS83820 is not set
+CONFIG_NET_VENDOR_8390=y
+# CONFIG_NE2K_PCI is not set
+CONFIG_NET_VENDOR_NVIDIA=y
+# CONFIG_FORCEDETH is not set
+CONFIG_NET_VENDOR_OKI=y
+# CONFIG_ETHOC is not set
+CONFIG_NET_PACKET_ENGINE=y
+# CONFIG_HAMACHI is not set
+# CONFIG_YELLOWFIN is not set
+CONFIG_NET_VENDOR_QLOGIC=y
+# CONFIG_QLA3XXX is not set
+# CONFIG_QLCNIC is not set
+# CONFIG_QLGE is not set
+# CONFIG_NETXEN_NIC is not set
+CONFIG_NET_VENDOR_QUALCOMM=y
+CONFIG_NET_VENDOR_REALTEK=y
+# CONFIG_8139CP is not set
+# CONFIG_8139TOO is not set
+# CONFIG_R8169 is not set
+CONFIG_NET_VENDOR_RDC=y
+# CONFIG_R6040 is not set
+CONFIG_NET_VENDOR_ROCKER=y
+CONFIG_NET_VENDOR_SAMSUNG=y
+# CONFIG_SXGBE_ETH is not set
+CONFIG_NET_VENDOR_SEEQ=y
+CONFIG_NET_VENDOR_SILAN=y
+# CONFIG_SC92031 is not set
+CONFIG_NET_VENDOR_SIS=y
+# CONFIG_SIS900 is not set
+# CONFIG_SIS190 is not set
+# CONFIG_SFC is not set
+CONFIG_NET_VENDOR_SMSC=y
+# CONFIG_EPIC100 is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_SMSC9420 is not set
+CONFIG_NET_VENDOR_STMICRO=y
+# CONFIG_STMMAC_ETH is not set
+CONFIG_NET_VENDOR_SUN=y
+# CONFIG_HAPPYMEAL is not set
+# CONFIG_SUNGEM is not set
+# CONFIG_CASSINI is not set
+# CONFIG_NIU is not set
+CONFIG_NET_VENDOR_TEHUTI=y
+# CONFIG_TEHUTI is not set
+CONFIG_NET_VENDOR_TI=y
+# CONFIG_TI_CPSW_ALE is not set
+# CONFIG_TLAN is not set
+CONFIG_NET_VENDOR_VIA=y
+# CONFIG_VIA_RHINE is not set
+# CONFIG_VIA_VELOCITY is not set
+CONFIG_NET_VENDOR_WIZNET=y
+# CONFIG_WIZNET_W5100 is not set
+# CONFIG_WIZNET_W5300 is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+# CONFIG_NET_SB1000 is not set
+# CONFIG_PHYLIB is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+
+#
+# Host-side USB support is needed for USB Network Adapter support
+#
+CONFIG_WLAN=y
+# CONFIG_PRISM54 is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_WL_TI is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_LIFEBOOK=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+# CONFIG_MOUSE_PS2_SENTELIC is not set
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_SYNAPTICS_USB is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+CONFIG_DEVKMEM=y
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MFD_HSU is not set
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_RP2 is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_VIRTIO_CONSOLE=y
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_NVRAM is not set
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_MWAVE is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
+# CONFIG_HANGCHECK_TIMER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_TELCLOCK is not set
+CONFIG_DEVPORT=y
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+# CONFIG_GPIOLIB is not set
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_K8TEMP is not set
+# CONFIG_SENSORS_K10TEMP is not set
+# CONFIG_SENSORS_FAM15H_POWER is not set
+# CONFIG_SENSORS_APPLESMC is not set
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_I5500 is not set
+# CONFIG_SENSORS_CORETEMP is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_NCT6683 is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_VIA_CPUTEMP is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+
+#
+# ACPI drivers
+#
+# CONFIG_SENSORS_ACPI_POWER is not set
+# CONFIG_SENSORS_ATK0110 is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_GOV_STEP_WISE=y
+# CONFIG_THERMAL_GOV_BANG_BANG is not set
+# CONFIG_THERMAL_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_EMULATION is not set
+# CONFIG_INTEL_POWERCLAMP is not set
+# CONFIG_INTEL_SOC_DTS_THERMAL is not set
+# CONFIG_INT340X_THERMAL is not set
+
+#
+# Texas Instruments thermal drivers
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_RTSX_PCI is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+# CONFIG_AGP is not set
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+# CONFIG_VGA_SWITCHEROO is not set
+
+#
+# Direct Rendering Manager
+#
+# CONFIG_DRM is not set
+
+#
+# Frame buffer Devices
+#
+# CONFIG_FB is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+
+#
+# Console display driver support
+#
+CONFIG_VGA_CONSOLE=y
+# CONFIG_VGACON_SOFT_SCROLLBACK is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=80
+CONFIG_DUMMY_CONSOLE_ROWS=25
+CONFIG_SOUND=y
+# CONFIG_SOUND_OSS_CORE is not set
+# CONFIG_SND is not set
+# CONFIG_SOUND_PRIME is not set
+
+#
+# HID support
+#
+CONFIG_HID=y
+# CONFIG_HID_BATTERY_STRENGTH is not set
+# CONFIG_HIDRAW is not set
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=y
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=y
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=y
+# CONFIG_HID_AUREAL is not set
+CONFIG_HID_BELKIN=y
+CONFIG_HID_CHERRY=y
+CONFIG_HID_CHICONY=y
+CONFIG_HID_CYPRESS=y
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+CONFIG_HID_EZKEY=y
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=y
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+CONFIG_HID_LOGITECH=y
+# CONFIG_HID_LOGITECH_HIDPP is not set
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+# CONFIG_HID_MAGICMOUSE is not set
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MONTEREY=y
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+CONFIG_HID_PLANTRONICS=y
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB is not set
+
+#
+# USB port drivers
+#
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_NEW_LEDS is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+# CONFIG_EDAC is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+CONFIG_VIRTIO=y
+
+#
+# Virtio drivers
+#
+CONFIG_VIRTIO_PCI=y
+CONFIG_VIRTIO_PCI_LEGACY=y
+CONFIG_VIRTIO_BALLOON=y
+CONFIG_VIRTIO_MMIO=y
+# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+# CONFIG_STAGING is not set
+CONFIG_X86_PLATFORM_DEVICES=y
+# CONFIG_ACERHDF is not set
+# CONFIG_ASUS_LAPTOP is not set
+# CONFIG_DELL_SMO8800 is not set
+# CONFIG_FUJITSU_TABLET is not set
+# CONFIG_HP_ACCEL is not set
+# CONFIG_HP_WIRELESS is not set
+# CONFIG_THINKPAD_ACPI is not set
+# CONFIG_SENSORS_HDAPS is not set
+# CONFIG_INTEL_MENLOW is not set
+# CONFIG_ACPI_WMI is not set
+# CONFIG_TOPSTAR_LAPTOP is not set
+# CONFIG_TOSHIBA_BT_RFKILL is not set
+# CONFIG_TOSHIBA_HAPS is not set
+# CONFIG_ACPI_CMPC is not set
+# CONFIG_INTEL_IPS is not set
+# CONFIG_IBM_RTL is not set
+# CONFIG_SAMSUNG_Q10 is not set
+# CONFIG_INTEL_RST is not set
+# CONFIG_INTEL_SMARTCONNECT is not set
+# CONFIG_PVPANIC is not set
+# CONFIG_CHROME_PLATFORMS is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+CONFIG_CLKEVT_I8253=y
+CONFIG_I8253_LOCK=y
+CONFIG_CLKBLD_I8253=y
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Generic IOMMU Pagetable Support
+#
+# CONFIG_AMD_IOMMU is not set
+# CONFIG_INTEL_IOMMU is not set
+# CONFIG_IRQ_REMAP is not set
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_NTB is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_PWM is not set
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+# CONFIG_GENERIC_PHY is not set
+# CONFIG_BCM_KONA_USB2_PHY is not set
+# CONFIG_POWERCAP is not set
+# CONFIG_MCB is not set
+# CONFIG_THUNDERBOLT is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_EDD is not set
+CONFIG_FIRMWARE_MEMMAP=y
+# CONFIG_DELL_RBU is not set
+# CONFIG_DCDBAS is not set
+CONFIG_DMIID=y
+# CONFIG_DMI_SYSFS is not set
+CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y
+# CONFIG_ISCSI_IBFT_FIND is not set
+# CONFIG_GOOGLE_FIRMWARE is not set
+
+#
+# File systems
+#
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_FS_DAX is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
+CONFIG_QUOTA=y
+# CONFIG_QUOTA_NETLINK_INTERFACE is not set
+CONFIG_PRINT_QUOTA_WARNING=y
+# CONFIG_QUOTA_DEBUG is not set
+# CONFIG_QFMT_V1 is not set
+# CONFIG_QFMT_V2 is not set
+CONFIG_QUOTACTL=y
+CONFIG_AUTOFS4_FS=y
+# CONFIG_FUSE_FS is not set
+# CONFIG_OVERLAY_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+# CONFIG_ZISOFS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+# CONFIG_MSDOS_FS is not set
+# CONFIG_VFAT_FS is not set
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_QNX6FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+# CONFIG_NFS_FS is not set
+# CONFIG_NFSD is not set
+# CONFIG_CEPH_FS is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=y
+CONFIG_9P_FS_POSIX_ACL=y
+# CONFIG_9P_FS_SECURITY is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+# CONFIG_NLS_CODEPAGE_437 is not set
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+# CONFIG_NLS_ASCII is not set
+# CONFIG_NLS_ISO8859_1 is not set
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+# CONFIG_NLS_MAC_ROMAN is not set
+# CONFIG_NLS_MAC_CELTIC is not set
+# CONFIG_NLS_MAC_CENTEURO is not set
+# CONFIG_NLS_MAC_CROATIAN is not set
+# CONFIG_NLS_MAC_CYRILLIC is not set
+# CONFIG_NLS_MAC_GAELIC is not set
+# CONFIG_NLS_MAC_GREEK is not set
+# CONFIG_NLS_MAC_ICELAND is not set
+# CONFIG_NLS_MAC_INUIT is not set
+# CONFIG_NLS_MAC_ROMANIAN is not set
+# CONFIG_NLS_MAC_TURKISH is not set
+# CONFIG_NLS_UTF8 is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+
+#
+# Compile-time checks and compiler options
+#
+CONFIG_DEBUG_INFO=y
+# CONFIG_DEBUG_INFO_REDUCED is not set
+# CONFIG_DEBUG_INFO_SPLIT is not set
+# CONFIG_DEBUG_INFO_DWARF4 is not set
+# CONFIG_GDB_SCRIPTS is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+CONFIG_ARCH_WANT_FRAME_POINTERS=y
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+# CONFIG_MAGIC_SYSRQ is not set
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_DEBUG_SLAB is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_VIRTUAL is not set
+CONFIG_DEBUG_MEMORY_INIT=y
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+CONFIG_HAVE_ARCH_KMEMCHECK=y
+CONFIG_HAVE_ARCH_KASAN=y
+CONFIG_KASAN_SHADOW_OFFSET=0xdffffc0000000000
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+# CONFIG_LOCKUP_DETECTOR is not set
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+# CONFIG_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_TIMER_STATS is not set
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_STACKTRACE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+CONFIG_ARCH_HAS_DEBUG_STRICT_USER_COPY_CHECKS=y
+# CONFIG_DEBUG_STRICT_USER_COPY_CHECKS is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_FENTRY=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+CONFIG_FTRACE=y
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_ENABLE_DEFAULT_TRACERS is not set
+# CONFIG_FTRACE_SYSCALLS is not set
+# CONFIG_TRACER_SNAPSHOT is not set
+CONFIG_BRANCH_PROFILE_NONE=y
+# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set
+# CONFIG_PROFILE_ALL_BRANCHES is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_UPROBE_EVENT is not set
+# CONFIG_PROBE_EVENTS is not set
+# CONFIG_MMIOTRACE is not set
+# CONFIG_TRACEPOINT_BENCHMARK is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+# CONFIG_STRICT_DEVMEM is not set
+CONFIG_X86_VERBOSE_BOOTUP=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_EARLY_PRINTK_DBGP is not set
+# CONFIG_X86_PTDUMP is not set
+CONFIG_DEBUG_RODATA=y
+CONFIG_DEBUG_RODATA_TEST=y
+CONFIG_DOUBLEFAULT=y
+# CONFIG_DEBUG_TLBFLUSH is not set
+# CONFIG_IOMMU_DEBUG is not set
+# CONFIG_IOMMU_STRESS is not set
+CONFIG_HAVE_MMIOTRACE_SUPPORT=y
+CONFIG_IO_DELAY_TYPE_0X80=0
+CONFIG_IO_DELAY_TYPE_0XED=1
+CONFIG_IO_DELAY_TYPE_UDELAY=2
+CONFIG_IO_DELAY_TYPE_NONE=3
+CONFIG_IO_DELAY_0X80=y
+# CONFIG_IO_DELAY_0XED is not set
+# CONFIG_IO_DELAY_UDELAY is not set
+# CONFIG_IO_DELAY_NONE is not set
+CONFIG_DEFAULT_IO_DELAY_TYPE=0
+# CONFIG_CPA_DEBUG is not set
+# CONFIG_OPTIMIZE_INLINING is not set
+# CONFIG_DEBUG_NMI_SELFTEST is not set
+# CONFIG_X86_DEBUG_STATIC_CPU_HAS is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_USER=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=y
+# CONFIG_CRYPTO_MCRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=y
+CONFIG_CRYPTO_ABLK_HELPER=y
+CONFIG_CRYPTO_GLUE_HELPER_X86=y
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_SEQIV=y
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_CTR=y
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_LRW=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_XTS=y
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_XCBC=y
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32C_INTEL is not set
+# CONFIG_CRYPTO_CRC32 is not set
+# CONFIG_CRYPTO_CRC32_PCLMUL is not set
+# CONFIG_CRYPTO_CRCT10DIF is not set
+CONFIG_CRYPTO_GHASH=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=y
+CONFIG_CRYPTO_RMD128=y
+CONFIG_CRYPTO_RMD160=y
+CONFIG_CRYPTO_RMD256=y
+CONFIG_CRYPTO_RMD320=y
+CONFIG_CRYPTO_SHA1=y
+# CONFIG_CRYPTO_SHA1_SSSE3 is not set
+CONFIG_CRYPTO_SHA256_SSSE3=y
+CONFIG_CRYPTO_SHA512_SSSE3=y
+# CONFIG_CRYPTO_SHA1_MB is not set
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_TGR192=y
+CONFIG_CRYPTO_WP512=y
+# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_AES_X86_64=y
+CONFIG_CRYPTO_AES_NI_INTEL=y
+CONFIG_CRYPTO_ANUBIS=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=y
+CONFIG_CRYPTO_BLOWFISH_COMMON=y
+CONFIG_CRYPTO_BLOWFISH_X86_64=y
+CONFIG_CRYPTO_CAMELLIA=y
+CONFIG_CRYPTO_CAMELLIA_X86_64=y
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64=y
+CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64=y
+CONFIG_CRYPTO_CAST_COMMON=y
+CONFIG_CRYPTO_CAST5=y
+CONFIG_CRYPTO_CAST5_AVX_X86_64=y
+CONFIG_CRYPTO_CAST6=y
+CONFIG_CRYPTO_CAST6_AVX_X86_64=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_DES3_EDE_X86_64 is not set
+CONFIG_CRYPTO_FCRYPT=y
+CONFIG_CRYPTO_KHAZAD=y
+CONFIG_CRYPTO_SALSA20=y
+CONFIG_CRYPTO_SALSA20_X86_64=y
+CONFIG_CRYPTO_SEED=y
+CONFIG_CRYPTO_SERPENT=y
+CONFIG_CRYPTO_SERPENT_SSE2_X86_64=y
+CONFIG_CRYPTO_SERPENT_AVX_X86_64=y
+CONFIG_CRYPTO_SERPENT_AVX2_X86_64=y
+CONFIG_CRYPTO_TEA=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_TWOFISH_COMMON=y
+CONFIG_CRYPTO_TWOFISH_X86_64=y
+CONFIG_CRYPTO_TWOFISH_X86_64_3WAY=y
+CONFIG_CRYPTO_TWOFISH_AVX_X86_64=y
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ZLIB=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_LZ4=y
+CONFIG_CRYPTO_LZ4HC=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_DRBG_MENU is not set
+CONFIG_CRYPTO_USER_API=y
+CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_USER_API_SKCIPHER=y
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_HW is not set
+CONFIG_HAVE_KVM=y
+CONFIG_VIRTUALIZATION=y
+# CONFIG_KVM is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_GENERIC_FIND_FIRST_BIT=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y
+CONFIG_ARCH_HAS_FAST_MULTIPLIER=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
+# CONFIG_CRC_T10DIF is not set
+CONFIG_CRC_ITU_T=y
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+CONFIG_CRC7=y
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=y
+CONFIG_LZ4HC_COMPRESS=y
+CONFIG_LZ4_DECOMPRESS=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=y
+CONFIG_TEXTSEARCH_BM=y
+CONFIG_TEXTSEARCH_FSM=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_ARCH_HAS_SG_CHAIN=y
diff --git a/testing/hosts/winnetou/etc/openssl/research/index.txt b/testing/hosts/winnetou/etc/openssl/research/index.txt
index 25f5737..13510ba 100644
--- a/testing/hosts/winnetou/etc/openssl/research/index.txt
+++ b/testing/hosts/winnetou/etc/openssl/research/index.txt
@@ -3,8 +3,9 @@ R	100615195710Z	100703145747Z,superseded	02	unknown	/C=CH/O=Linux strongSwan/OU=
 R	120323210330Z	140324140605Z,superseded	03	unknown	/C=CH/O=Linux strongSwan/OU=Research OCSP Signing Authority/CN=ocsp.research.strongswan.org
 R	140323203747Z	140324142334Z,superseded	04	unknown	/C=CH/O=Linux strongSwan/OU=Research no CDP/CN=carol at strongswan.org
 R	151103161503Z	141128215838Z,superseded	05	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Duck Research CA
-V	150406092057Z		06	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=carol at strongswan.org
+R	150406092057Z	150426102340Z,superseded	06	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=carol at strongswan.org
 V	150702151839Z		07	unknown	/C=CH/O=Linux strongSwan/OU=Sales/CN=Sales CA
 V	190323140633Z		08	unknown	/C=CH/O=Linux strongSwan/OU=Research OCSP Signing Authority/CN=ocsp.research.strongswan.org
 V	190323142352Z		09	unknown	/C=CH/O=Linux strongSwan/OU=Research no CDP/CN=carol at strongswan.org
 V	190401220708Z		0A	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Duck Research CA
+V	190403102504Z		0B	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=carol at strongswan.org
diff --git a/testing/hosts/winnetou/etc/openssl/research/index.txt.old b/testing/hosts/winnetou/etc/openssl/research/index.txt.old
index 3fc101e..dc1c912 100644
--- a/testing/hosts/winnetou/etc/openssl/research/index.txt.old
+++ b/testing/hosts/winnetou/etc/openssl/research/index.txt.old
@@ -3,7 +3,8 @@ R	100615195710Z	100703145747Z,superseded	02	unknown	/C=CH/O=Linux strongSwan/OU=
 R	120323210330Z	140324140605Z,superseded	03	unknown	/C=CH/O=Linux strongSwan/OU=Research OCSP Signing Authority/CN=ocsp.research.strongswan.org
 R	140323203747Z	140324142334Z,superseded	04	unknown	/C=CH/O=Linux strongSwan/OU=Research no CDP/CN=carol at strongswan.org
 R	151103161503Z	141128215838Z,superseded	05	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Duck Research CA
-V	150406092057Z		06	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=carol at strongswan.org
+R	150406092057Z	150426102340Z,superseded	06	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=carol at strongswan.org
 V	150702151839Z		07	unknown	/C=CH/O=Linux strongSwan/OU=Sales/CN=Sales CA
 V	190323140633Z		08	unknown	/C=CH/O=Linux strongSwan/OU=Research OCSP Signing Authority/CN=ocsp.research.strongswan.org
 V	190323142352Z		09	unknown	/C=CH/O=Linux strongSwan/OU=Research no CDP/CN=carol at strongswan.org
+V	190401220708Z		0A	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Duck Research CA
diff --git a/testing/hosts/winnetou/etc/openssl/research/newcerts/0B.pem b/testing/hosts/winnetou/etc/openssl/research/newcerts/0B.pem
new file mode 100644
index 0000000..698e47c
--- /dev/null
+++ b/testing/hosts/winnetou/etc/openssl/research/newcerts/0B.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIELDCCAxSgAwIBAgIBCzANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjERMA8GA1UECxMIUmVzZWFyY2gxFDAS
+BgNVBAMTC1Jlc2VhcmNoIENBMB4XDTE1MDQyNjEwMjUwNFoXDTE5MDQwMzEwMjUw
+NFowWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
+BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZzCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKupuHqUUqSufsEtjSTZEkTF
+sTGWXQkwZoLbAPNlZ4PV0Dx1ju3xRvVtjQHN3Tsx6IsB1JO3k/dMExwttbeBA8HK
+oKYw+CFG8+6XWUU+tBT5xlwa5sdVUHIo8On1x7Rb3s+RDhJ2/YvCf/H13aOtqG+L
+7Xyt7OwRQZNx4Gx60sgU2Zhr9WsMslWJQeS92va6UiGYN4c6qRNyrS9zTZEJ0yib
+tflhd07LLcgz+jHqCdUcPK4g8+TH8HCtek0n2QRu3IfbEM+i6EaZjUJq1kp6k9HA
+IgKR48r9HVk3zBsWJBo6sxUn8/avFM54vdwD8NAClNn9xobEXsO3jwGljc5mb40C
+AwEAAaOCAQQwggEAMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdDgQWBBRd
+qfnvgHGNOog5OOLebmYkmJ/faTBtBgNVHSMEZjBkgBTndfCg8q0gzc1gI8zHyA8p
+891UIKFJpEcwRTELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3
+YW4xGzAZBgNVBAMTEnN0cm9uZ1N3YW4gUm9vdCBDQYIBIDAfBgNVHREEGDAWgRRj
+YXJvbEBzdHJvbmdzd2FuLm9yZzA3BgNVHR8EMDAuMCygKqAohiZodHRwOi8vY3Js
+LnN0cm9uZ3N3YW4ub3JnL3Jlc2VhcmNoLmNybDANBgkqhkiG9w0BAQsFAAOCAQEA
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
+-----END CERTIFICATE-----
diff --git a/testing/hosts/winnetou/etc/openssl/research/serial b/testing/hosts/winnetou/etc/openssl/research/serial
index eb589e9..d73cdef 100644
--- a/testing/hosts/winnetou/etc/openssl/research/serial
+++ b/testing/hosts/winnetou/etc/openssl/research/serial
@@ -1 +1 @@
-0B
+0C
diff --git a/testing/hosts/winnetou/etc/openssl/research/serial.old b/testing/hosts/winnetou/etc/openssl/research/serial.old
index d9bb888..eb589e9 100644
--- a/testing/hosts/winnetou/etc/openssl/research/serial.old
+++ b/testing/hosts/winnetou/etc/openssl/research/serial.old
@@ -1 +1 @@
-0A
+0B
diff --git a/testing/hosts/winnetou/etc/openssl/sales/index.txt b/testing/hosts/winnetou/etc/openssl/sales/index.txt
index 36b24a6..c4ff334 100644
--- a/testing/hosts/winnetou/etc/openssl/sales/index.txt
+++ b/testing/hosts/winnetou/etc/openssl/sales/index.txt
@@ -2,7 +2,8 @@ R	100322071017Z	100407093948Z,superseded	01	unknown	/C=CH/O=Linux strongSwan/OU=
 R	100615195536Z	100703150410Z,superseded	02	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Research CA
 R	120323211811Z	140324141327Z,superseded	03	unknown	/C=CH/O=Linux strongSwan/OU=Sales OCSP Signing Authority/CN=ocsp.sales.strongswan.org
 R	140323211053Z	140324141726Z,superseded	04	unknown	/C=CH/O=Linux strongSwan/OU=Sales no CDP/CN=dave at strongswan.org
-V	150406094241Z		05	unknown	/C=CH/O=Linux strongSwan/OU=Sales/CN=dave at strongswan.org
+R	150406094241Z	150426095935Z,superseded	05	unknown	/C=CH/O=Linux strongSwan/OU=Sales/CN=dave at strongswan.org
 V	150702152829Z		06	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Research CA
 V	190323141524Z		07	unknown	/C=CH/O=Linux strongSwan/OU=Sales OCSP Signing Authority/CN=ocsp.sales.strongswan.org
 V	190323152702Z		08	unknown	/C=CH/O=Linux strongSwan/OU=Sales no CDP/CN=dave at strongswan.org
+V	190403102220Z		09	unknown	/C=CH/O=Linux strongSwan/OU=Sales/CN=dave at strongswan.org
diff --git a/testing/hosts/winnetou/etc/openssl/sales/index.txt.old b/testing/hosts/winnetou/etc/openssl/sales/index.txt.old
index 1db0072..46d4c4b 100644
--- a/testing/hosts/winnetou/etc/openssl/sales/index.txt.old
+++ b/testing/hosts/winnetou/etc/openssl/sales/index.txt.old
@@ -2,6 +2,7 @@ R	100322071017Z	100407093948Z,superseded	01	unknown	/C=CH/O=Linux strongSwan/OU=
 R	100615195536Z	100703150410Z,superseded	02	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Research CA
 R	120323211811Z	140324141327Z,superseded	03	unknown	/C=CH/O=Linux strongSwan/OU=Sales OCSP Signing Authority/CN=ocsp.sales.strongswan.org
 R	140323211053Z	140324141726Z,superseded	04	unknown	/C=CH/O=Linux strongSwan/OU=Sales no CDP/CN=dave at strongswan.org
-V	150406094241Z		05	unknown	/C=CH/O=Linux strongSwan/OU=Sales/CN=dave at strongswan.org
+R	150406094241Z	150426095935Z,superseded	05	unknown	/C=CH/O=Linux strongSwan/OU=Sales/CN=dave at strongswan.org
 V	150702152829Z		06	unknown	/C=CH/O=Linux strongSwan/OU=Research/CN=Research CA
 V	190323141524Z		07	unknown	/C=CH/O=Linux strongSwan/OU=Sales OCSP Signing Authority/CN=ocsp.sales.strongswan.org
+V	190323152702Z		08	unknown	/C=CH/O=Linux strongSwan/OU=Sales no CDP/CN=dave at strongswan.org
diff --git a/testing/hosts/winnetou/etc/openssl/sales/newcerts/09.pem b/testing/hosts/winnetou/etc/openssl/sales/newcerts/09.pem
new file mode 100644
index 0000000..4718e7a
--- /dev/null
+++ b/testing/hosts/winnetou/etc/openssl/sales/newcerts/09.pem
@@ -0,0 +1,24 @@
+-----BEGIN CERTIFICATE-----
+MIIEHDCCAwSgAwIBAgIBCTANBgkqhkiG9w0BAQsFADBLMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEOMAwGA1UECxMFU2FsZXMxETAPBgNV
+BAMTCFNhbGVzIENBMB4XDTE1MDQyNjEwMjIyMFoXDTE5MDQwMzEwMjIyMFowVjEL
+MAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xDjAMBgNVBAsT
+BVNhbGVzMRwwGgYDVQQDFBNkYXZlQHN0cm9uZ3N3YW4ub3JnMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvNnrgEQdETpkdY/PaSj9KeNrg8+MCwCH/SPk
+UE6ijIn++yyhaZaji5JrA3z9ya+si0R/4PjxsgwjuqrxARV4gG63jKOmOLWMK9ER
+0/APr9KmXfnmFddqZwltGdo9hmDiBQimEdvvK4XK4nA2BY+pJ0b5go+5P4gIbHUN
+5GGh1u34R/9JDCvX1HHnIYmKv4ERD5TbODnKDjR7KT3q8Qy+DEndji+2Y1NWLot8
+XOynqCNW9Ii0Zs7850wzV1gz1kkm4Qdte0ndlUQu+gSbS7uM+AVPEgd0ZGY23ecA
+V2HsNtCGecj/OnsQ4z8+gSIKJfwEqeumVsSbZimllo5mf3l7jwIDAQABo4H/MIH8
+MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdDgQWBBSBwMHfoTTG9g4LmkL/
+kBl3thRfxzBtBgNVHSMEZjBkgBRfmxNG+SByyADViLWnTC6X6guTKKFJpEcwRTEL
+MAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMT
+EnN0cm9uZ1N3YW4gUm9vdCBDQYIBITAeBgNVHREEFzAVgRNkYXZlQHN0cm9uZ3N3
+YW4ub3JnMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuc3Ryb25nc3dhbi5v
+cmcvc2FsZXMuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQC5VfuhrOErCX6nlfnzgXIB
+HheWTfcuobNz1cRatdIGRZVBLIktkQjABsX62t0wcCJ4gUMgT0DxgR/bZQDv9tp5
+q6bo5XJM+bFkuf0NiPme+w9Or+VYcuyiljHnHF3rihK2ZFOBXl2kY667tiGFML3B
+jhaYQVHA0ZsSfe3Auxccku0U25dJNLq1+ATjeDuye8/NJqS95YBcMZzWiwG/VgMF
+mCeiygAobWmIk2LOijFFpNN2ySCiLimueQp/DO3kBdWlhael3Ee9lkA5bqoFchpb
+HH8eQKyOLhRnB2Lk/RhC3mGIFjW127sJdjdWkroyULepnULLyQQA6jy+tEu4XZ2C
+-----END CERTIFICATE-----
diff --git a/testing/hosts/winnetou/etc/openssl/sales/serial b/testing/hosts/winnetou/etc/openssl/sales/serial
index 86397e5..d9bb888 100644
--- a/testing/hosts/winnetou/etc/openssl/sales/serial
+++ b/testing/hosts/winnetou/etc/openssl/sales/serial
@@ -1 +1 @@
-09
+0A
diff --git a/testing/hosts/winnetou/etc/openssl/sales/serial.old b/testing/hosts/winnetou/etc/openssl/sales/serial.old
index adb9de8..86397e5 100644
--- a/testing/hosts/winnetou/etc/openssl/sales/serial.old
+++ b/testing/hosts/winnetou/etc/openssl/sales/serial.old
@@ -1 +1 @@
-08
+09
diff --git a/testing/scripts/build-baseimage b/testing/scripts/build-baseimage
index c927934..d9500cb 100755
--- a/testing/scripts/build-baseimage
+++ b/testing/scripts/build-baseimage
@@ -16,9 +16,9 @@ INC=automake,autoconf,libtool,bison,flex,gperf,pkg-config,gettext
 INC=$INC,build-essential,libgmp-dev,libldap2-dev,libcurl4-openssl-dev,ethtool
 INC=$INC,libxml2-dev,libtspi-dev,libsqlite3-dev,openssh-server,tcpdump,psmisc
 INC=$INC,openssl,vim,sqlite3,conntrack,gdb,cmake,libxerces-c2-dev,libltdl-dev
-INC=$INC,liblog4cxx10-dev,libboost-thread-dev,libboost-system-dev,git-core
+INC=$INC,liblog4cxx10-dev,libboost-thread-dev,libboost-system-dev,git-core,iperf
 INC=$INC,less,acpid,acpi-support-base,libldns-dev,libunbound-dev,dnsutils,screen
-INC=$INC,gnat,gprbuild,libahven3-dev,libxmlada4.1-dev,libgmpada3-dev
+INC=$INC,gnat,gprbuild,libahven3-dev,libxmlada4.1-dev,libgmpada3-dev,htop
 INC=$INC,libalog0.4.1-base-dev,hostapd,libsoup2.4-dev,ca-certificates,unzip
 INC=$INC,python,python-setuptools,python-dev,python-pip
 INC=$INC,libjson0-dev,libxslt1-dev,libapache2-mod-wsgi,iptables-dev
diff --git a/testing/scripts/build-guestkernel b/testing/scripts/build-guestkernel
index 40aa1b4..17f22bd 100755
--- a/testing/scripts/build-guestkernel
+++ b/testing/scripts/build-guestkernel
@@ -14,7 +14,7 @@ cd $BUILDDIR
 
 if [ ! -f "$KERNELTARBALL" ]
 then
-	url=ftp://ftp.kernel.org/pub/linux/kernel/v3.x/$KERNELTARBALL
+	url=ftp://ftp.kernel.org/pub/linux/kernel/v${KERNELVERSION:0:1}.x/$KERNELTARBALL
 	log_action "Downloading $url"
 	execute "wget -q $url"
 fi
diff --git a/testing/scripts/recipes/005_anet.mk b/testing/scripts/recipes/005_anet.mk
index 2d982d0..b02d630 100644
--- a/testing/scripts/recipes/005_anet.mk
+++ b/testing/scripts/recipes/005_anet.mk
@@ -2,7 +2,7 @@
 
 PKG = anet
 SRC = http://git.codelabs.ch/git/$(PKG).git
-REV = v0.2.2
+REV = v0.3.1
 
 PREFIX = /usr/local/ada
 
diff --git a/testing/scripts/recipes/006_tkm-rpc.mk b/testing/scripts/recipes/006_tkm-rpc.mk
index 6c4aae0..5c98123 100644
--- a/testing/scripts/recipes/006_tkm-rpc.mk
+++ b/testing/scripts/recipes/006_tkm-rpc.mk
@@ -2,7 +2,7 @@
 
 PKG = tkm-rpc
 SRC = http://git.codelabs.ch/git/$(PKG).git
-REV = v0.1
+REV = v0.2
 
 PREFIX = /usr/local/ada
 
diff --git a/testing/scripts/recipes/010_tkm.mk b/testing/scripts/recipes/010_tkm.mk
index 12eafd6..5abd217 100644
--- a/testing/scripts/recipes/010_tkm.mk
+++ b/testing/scripts/recipes/010_tkm.mk
@@ -2,7 +2,7 @@
 
 PKG = tkm
 SRC = http://git.codelabs.ch/git/$(PKG).git
-REV = v0.1.1
+REV = v0.1.2
 
 export ADA_PROJECT_PATH=/usr/local/ada/lib/gnat
 
diff --git a/testing/scripts/recipes/012_openssl.mk b/testing/scripts/recipes/012_openssl.mk
index 9312445..16aec23 100644
--- a/testing/scripts/recipes/012_openssl.mk
+++ b/testing/scripts/recipes/012_openssl.mk
@@ -7,7 +7,7 @@ SRC = http://download.strongswan.org/testing/openssl-fips/
 all: install
 
 $(PKG):
-	wget -r $(SRC) --no-directories --directory-prefix $(PKG) --accept deb
+	wget -r $(SRC) --no-directories --directory-prefix $(PKG) --accept deb --no-parent
 
 install: $(PKG)
 	cd $(PKG) && dpkg -i *.deb
diff --git a/testing/testing.conf b/testing/testing.conf
index f5e65b2..737bcae 100644
--- a/testing/testing.conf
+++ b/testing/testing.conf
@@ -24,14 +24,14 @@ fi
 : ${TESTDIR=/srv/strongswan-testing}
 
 # Kernel configuration
-: ${KERNELVERSION=3.15.1}
+: ${KERNELVERSION=4.0}
 : ${KERNEL=linux-$KERNELVERSION}
 : ${KERNELTARBALL=$KERNEL.tar.xz}
-: ${KERNELCONFIG=$DIR/../config/kernel/config-3.15}
-: ${KERNELPATCH=ha-3.15-ah-abicompat.patch.bz2}
+: ${KERNELCONFIG=$DIR/../config/kernel/config-4.0}
+: ${KERNELPATCH=ha-3.18-abicompat.patch.bz2}
 
 # strongSwan version used in tests
-: ${SWANVERSION=5.2.0}
+: ${SWANVERSION=5.3.1}
 
 # Build directory where the guest kernel and images will be built
 : ${BUILDDIR=$TESTDIR/build}
diff --git a/testing/tests/af-alg/rw-cert/pretest.dat b/testing/tests/af-alg/rw-cert/pretest.dat
index 8bbea14..c582e03 100644
--- a/testing/tests/af-alg/rw-cert/pretest.dat
+++ b/testing/tests/af-alg/rw-cert/pretest.dat
@@ -4,6 +4,6 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-carol::sleep 1
+carol::sleep 3
 carol::ipsec up home
 dave::ipsec up home
diff --git a/testing/tests/gcrypt-ikev2/rw-cert/pretest.dat b/testing/tests/gcrypt-ikev2/rw-cert/pretest.dat
index 8bbea14..c582e03 100644
--- a/testing/tests/gcrypt-ikev2/rw-cert/pretest.dat
+++ b/testing/tests/gcrypt-ikev2/rw-cert/pretest.dat
@@ -4,6 +4,6 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-carol::sleep 1
+carol::sleep 3
 carol::ipsec up home
 dave::ipsec up home
diff --git a/testing/tests/ha/active-passive/description.txt b/testing/tests/ha/active-passive/description.txt
new file mode 100644
index 0000000..519fa33
--- /dev/null
+++ b/testing/tests/ha/active-passive/description.txt
@@ -0,0 +1,8 @@
+The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each 
+to the virtual gateway <b>mars</b> implemented by the two real gateways
+<b>alice</b> and <b>moon</b> in a <b>High Availability</b> (HA) setup 
+based on <b>ClusterIP</b>. The HA synchronisation link between the two
+gatways is secured by an IPsec transport connection. At the outset
+<b>alice</b> is the active and <b>moon</b> is the passive gateway.
+After <b>alice</b> gets killed <b>moon</b> automatically takes over
+all existing IKE_SAs and CHILD_SAs.
diff --git a/testing/tests/ha/active-passive/evaltest.dat b/testing/tests/ha/active-passive/evaltest.dat
new file mode 100644
index 0000000..448f283
--- /dev/null
+++ b/testing/tests/ha/active-passive/evaltest.dat
@@ -0,0 +1,32 @@
+alice::cat /var/log/daemon.log::HA segment 1 was not handled, taking::YES
+moon:: cat /var/log/daemon.log::remote node takes segment 1::YES
+alice::ipsec status 2> /dev/null::ha.*ESTABLISHED.*10.1.0.10.*10.1.0.1::YES
+alice::ipsec status 2> /dev/null::rw.*ESTABLISHED.*mars.strongswan.org.*carol at strongswan.org::YES
+alice::ipsec status 2> /dev/null::rw.*ESTABLISHED.*mars.strongswan.org.*dave at strongswan.org::YES
+moon:: ipsec status 2> /dev/null::ha.*ESTABLISHED.*10.1.0.1.*10.1.0.10::YES
+moon:: ipsec status 2> /dev/null::rw.*PASSIVE.*mars.strongswan.org.*carol at strongswan.org::YES
+moon:: ipsec status 2> /dev/null::rw.*PASSIVE.*mars.strongswan.org.*dave at strongswan.org::YES
+carol::ipsec status 2> /dev/null::home.*ESTABLISHED.*carol at strongswan.org.*mars.strongswan.org::YES
+dave:: ipsec status 2> /dev/null::home.*ESTABLISHED.*dave at strongswan.org.*mars.strongswan.org::YES
+alice::cat /var/log/daemon.log::HA segment 1 activated::YES
+alice::cat /var/log/daemon.log::handling HA CHILD_SA::YES
+moon:: cat /var/log/daemon.log::installed HA CHILD_SA::YES
+carol::ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
+dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
+alice::ip xfrm policy flush::no output expected::NO
+alice::ip xfrm state flush::no output expected::NO
+alice::killall -9 starter charon::no output expected::NO
+carol::sleep 3::no output expected::NO
+moon:: cat /var/log/daemon.log::no heartbeat received, taking all segments::YES
+moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*mars.strongswan.org.*carol at strongswan.org::YES
+moon:: ipsec status 2> /dev/null::rw.*ESTABLISHED.*mars.strongswan.org.*dave at strongswan.org::YES
+carol::ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
+dave:: ping -c 1 PH_IP_VENUS::64 bytes from PH_IP_VENUS: icmp_req=1::YES
+carol::tcpdump::IP carol.strongswan.org > mars.strongswan.org: ESP::YES
+carol::tcpdump::IP mars.strongswan.org > carol.strongswan.org: ESP::YES
+dave::tcpdump::IP dave.strongswan.org > mars.strongswan.org: ESP::YES
+dave::tcpdump::IP mars.strongswan.org > dave.strongswan.org: ESP::YES
+venus::tcpdump::IP carol.strongswan.org > venus.strongswan.org: ICMP echo request::YES
+venus::tcpdump::IP venus.strongswan.org > carol.strongswan.org: ICMP echo reply::YES
+venus::tcpdump::IP dave.strongswan.org > venus.strongswan.org: ICMP echo request::YES
+venus::tcpdump::IP venus.strongswan.org > dave.strongswan.org: ICMP echo reply::YES
diff --git a/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.conf b/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.conf
new file mode 100644
index 0000000..363473b
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.conf
@@ -0,0 +1,19 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+
+conn rw
+	left=192.168.0.5
+	leftcert=marsCert.pem
+	leftid=@mars.strongswan.org
+	leftsubnet=10.1.0.0/16
+	leftfirewall=yes
+	right=%any
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.d/certs/marsCert.pem b/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.d/certs/marsCert.pem
new file mode 100644
index 0000000..5077ab1
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.d/certs/marsCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEQDCCAyigAwIBAgIBIzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTEwMTEyMDE2NTkyMloXDTE1MTExOTE2NTkyMlowZDELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xHDAaBgNVBAsTE1ZpcnR1
+YWwgVlBOIEdhdGV3YXkxHDAaBgNVBAMTE21hcnMuc3Ryb25nc3dhbi5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSNOzGeYVXLzZv43dinLxAC67D
+l/1pUIwZIT7pzWGTbbeYBgRQDIV46HAAJTxnYWEq2eEecTbLQhgX7QPUeOJXk9vU
+j5FeCrNXkv01FPsjwRdvBCWwEHYhGczeP9/8Gg7zU36t3EySv5ZRYKqv6O42lrg+
+E79wm2BwdPik7G5mCLmXn3Bg1IKNJhBJWKkP366dpAukywP1gGMwmW3MqfVm2fXB
+QVDlqCJjpvyNiJhW6UqOf+NkKZPugjlfWMQKyFxEC6krBDT4WdnoKj5S0hyyeAvG
+7HlL5YSiPhd1DNaxV0OX/aBwYFW0zMZOVmYLv2cwRVf3LlP/3Nv66BtjtxwZAgMB
+AAGjggEaMIIBFjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDqDAdBgNVHQ4EFgQUuo7D
+ahZ1x1JvkUAc2aAHvlfUu7EwbQYDVR0jBGYwZIAUXafdcAZRMn7ntm2zteXgYOou
+Te+hSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2Fu
+MRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCAQAwHgYDVR0RBBcwFYITbWFy
+cy5zdHJvbmdzd2FuLm9yZzATBgNVHSUEDDAKBggrBgEFBQcDATA5BgNVHR8EMjAw
+MC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4ub3JnL3N0cm9uZ3N3YW4uY3Js
+MA0GCSqGSIb3DQEBCwUAA4IBAQCMaii+mvarQiElzu5VmIPQfrec+S5DUun9Di9/
+n23B8UdYtoITtu38vm2kHIo/oaYBFtUziBTFb48zyMJxVqc42JbwQ0CCO7TekJ2R
+atGO72QG69hZkspfNijZr1576jBYyNxCfOOAXlf0zQpkVc0dcuxgQM1IrFH+cz+7
+ekupVdM2IZoouqWDU0M2nAze4du1rKAgG0Cuy3I4tCN43PR4BmggfaaKBOzU8Ju1
+b/FUFKKdPTrTfi52OywgzcDMZPyWgmHZb60koH7jXiVyP30OHVwMzU6kNXxOx2Le
+i2lQE1/k8yL3k1ht48upXfuTZU4gUVCUc2CYUVHOOjNHk3BU
+-----END CERTIFICATE-----
diff --git a/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.d/private/marsKey.pem b/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.d/private/marsKey.pem
new file mode 100644
index 0000000..9196315
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.d/private/marsKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0jTsxnmFVy82b+N3Ypy8QAuuw5f9aVCMGSE+6c1hk223mAYE
+UAyFeOhwACU8Z2FhKtnhHnE2y0IYF+0D1HjiV5Pb1I+RXgqzV5L9NRT7I8EXbwQl
+sBB2IRnM3j/f/BoO81N+rdxMkr+WUWCqr+juNpa4PhO/cJtgcHT4pOxuZgi5l59w
+YNSCjSYQSVipD9+unaQLpMsD9YBjMJltzKn1Ztn1wUFQ5agiY6b8jYiYVulKjn/j
+ZCmT7oI5X1jECshcRAupKwQ0+FnZ6Co+UtIcsngLxux5S+WEoj4XdQzWsVdDl/2g
+cGBVtMzGTlZmC79nMEVX9y5T/9zb+ugbY7ccGQIDAQABAoIBAHmuW1W06KQEV33D
+bctusWZdnOfqZq39C2xMm2+aDR7bh0iASyTPasAHxTXAWEv7ydSVVURbAv38H5hS
+AkKPS26oz7sm9F480X4jP2Hn6EzVLKx9+RcHIGqe1cHdtdnod7kRHyajfMwCDZDD
+5Wp46tQ8wSBmLA6SUuwmOfy2RF3ZKGSYUxZEA3Pj7oMuCwgUVg62MN5kbOdviW1u
+DpRAWO3UE64nHYSFYeRiVRYmrZ0pOF2oBkfuALn2frcGX0v97xxNH9mpJfc1T6Km
+KwfSpKtB5BlF4QRukZC3smoiO0aXI4ZuxuuRzujYIHJvp21+Lg5UybwOu/w4R1nB
+UnaCZHUCgYEA7/5Q06+Mpn9UxxcP5tNGeeGEV5EVhXzLHq8IyTb+Dp8AnJ+EXuHK
+QAiyxvavorZCQN9xAa3IOi1789NeaVWU7DKWI4pMfXETkFGYI2q08bf16XYAvSgt
+AOeEKzILADHaqOKbLJhFxUIAGLJ4LP+IBapKrTHF5qELW6jO4YYaH1cCgYEA4DoG
+3MgDnmCsikmDkP7Z/HS6XwAqKKF6CMlJW05Dq5J/wgWIXfBU9QdWbHl2H2fa/n1b
+M8u3M4wA9NY7kKtan3VBDFxEARRcSX50YB1TCLnplDVO3IxYUkjfKhTjBFF9R0Iv
+2nj8QXAnb+vbx+30Pbi7bkvb93nSe4yzXPFtKg8CgYEAuZso7Z5eG8JsUZEvdig9
+4DMehA6r41IRUUizddK3B53G/lqMKEldfsp7YU8VpLRqZvunzVGWgg/9RiRZZwOO
+KmIxJYlnALj8FWhVTkbPbAYHBKiDh8dTjth+ql2Ijn0ADA89TW7yvsz9gBw+vyZd
+D2yVVn8g++3e9+OFJHvvJf8CgYBHEn18W7Wx7Mij6JtYST+FIua0GBRE3rIUuOCU
+nWEbsAroz+IijHwRUqsVJQbI+51RjyBqcYb3QshG0uT8fSPzaTIeHdy8TtzVusxe
+bs0T9gHQpXkCtUWFh22dJBO1GbNQ8+zBHhovD8KgWi1G2OjS64wVcNwfPDD4UmfD
+7Q6CBwKBgBOeDK7R5mGwC4nV1Y+KDBgvE/W8BloZpcD+d7sfZsrU8w7LemBKreDa
+qT1vgk1ZOeHFkvwdWH7LSxRUEGRd+HmqOFKv/hfmxXHlepdnjqt4JMNo9UyddXmX
+onErIOM7BXcBmqvY77ODDOk8ER3zUjKHvYUzxz4PPuEM3hGTTRbQ
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.secrets b/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.secrets
new file mode 100644
index 0000000..d65b96e
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/alice/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA marsKey.pem
diff --git a/testing/tests/ha/active-passive/hosts/alice/etc/iptables.rules b/testing/tests/ha/active-passive/hosts/alice/etc/iptables.rules
new file mode 100644
index 0000000..8735786
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/alice/etc/iptables.rules
@@ -0,0 +1,57 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# forward ESP-tunneled traffic
+-A FORWARD -i eth1 -m policy --dir in  --pol ipsec --proto esp -s PH_IP_CAROL -j ACCEPT
+-A FORWARD -i eth1 -m policy --dir in  --pol ipsec --proto esp -s PH_IP_DAVE  -j ACCEPT
+-A FORWARD -o eth1 -m policy --dir out --pol ipsec --proto esp -j ACCEPT
+
+# clusterip rules
+-A INPUT -i eth1 -d 192.168.0.5 -j CLUSTERIP --new --hashmode sourceip --clustermac 01:00:c0:a8:00:05 --total-nodes 1 --local-node 0 
+-A INPUT -i eth0 -d 10.1.0.5    -j CLUSTERIP --new --hashmode sourceip --clustermac 01:00:0a:01:00:05 --total-nodes 1 --local-node 0 
+
+# allow esp
+-A INPUT  -p 50 -j ACCEPT
+-A OUTPUT -p 50 -d PH_IP_CAROL -j ACCEPT
+-A OUTPUT -p 50 -d PH_IP_DAVE -j ACCEPT
+
+# allow esp on internal interface
+-A OUTPUT -o eth0 -s PH_IP_ALICE -d PH_IP_MOON1 -p 50 -j ACCEPT
+
+# allow IKE on internal interface
+-A INPUT  -i eth0 -d PH_IP_ALICE -s PH_IP_MOON1 -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth0 -s PH_IP_ALICE -d PH_IP_MOON1 -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow IKE
+-A INPUT  -i eth1 -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth1 -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow MobIKE
+-A INPUT  -i eth1 -p udp --sport 4500 --dport 4500 -j ACCEPT
+-A OUTPUT -o eth1 -p udp --dport 4500 --sport 4500 -j ACCEPT
+
+# allow crl fetch from winnetou
+-A INPUT  -i eth1 -p tcp --sport 80 -s PH_IP_WINNETOU -j ACCEPT
+-A OUTPUT -o eth1 -p tcp --dport 80 -d PH_IP_WINNETOU -j ACCEPT
+
+# allow heartbeat
+-A INPUT  -i eth0 -d PH_IP_ALICE -s PH_IP_MOON1 -p udp --dport 4510 --sport 4510 -j ACCEPT
+-A OUTPUT -o eth0 -s PH_IP_ALICE -d PH_IP_MOON1 -p udp --dport 4510 --sport 4510 -j ACCEPT
+
+# allow ICMP type 3
+-A INPUT  -i eth0 -d PH_IP_ALICE -s PH_IP_MOON1 -p icmp --icmp-type 3 -j ACCEPT
+-A OUTPUT -o eth0 -s PH_IP_ALICE -d PH_IP_MOON1 -p icmp --icmp-type 3 -j ACCEPT
+
+# allow IGMP multicasts
+-A INPUT  -d 224.0.0.1 -p igmp -j ACCEPT
+-A OUTPUT -s 224.0.0.1 -p igmp -j ACCEPT
+
+# allow ssh
+-A INPUT  -p tcp --dport 22 -j ACCEPT
+-A OUTPUT -p tcp --sport 22 -j ACCEPT
+
+COMMIT
diff --git a/testing/tests/ha/active-passive/hosts/alice/etc/strongswan.conf b/testing/tests/ha/active-passive/hosts/alice/etc/strongswan.conf
new file mode 100644
index 0000000..d6d4539
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/alice/etc/strongswan.conf
@@ -0,0 +1,16 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default ha 
+  plugins {
+    ha {
+      local = PH_IP_ALICE
+      remote = PH_IP_MOON1
+      secret = PliyxREnfoPaSXDJx1NrlH0kkKXT/LWZ
+      segment_count = 1 
+      fifo_interface = yes
+      monitor = yes
+    }
+  }
+}
+
diff --git a/testing/tests/ha/active-passive/hosts/carol/etc/ipsec.conf b/testing/tests/ha/active-passive/hosts/carol/etc/ipsec.conf
new file mode 100644
index 0000000..3040f6a
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/carol/etc/ipsec.conf
@@ -0,0 +1,20 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+
+conn home
+	left=PH_IP_CAROL
+	leftcert=carolCert.pem
+	leftid=carol at strongswan.org
+	leftfirewall=yes
+	right=192.168.0.5
+	rightid=@mars.strongswan.org
+	rightsubnet=10.1.0.0/16
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ha/active-passive/hosts/carol/etc/strongswan.conf b/testing/tests/ha/active-passive/hosts/carol/etc/strongswan.conf
new file mode 100644
index 0000000..e58af9e
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/carol/etc/strongswan.conf
@@ -0,0 +1,5 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+}
diff --git a/testing/tests/ha/active-passive/hosts/dave/etc/ipsec.conf b/testing/tests/ha/active-passive/hosts/dave/etc/ipsec.conf
new file mode 100644
index 0000000..27d6b8d
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/dave/etc/ipsec.conf
@@ -0,0 +1,20 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+
+conn home
+	left=PH_IP_DAVE
+	leftcert=daveCert.pem
+	leftid=dave at strongswan.org
+	leftfirewall=yes
+	right=192.168.0.5
+	rightid=@mars.strongswan.org
+	rightsubnet=10.1.0.0/16
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ha/active-passive/hosts/dave/etc/strongswan.conf b/testing/tests/ha/active-passive/hosts/dave/etc/strongswan.conf
new file mode 100644
index 0000000..ecbad66
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/dave/etc/strongswan.conf
@@ -0,0 +1,6 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac xcbc ctr ccm gcm stroke kernel-netlink socket-default updown
+}
+
diff --git a/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.conf b/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.conf
new file mode 100644
index 0000000..363473b
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,19 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+config setup
+
+conn %default
+	ikelifetime=60m
+	keylife=20m
+	rekeymargin=3m
+	keyingtries=1
+
+conn rw
+	left=192.168.0.5
+	leftcert=marsCert.pem
+	leftid=@mars.strongswan.org
+	leftsubnet=10.1.0.0/16
+	leftfirewall=yes
+	right=%any
+	keyexchange=ikev2
+	auto=add
diff --git a/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.d/certs/marsCert.pem b/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.d/certs/marsCert.pem
new file mode 100644
index 0000000..5077ab1
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.d/certs/marsCert.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIEQDCCAyigAwIBAgIBIzANBgkqhkiG9w0BAQsFADBFMQswCQYDVQQGEwJDSDEZ
+MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjEbMBkGA1UEAxMSc3Ryb25nU3dhbiBS
+b290IENBMB4XDTEwMTEyMDE2NTkyMloXDTE1MTExOTE2NTkyMlowZDELMAkGA1UE
+BhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xHDAaBgNVBAsTE1ZpcnR1
+YWwgVlBOIEdhdGV3YXkxHDAaBgNVBAMTE21hcnMuc3Ryb25nc3dhbi5vcmcwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDSNOzGeYVXLzZv43dinLxAC67D
+l/1pUIwZIT7pzWGTbbeYBgRQDIV46HAAJTxnYWEq2eEecTbLQhgX7QPUeOJXk9vU
+j5FeCrNXkv01FPsjwRdvBCWwEHYhGczeP9/8Gg7zU36t3EySv5ZRYKqv6O42lrg+
+E79wm2BwdPik7G5mCLmXn3Bg1IKNJhBJWKkP366dpAukywP1gGMwmW3MqfVm2fXB
+QVDlqCJjpvyNiJhW6UqOf+NkKZPugjlfWMQKyFxEC6krBDT4WdnoKj5S0hyyeAvG
+7HlL5YSiPhd1DNaxV0OX/aBwYFW0zMZOVmYLv2cwRVf3LlP/3Nv66BtjtxwZAgMB
+AAGjggEaMIIBFjAJBgNVHRMEAjAAMAsGA1UdDwQEAwIDqDAdBgNVHQ4EFgQUuo7D
+ahZ1x1JvkUAc2aAHvlfUu7EwbQYDVR0jBGYwZIAUXafdcAZRMn7ntm2zteXgYOou
+Te+hSaRHMEUxCzAJBgNVBAYTAkNIMRkwFwYDVQQKExBMaW51eCBzdHJvbmdTd2Fu
+MRswGQYDVQQDExJzdHJvbmdTd2FuIFJvb3QgQ0GCAQAwHgYDVR0RBBcwFYITbWFy
+cy5zdHJvbmdzd2FuLm9yZzATBgNVHSUEDDAKBggrBgEFBQcDATA5BgNVHR8EMjAw
+MC6gLKAqhihodHRwOi8vY3JsLnN0cm9uZ3N3YW4ub3JnL3N0cm9uZ3N3YW4uY3Js
+MA0GCSqGSIb3DQEBCwUAA4IBAQCMaii+mvarQiElzu5VmIPQfrec+S5DUun9Di9/
+n23B8UdYtoITtu38vm2kHIo/oaYBFtUziBTFb48zyMJxVqc42JbwQ0CCO7TekJ2R
+atGO72QG69hZkspfNijZr1576jBYyNxCfOOAXlf0zQpkVc0dcuxgQM1IrFH+cz+7
+ekupVdM2IZoouqWDU0M2nAze4du1rKAgG0Cuy3I4tCN43PR4BmggfaaKBOzU8Ju1
+b/FUFKKdPTrTfi52OywgzcDMZPyWgmHZb60koH7jXiVyP30OHVwMzU6kNXxOx2Le
+i2lQE1/k8yL3k1ht48upXfuTZU4gUVCUc2CYUVHOOjNHk3BU
+-----END CERTIFICATE-----
diff --git a/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.d/private/marsKey.pem b/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.d/private/marsKey.pem
new file mode 100644
index 0000000..9196315
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.d/private/marsKey.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEowIBAAKCAQEA0jTsxnmFVy82b+N3Ypy8QAuuw5f9aVCMGSE+6c1hk223mAYE
+UAyFeOhwACU8Z2FhKtnhHnE2y0IYF+0D1HjiV5Pb1I+RXgqzV5L9NRT7I8EXbwQl
+sBB2IRnM3j/f/BoO81N+rdxMkr+WUWCqr+juNpa4PhO/cJtgcHT4pOxuZgi5l59w
+YNSCjSYQSVipD9+unaQLpMsD9YBjMJltzKn1Ztn1wUFQ5agiY6b8jYiYVulKjn/j
+ZCmT7oI5X1jECshcRAupKwQ0+FnZ6Co+UtIcsngLxux5S+WEoj4XdQzWsVdDl/2g
+cGBVtMzGTlZmC79nMEVX9y5T/9zb+ugbY7ccGQIDAQABAoIBAHmuW1W06KQEV33D
+bctusWZdnOfqZq39C2xMm2+aDR7bh0iASyTPasAHxTXAWEv7ydSVVURbAv38H5hS
+AkKPS26oz7sm9F480X4jP2Hn6EzVLKx9+RcHIGqe1cHdtdnod7kRHyajfMwCDZDD
+5Wp46tQ8wSBmLA6SUuwmOfy2RF3ZKGSYUxZEA3Pj7oMuCwgUVg62MN5kbOdviW1u
+DpRAWO3UE64nHYSFYeRiVRYmrZ0pOF2oBkfuALn2frcGX0v97xxNH9mpJfc1T6Km
+KwfSpKtB5BlF4QRukZC3smoiO0aXI4ZuxuuRzujYIHJvp21+Lg5UybwOu/w4R1nB
+UnaCZHUCgYEA7/5Q06+Mpn9UxxcP5tNGeeGEV5EVhXzLHq8IyTb+Dp8AnJ+EXuHK
+QAiyxvavorZCQN9xAa3IOi1789NeaVWU7DKWI4pMfXETkFGYI2q08bf16XYAvSgt
+AOeEKzILADHaqOKbLJhFxUIAGLJ4LP+IBapKrTHF5qELW6jO4YYaH1cCgYEA4DoG
+3MgDnmCsikmDkP7Z/HS6XwAqKKF6CMlJW05Dq5J/wgWIXfBU9QdWbHl2H2fa/n1b
+M8u3M4wA9NY7kKtan3VBDFxEARRcSX50YB1TCLnplDVO3IxYUkjfKhTjBFF9R0Iv
+2nj8QXAnb+vbx+30Pbi7bkvb93nSe4yzXPFtKg8CgYEAuZso7Z5eG8JsUZEvdig9
+4DMehA6r41IRUUizddK3B53G/lqMKEldfsp7YU8VpLRqZvunzVGWgg/9RiRZZwOO
+KmIxJYlnALj8FWhVTkbPbAYHBKiDh8dTjth+ql2Ijn0ADA89TW7yvsz9gBw+vyZd
+D2yVVn8g++3e9+OFJHvvJf8CgYBHEn18W7Wx7Mij6JtYST+FIua0GBRE3rIUuOCU
+nWEbsAroz+IijHwRUqsVJQbI+51RjyBqcYb3QshG0uT8fSPzaTIeHdy8TtzVusxe
+bs0T9gHQpXkCtUWFh22dJBO1GbNQ8+zBHhovD8KgWi1G2OjS64wVcNwfPDD4UmfD
+7Q6CBwKBgBOeDK7R5mGwC4nV1Y+KDBgvE/W8BloZpcD+d7sfZsrU8w7LemBKreDa
+qT1vgk1ZOeHFkvwdWH7LSxRUEGRd+HmqOFKv/hfmxXHlepdnjqt4JMNo9UyddXmX
+onErIOM7BXcBmqvY77ODDOk8ER3zUjKHvYUzxz4PPuEM3hGTTRbQ
+-----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.secrets b/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.secrets
new file mode 100644
index 0000000..d65b96e
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/moon/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+: RSA marsKey.pem
diff --git a/testing/tests/ha/active-passive/hosts/moon/etc/iptables.rules b/testing/tests/ha/active-passive/hosts/moon/etc/iptables.rules
new file mode 100644
index 0000000..09df222
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/moon/etc/iptables.rules
@@ -0,0 +1,57 @@
+*filter
+
+# default policy is DROP
+-P INPUT DROP
+-P OUTPUT DROP
+-P FORWARD DROP
+
+# forward ESP-tunneled traffic
+-A FORWARD -m policy -i eth0 --dir in  --pol ipsec --proto esp -s PH_IP_CAROL -j ACCEPT
+-A FORWARD -m policy -i eth0 --dir in  --pol ipsec --proto esp -s PH_IP_DAVE  -j ACCEPT
+-A FORWARD -m policy -o eth0 --dir out --pol ipsec --proto esp -j ACCEPT
+
+# clusterip rules
+-A INPUT -i eth0 -d 192.168.0.5 -j CLUSTERIP --new --hashmode sourceip --clustermac 01:00:c0:a8:00:05 --total-nodes 1 --local-node 0 
+-A INPUT -i eth1 -d 10.1.0.5    -j CLUSTERIP --new --hashmode sourceip --clustermac 01:00:0a:01:00:05 --total-nodes 1 --local-node 0 
+
+# allow esp
+-A INPUT  -p 50 -j ACCEPT
+-A OUTPUT -p 50 -d PH_IP_CAROL -j ACCEPT
+-A OUTPUT -p 50 -d PH_IP_DAVE  -j ACCEPT
+
+# allow esp on internal interface
+-A OUTPUT -o eth1 -s PH_IP_MOON1 -d PH_IP_ALICE -p 50 -j ACCEPT
+
+# allow IKE on internal interface
+-A INPUT  -i eth1 -d PH_IP_MOON1 -s PH_IP_ALICE -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth1 -s PH_IP_MOON1 -d PH_IP_ALICE -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow IKE
+-A INPUT  -i eth0 -p udp --sport 500 --dport 500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 500 --sport 500 -j ACCEPT
+
+# allow MobIKE
+-A INPUT  -i eth0 -p udp --sport 4500 --dport 4500 -j ACCEPT
+-A OUTPUT -o eth0 -p udp --dport 4500 --sport 4500 -j ACCEPT
+
+# allow crl fetch from winnetou
+-A INPUT  -i eth0 -p tcp --sport 80 -s PH_IP_WINNETOU -j ACCEPT
+-A OUTPUT -o eth0 -p tcp --dport 80 -d PH_IP_WINNETOU -j ACCEPT
+
+# allow heartbeat
+-A INPUT  -i eth1 -d PH_IP_MOON1 -s PH_IP_ALICE -p udp --dport 4510 --sport 4510 -j ACCEPT
+-A OUTPUT -o eth1 -s PH_IP_MOON1 -d PH_IP_ALICE -p udp --dport 4510 --sport 4510 -j ACCEPT
+
+# allow ICMP type 3
+-A INPUT  -i eth1 -d PH_IP_MOON1 -s PH_IP_ALICE -p icmp --icmp-type 3 -j ACCEPT
+-A OUTPUT -o eth1 -s PH_IP_MOON1 -d PH_IP_ALICE -p icmp --icmp-type 3 -j ACCEPT
+
+# allow IGMP multicasts
+-A INPUT  -d 224.0.0.1 -p igmp -j ACCEPT
+-A OUTPUT -s 224.0.0.1 -p igmp -j ACCEPT
+
+# allow ssh
+-A INPUT  -p tcp --dport 22 -j ACCEPT
+-A OUTPUT -p tcp --sport 22 -j ACCEPT
+
+COMMIT
diff --git a/testing/tests/ha/active-passive/hosts/moon/etc/strongswan.conf b/testing/tests/ha/active-passive/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..198f3a0
--- /dev/null
+++ b/testing/tests/ha/active-passive/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,15 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+charon {
+  load = aes des sha1 sha2 md5 pem pkcs1 gmp random nonce x509 curl revocation hmac stroke kernel-netlink socket-default ha
+  plugins {
+    ha {
+      local = PH_IP_MOON1
+      remote = PH_IP_ALICE
+      secret = PliyxREnfoPaSXDJx1NrlH0kkKXT/LWZ
+      segment_count = 1 
+      fifo_interface = yes
+      monitor = yes
+    }
+  }
+}
diff --git a/testing/tests/ha/active-passive/posttest.dat b/testing/tests/ha/active-passive/posttest.dat
new file mode 100644
index 0000000..c21aac9
--- /dev/null
+++ b/testing/tests/ha/active-passive/posttest.dat
@@ -0,0 +1,15 @@
+carol::ipsec stop
+dave::ipsec stop
+moon::ipsec stop
+alice::rm /var/run/charon.pid /var/run/starter.charon.pid
+moon::iptables-restore < /etc/iptables.flush
+alice::iptables-restore < /etc/iptables.flush
+carol::iptables-restore < /etc/iptables.flush
+dave::iptables-restore < /etc/iptables.flush
+moon::ip addr del 192.168.0.5/24 dev eth0
+moon::ip addr del 10.1.0.5/16 dev eth1
+alice::ip addr del 192.168.0.5/24 dev eth1
+alice::ip addr del 10.1.0.5/16 dev eth0
+alice::ifdown eth1
+venus::ip route del default via 10.1.0.5 dev eth0
+venus::ip route add default via 10.1.0.1 dev eth0
diff --git a/testing/tests/ha/active-passive/pretest.dat b/testing/tests/ha/active-passive/pretest.dat
new file mode 100644
index 0000000..d0efb76
--- /dev/null
+++ b/testing/tests/ha/active-passive/pretest.dat
@@ -0,0 +1,21 @@
+moon::ip addr add 192.168.0.5/24 dev eth0
+moon::ip addr add 10.1.0.5/16 dev eth1
+alice::ifup eth1
+alice::ip addr add 192.168.0.5/24 dev eth1
+alice::ip addr add 10.1.0.5/16 dev eth0
+venus::ip route del default via 10.1.0.1 dev eth0
+venus::ip route add default via 10.1.0.5 dev eth0
+moon::iptables-restore < /etc/iptables.rules
+alice::iptables-restore < /etc/iptables.rules
+carol::iptables-restore < /etc/iptables.rules
+dave::iptables-restore < /etc/iptables.rules
+moon::ipsec start
+alice::ipsec start
+moon::ipsec start
+moon::sleep 2 
+alice::echo "+1" > /var/run/charon.ha
+carol::ipsec start
+dave::ipsec start
+carol::sleep 1
+carol::ipsec up home
+dave::ipsec up home
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf b/testing/tests/ha/active-passive/test.conf
similarity index 64%
copy from testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
copy to testing/tests/ha/active-passive/test.conf
index 0887e4d..8056d9c 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
+++ b/testing/tests/ha/active-passive/test.conf
@@ -5,22 +5,17 @@
 
 # All guest instances that are required for this test
 #
-VIRTHOSTS="alice moon carol winnetou dave"
+VIRTHOSTS="alice venus moon carol winnetou dave"
 
 # Corresponding block diagram
 #
-DIAGRAM="a-m-c-w-d.png"
+DIAGRAM="a-v-m-c-w-d.png"
 
 # Guest instances on which tcpdump is to be started
 #
-TCPDUMPHOSTS="moon"
+TCPDUMPHOSTS="venus carol dave"
 
 # Guest instances on which IPsec is started
 # Used for IPsec logging purposes
 #
-IPSECHOSTS="carol dave alice"
-
-# Guest instances on which FreeRadius is started
-#
-RADIUSHOSTS=
-
+IPSECHOSTS="alice moon carol dave"
diff --git a/testing/tests/ikev1/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev1/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev1/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev1/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+BgNVBAMTC1Jlc2VhcmNoIENBMB4XDTE1MDQyNjEwMjUwNFoXDTE5MDQwMzEwMjUw
+NFowWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
 BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZzCC
-ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOio9tKOkESjZumThDvt1aFy
-dPDPNAhNrIon8aCvZMxFQBXsams1LOL47UKQEeOJcDUQ1s90P05vAwX+TwOA2nBD
-hgVBe8c+RsBRfERmxcszK7dgj5yrjwbJFrUJPem04KEPnrR7LpT5s7+z1n+pZYr9
-HyJTvYJd3c968frowQW98mgEJG9xs2LfaqTV3RES1B9vIeQGWh64DSrF6Xy/HY+n
-3MeSMGZ3UJoXS6YZIxvGNd7heB/2xxv3Vv0TNyGikmP8Z5ibgN5jn7mQkU9SM9Qz
-Qb2ZY1m3Dn93cbJ5w3AXeClhJhoze6UvhVs4e/ASuJb6b9NLML4eB0BMCZD66Y8C
-AwEAAaOCAQQwggEAMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdDgQWBBTE
-AO+W2V1eu0sjCQcfemzz9lSRvTBtBgNVHSMEZjBkgBTndfCg8q0gzc1gI8zHyA8p
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev1/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev1/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev1/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev1/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEA6Kj20o6QRKNm6ZOEO+3VoXJ08M80CE2siifxoK9kzEVAFexq
-azUs4vjtQpAR44lwNRDWz3Q/Tm8DBf5PA4DacEOGBUF7xz5GwFF8RGbFyzMrt2CP
-nKuPBskWtQk96bTgoQ+etHsulPmzv7PWf6lliv0fIlO9gl3dz3rx+ujBBb3yaAQk
-b3GzYt9qpNXdERLUH28h5AZaHrgNKsXpfL8dj6fcx5IwZndQmhdLphkjG8Y13uF4
-H/bHG/dW/RM3IaKSY/xnmJuA3mOfuZCRT1Iz1DNBvZljWbcOf3dxsnnDcBd4KWEm
-GjN7pS+FWzh78BK4lvpv00swvh4HQEwJkPrpjwIDAQABAoIBAQCGhpwg5znX1jt9
-N0SwejaaIVoom0ZUvsTTJYF7Da9UxX3mr0phLuADZTea0z7kt+VfaZsrXOX17g5r
-er4pImorm390roZpkELMlNEro9keQzo1z+l6B2Ct5bvxdaSM638u4Z88cDVhAnjC
-kbOnIUWLdgx4hr7/EFNe0pH0KHzjWfS4YMUXZFYER3W+lQ68j3U/iFdCsMdABrLV
-BnKozAUOWTHeZc+8Ca0MFWChrj9b2DCs2M0ASgAx5s9CNo1dIbqwJmb7OLlwm3G+
-Xx0JzN7eOOZdiFSPcyNoRwE6rKvrs2GtQ9LqWdkvVEuFjyIkl97cnoOkRIj5bAvN
-DfjfjmeBAoGBAP9rdEPjprVbEeAS+acLc/6oWlGqo23nO31IuUWHT10yxf0E5FIp
-waLJchqT+jD5tYehfZ1+OVtYiWWKBJIXnVK+a4rc/GIRWX/BRHMtWeenv7wR72pt
-1GRxp7yTZtj1AeJhuXcSHpntAo0kG6gHC/+FvbrNgyuSYn9siIa+C5RhAoGBAOkw
-RgOX7hXYzOSATbKZcnNFdPECYaBDjXV/Rcg966Ng4UcxWl3vJRYf3A55ehmc2Jdm
-CSqt6CrsR/RxKrljsCe7gD/GGEktV7fknnXC5Bfx3hUXQ4rATLx8xwlae+wc+ANM
-eaY1HB0KOGGGH2kT4l4UFChgnfpZN+vpel/cFkPvAoGBAJPqZZVfQ87o44wxUPSl
-FFKYql17BVQDQhdGw0x5lMNzQOdLKvJODj44jOTJZ21vXuoh4n4PeCXnOwJbkFQO
-auRdNChh26LrSzpJ8VsGG3elVMsUU+L9oa9dhncVoczo7mNslpxXGPOpJv4XuBBx
-rEgY6oxAscLM7k++yb3GVyxhAoGBAMK6lT0a+q8zxKZsnnWuvmyUa/t3SZ9TyiV8
-iwGU89oTZQzWoegfdJDtOg68UsJgwF5tzundICv39H6kolD+dnQ3l/mpq04wlzfx
-qoIcpe15BUQHkVelDm+4o12kOigKaPIYQt4RK9D0X/DQ2BofiMGXct3lEQemyZQv
-/Qlf+RfxAoGABBRf9DcyA/RdmTszqebfPPNmx7iHaNbrZ3Xbvyv3P5LkzXlFLTvA
-hDz/UqnVM7Bwe1OGeJYkXfmijRjpJ+U8dteb2YzZ3tnlzKwifz+051/LcjavX9X2
-5PuEB2Y65V0OWImIFVlLnp3MRyE4bImveBliWrTRQUVsxQt2WIDgThw=
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev1/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev1/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev1/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev1/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
+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
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev1/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev1/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev1/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev1/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
+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
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev1/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev1/multi-level-ca/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev1/multi-level-ca/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev1/multi-level-ca/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev1/multi-level-ca/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev1/multi-level-ca/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev1/multi-level-ca/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev1/multi-level-ca/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev1/multi-level-ca/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev1/multi-level-ca/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev1/multi-level-ca/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev1/multi-level-ca/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev1/multi-level-ca/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+BAMTCFNhbGVzIENBMB4XDTE1MDQyNjEwMjIyMFoXDTE5MDQwMzEwMjIyMFowVjEL
 MAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xDjAMBgNVBAsT
 BVNhbGVzMRwwGgYDVQQDFBNkYXZlQHN0cm9uZ3N3YW4ub3JnMIIBIjANBgkqhkiG
-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
+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
-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
+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
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev1/multi-level-ca/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev1/multi-level-ca/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev1/multi-level-ca/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev1/multi-level-ca/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev2/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev2/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev2/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev2/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-cr-init/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev2/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev2/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
+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
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev2/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev2/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-cr-init/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEAztqGSb3H9Xh6I4xiDkmsN5WRjKnEQfSRZsSi0umR7a1jysVv
-MgLKnmk2hAMJkDTjBXndEemnLiXemxNq4Wp3x0ZgpNWC6y1klZY6J7T76/4YhpII
-s8HA1+ZiIAEhYCkeqy/ULPk0qa6yK6Ma2FKLEC4wz6OBbjhctqLzVsxxKDkLaivn
-J16bX8CCNsCq86Ba64m6K1Mpsev5RKnOz0Ey1WwBhgLmipZRgAMHK6yPTRaOccvF
-VrOpi1bfprKXkrCYt6sQoDjbfheZ/tKyW2iJ+WbH0lsA4NbPi1s/5/rOIH+16CGf
-anXiZvZ7NbxLyb8ffPIXFxDTqiS8wFreRZR85wIDAQABAoIBAQCZSpoP1cN0Zvbk
-lykne3NTsdSuEDUvx4VlSj173bnWEBOO9idEQYtUP5Y12GZi5r6ClV+94ZCSA2Bn
-PcmMCTGAjOgb31po3DfZHv4z5Mx4g9I7D8fBJsm5dbKsEwpfz7k5lXVAauGbCaph
-6jp/qxQBRqnHhlzpiH00n6eDYHhPHDoFHe+vGbnjWzJKsvs6EZiXpfJ/WKd1eQah
-sGF7g+9qV5xqwshCBKf25LZ2XjdvZDt78HS4hsSaStnemetK9NVJGJqmLzehQ16m
-RXAr8Ybk9g7/MSFhpwGPGjcqm2/szL4Cs9IMtYSxiroY3QL+DZydG9+K9g5NF7lX
-lbEX9HXRAoGBAOduCSLaoEJsgZathny9kSsBtDmTAuiVZukqRdMjDN2I0kOsRsIw
-CEF1DIvFsX7nfHkKve8+XyTc05y7LTXmX1AEjMgzFel7uy5HjS7AsJZgTippC8g/
-l2jGq+s59zATNZ2el9Q9dbeK2lBdrVy+jqNITdQge9BigFfhWbkAGFRPAoGBAOTQ
-if2+Yrh0zDPO53I6kShehaZvNtPmQxmmhvH4HGMY8EyRajFOSMpV1w3VYDuTA47v
-yol+90BWMY8ZslrXq+Bmwx2ocSc2feyUYcJoOoRL/b+b1lY2Vnog3Hs5BQLsULzH
-dwkEuK8wjjw1g4ksuIMbX/X9nEvJs0xemzh7Ju/pAoGACNI24u82YJHGNroSgDqx
-h9QezHsAB2F6dLS5yJxzZxZJ/W5ZnBk8l1Ig0ksMwuuL4Qk5yB62fa81GapAxOct
-Bt3Fh/P6h9XBgrgTd468rF6rXA549n8GBGZeMy8Ybuqshn9/BgX5sK9INvv7Gafh
-w/ODk+xRC9ZVUgQy6UxJoR0CgYEAybmYjl40xo4iIWK95ZUAuGhsx8iwu6v7aDfK
-LLUiwbMQ11A0IPf1cHyxNf7x8lOwBWoeU43eCZhz5Mcw2KnfW9z9E76W041VAyfl
-7/DX9h7QvQZ0tlj9cHpcJz6jzmns3CG2Lfs9nyXdn/NF3b/Rg7S0qzhFfQN70U5u
-5iKct1ECgYEAmR/0IbYGh1YJ7Z9im44MTSz6H7bTnmIDjM3/+IVydSVgFbzcoVG6
-4sQ5fIViMLtz9PHDRRKbs8TBzpy7C/wC1qRqpq9I17INSQzvm3DpZ2PlR0SeN2dA
-fO9XtkE73cEff/gI7JWOouy/vczizfRemnWlNK5Ui29Fe0QlGC9TyX0=
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvNnrgEQdETpkdY/PaSj9KeNrg8+MCwCH/SPk
+UE6ijIn++yyhaZaji5JrA3z9ya+si0R/4PjxsgwjuqrxARV4gG63jKOmOLWMK9ER
+0/APr9KmXfnmFddqZwltGdo9hmDiBQimEdvvK4XK4nA2BY+pJ0b5go+5P4gIbHUN
+5GGh1u34R/9JDCvX1HHnIYmKv4ERD5TbODnKDjR7KT3q8Qy+DEndji+2Y1NWLot8
+XOynqCNW9Ii0Zs7850wzV1gz1kkm4Qdte0ndlUQu+gSbS7uM+AVPEgd0ZGY23ecA
+V2HsNtCGecj/OnsQ4z8+gSIKJfwEqeumVsSbZimllo5mf3l7jwIDAQABo4H/MIH8
+MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgOoMB0GA1UdDgQWBBSBwMHfoTTG9g4LmkL/
+kBl3thRfxzBtBgNVHSMEZjBkgBRfmxNG+SByyADViLWnTC6X6guTKKFJpEcwRTEL
 MAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xGzAZBgNVBAMT
 EnN0cm9uZ1N3YW4gUm9vdCBDQYIBITAeBgNVHREEFzAVgRNkYXZlQHN0cm9uZ3N3
 YW4ub3JnMDQGA1UdHwQtMCswKaAnoCWGI2h0dHA6Ly9jcmwuc3Ryb25nc3dhbi5v
-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
+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
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-cr-resp/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-ldap/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev2/multi-level-ca-ldap/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev2/multi-level-ca-ldap/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-ldap/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-ldap/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev2/multi-level-ca-ldap/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev2/multi-level-ca-ldap/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-ldap/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-ldap/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev2/multi-level-ca-ldap/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev2/multi-level-ca-ldap/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-ldap/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
+cmcvc2FsZXMuY3JsMA0GCSqGSIb3DQEBCwUAA4IBAQC5VfuhrOErCX6nlfnzgXIB
+HheWTfcuobNz1cRatdIGRZVBLIktkQjABsX62t0wcCJ4gUMgT0DxgR/bZQDv9tp5
+q6bo5XJM+bFkuf0NiPme+w9Or+VYcuyiljHnHF3rihK2ZFOBXl2kY667tiGFML3B
+jhaYQVHA0ZsSfe3Auxccku0U25dJNLq1+ATjeDuye8/NJqS95YBcMZzWiwG/VgMF
+mCeiygAobWmIk2LOijFFpNN2ySCiLimueQp/DO3kBdWlhael3Ee9lkA5bqoFchpb
+HH8eQKyOLhRnB2Lk/RhC3mGIFjW127sJdjdWkroyULepnULLyQQA6jy+tEu4XZ2C
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-ldap/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev2/multi-level-ca-ldap/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev2/multi-level-ca-ldap/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-ldap/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-loop/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev2/multi-level-ca-loop/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev2/multi-level-ca-loop/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-loop/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIELDCCAxSgAwIBAgIBBjANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJDSDEZ
+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
-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
+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
-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
+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
-ajgFI8Kz611i0Ihu8+M1C2W1kFbL4EoYyon3trjRZ3Iqz6ksf9KSKCS6Fiylq4DG
-il0mtMtlP+HKcXzRgSY96M4CO73w26liwmZsFBNaZKI/5vKRPPLyU9raGshfpBeC
-CywZ4vcb+EViIPstzOYiK5y/1tSGsMEdnlX2JZsJAKhbLRTmC02O3MbGGBQQq1eU
-n1xkR8pndTWTJmFZ61fZlUMSwLgLF9/VchAa7cIdEA044OCtTdabiYoyLFmqDutq
-8GYvWOzLf2qOKcRxkHxPfeJDrWOLePEYnaMkSBkUKAUIkI+LaJbWF3ASTGgHqh2/
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-loop/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev2/multi-level-ca-loop/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev2/multi-level-ca-loop/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-loop/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-revoked/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev2/multi-level-ca-revoked/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev2/multi-level-ca-revoked/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-revoked/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-revoked/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev2/multi-level-ca-revoked/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev2/multi-level-ca-revoked/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-revoked/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+MIIEpAIBAAKCAQEAq6m4epRSpK5+wS2NJNkSRMWxMZZdCTBmgtsA82Vng9XQPHWO
+7fFG9W2NAc3dOzHoiwHUk7eT90wTHC21t4EDwcqgpjD4IUbz7pdZRT60FPnGXBrm
+x1VQcijw6fXHtFvez5EOEnb9i8J/8fXdo62ob4vtfK3s7BFBk3HgbHrSyBTZmGv1
+awyyVYlB5L3a9rpSIZg3hzqpE3KtL3NNkQnTKJu1+WF3TsstyDP6MeoJ1Rw8riDz
+5MfwcK16TSfZBG7ch9sQz6LoRpmNQmrWSnqT0cAiApHjyv0dWTfMGxYkGjqzFSfz
+9q8Uzni93APw0AKU2f3GhsRew7ePAaWNzmZvjQIDAQABAoIBAEJqa+GhOUhV6ty6
+zv0Ory7EfgX9cwl3HHJMYVXKSf6L3wFFSoNs8lNKi1/DUnDwolQF5UUxpaHsYQhp
+9wCEffugdf9WuunFFeOd0wAjfnEPIlvIXLmKnJFOnccnPJjfYplUOemS+A32tqHa
+ymHlcmGV9dBjSmMbWg+942KVMrAOHtCnAk0yT2WlE+9efLTuXoZIQCx+Ico6Lwp8
+JCmZYW2pfUk9co9di6UCl50C+A5RcvpsE7CZcXCzEAqz06eFz4imgQuzQSLaedup
+F77cyPd13nD2N7+YGfWrWKbdqGMuQnmfrOQWZf94rlOsQjyCzbHIeItJsXT+DBKT
+0SwEIQECgYEA1mcoUiCYOcQcA+FtSO8byzSu0uQZO1cS/VES5mbtRIuLo33L0P0y
+bVnBIfk3iaBq70GU98XjhCGUwNwQDQm+zbLK+p+j+4L2ayvjtOV5ql0b2gk6eyRZ
+oX14evsmxC2OFqGmGD+VePN4pP+Q39QMCFvf26BMtKHyXQnkwA61G30CgYEAzPfH
+Lp3iT9xLqpp9zP9j2m9Ts6m6/Uzzuazpzl7rYMlLkd6fBWBquQ46qbO5Wv+SO7yZ
+aWU7OuWGe6zng1VWSrLBZlRMfu+ze1uEETNdedRI858nv1bMlHmt9+RiZgOgZe7H
+3D4dLphrQrJC8tlsaP0GWYRZkf64n+37KZX2QVECgYEAyKcmbyYeEQHeDius8XMF
+mfmmG6xpiMWG+hgkDgkJyPqoJswWMXKk/P3g6ACq31yId33zAqfqs8ARzSSmyOzz
+6uKHYGKDP2FjaQ1cP/H7GVumMzorxw9P6vjYBpCByVuw/LEwFsV7CAUkRZcAaNm0
+oSYKrSqqXuqpPjWCJdQd3qkCgYAdIf6ylohLN5GdrxXAZHBp5Lbt62sDg8OEmZol
+1gH4oMPX+N97YSfqI6ac5kmrMHY1fWoEu/m+Nk92Fq5VUXTRazTn+YVh6WoGV4ye
+8UERBuZTkkSRAqJTXDQo7tI5k7xhoJ3RpRZ6v/lG4pV3dQXeqlATuycMBDtzp9yy
+HXmB8QKBgQCut7SsOJ0DtgpzjatYzKBh43WgwjbeRyReyT6OWuPiLUiKQYN8W5od
+pZ51zorvFxu6iEMjAzXs0k1zbM4/EaQwwatTEZF0ZQMYMvm46f0ndhN3fY0O0ENY
+zZES5DrfCgboPlmrWoVexU3xEDCWO8hO0fLmwqIK8F4EU8ByOVsHcg==
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-strict/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev2/multi-level-ca-strict/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev2/multi-level-ca-strict/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-strict/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+MIIELDCCAxSgAwIBAgIBCzANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJDSDEZ
 MBcGA1UEChMQTGludXggc3Ryb25nU3dhbjERMA8GA1UECxMIUmVzZWFyY2gxFDAS
-BgNVBAMTC1Jlc2VhcmNoIENBMB4XDTEwMDQwNzA5MjA1N1oXDTE1MDQwNjA5MjA1
-N1owWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
+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
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-strict/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev2/multi-level-ca-strict/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev2/multi-level-ca-strict/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-strict/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca-strict/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev2/multi-level-ca-strict/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev2/multi-level-ca-strict/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev2/multi-level-ca-strict/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
+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
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca-strict/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev2/multi-level-ca-strict/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev2/multi-level-ca-strict/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev2/multi-level-ca-strict/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev2/multi-level-ca/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev2/multi-level-ca/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev2/multi-level-ca/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-MIIELDCCAxSgAwIBAgIBBjANBgkqhkiG9w0BAQsFADBRMQswCQYDVQQGEwJDSDEZ
+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
-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
+BgNVBAMTC1Jlc2VhcmNoIENBMB4XDTE1MDQyNjEwMjUwNFoXDTE5MDQwMzEwMjUw
+NFowWjELMAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xETAP
 BgNVBAsTCFJlc2VhcmNoMR0wGwYDVQQDFBRjYXJvbEBzdHJvbmdzd2FuLm9yZzCC
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev2/multi-level-ca/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev2/multi-level-ca/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev2/multi-level-ca/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-MIIEpQIBAAKCAQEA6Kj20o6QRKNm6ZOEO+3VoXJ08M80CE2siifxoK9kzEVAFexq
-azUs4vjtQpAR44lwNRDWz3Q/Tm8DBf5PA4DacEOGBUF7xz5GwFF8RGbFyzMrt2CP
-nKuPBskWtQk96bTgoQ+etHsulPmzv7PWf6lliv0fIlO9gl3dz3rx+ujBBb3yaAQk
-b3GzYt9qpNXdERLUH28h5AZaHrgNKsXpfL8dj6fcx5IwZndQmhdLphkjG8Y13uF4
-H/bHG/dW/RM3IaKSY/xnmJuA3mOfuZCRT1Iz1DNBvZljWbcOf3dxsnnDcBd4KWEm
-GjN7pS+FWzh78BK4lvpv00swvh4HQEwJkPrpjwIDAQABAoIBAQCGhpwg5znX1jt9
-N0SwejaaIVoom0ZUvsTTJYF7Da9UxX3mr0phLuADZTea0z7kt+VfaZsrXOX17g5r
-er4pImorm390roZpkELMlNEro9keQzo1z+l6B2Ct5bvxdaSM638u4Z88cDVhAnjC
-kbOnIUWLdgx4hr7/EFNe0pH0KHzjWfS4YMUXZFYER3W+lQ68j3U/iFdCsMdABrLV
-BnKozAUOWTHeZc+8Ca0MFWChrj9b2DCs2M0ASgAx5s9CNo1dIbqwJmb7OLlwm3G+
-Xx0JzN7eOOZdiFSPcyNoRwE6rKvrs2GtQ9LqWdkvVEuFjyIkl97cnoOkRIj5bAvN
-DfjfjmeBAoGBAP9rdEPjprVbEeAS+acLc/6oWlGqo23nO31IuUWHT10yxf0E5FIp
-waLJchqT+jD5tYehfZ1+OVtYiWWKBJIXnVK+a4rc/GIRWX/BRHMtWeenv7wR72pt
-1GRxp7yTZtj1AeJhuXcSHpntAo0kG6gHC/+FvbrNgyuSYn9siIa+C5RhAoGBAOkw
-RgOX7hXYzOSATbKZcnNFdPECYaBDjXV/Rcg966Ng4UcxWl3vJRYf3A55ehmc2Jdm
-CSqt6CrsR/RxKrljsCe7gD/GGEktV7fknnXC5Bfx3hUXQ4rATLx8xwlae+wc+ANM
-eaY1HB0KOGGGH2kT4l4UFChgnfpZN+vpel/cFkPvAoGBAJPqZZVfQ87o44wxUPSl
-FFKYql17BVQDQhdGw0x5lMNzQOdLKvJODj44jOTJZ21vXuoh4n4PeCXnOwJbkFQO
-auRdNChh26LrSzpJ8VsGG3elVMsUU+L9oa9dhncVoczo7mNslpxXGPOpJv4XuBBx
-rEgY6oxAscLM7k++yb3GVyxhAoGBAMK6lT0a+q8zxKZsnnWuvmyUa/t3SZ9TyiV8
-iwGU89oTZQzWoegfdJDtOg68UsJgwF5tzundICv39H6kolD+dnQ3l/mpq04wlzfx
-qoIcpe15BUQHkVelDm+4o12kOigKaPIYQt4RK9D0X/DQ2BofiMGXct3lEQemyZQv
-/Qlf+RfxAoGABBRf9DcyA/RdmTszqebfPPNmx7iHaNbrZ3Xbvyv3P5LkzXlFLTvA
-hDz/UqnVM7Bwe1OGeJYkXfmijRjpJ+U8dteb2YzZ3tnlzKwifz+051/LcjavX9X2
-5PuEB2Y65V0OWImIFVlLnp3MRyE4bImveBliWrTRQUVsxQt2WIDgThw=
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/multi-level-ca/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev2/multi-level-ca/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev2/multi-level-ca/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev2/multi-level-ca/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+BAMTCFNhbGVzIENBMB4XDTE1MDQyNjEwMjIyMFoXDTE5MDQwMzEwMjIyMFowVjEL
 MAkGA1UEBhMCQ0gxGTAXBgNVBAoTEExpbnV4IHN0cm9uZ1N3YW4xDjAMBgNVBAsT
 BVNhbGVzMRwwGgYDVQQDFBNkYXZlQHN0cm9uZ3N3YW4ub3JnMIIBIjANBgkqhkiG
-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
+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
-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
+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
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/multi-level-ca/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev2/multi-level-ca/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev2/multi-level-ca/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev2/multi-level-ca/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/ocsp-multi-level/hosts/carol/etc/ipsec.d/certs/carolCert.pem b/testing/tests/ikev2/ocsp-multi-level/hosts/carol/etc/ipsec.d/certs/carolCert.pem
index 69e5c05..698e47c 100644
--- a/testing/tests/ikev2/ocsp-multi-level/hosts/carol/etc/ipsec.d/certs/carolCert.pem
+++ b/testing/tests/ikev2/ocsp-multi-level/hosts/carol/etc/ipsec.d/certs/carolCert.pem
@@ -1,25 +1,25 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
-pwU12A3BovJKUaR0B7Uy2A==
+TgUJbXL83e11Fzo+XGMQ24FfxdUvlex9IcnnNZnjsy4cYaUhofdI1AIkOhdh7R4i
+9dtdfbFLLQR3qc2jmL9ubdQP83FiZZQOXX55XV5/Gb4E4g2T2ZU8ahby+ZzQsEcI
+jGeot7fRfbxUrcjnIKxZd7JsQSaR45rMrNcUOQpFT212urojUngrEoAeaC5USEiX
+sF11P654UejR8DCczwLi4QBvjRTH3bcMC57FjsWt1n/KCB08dS0ojD+T+6lN7/1K
+yLreeRNynXzc1GAln5G03Ivwm9STFT1mYjkBMOCY+3ihEOpzlR9pWCWl9p728db3
+mk0VsDm1jdOf3PK1Xd2PJw==
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/ocsp-multi-level/hosts/carol/etc/ipsec.d/private/carolKey.pem b/testing/tests/ikev2/ocsp-multi-level/hosts/carol/etc/ipsec.d/private/carolKey.pem
index 53e1868..3a5d7c4 100644
--- a/testing/tests/ikev2/ocsp-multi-level/hosts/carol/etc/ipsec.d/private/carolKey.pem
+++ b/testing/tests/ikev2/ocsp-multi-level/hosts/carol/etc/ipsec.d/private/carolKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/ocsp-multi-level/hosts/dave/etc/ipsec.d/certs/daveCert.pem b/testing/tests/ikev2/ocsp-multi-level/hosts/dave/etc/ipsec.d/certs/daveCert.pem
index 91df37a..4718e7a 100644
--- a/testing/tests/ikev2/ocsp-multi-level/hosts/dave/etc/ipsec.d/certs/daveCert.pem
+++ b/testing/tests/ikev2/ocsp-multi-level/hosts/dave/etc/ipsec.d/certs/daveCert.pem
@@ -1,24 +1,24 @@
 -----BEGIN CERTIFICATE-----
-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
+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
-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
+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
-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
+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
-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
+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
 -----END CERTIFICATE-----
diff --git a/testing/tests/ikev2/ocsp-multi-level/hosts/dave/etc/ipsec.d/private/daveKey.pem b/testing/tests/ikev2/ocsp-multi-level/hosts/dave/etc/ipsec.d/private/daveKey.pem
index 86740e8..ebba49c 100644
--- a/testing/tests/ikev2/ocsp-multi-level/hosts/dave/etc/ipsec.d/private/daveKey.pem
+++ b/testing/tests/ikev2/ocsp-multi-level/hosts/dave/etc/ipsec.d/private/daveKey.pem
@@ -1,27 +1,27 @@
 -----BEGIN RSA PRIVATE KEY-----
-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
+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
 -----END RSA PRIVATE KEY-----
diff --git a/testing/tests/ikev2/rw-cert/pretest.dat b/testing/tests/ikev2/rw-cert/pretest.dat
index 8bbea14..c582e03 100644
--- a/testing/tests/ikev2/rw-cert/pretest.dat
+++ b/testing/tests/ikev2/rw-cert/pretest.dat
@@ -4,6 +4,6 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-carol::sleep 1
+carol::sleep 3
 carol::ipsec up home
 dave::ipsec up home
diff --git a/testing/tests/openssl-ikev2/rw-cert/pretest.dat b/testing/tests/openssl-ikev2/rw-cert/pretest.dat
index 8bbea14..c582e03 100644
--- a/testing/tests/openssl-ikev2/rw-cert/pretest.dat
+++ b/testing/tests/openssl-ikev2/rw-cert/pretest.dat
@@ -4,6 +4,6 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-carol::sleep 1
+carol::sleep 3
 carol::ipsec up home
 dave::ipsec up home
diff --git a/testing/tests/openssl-ikev2/rw-suite-b-128/pretest.dat b/testing/tests/openssl-ikev2/rw-suite-b-128/pretest.dat
index fc71734..b939394 100644
--- a/testing/tests/openssl-ikev2/rw-suite-b-128/pretest.dat
+++ b/testing/tests/openssl-ikev2/rw-suite-b-128/pretest.dat
@@ -4,6 +4,6 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-carol::sleep 1
+carol::sleep 3
 dave::ipsec up peer
 carol::ipsec up home
diff --git a/testing/tests/openssl-ikev2/rw-suite-b-192/pretest.dat b/testing/tests/openssl-ikev2/rw-suite-b-192/pretest.dat
index fc71734..b939394 100644
--- a/testing/tests/openssl-ikev2/rw-suite-b-192/pretest.dat
+++ b/testing/tests/openssl-ikev2/rw-suite-b-192/pretest.dat
@@ -4,6 +4,6 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-carol::sleep 1
+carol::sleep 3
 dave::ipsec up peer
 carol::ipsec up home
diff --git a/testing/tests/pfkey/rw-cert/pretest.dat b/testing/tests/pfkey/rw-cert/pretest.dat
index 8bbea14..c582e03 100644
--- a/testing/tests/pfkey/rw-cert/pretest.dat
+++ b/testing/tests/pfkey/rw-cert/pretest.dat
@@ -4,6 +4,6 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-carol::sleep 1
+carol::sleep 3
 carol::ipsec up home
 dave::ipsec up home
diff --git a/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql
index 335abe2..bd2f3b8 100644
--- a/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql
@@ -43,7 +43,7 @@ INSERT INTO identities (
 INSERT INTO identities (
   type, data
 ) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org' */
-  11, X'c400ef96d95d5ebb4b2309071f7a6cf3f65491bd'
+  11, X'5da9f9ef80718d3a883938e2de6e6624989fdf69'
  );
 
 INSERT INTO identities (
@@ -69,8 +69,7 @@ INSERT INTO certificates (
 INSERT INTO certificates (
    type, keytype, data
 ) VALUES ( /* C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org */
-  1, 1, X'3082042c30820314a003020102020106300d06092a864886f70d01010b05003051310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e3111300f060355040b13085265736561726368311430120603550403130b5265736561726368204341301e170d3130303430373039323035375a170d3135303430363039323035375a305a310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e3111300f060355040b13085265736561726368311d301b060355040314146361726f6c407374726f6e677377616e2e6f7267308201 [...]
-);
+  1, 1, X'3082042c30820314a00302010202010b300d06092a864886f70d01010b05003051310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e3111300f060355040b13085265736561726368311430120603550403130b5265736561726368204341301e170d3135303432363130323530345a170d3139303430333130323530345a305a310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e3111300f060355040b13085265736561726368311d301b060355040314146361726f6c407374726f6e677377616e2e6f7267308201 [...]
 
 INSERT INTO certificate_identity (
   certificate, identity
@@ -125,7 +124,7 @@ INSERT INTO certificate_identity (
 INSERT INTO private_keys (
    type, data
 ) VALUES ( /* key of 'C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org' */
-  1, X'308204a50201000282010100e8a8f6d28e9044a366e993843bedd5a17274f0cf34084dac8a27f1a0af64cc454015ec6a6b352ce2f8ed429011e389703510d6cf743f4e6f0305fe4f0380da70438605417bc73e46c0517c4466c5cb332bb7608f9cab8f06c916b5093de9b4e0a10f9eb47b2e94f9b3bfb3d67fa9658afd1f2253bd825dddcf7af1fae8c105bdf26804246f71b362df6aa4d5dd1112d41f6f21e4065a1eb80d2ac5e97cbf1d8fa7dcc792306677509a174ba619231bc635dee1781ff6c71bf756fd133721a29263fc67989b80de639fb990914f5233d43341bd996359b70e7f7771b279c37017782961261a337 [...]
+  1, X'308204a40201000282010100aba9b87a9452a4ae7ec12d8d24d91244c5b131965d09306682db00f3656783d5d03c758eedf146f56d8d01cddd3b31e88b01d493b793f74c131c2db5b78103c1caa0a630f82146f3ee9759453eb414f9c65c1ae6c755507228f0e9f5c7b45bdecf910e1276fd8bc27ff1f5dda3ada86f8bed7cadecec11419371e06c7ad2c814d9986bf56b0cb2558941e4bddaf6ba52219837873aa91372ad2f734d9109d3289bb5f961774ecb2dc833fa31ea09d51c3cae20f3e4c7f070ad7a4d27d9046edc87db10cfa2e846998d426ad64a7a93d1c0220291e3cafd1d5937cc1b16241a3ab31527f3f6af1 [...]
 );
 
 INSERT INTO private_key_identity (
diff --git a/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql b/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql~
similarity index 69%
copy from testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql
copy to testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql~
index 335abe2..4040b95 100644
--- a/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/multi-level-ca/hosts/carol/etc/ipsec.d/data.sql~
@@ -43,7 +43,7 @@ INSERT INTO identities (
 INSERT INTO identities (
   type, data
 ) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org' */
-  11, X'c400ef96d95d5ebb4b2309071f7a6cf3f65491bd'
+  11, X'5da9f9ef80718d3a883938e2de6e6624989fdf69'
  );
 
 INSERT INTO identities (
@@ -69,8 +69,7 @@ INSERT INTO certificates (
 INSERT INTO certificates (
    type, keytype, data
 ) VALUES ( /* C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org */
-  1, 1, X'3082042c30820314a003020102020106300d06092a864886f70d01010b05003051310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e3111300f060355040b13085265736561726368311430120603550403130b5265736561726368204341301e170d3130303430373039323035375a170d3135303430363039323035375a305a310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e3111300f060355040b13085265736561726368311d301b060355040314146361726f6c407374726f6e677377616e2e6f7267308201 [...]
-);
+  1, 1, X'3082042c30820314a00302010202010b300d06092a864886f70d01010b05003051310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e3111300f060355040b13085265736561726368311430120603550403130b5265736561726368204341301e170d3135303432363130323530345a170d3139303430333130323530345a305a310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e3111300f060355040b13085265736561726368311d301b060355040314146361726f6c407374726f6e677377616e2e6f7267308201 [...]
 
 INSERT INTO certificate_identity (
   certificate, identity
@@ -125,8 +124,7 @@ INSERT INTO certificate_identity (
 INSERT INTO private_keys (
    type, data
 ) VALUES ( /* key of 'C=CH, O=Linux strongSwan, OU=Research, CN=carol at strongswan.org' */
-  1, X'308204a50201000282010100e8a8f6d28e9044a366e993843bedd5a17274f0cf34084dac8a27f1a0af64cc454015ec6a6b352ce2f8ed429011e389703510d6cf743f4e6f0305fe4f0380da70438605417bc73e46c0517c4466c5cb332bb7608f9cab8f06c916b5093de9b4e0a10f9eb47b2e94f9b3bfb3d67fa9658afd1f2253bd825dddcf7af1fae8c105bdf26804246f71b362df6aa4d5dd1112d41f6f21e4065a1eb80d2ac5e97cbf1d8fa7dcc792306677509a174ba619231bc635dee1781ff6c71bf756fd133721a29263fc67989b80de639fb990914f5233d43341bd996359b70e7f7771b279c37017782961261a337 [...]
-);
+  1, X'308204a40201000282010100aba9b87a9452a4ae7ec12d8d24d91244c5b131965d09306682db00f3656783d5d03c758eedf146f56d8d01cddd3b31e88b01d493b793f74c131c2db5b78103c1caa0a630f82146f3ee9759453eb414f9c65c1ae6c755507228f0e9f5c7b45bdecf910e1276fd8bc27ff1f5dda3ada86f8bed7cadecec11419371e06c7ad2c814d9986bf56b0cb2558941e4bddaf6ba52219837873aa91372ad2f734d9109d3289bb5f961774ecb2dc833fa31ea09d51c3cae20f3e4c7f070ad7a4d27d9046edc87db10cfa2e846998d426ad64a7a93d1c0220291e3cafd1d5937cc1b16241a3ab31527f3f6af1 [...]
 
 INSERT INTO private_key_identity (
   private_key, identity
diff --git a/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql
index 91ddf01..eae9b59 100644
--- a/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql
@@ -45,7 +45,7 @@ INSERT INTO identities (
 INSERT INTO identities (
   type, data
 ) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, OU=Sales, CN=dave at strongswan.org' */
-  11, X'671081ec8703e10c31abdf12d53275046eba1522'
+  11, X'81c0c1dfa134c6f60e0b9a42ff901977b6145fc7'
  );
 
 INSERT INTO identities (
@@ -71,7 +71,7 @@ INSERT INTO certificates (
 INSERT INTO certificates (
    type, keytype, data
 ) VALUES ( /* C=CH, O=Linux strongSwan, OU=Sales, CN=dave at strongswan.org */
-  1, 1, X'3082041c30820304a003020102020105300d06092a864886f70d01010b0500304b310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c65733111300f0603550403130853616c6573204341301e170d3130303430373039343234315a170d3135303430363039343234315a3056310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c6573311c301a0603550403141364617665407374726f6e677377616e2e6f726730820122300d06092a864886f7 [...]
+  1, 1, X'3082041c30820304a003020102020109300d06092a864886f70d01010b0500304b310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c65733111300f0603550403130853616c6573204341301e170d3135303432363130323232305a170d3139303430333130323232305a3056310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c6573311c301a0603550403141364617665407374726f6e677377616e2e6f726730820122300d06092a864886f7 [...]
 );
 
 INSERT INTO certificate_identity (
@@ -127,7 +127,7 @@ INSERT INTO certificate_identity (
 INSERT INTO private_keys (
    type, data
 ) VALUES ( /* key of 'C=CH, O=Linux strongSwan, OU=Sales, CN=dave at strongswan.org' */
-  1, X'308204a50201000282010100ceda8649bdc7f5787a238c620e49ac3795918ca9c441f49166c4a2d2e991edad63cac56f3202ca9e69368403099034e30579dd11e9a72e25de9b136ae16a77c74660a4d582eb2d6495963a27b4fbebfe18869208b3c1c0d7e66220012160291eab2fd42cf934a9aeb22ba31ad8528b102e30cfa3816e385cb6a2f356cc7128390b6a2be7275e9b5fc08236c0aaf3a05aeb89ba2b5329b1ebf944a9cecf4132d56c018602e68a96518003072bac8f4d168e71cbc556b3a98b56dfa6b29792b098b7ab10a038db7e1799fed2b25b6889f966c7d25b00e0d6cf8b5b3fe7face207fb5e8219f6a75e [...]
+  1, X'308204a40201000282010100bcd9eb80441d113a64758fcf6928fd29e36b83cf8c0b0087fd23e4504ea28c89fefb2ca16996a38b926b037cfdc9afac8b447fe0f8f1b20c23baaaf1011578806eb78ca3a638b58c2bd111d3f00fafd2a65df9e615d76a67096d19da3d8660e20508a611dbef2b85cae27036058fa92746f9828fb93f88086c750de461a1d6edf847ff490c2bd7d471e721898abf81110f94db3839ca0e347b293deaf10cbe0c49dd8e2fb66353562e8b7c5ceca7a82356f488b466cefce74c33575833d64926e1076d7b49dd95442efa049b4bbb8cf8054f120774646636dde7005761ec36d08679c8ff3a7b1 [...]
 );
 
 INSERT INTO private_key_identity (
diff --git a/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql b/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql~
similarity index 68%
copy from testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql
copy to testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql~
index 91ddf01..656a5ad 100644
--- a/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql
+++ b/testing/tests/sql/multi-level-ca/hosts/dave/etc/ipsec.d/data.sql~
@@ -45,7 +45,7 @@ INSERT INTO identities (
 INSERT INTO identities (
   type, data
 ) VALUES ( /* subjkey of 'C=CH, O=Linux strongSwan, OU=Sales, CN=dave at strongswan.org' */
-  11, X'671081ec8703e10c31abdf12d53275046eba1522'
+  11, X'81c0c1dfa134c6f60e0b9a42ff901977b6145fc7'
  );
 
 INSERT INTO identities (
@@ -71,7 +71,7 @@ INSERT INTO certificates (
 INSERT INTO certificates (
    type, keytype, data
 ) VALUES ( /* C=CH, O=Linux strongSwan, OU=Sales, CN=dave at strongswan.org */
-  1, 1, X'3082041c30820304a003020102020105300d06092a864886f70d01010b0500304b310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c65733111300f0603550403130853616c6573204341301e170d3130303430373039343234315a170d3135303430363039343234315a3056310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c6573311c301a0603550403141364617665407374726f6e677377616e2e6f726730820122300d06092a864886f7 [...]
+  1, 1, X'3082041c30820304a003020102020109300d06092a864886f70d01010b0500304b310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c65733111300f0603550403130853616c6573204341301e170d3135303432363130323232305a170d3139303430333130323232305a3056310b300906035504061302434831193017060355040a13104c696e7578207374726f6e675377616e310e300c060355040b130553616c6573311c301a0603550403141364617665407374726f6e677377616e2e6f726730820122300d06092a864886f7 [...]
 );
 
 INSERT INTO certificate_identity (
@@ -127,8 +127,7 @@ INSERT INTO certificate_identity (
 INSERT INTO private_keys (
    type, data
 ) VALUES ( /* key of 'C=CH, O=Linux strongSwan, OU=Sales, CN=dave at strongswan.org' */
-  1, X'308204a50201000282010100ceda8649bdc7f5787a238c620e49ac3795918ca9c441f49166c4a2d2e991edad63cac56f3202ca9e69368403099034e30579dd11e9a72e25de9b136ae16a77c74660a4d582eb2d6495963a27b4fbebfe18869208b3c1c0d7e66220012160291eab2fd42cf934a9aeb22ba31ad8528b102e30cfa3816e385cb6a2f356cc7128390b6a2be7275e9b5fc08236c0aaf3a05aeb89ba2b5329b1ebf944a9cecf4132d56c018602e68a96518003072bac8f4d168e71cbc556b3a98b56dfa6b29792b098b7ab10a038db7e1799fed2b25b6889f966c7d25b00e0d6cf8b5b3fe7face207fb5e8219f6a75e [...]
-);
+  1, X'308204a40201000282010100bcd9eb80441d113a64758fcf6928fd29e36b83cf8c0b0087fd23e4504ea28c89fefb2ca16996a38b926b037cfdc9afac8b447fe0f8f1b20c23baaaf1011578806eb78ca3a638b58c2bd111d3f00fafd2a65df9e615d76a67096d19da3d8660e20508a611dbef2b85cae27036058fa92746f9828fb93f88086c750de461a1d6edf847ff490c2bd7d471e721898abf81110f94db3839ca0e347b293deaf10cbe0c49dd8e2fb66353562e8b7c5ceca7a82356f488b466cefce74c33575833d64926e1076d7b49dd95442efa049b4bbb8cf8054f120774646636dde7005761ec36d08679c8ff3a7b1 [...]
 
 INSERT INTO private_key_identity (
   private_key, identity
diff --git a/testing/tests/sql/rw-cert/pretest.dat b/testing/tests/sql/rw-cert/pretest.dat
index 6d56ede..7958f09 100644
--- a/testing/tests/sql/rw-cert/pretest.dat
+++ b/testing/tests/sql/rw-cert/pretest.dat
@@ -13,6 +13,6 @@ dave::iptables-restore < /etc/iptables.rules
 moon::ipsec start
 carol::ipsec start
 dave::ipsec start
-carol::sleep 1
+carol::sleep 3
 carol::ipsec up home
 dave::ipsec up home
diff --git a/testing/tests/tkm/host2host-initiator/evaltest.dat b/testing/tests/tkm/host2host-initiator/evaltest.dat
index de50ab3..cf34e41 100644
--- a/testing/tests/tkm/host2host-initiator/evaltest.dat
+++ b/testing/tests/tkm/host2host-initiator/evaltest.dat
@@ -9,8 +9,8 @@ moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
 moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
 moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
 moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
-moon::cat /tmp/tkm.log::Adding SA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
+moon::cat /tmp/tkm.log::Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
 moon::DAEMON_NAME=charon-tkm ipsec down conn1 && sleep 1::no output expected::NO
 moon::cat /var/log/daemon.log::deleting child SA (esa: 1, spi:.*)::YES
 moon::cat /tmp/tkm.log::Resetting ESA context 1::YES
-moon::cat /tmp/tkm.log::Deleting SA \[ 1, 192.168.0.1 <=> 192.168.0.2, SPI_in.*, SPI_out.* \]::YES
+moon::cat /tmp/tkm.log::Deleting ESA \[ 1, 192.168.0.1 <=> 192.168.0.2, SPI_in.*, SPI_out.* \]::YES
diff --git a/testing/tests/tkm/host2host-responder/evaltest.dat b/testing/tests/tkm/host2host-responder/evaltest.dat
index d8d44df..bc04360 100644
--- a/testing/tests/tkm/host2host-responder/evaltest.dat
+++ b/testing/tests/tkm/host2host-responder/evaltest.dat
@@ -9,4 +9,4 @@ moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
 moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
 moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
 moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
-moon::cat /tmp/tkm.log::Adding SA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
+moon::cat /tmp/tkm.log::Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
diff --git a/testing/tests/tkm/host2host-xfrmproxy/evaltest.dat b/testing/tests/tkm/host2host-xfrmproxy/evaltest.dat
index f5143f1..6b9050a 100644
--- a/testing/tests/tkm/host2host-xfrmproxy/evaltest.dat
+++ b/testing/tests/tkm/host2host-xfrmproxy/evaltest.dat
@@ -10,5 +10,5 @@ moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
 moon::cat /tmp/tkm.log::Adding policy \[ 1, 192.168.0.1 <-> 192.168.0.2 \]::YES
 moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
 moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
-moon::cat /tmp/tkm.log::Adding SA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
+moon::cat /tmp/tkm.log::Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
 moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES
diff --git a/testing/tests/tkm/multiple-clients/evaltest.dat b/testing/tests/tkm/multiple-clients/evaltest.dat
index 1f0c88b..89da764 100644
--- a/testing/tests/tkm/multiple-clients/evaltest.dat
+++ b/testing/tests/tkm/multiple-clients/evaltest.dat
@@ -18,5 +18,5 @@ sun::cat /tmp/tkm.log::Adding policy \[ 2, 192.168.0.2 <-> 192.168.0.200 \]::YES
 sun::cat /tmp/tkm.log | grep "Checked CA certificate of CC context 1" | wc -l::2::YES
 sun::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
 sun::cat /tmp/tkm.log::Authentication of ISA context 2 successful::YES
-sun::cat /tmp/tkm.log::Adding SA \[ 1, 192.168.0.2 <-> 192.168.0.100, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
-sun::cat /tmp/tkm.log::Adding SA \[ 2, 192.168.0.2 <-> 192.168.0.200, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
+sun::cat /tmp/tkm.log::Adding ESA \[ 1, 192.168.0.2 <-> 192.168.0.100, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
+sun::cat /tmp/tkm.log::Adding ESA \[ 2, 192.168.0.2 <-> 192.168.0.200, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
diff --git a/testing/tests/tkm/net2net-initiator/evaltest.dat b/testing/tests/tkm/net2net-initiator/evaltest.dat
index 8d4794f..80492a9 100644
--- a/testing/tests/tkm/net2net-initiator/evaltest.dat
+++ b/testing/tests/tkm/net2net-initiator/evaltest.dat
@@ -9,4 +9,4 @@ moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
 moon::cat /tmp/tkm.log::Adding policy \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16 \]::YES
 moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
 moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
-moon::cat /tmp/tkm.log::Adding SA \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
+moon::cat /tmp/tkm.log::Adding ESA \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
diff --git a/testing/tests/tkm/net2net-xfrmproxy/evaltest.dat b/testing/tests/tkm/net2net-xfrmproxy/evaltest.dat
index 98eff24..6c5d8b3 100644
--- a/testing/tests/tkm/net2net-xfrmproxy/evaltest.dat
+++ b/testing/tests/tkm/net2net-xfrmproxy/evaltest.dat
@@ -10,5 +10,5 @@ moon::cat /tmp/tkm.log::RSA private key '/etc/tkm/moonKey.der' loaded::YES
 moon::cat /tmp/tkm.log::Adding policy \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16 \]::YES
 moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
 moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
-moon::cat /tmp/tkm.log::Adding SA \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
+moon::cat /tmp/tkm.log::Adding ESA \[ 1, 10.1.0.0/16 > 192.168.0.1 <=> 192.168.0.2 < 10.2.0.0/16, SPI_in.*, SPI_out.*, soft 30, hard 60 \]::YES
 moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES
diff --git a/testing/tests/tkm/xfrmproxy-expire/evaltest.dat b/testing/tests/tkm/xfrmproxy-expire/evaltest.dat
index 96b486a..21d198c 100644
--- a/testing/tests/tkm/xfrmproxy-expire/evaltest.dat
+++ b/testing/tests/tkm/xfrmproxy-expire/evaltest.dat
@@ -15,8 +15,8 @@ moon::cat /tmp/tkm.log::Checked CA certificate of CC context 1::YES
 moon::cat /tmp/tkm.log::Authentication of ISA context 1 successful::YES
 moon::cat /tmp/tkm.log::Creating first new ESA context with ID 1 (Isa 1, Sp 1, Ea 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES
 moon::cat /tmp/tkm.log::Creating ESA context with ID 2 (Isa 1, Sp 1, Ea 1, Dh_Id 1, Nc_Loc_Id 1, Initiator TRUE, spi_loc.*, spi_rem.*)::YES
-moon::cat /tmp/tkm.log | grep 'Adding SA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 2, hard 60 \]' | wc -l::2::YES
+moon::cat /tmp/tkm.log | grep 'Adding ESA \[ 1, 192.168.0.1 <-> 192.168.0.2, SPI_in.*, SPI_out.*, soft 2, hard 60 \]' | wc -l::2::YES
 moon::cat /tmp/tkm.log::Resetting ESA context 1::YES
-moon::cat /tmp/tkm.log::Deleting SA \[ 1, 192.168.0.1 <=> 192.168.0.2, SPI_in.*, SPI_out.* \]::YES
+moon::cat /tmp/tkm.log::Deleting ESA \[ 1, 192.168.0.1 <=> 192.168.0.2, SPI_in.*, SPI_out.* \]::YES
 moon::cat /tmp/xfrm_proxy.log::Initiating ESA acquire for reqid 1::YES
 moon::cat /tmp/xfrm_proxy.log::Initiating ESA expire (reqid 1, proto 50, SPI.*, hard FALSE)::YES
diff --git a/testing/tests/tnc/tnccs-11-fhh/description.txt b/testing/tests/tnc/tnccs-11-fhh/description.txt
index 406b163..8ce1157 100644
--- a/testing/tests/tnc/tnccs-11-fhh/description.txt
+++ b/testing/tests/tnc/tnccs-11-fhh/description.txt
@@ -4,7 +4,7 @@ the clients doing EAP-MD5 password-based authentication.
 In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
 health of <b>carol</b> and <b>dave</b> via the <b>IF-TNCCS 1.1</b> client-server interface.
 The Dummy IMC and IMV from the
-<a href="http://trust.inform.fh-hannover.de/joomla/index.php/projects/tncfhh" target="popup">
+<a href="http://trust.f4.hs-hannover.de/projects/tncatfhh.html" target="popup">
 <b>TNC at FHH</b></a> project are used which communicate over a proprietary protocol.
 <p>
 <b>carol</b> passes the health test and <b>dave</b> fails. Based on these measurements the
diff --git a/testing/tests/tnc/tnccs-11-radius-block/description.txt b/testing/tests/tnc/tnccs-11-radius-block/description.txt
index 55b63ed..67b1a2a 100644
--- a/testing/tests/tnc/tnccs-11-radius-block/description.txt
+++ b/testing/tests/tnc/tnccs-11-radius-block/description.txt
@@ -2,7 +2,7 @@ The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gatewa
 At the outset the gateway authenticates itself to the clients by sending an IKEv2
 <b>RSA signature</b> accompanied by a certificate.
 <b>carol</b> and <b>dave</b> then set up an <b>EAP-TTLS</b> tunnel each via <b>moon</b> to the
-<a href="http://trust.inform.fh-hannover.de/joomla/index.php/projects/tncfhh" target="popup">
+<a href="http://trust.f4.hs-hannover.de/projects/tncatfhh.html" target="popup">
 <b>TNC at FHH</b></a>-enhanced FreeRADIUS server <b>alice</b> authenticated by an X.509 AAA certificate.
 The strong EAP-TTLS tunnel protects the ensuing weak client authentication based on <b>EAP-MD5</b>.
 In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
@@ -10,5 +10,5 @@ health of <b>carol</b> and <b>dave</b> via the <b>IF-TNCCS 1.1</b> client-server
 The IMC and IMV communicate are using the <b>IF-M</b> protocol defined by <b>RFC 5792 PA-TNC</b>.
 <p>
 <b>carol</b> passes the health test and <b>dave</b> fails. Based on these measurements <b>carol</b>
-is authenticated successfully and is granted access to the subnet behind <b>moon</b> whereas 
+is authenticated successfully and is granted access to the subnet behind <b>moon</b> whereas
 <b>dave</b> fails the layered EAP authentication and is rejected.
diff --git a/testing/tests/tnc/tnccs-11-radius-pts/description.txt b/testing/tests/tnc/tnccs-11-radius-pts/description.txt
index f71837b..d5729dd 100644
--- a/testing/tests/tnc/tnccs-11-radius-pts/description.txt
+++ b/testing/tests/tnc/tnccs-11-radius-pts/description.txt
@@ -2,7 +2,7 @@ The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gatewa
 At the outset the gateway authenticates itself to the clients by sending an IKEv2
 <b>RSA signature</b> accompanied by a certificate.
 <b>carol</b> and <b>dave</b> then set up an <b>EAP-TTLS</b> tunnel each via <b>moon</b> to the
-<a href="http://trust.inform.fh-hannover.de/joomla/index.php/projects/tncfhh" target="popup">
+<a href="http://trust.f4.hs-hannover.de/projects/tncatfhh.html" target="popup">
 <b>TNC at FHH</b></a>-enhanced FreeRADIUS server <b>alice</b> authenticated by an X.509 AAA certificate.
 The strong EAP-TTLS tunnel protects the ensuing weak client authentication based on <b>EAP-MD5</b>.
 In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
diff --git a/testing/tests/tnc/tnccs-11-radius/description.txt b/testing/tests/tnc/tnccs-11-radius/description.txt
index 83e5b96..4017c6e 100644
--- a/testing/tests/tnc/tnccs-11-radius/description.txt
+++ b/testing/tests/tnc/tnccs-11-radius/description.txt
@@ -2,7 +2,7 @@ The roadwarriors <b>carol</b> and <b>dave</b> set up a connection each to gatewa
 At the outset the gateway authenticates itself to the clients by sending an IKEv2
 <b>RSA signature</b> accompanied by a certificate.
 <b>carol</b> and <b>dave</b> then set up an <b>EAP-TTLS</b> tunnel each via <b>moon</b> to the
-<a href="http://trust.inform.fh-hannover.de/joomla/index.php/projects/tncfhh" target="popup">
+<a href="http://trust.f4.hs-hannover.de/projects/tncatfhh.html" target="popup">
 <b>TNC at FHH</b></a>-enhanced FreeRADIUS server <b>alice</b> authenticated by an X.509 AAA certificate.
 The strong EAP-TTLS tunnel protects the ensuing weak client authentication based on <b>EAP-MD5</b>.
 In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
diff --git a/testing/tests/tnc/tnccs-11-supplicant/description.txt b/testing/tests/tnc/tnccs-11-supplicant/description.txt
index 6505750..5d01553 100644
--- a/testing/tests/tnc/tnccs-11-supplicant/description.txt
+++ b/testing/tests/tnc/tnccs-11-supplicant/description.txt
@@ -1,7 +1,7 @@
 The layer 2 supplicants <b>carol</b> and <b>dave</b> want to connect to a network
 via switch <b>moon</b> which delegates the IEEE 802.1X authentication to the RADIUS
 server <b>alice</b>. <b>carol</b> and <b>dave</b> set up an <b>EAP-TTLS</b> tunnel
-each via <b>moon</b> to the <a href="http://trust.inform.fh-hannover.de/joomla/index.php/projects/tncfhh" target="popup"> <b>TNC at FHH</b></a>-enhanced FreeRADIUS server <b>alice</b> authenticated
+each via <b>moon</b> to the <a href="http://trust.f4.hs-hannover.de/projects/tncatfhh.html" target="popup"> <b>TNC at FHH</b></a>-enhanced FreeRADIUS server <b>alice</b> authenticated
 by an X.509 AAA certificate.
 The strong EAP-TTLS tunnel protects the ensuing weak client authentication based on <b>EAP-MD5</b>.
 In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
diff --git a/testing/tests/tnc/tnccs-20-fhh/description.txt b/testing/tests/tnc/tnccs-20-fhh/description.txt
index e68f363..8bf1543 100644
--- a/testing/tests/tnc/tnccs-20-fhh/description.txt
+++ b/testing/tests/tnc/tnccs-20-fhh/description.txt
@@ -3,8 +3,8 @@ using EAP-TTLS authentication only with the gateway presenting a server certific
 the clients doing EAP-MD5 password-based authentication.
 In a next step the EAP-TNC protocol is used within the EAP-TTLS tunnel to determine the
 health of <b>carol</b> and <b>dave</b> via the <b>TNCCS 2.0 </b> client-server interface
-compliant with <b>RFC 5793 PB-TNC</b>. The Dummy IMC and IMV from the 
-<a href="http://trust.inform.fh-hannover.de/joomla/index.php/projects/tncfhh" target="popup">
+compliant with <b>RFC 5793 PB-TNC</b>. The Dummy IMC and IMV from the
+<a href="http://trust.f4.hs-hannover.de/projects/tncatfhh.html" target="popup">
 <b>TNC at FHH</b></a> project are used which communicate over a proprietary protocol.
 <p>
 <b>carol</b> passes the health test and <b>dave</b> fails. Based on these measurements the
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat b/testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat
index 3b48073..c3409fd 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/evaltest.dat
@@ -9,6 +9,8 @@ alice::cat /var/log/daemon.log::certificate status is good::YES
 alice::cat /var/log/daemon.log::skipping SASL, client already authenticated by TLS certificate::YES
 alice::cat /var/log/daemon.log::user AR identity.*C=CH, O=Linux strongSwan, OU=Accounting, CN=dave at strongswan.org.*authenticated by certificate::YES
 alice::cat /var/log/daemon.log::received SWID tag inventory with ... items for request 3 at eid 1 of epoch::YES
+alice::cat /var/log/daemon.log::successful system command: ssh root at moon.*logger -t charon -p auth.alert.*host with IP address 192.168.0.200 is blocked::YES
+moon:: cat /var/log/auth.log::host with IP address 192.168.0.200 is blocked::YES
 alice::cat /var/log/daemon.log::accepting PT-TLS stream from PH_IP_CAROL::YES
 alice::cat /var/log/daemon.log::SASL PLAIN authentication successful::YES
 alice::cat /var/log/daemon.log::SASL client identity is.*carol::YES
@@ -17,3 +19,5 @@ alice::cat /var/log/daemon.log::received SWID tag ID inventory with ... items fo
 alice::cat /var/log/daemon.log::1 SWID tag target::YES
 alice::cat /var/log/daemon.log::received SWID tag inventory with 1 item for request 9 at eid 1 of epoch::YES
 alice::cat /var/log/daemon.log::regid.2004-03.org.strongswan_strongSwan-::YES
+alice::cat /var/log/daemon.log::successful system command: ssh root at moon.*logger -t charon -p auth.alert.*host with IP address 192.168.0.100 is allowed::YES
+moon::cat /var/log/auth.log::host with IP address 192.168.0.100 is allowed::YES
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/iptables.rules b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/iptables.rules
index 1586214..48b1cf5 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/iptables.rules
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/iptables.rules
@@ -13,10 +13,14 @@
 -A INPUT  -i eth0 -p tcp --dport 271 -j ACCEPT
 -A OUTPUT -o eth0 -p tcp --sport 271 -j ACCEPT
 
-# allow ssh
+# allow inbound ssh
 -A INPUT  -p tcp --dport 22 -j ACCEPT
 -A OUTPUT -p tcp --sport 22 -j ACCEPT
 
+# allow outbound ssh
+-A OUTPU  -p tcp --dport 22 -j ACCEPT
+-A INPUT  -p tcp --sport 22 -j ACCEPT
+
 # allow crl fetch from winnetou
 -A INPUT  -i eth0 -p tcp --sport 80 -s 192.168.0.150 -j ACCEPT
 -A OUTPUT -o eth0 -p tcp --dport 80 -d 192.168.0.150 -j ACCEPT
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
index 935973c..857e6d6 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
@@ -27,3 +27,8 @@ libimcv {
     }
   }
 }
+
+imv_policy_manager {
+  command_allow = ssh root at moon 'logger -t charon -p auth.alert "\"host with IP address %s is allowed\""'
+  command_block = ssh root at moon 'logger -t charon -p auth.alert "\"host with IP address %s is blocked\""'
+}
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf~
similarity index 83%
copy from testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
copy to testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf~
index 935973c..87dd585 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/alice/etc/strongswan.conf~
@@ -27,3 +27,8 @@ libimcv {
     }
   }
 }
+
+imv_policy_manager {
+  command_allow = host with IP address %s is allowed
+  command_block = host with IP address %s is blocked
+} 
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.conf
new file mode 100644
index 0000000..ecd9d47
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.conf
@@ -0,0 +1,3 @@
+# /etc/ipsec.conf - strongSwan IPsec configuration file
+
+# this file is not used in this scenario 
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.secrets b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.secrets
new file mode 100644
index 0000000..41cf8f8
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/ipsec.secrets
@@ -0,0 +1,3 @@
+# /etc/ipsec.secrets - strongSwan IPsec secrets file
+
+# this file is not used in this scenario 
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/strongswan.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/strongswan.conf
new file mode 100644
index 0000000..d99a4b7
--- /dev/null
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/hosts/moon/etc/strongswan.conf
@@ -0,0 +1,3 @@
+# /etc/strongswan.conf - strongSwan configuration file
+
+# this file is not used in this scenario 
diff --git a/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf b/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
index 0887e4d..5f4f8e7 100644
--- a/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
+++ b/testing/tests/tnc/tnccs-20-pdp-pt-tls/test.conf
@@ -18,7 +18,7 @@ TCPDUMPHOSTS="moon"
 # Guest instances on which IPsec is started
 # Used for IPsec logging purposes
 #
-IPSECHOSTS="carol dave alice"
+IPSECHOSTS="carol moon dave alice"
 
 # Guest instances on which FreeRadius is started
 #

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-swan/strongswan.git



More information about the Pkg-swan-devel mailing list